Annotation of uae/src/traps.c, revision 1.1

1.1     ! root        1:  /*
        !             2:   * E-UAE - The portable Amiga Emulator
        !             3:   *
        !             4:   * Support for traps
        !             5:   *
        !             6:   * Copyright Richard Drummond 2005
        !             7:   *
        !             8:   * Inspired by code from UAE:
        !             9:   * Copyright 1995, 1996 Bernd Schmidt
        !            10:   * Copyright 1996 Ed Hanway
        !            11:   */
        !            12: 
        !            13: #include "sysconfig.h"
        !            14: #include "sysdeps.h"
        !            15: 
        !            16: #include "options.h"
        !            17: #include "memory.h"
        !            18: #include "custom.h"
        !            19: #include "newcpu.h"
        !            20: #include "threaddep/thread.h"
        !            21: #include "autoconf.h"
        !            22: #include "traps.h"
        !            23: 
        !            24: /* We'll need a lot of these. */
        !            25: #define MAX_TRAPS 4096
        !            26: static TrapFunction traps[MAX_TRAPS];
        !            27: static int trapmode[MAX_TRAPS];
        !            28: static const char *trapstr[MAX_TRAPS];
        !            29: static uaecptr trapoldfunc[MAX_TRAPS];
        !            30: 
        !            31: static int max_trap = 0;
        !            32: 
        !            33: /* Stack management */
        !            34: 
        !            35: /* The mechanism for doing m68k calls from native code is as follows:
        !            36:  *
        !            37:  * m68k code executes, stack is main
        !            38:  * calltrap to execute_fn_on_extra_stack. new stack is allocated
        !            39:  * do_stack_magic is called for the first time
        !            40:  * current context is saved with setjmp [0]
        !            41:  *  transfer_control is done
        !            42:  *   native code executes on new stack
        !            43:  *   native code calls call_m68k
        !            44:  *   setjmp saves current context [1]
        !            45:  *  longjmp back to execute_fn_on_extra_stack [0]
        !            46:  * pointer to new stack is saved on m68k stack. m68k return address set
        !            47:  * to RTAREA_BASE + 0xFF00. m68k PC set to called function
        !            48:  * m68k function executes, stack is main
        !            49:  * m68k function returns to RTAREA_BASE + 0xFF00
        !            50:  * calltrap to m68k_mode_return
        !            51:  * do_stack_magic is called again
        !            52:  * current context is saved again with setjmp [0]
        !            53:  *  this time, transfer_control is _not_ done, instead a longjmp[1]
        !            54:  *  to the previously saved context
        !            55:  *   native code executes again on temp stack
        !            56:  *   native function returns to stack_stub
        !            57:  *  longjmp[0] back to old context
        !            58:  * back again!
        !            59:  *
        !            60:  * A bearded man enters the room, carrying a bowl of spaghetti.
        !            61:  */
        !            62: 
        !            63: /* This _shouldn't_ crash with a stack size of 4096, but it does...
        !            64:  * might be a bug */
        !            65: #ifndef EXTRA_STACK_SIZE
        !            66: #define EXTRA_STACK_SIZE 65536
        !            67: #endif
        !            68: 
        !            69: static void *extra_stack_list = NULL;
        !            70: 
        !            71: static void *get_extra_stack (void)
        !            72: {
        !            73:     void *s = extra_stack_list;
        !            74:     if (s)
        !            75:        extra_stack_list = *(void **)s;
        !            76:     if (!s)
        !            77:        s = xmalloc (EXTRA_STACK_SIZE);
        !            78:     return s;
        !            79: }
        !            80: 
        !            81: static void free_extra_stack (void *s)
        !            82: {
        !            83:     *(void **)s = extra_stack_list;
        !            84:     extra_stack_list = s;
        !            85: }
        !            86: 
        !            87: static void stack_stub (void *s, TrapFunction f, uae_u32 *retval)
        !            88: {
        !            89: #ifdef CAN_DO_STACK_MAGIC
        !            90:     /*printf("in stack_stub: %p %p %p %x\n", s, f, retval, (int)*retval);*/
        !            91:     *retval = f ();
        !            92:     /*write_log ("returning from stack_stub\n");*/
        !            93:     longjmp (((jmp_buf *)s)[0], 1);
        !            94: #endif
        !            95: }
        !            96: 
        !            97: static void *current_extra_stack = NULL;
        !            98: static uaecptr m68k_calladdr;
        !            99: 
        !           100: static void do_stack_magic (TrapFunction f, void *s, int has_retval)
        !           101: {
        !           102: #ifdef CAN_DO_STACK_MAGIC
        !           103:     uaecptr a7;
        !           104:     jmp_buf *j = (jmp_buf *)s;
        !           105:     switch (setjmp (j[0])) {
        !           106:      case 0:
        !           107:        /* Returning directly */
        !           108:        current_extra_stack = s;
        !           109:        if (has_retval == -1) {
        !           110:            /*write_log ("finishing m68k mode return\n");*/
        !           111:            longjmp (j[1], 1);
        !           112:        }
        !           113:        /*write_log ("calling native function\n");*/
        !           114:        transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval);
        !           115:        /* not reached */
        !           116:        abort ();
        !           117: 
        !           118:      case 1:
        !           119:        /*write_log ("native function complete\n");*/
        !           120:        /* Returning normally. */
        !           121:        if (stack_has_retval (s, EXTRA_STACK_SIZE))
        !           122:            m68k_dreg (regs, 0) = get_retval_from_stack (s, EXTRA_STACK_SIZE);
        !           123:        free_extra_stack (s);
        !           124:        break;
        !           125: 
        !           126:      case 2:
        !           127:        /* Returning to do a m68k call. We're now back on the main stack. */
        !           128:        a7 = m68k_areg(regs, 7) -= (sizeof (void *) + 7) & ~3;
        !           129:        /* Save stack to restore */
        !           130:        *((void **)get_real_address (a7 + 4)) = s;
        !           131:        /* Save special return address: this address contains a
        !           132:         * calltrap that will longjmp to the right stack. */
        !           133:        put_long (m68k_areg (regs, 7), RTAREA_BASE + 0xFF00);
        !           134:        m68k_setpc (m68k_calladdr);
        !           135:        fill_prefetch_slow ();
        !           136:        /*write_log ("native function calls m68k\n");*/
        !           137:        break;
        !           138:     }
        !           139:     current_extra_stack = 0;
        !           140: #endif
        !           141: }
        !           142: 
        !           143: static uae_u32 execute_fn_on_extra_stack (TrapFunction f, int has_retval)
        !           144: {
        !           145: #ifdef CAN_DO_STACK_MAGIC
        !           146:     void *s = get_extra_stack ();
        !           147:     do_stack_magic (f, s, has_retval);
        !           148: #endif
        !           149:     return 0;
        !           150: }
        !           151: 
        !           152: uae_u32 m68k_mode_return (void)
        !           153: {
        !           154: #ifdef CAN_DO_STACK_MAGIC
        !           155:     uaecptr a7 = m68k_areg(regs, 7);
        !           156:     void *s = *(void **)get_real_address(a7);
        !           157:     m68k_areg(regs, 7) += (sizeof (void *) + 3) & ~3;
        !           158:     /*write_log ("doing m68k mode return\n");*/
        !           159:     do_stack_magic (NULL, s, -1);
        !           160: #endif
        !           161:     return 0;
        !           162: }
        !           163: 
        !           164: static uae_u32 call_m68k (uaecptr addr, int saveregs)
        !           165: {
        !           166:     volatile uae_u32 retval = 0;
        !           167:     volatile int do_save = saveregs;
        !           168:     if (current_extra_stack == NULL)
        !           169:        abort();
        !           170: #ifdef CAN_DO_STACK_MAGIC
        !           171:     {
        !           172:        volatile struct regstruct saved_regs;
        !           173:        jmp_buf *j = (jmp_buf *)current_extra_stack;
        !           174: 
        !           175:        if (do_save)
        !           176:            saved_regs = regs;
        !           177:        m68k_calladdr = addr;
        !           178:        switch (setjmp(j[1])) {
        !           179:         case 0:
        !           180:            /*write_log ("doing call\n");*/
        !           181:            /* Returning directly: now switch to main stack and do the call */
        !           182:            longjmp (j[0], 2);
        !           183:         case 1:
        !           184:            /*write_log ("returning from call\n");*/
        !           185:            retval = m68k_dreg (regs, 0);
        !           186:            if (do_save)
        !           187:                regs = saved_regs;
        !           188:            /* Returning after the call. */
        !           189:            break;
        !           190:        }
        !           191:     }
        !           192: #endif
        !           193:     return retval;
        !           194: }
        !           195: 
        !           196: uae_u32 CallLib (uaecptr base, uae_s16 offset)
        !           197: {
        !           198:     int i;
        !           199:     uaecptr olda6 = m68k_areg(regs, 6);
        !           200:     uae_u32 retval;
        !           201: #if 0
        !           202:     for (i = 0; i < n_libpatches; i++) {
        !           203:        if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
        !           204:            return (*libpatches[i].functions[-offset/6])();
        !           205:     }
        !           206: #endif
        !           207:     m68k_areg(regs, 6) = base;
        !           208:     retval = call_m68k(base + offset, 1);
        !           209:     m68k_areg(regs, 6) = olda6;
        !           210:     return retval;
        !           211: }
        !           212: 
        !           213: static int trace_traps = 1;
        !           214: 
        !           215: void REGPARAM2 call_calltrap(int func)
        !           216: {
        !           217:     uae_u32 retval = 0;
        !           218:     int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0;
        !           219:     int implicit_rts = (trapmode[func] & TRAPFLAG_DORET) != 0;
        !           220: 
        !           221:     if (*trapstr[func] != 0 && trace_traps)
        !           222:        write_log ("TRAP: %s\n", trapstr[func]);
        !           223: 
        !           224:     /* For monitoring only? */
        !           225:     if (traps[func] == NULL) {
        !           226:        m68k_setpc(trapoldfunc[func]);
        !           227:        fill_prefetch_slow ();
        !           228:        return;
        !           229:     }
        !           230: 
        !           231:     if (func < max_trap) {
        !           232:        if (trapmode[func] & TRAPFLAG_EXTRA_STACK) {
        !           233:            execute_fn_on_extra_stack(traps[func], has_retval);
        !           234:            return;
        !           235:        }
        !           236:        retval = (*traps[func])();
        !           237:     } else
        !           238:        write_log ("illegal emulator trap\n");
        !           239: 
        !           240:     if (has_retval)
        !           241:        m68k_dreg(regs, 0) = retval;
        !           242:     if (implicit_rts) {
        !           243:        m68k_do_rts ();
        !           244:        fill_prefetch_slow ();
        !           245:     }
        !           246: }
        !           247: 
        !           248: static volatile int four = 4;
        !           249: uaecptr libemu_InstallFunctionFlags (TrapFunction f, uaecptr libbase, int offset,
        !           250:                                     int flags, const char *tracename)
        !           251: {
        !           252:     int i;
        !           253:     uaecptr retval;
        !           254:     uaecptr execbase = get_long (four);
        !           255:     int trnum;
        !           256:     uaecptr addr = here();
        !           257:     calltrap (trnum = deftrap2 (f, flags, tracename));
        !           258:     dw (RTS);
        !           259:     
        !           260:     m68k_areg(regs, 1) = libbase;
        !           261:     m68k_areg(regs, 0) = offset;
        !           262:     m68k_dreg(regs, 0) = addr;
        !           263:     retval = CallLib (execbase, -420);
        !           264:     
        !           265:     trapoldfunc[trnum] = retval;
        !           266: #if 0
        !           267:     for (i = 0; i < n_libpatches; i++) {
        !           268:        if (libpatches[i].libbase == libbase)
        !           269:            break;
        !           270:     }
        !           271:     if (i == n_libpatches) {
        !           272:        int j;
        !           273:        libpatches[i].libbase = libbase;
        !           274:        for (j = 0; j < 300; j++)
        !           275:            libpatches[i].functions[j] = NULL;
        !           276:        n_libpatches++;
        !           277:     }
        !           278:     libpatches[i].functions[-offset/6] = f;
        !           279: #endif
        !           280:     return retval;
        !           281: }
        !           282: 
        !           283: int deftrap2 (TrapFunction func, int mode, const char *str)
        !           284: {
        !           285:     int num = max_trap++;
        !           286:     traps[num] = func;
        !           287:     trapstr[num] = str;
        !           288:     trapmode[num] = mode;
        !           289:     return num;
        !           290: }
        !           291: 
        !           292: int deftrap (TrapFunction func)
        !           293: {
        !           294:     return deftrap2 (func, 0, "");
        !           295: }

unix.superglobalmegacorp.com

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