Annotation of uae/src/traps.c, revision 1.1.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.