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

1.1     ! root        1: /*ident        "%W%" */
        !             2: /**************************************************************************
        !             3:                        Copyright (c) 1984 AT&T
        !             4:                          All Rights Reserved   
        !             5: 
        !             6:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
        !             7:        
        !             8:        The copyright notice above does not evidence any        
        !             9:        actual or intended publication of such source code.
        !            10: 
        !            11: *****************************************************************************/
        !            12: #include <task.h>
        !            13: #include "hw_stack.h"
        !            14: 
        !            15: // Sun MC68000 frame fudger
        !            16: 
        !            17: /* careful -- stack frame not self-describing */
        !            18: // STACK GROWS DOWN
        !            19: 
        !            20: /*
        !            21:  * On the 68K Suns, the four forms of function call generated
        !            22:  * by the compiler are:
        !            23:  *     jsr     followed by the function address (int)
        !            24:  *     bsrl    followed by the function offset (int) (68020 only)
        !            25:  *     bsr     followed by the function offset (short)
        !            26:  *     bsrb    low order byte is the offset
        !            27:  *             (not actually seen or tested)
        !            28:  */
        !            29: const JSR_CALL = 047271;
        !            30: const BSRL_CALL        = 060777;
        !            31: const BSR_CALL = 060400;
        !            32: const BSRB_CALL        = 0x61;         // Really 0x61NN, where NN is the offset.
        !            33: 
        !            34: /* On the 68K Suns, the function prologue may include the following
        !            35:  * instructions.  See FrameLayout for sequencing.
        !            36:  */
        !            37: const LINKW    = 047126;       // linkw a6,xxx
        !            38: const ADDL     = 0157774;      // addl #yyy,sp
        !            39: const MOVLA5   = 027215;       // movl a5,sp@
        !            40: const MOVLD7   = 027207;       // movl d7,sp@
        !            41: const MOVEM    = 044327;       // movem mask,sp@
        !            42:                                //  (for movem M,a6@(xx) )
        !            43: 
        !            44: int*   Skip_pc_p;      // global to hold fudged return pc.
        !            45:                        // See comments in hw_stack.c.
        !            46: 
        !            47: FrameLayout::FrameLayout(int* fp)
        !            48: {
        !            49:        unsigned short* ret_addr = (unsigned short*)OLD_PC(fp);
        !            50: /*
        !            51:  * find the starting address of the function.  The idea is that the
        !            52:  * instruction immediately before the return address must be the function call.
        !            53:  * Only works if the function was called by name.
        !            54:  */
        !            55:        unsigned short* func_addr =     
        !            56:                (ret_addr[-3] == JSR_CALL) ?
        !            57:                        (unsigned short*)*(int*)(ret_addr-2) :
        !            58:                (ret_addr[-3] == BSRL_CALL) ? 
        !            59:                        (unsigned short*) ((char*)(ret_addr-2)
        !            60:                                + *(int*)(ret_addr-2)) :
        !            61:                (ret_addr[-2] == BSR_CALL) ?
        !            62:                        (unsigned short*) ((char*)(ret_addr-1)
        !            63:                                + *(short*)(ret_addr-1)) :
        !            64:                (*(char*)(ret_addr-1) == BSRB_CALL) ?
        !            65:                        (unsigned short*) ((char*)ret_addr
        !            66:                                + *((char*)ret_addr-1)) :
        !            67:                (unsigned short*)object::task_error(E_FUNCS, (object*)0);
        !            68: /*
        !            69:  * the first instruction in the function is linkw a6,xxx
        !            70:  * if -O was used, xxx is the frame size in bytes (saved regs + automatics),
        !            71:  * otherwise xxx is 0 and the next instruction is addl #yyy, sp
        !            72:  * where yyy is the frame size.
        !            73:  */
        !            74:        if (*func_addr == LINKW) {
        !            75:                if ((offset = (short)*++func_addr / 4) == 0)
        !            76:                        if (*++func_addr == ADDL)  
        !            77:                                offset = (short)*(func_addr += 2) / 4;
        !            78:        } else object::task_error(E_FRAMES, (object*)0);
        !            79: /*
        !            80:  * The next instruction saves the registers in the frame.  Possibilities are:
        !            81:  *     movem   mask,sp@        | save the regs specified by the mask word
        !            82:  *     movl    a5,sp@          | just save a5
        !            83:  *     movl    d7,sp@          | just save d7
        !            84:  * The mask uses the standard 68000 layout
        !            85:  */
        !            86:        switch (*++func_addr) {
        !            87:        case MOVLA5:                    // movl a5,sp@
        !            88:                mask = 020000;          //  just a5
        !            89:                break;
        !            90:        case MOVEM:                     // movem mask,sp@
        !            91:                mask = *++func_addr;    //  mask word
        !            92:                break;
        !            93:        case MOVLD7:                    // movl d7,sp@
        !            94:                mask = 0200;            //  just d7
        !            95:                break;
        !            96:        default:                        // no saved registers is also possible
        !            97:                mask = 0;
        !            98:                break;
        !            99:        }
        !           100: }
        !           101: 
        !           102: /*
        !           103:  * Fudge frame of function-defined-by-f_fp (called "f" below)
        !           104:  * so that that function returns to its grandparent,
        !           105:  * in particular, so a parent task returns to the function that
        !           106:  * called the derived constructor (de_ctor), skipping de_ctor;
        !           107:  * the child will return to the derived constructor, which is its "main."
        !           108:  * To do this we will overwrite the old fp and pc (those saved by
        !           109:  * f) with the old-old ones (those saved by f's caller),
        !           110:  * and we will overwrite the register save area with registers saved by 
        !           111:  * f's caller (referred to as "skip" below).
        !           112:  *
        !           113:  * There are 2 register-save cases to deal with:
        !           114:  *     1. skip_n_saved <= f_n_saved
        !           115:  *     3. skip_n_saved >  f_n_saved
        !           116:  *
        !           117:  * These are handled as follows:
        !           118:  *     1. copy the saved skip_regs over the corresponding f_regs,
        !           119:  *        leaving any additional saved f_regs intact.
        !           120:  *        f's epilogue instructions will be correct.
        !           121:  *     2. f's epilogue instructions will restore too few regs,
        !           122:  *       must take special care to see that the extras are restored properly.
        !           123:  *       -Copy saved skip_regs over any corresponding f_regs,
        !           124:  *       -If fudge_return saved more regs than f did, then
        !           125:  *        copy saved extra saved skip_regs over any corresponding fudge_regs,
        !           126:  *       -If more extra skip_regs (not saved by either f or fudge_return,
        !           127:  *        and therefore not used by either) remain, restore them explicitly.
        !           128:  *        They will not be disturbed by the return from fudge_return or f,
        !           129:  */
        !           130: void
        !           131: task::fudge_return(int* f_fp)
        !           132: {
        !           133:        register int*   fp = f_fp;              // fp of frame-to-be-fudged
        !           134:        FrameLayout     lo(fp);                 // frame to be fudged
        !           135:        register int*   skip_fp = (int*)OLD_FP(fp); // fp for f's caller (skip)
        !           136:        FrameLayout     skip_lo(skip_fp);       // frame for skip
        !           137:        register int*   fr_fp = FP();           // fp for fudge_return
        !           138:        FrameLayout     fr_lo(fr_fp);           // frame for fudge_return
        !           139: 
        !           140:        OLD_PC(fp) = (int)&fudge_sp;    // task::task will return through
        !           141:                                        // fudge_sp, which will reset the sp
        !           142:                                        // to point at the return-pc in
        !           143:                                        // skip's frame
        !           144:        // copy old fp
        !           145:        OLD_FP(fp) = OLD_FP(skip_fp);
        !           146: 
        !           147:        // now copy saved registers
        !           148:        // copy any saved skip regs over corresponding f regs; if there isn't
        !           149:        // a corresponding f reg, copy over corresponding fudge_return reg;
        !           150:        // if there isn't a corresponding fr_reg, restore it explicitly.
        !           151:        register int*   to = FIRST_SAVED_REG_P(fp, lo.offset);
        !           152:        register int*   from = FIRST_SAVED_REG_P(skip_fp, skip_lo.offset);
        !           153:        register int*   fr_to = FIRST_SAVED_REG_P(fr_fp, fr_lo.offset);
        !           154:        for (register int m = 1; m != 0x10000; m <<=1) {
        !           155:                if (m & lo.mask) {
        !           156:                        if (m & skip_lo.mask) {
        !           157:                                *to++ = *from++;
        !           158:                                if (m & fr_lo.mask) fr_to++;
        !           159:                        } else {  // nothing to copy
        !           160:                                to++;
        !           161:                                if (m & fr_lo.mask) fr_to++;
        !           162:                        }
        !           163:                } else if (m & skip_lo.mask) {
        !           164:                        // No slot for *from in f's frame
        !           165:                        if (m & fr_lo.mask) {  // copy to fudge_return's frame
        !           166:                                *fr_to++ = *from++;
        !           167:                        } else {
        !           168:                                // Not used in f or fudge_return;
        !           169:                                // restore explicitly
        !           170:                                switch(m)       {
        !           171:                                case 0x0004:
        !           172:                                        set_d2(from++);
        !           173:                                        break;
        !           174:                                case 0x0008:
        !           175:                                        set_d3(from++);
        !           176:                                        break;
        !           177:                                case 0x0010:
        !           178:                                        set_d4(from++);
        !           179:                                        break;
        !           180:                                case 0x0020:
        !           181:                                        set_d5(from++);
        !           182:                                        break;
        !           183:                                case 0x0040:
        !           184:                                        set_d6(from++);
        !           185:                                        break;
        !           186:                                case 0x0080:
        !           187:                                        set_d7(from++);
        !           188:                                        break;
        !           189:                                case 0x0400:
        !           190:                                        set_a2(from++);
        !           191:                                        break;
        !           192:                                case 0x0800:
        !           193:                                        set_a3(from++);
        !           194:                                        break;
        !           195:                                case 0x1000:
        !           196:                                        set_a4(from++);
        !           197:                                        break;
        !           198:                                case 0x2000:
        !           199:                                        set_a5(from++);
        !           200:                                        break;
        !           201:                                default:
        !           202:                                        // Oops--don't expect other regs
        !           203:                                        // to be saved
        !           204:                                        from++;
        !           205:                                        task_error(E_REGMASK, this);
        !           206:                                        break;
        !           207:                                }
        !           208:                        }
        !           209:                }
        !           210:        }
        !           211: }
        !           212: 

unix.superglobalmegacorp.com

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