Annotation of researchv10no/cmd/cfront/libC/otask/fudge.c.68k, revision 1.1.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.