Annotation of researchv10no/cmd/cfront/libC/otask/fudge.c.68k, revision 1.1

1.1     ! root        1: #include "task.h"
        !             2: 
        !             3: // MC68000 frame fudger
        !             4: 
        !             5: /* careful -- stack frame not self-describing */
        !             6: // STACK GROWS DOWN
        !             7: #define FP(p)          ( (int*)(&p+1) )
        !             8: #define AP()           0       /* unnecessary on mc68000 */
        !             9: #define OLD_AP(fp)     0       /* unnecessary on mc68000 */
        !            10: #define OLD_FP(fp)     (*fp)
        !            11: 
        !            12: struct FrameLayout {
        !            13:        short   offset; // of top of frame from fp (size of locals + regs)
        !            14:        unsigned short  mask;   // of registers saved in frame
        !            15:                FrameLayout(int*);  // called with frame pointer
        !            16: };
        !            17: 
        !            18: /*
        !            19:  * This code figures out the layout of the frame of the user's constructor.  Note
        !            20:  * the user's class is directly derived from class task and the call to the
        !            21:  * constructor is automatically generated.
        !            22:  */
        !            23: FrameLayout::FrameLayout(int* fp)
        !            24: {
        !            25:        unsigned short* ret_addr = (unsigned short*)*(fp+1);
        !            26: /*
        !            27:  * find the starting address of the function.  The idea is that the instruction
        !            28:  * immediately before the return address must be the function call.  Only works
        !            29:  * if the function was called by name.
        !            30:  */
        !            31: /*
        !            32:  * On the 68000, the four forms of function call generated by the compiler are
        !            33:  *     047271  jsr     followed by the function address (long)
        !            34:  *     060777  bsrl    followed by the function offset (long) (68020 only)
        !            35:  *     060400  bsr     followed by the function offset (short)
        !            36:  *     0x61NN  bsrb    low order byte is the offset (not actually seen or tested)
        !            37:  */
        !            38:        unsigned short* func_addr =     
        !            39:                (ret_addr[-3] == 047271) ?
        !            40:                        (unsigned short*)*(int*)(ret_addr-2) :
        !            41:                (ret_addr[-3] == 060777) ? 
        !            42:                        (unsigned short*) ((char*)(ret_addr-2) + *(int*)(ret_addr-2)) :
        !            43:                (ret_addr[-2] == 060400) ?
        !            44:                        (unsigned short*) ((char*)(ret_addr-1) + *(short*)(ret_addr-1)) :
        !            45:                (*(char*)(ret_addr-1) == 0x61) ?
        !            46:                        (unsigned short*) ((char*)ret_addr + *((char*)ret_addr-1)) :
        !            47:                        (unsigned short*)((object*)0)->task_error(E_FUNCS);
        !            48: /*
        !            49:  * the first instruction in the function is linkw a6,xxx
        !            50:  * if -O was used, xxx is the frame size in bytes, otherwise
        !            51:  * xxx is 0 and the next instruction is addl #yyy, sp
        !            52:  * where yyy is the frame size
        !            53:  */
        !            54:        if (*func_addr == 047126) { // linkw instruction
        !            55:                if ((offset = (short)*++func_addr / 4) == 0)
        !            56:                        if (*++func_addr == 0157774)  // addl
        !            57:                                offset = (short)*(func_addr += 2) / 4;
        !            58:        } else ((object*)0)->task_error(E_FRAMES);
        !            59: /*
        !            60:  * The next instruction saves the registers in the frame.  The possibilities are
        !            61:  *     movem   mask,@sp        | save the register specified by the mask word
        !            62:  *     movl    a5,@sp          | just save a5
        !            63:  *     movl    d7,@sp          | just save d7
        !            64:  * The mask uses the standard 68000 layout
        !            65:  */
        !            66:        switch (*++func_addr) {
        !            67:        case 027215:                    // movl a5,sp@
        !            68:                mask = 020000;          //  just a5
        !            69:                break;
        !            70:        case 044327:                    // movem mask,@sp
        !            71:                mask = *++func_addr;    //  mask word
        !            72:                break;
        !            73:        case 027207:                    // movl d7,sp@
        !            74:                mask = 0200;            //  just d7
        !            75:                break;
        !            76:        default:                        // no saved registers is also possible
        !            77:                mask = 0;
        !            78:                break;
        !            79:        }
        !            80: }
        !            81: 
        !            82: /*
        !            83:  * fix a frame so that it returns like the arg
        !            84:  * The idea is that task_fp points to the task::task() stack frame which
        !            85:  * contains all the saved registers.  t_framep points to the stack frame
        !            86:  * that contains the return address and old fp (and perhaps some registers).
        !            87:  * fill the frame pointed to by t_framep with the registers from task_fp.
        !            88:  */
        !            89: void
        !            90: task::fudge_return(int* task_fp, int offset, task* next)
        !            91: {
        !            92:        int*    fp = t_framep + offset;
        !            93:        task_fp += offset;              // in case this is SHARED
        !            94:        FrameLayout     this_lo(fp);
        !            95:        FrameLayout     task_lo(task_fp);
        !            96:        // copy any saved registers from this to task frame
        !            97:        register int*   task_rp = task_fp + task_lo.offset;
        !            98:        register int*   this_rp = fp + this_lo.offset;
        !            99:        register int    reg_count = 0;
        !           100:        for (register mask = 1; mask != 0x10000; mask <<= 1) {
        !           101:                if (mask & task_lo.mask) {
        !           102:                        reg_count++;
        !           103:                        if (mask & this_lo.mask)
        !           104:                                *task_rp++ = *this_rp++;
        !           105:                        else task_rp++;
        !           106:                } else if (mask & this_lo.mask)
        !           107:                        task_error(E_FUDGE);
        !           108:        }
        !           109:        // next copy all the registers from the task frame to this (using task offset)
        !           110:        task_rp = task_fp + task_lo.offset + reg_count;
        !           111:        this_rp = fp + task_lo.offset + reg_count;
        !           112:        while (reg_count--)
        !           113:                *--this_rp = *--task_rp;
        !           114:        if (next) next->restore();
        !           115: }
        !           116: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.