uae_u32 uaenative_get_function (TrapContext *context, int flags) { if (!currprefs.native_code) { return UNI_ERROR_NOT_ENABLED; } //m68k_dreg (regs, 1), m68k_areg (regs, 0), //m68k_dreg (regs, 0), m68k_areg (regs, 1), uaecptr name; uae_u32 library; if (flags & UNI_FLAG_COMPAT) { name = m68k_areg (regs, 0); library = m68k_dreg (regs, 1); } else { library = m68k_areg (regs, 0); name = m68k_areg (regs, 1); } uae_u32 result = get_function_handle ( library, (const char *) get_real_address (name)); if ((flags & UNI_FLAG_COMPAT) && !(result & 0x80000000)) { // error getting function, return 0 for error in compatibility mode return 0; } return result; }
uae_u32 uaenative_open_library (TrapContext *context, int flags) { if (!currprefs.native_code) { write_log(_T("uni: tried to open native library, but native code ") _T("is not enabled\n")); return UNI_ERROR_NOT_ENABLED; } uaecptr name; uae_u32 min_version; if (flags & UNI_FLAG_COMPAT) { name = m68k_areg (regs, 0); min_version = 0; } else { name = m68k_areg (regs, 1); min_version = m68k_dreg (regs, 0); } uae_u32 result = open_library ( (const char *) get_real_address (name), min_version); if ((flags & UNI_FLAG_COMPAT) && !(result & 0x80000000)) { // error opening library, return 0 for error in compatibility mode return 0; } return result; }
static uae_u32 REGPARAM2 lib_open (TrapContext *context) { // we could do some security checks here if only some specific Amiga // tasks can call us or something like that put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) + 1); return m68k_areg (regs, 6); }
static uae_u32 m68k_mode_return (void) { uaecptr a7 = m68k_areg (regs, 7); struct extra_stack *s = *(struct extra_stack **)get_real_address (a7); m68k_areg (regs, 7) += (sizeof (void *) + 3) & ~3; /*write_log ("doing m68k mode return\n");*/ do_stack_magic (NULL, s, -1); return 0; }
/* * Call a 68k library function from extended trap. */ uae_u32 CallLib (TrapContext *context, uaecptr base, uae_s16 offset) { uae_u32 retval; uaecptr olda6 = m68k_areg (regs, 6); m68k_areg (regs, 6) = base; retval = trap_Call68k (context, base + offset); m68k_areg (regs, 6) = olda6; return retval; }
static uae_u32 scsidev_close (void) { #ifdef DEBUGME printf("scsidev_close()\n"); #endif opencount--; put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1); return 0; }
static uae_u32 packetfilter (TrapContext *ctx, uaecptr hook, uaecptr ios2, uaecptr data) { uae_u32 a2, v; a2 = m68k_areg (regs, 2); m68k_areg (regs, 0) = hook; m68k_areg (regs, 2) = ios2; m68k_areg (regs, 1) = data; v = CallFunc (ctx, get_long (hook + 8)); m68k_areg (regs, 2) = a2; return v; }
// 3 word stack frame (68000 only) STATIC_INLINE void m68ki_stack_frame_3word(uint32_t pc, uint32_t sr) { #if 0 m68ki_push_32(pc); m68ki_push_16(sr); #else // Push PC on stack: m68k_areg(regs, 7) -= 4; m68k_write_memory_32(m68k_areg(regs, 7), pc); // Push SR on stack: m68k_areg(regs, 7) -= 2; m68k_write_memory_16(m68k_areg(regs, 7), sr); #endif }
static uae_u32 REGPARAM2 dev_open_2 (TrapContext *context, int type) { uaecptr ioreq = m68k_areg (&context->regs, 1); uae_u32 unit = m68k_dreg (&context->regs, 0); uae_u32 flags = m68k_dreg (&context->regs, 1); struct devstruct *dev = getdevstruct (unit); struct priv_devstruct *pdev = 0; int i; if (log_scsi) write_log ("opening %s:%d ioreq=%08.8X\n", getdevname (type), unit, ioreq); if (!dev) return openfail (ioreq, 32); /* badunitnum */ if (!dev->opencnt) { for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdev = &pdevst[i]; if (pdev->inuse == 0) break; } if (type == UAEDEV_SCSI_ID && sys_command_open (DF_SCSI, dev->unitnum)) { pdev->scsi = 1; pdev->mode = DF_SCSI; } if (type == UAEDEV_DISK_ID && sys_command_open (DF_IOCTL, dev->unitnum)) { pdev->ioctl = 1; pdev->mode = DF_IOCTL; } if (!pdev->scsi && !pdev->ioctl) return openfail (ioreq, -1); pdev->type = type; pdev->unit = unit; pdev->flags = flags; pdev->inuse = 1; put_long (ioreq + 24, pdev - pdevst); start_thread (dev); } else { for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdev = &pdevst[i]; if (pdev->inuse && pdev->unit == (int)unit) break; } if (i == MAX_OPEN_DEVICES) return openfail (ioreq, -1); put_long (ioreq + 24, pdev - pdevst); } dev->opencnt++; put_word (m68k_areg (&context->regs, 6) + 32, get_word (m68k_areg (&context->regs, 6) + 32) + 1); put_byte (ioreq + 31, 0); put_byte (ioreq + 8, 7); return 0; }
static uint32_t REGPARAM2 dev_close (TrapContext *context) { uint32_t request = m68k_areg (regs, 1); struct devstruct *dev; dev = getdevstruct (get_long (request + 24)); if (!dev) return 0; if (log_uaeserial) write_log (_T("%s:%d close, req=%x\n"), getdevname(), dev->unit, request); dev_close_3 (dev); put_long (request + 24, 0); put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1); return 0; }
static uint32_t REGPARAM2 dev_open (TrapContext *context) { uaecptr ioreq = m68k_areg (regs, 1); uint32_t unit = m68k_dreg (regs, 0); uint32_t flags = m68k_dreg (regs, 1); struct devstruct *dev; int32_t i, err; if (get_word (ioreq + 0x12) < IOSTDREQ_SIZE) return openfail (ioreq, IOERR_BADLENGTH); for (i = 0; i < MAX_TOTAL_DEVICES; i++) { if (devst[i].open && devst[i].unit == (int32_t)unit && devst[i].exclusive) return openfail (ioreq, IOERR_UNITBUSY); } for (i = 0; i < MAX_TOTAL_DEVICES; i++) { if (!devst[i].open) break; } if (i == MAX_TOTAL_DEVICES) return openfail (ioreq, IOERR_OPENFAIL); dev = &devst[i]; dev->sysdata = xcalloc (uint8_t, uaeser_getdatalength ()); if (!uaeser_open (dev->sysdata, dev, unit)) { xfree (dev->sysdata); return openfail (ioreq, IOERR_OPENFAIL); } dev->unit = unit; dev->open = 1; dev->uniq = ++uniq; dev->exclusive = (get_word (ioreq + io_SerFlags) & SERF_SHARED) ? 0 : 1; put_long (ioreq + 24, dev->uniq); resetparams (dev, ioreq); err = setparams (dev, ioreq); if (err) { uaeser_close (dev->sysdata); dev->open = 0; xfree (dev->sysdata); return openfail (ioreq, err); } if (log_uaeserial) write_log (_T("%s:%d open ioreq=%08X\n"), getdevname(), unit, ioreq); start_thread (dev); put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) + 1); put_byte (ioreq + 31, 0); put_byte (ioreq + 8, 7); return 0; }
uae_u32 CallLib (uaecptr base, uae_s16 offset) { int i; uaecptr olda6 = m68k_areg (regs, 6); uae_u32 retval; #if 0 for (i = 0; i < n_libpatches; i++) { if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL) return (*libpatches[i].functions[-offset/6])(); } #endif m68k_areg (regs, 6) = base; retval = call_m68k (base + offset, 1); m68k_areg (regs, 6) = olda6; return retval; }
static uae_u32 REGPARAM2 dev_beginio (TrapContext *context) { uae_u32 request = m68k_areg (&context->regs, 1); uae_u8 flags = get_byte (request + 30); int command = get_word (request + 28); struct priv_devstruct *pdev = getpdevstruct (request); struct devstruct *dev = getdevstruct (pdev->unit); put_byte (request+8, NT_MESSAGE); if (!dev || !pdev) { put_byte (request + 31, 32); return get_byte (request + 31); } put_byte (request+31, 0); if ((flags & 1) && dev_canquick (dev, request)) { if (dev_do_io (dev, request)) write_log ("device %s command %d bug with IO_QUICK\n", getdevname (pdev->type), command); return get_byte (request + 31); } else { add_async_request (dev, request, ASYNC_REQUEST_TEMP, 0); put_byte (request+30, get_byte (request + 30) & ~1); write_comm_pipe_u32 (&dev->requests, request, 1); return 0; } }
static void ersatz_doio (void) { uaecptr request = m68k_areg(®s, 1); switch (get_word (request + 0x1C)) { case 9: /* TD_MOTOR is harmless */ return; case 2: case 0x8002: /* READ commands */ break; default: write_log ("Only CMD_READ supported in DoIO()\n"); ersatz_failed (); } { uaecptr dest = get_long (request + 0x28); int start = get_long (request + 0x2C) / 512; int nsecs = get_long (request + 0x24) / 512; int tr = start / 11; int sec = start % 11; while (nsecs--) { DISK_ersatz_read (tr, sec, dest); dest += 512; if (++sec == 11) sec = 0, tr++; } } }
static int initint (TrapContext *ctx) { uae_u32 tmp1; uaecptr p; if (irq_init) return 1; m68k_dreg (regs, 0) = 26; m68k_dreg (regs, 1) = 65536 + 1; p = CallLib (ctx, get_long (4), -0xC6); /* AllocMem */ if (!p) return 0; tmp1 = here (); calltrap (deftrap2 (uaenet_int_handler, TRAPFLAG_EXTRA_STACK, _T("uaenet_int_handler"))); put_word (p + 8, 0x020a); put_long (p + 10, ROM_netdev_resid); put_long (p + 18, tmp1); m68k_areg (regs, 1) = p; m68k_dreg (regs, 0) = 3; /* PORTS */ dw (0x4a80); /* TST.L D0 */ dw (0x4e75); /* RTS */ CallLib (ctx, get_long (4), -168); /* AddIntServer */ irq_init = 1; return 1; }
static uae_u32 REGPARAM2 dev_beginio (TrapContext *context) { uae_u32 request = m68k_areg (regs, 1); uae_u8 flags = get_byte (request + 30); int command = get_word (request + 28); struct priv_s2devstruct *pdev = getps2devstruct (request); struct s2devstruct *dev; put_byte (request + 8, NT_MESSAGE); if (!pdev) { write_log (_T("%s unknown iorequest (1) %08x\n"), getdevname (), request); put_byte (request + 31, 32); return get_byte (request + 31); } dev = gets2devstruct (pdev->unit); if (!dev) { write_log (_T("%s unknown iorequest (2) %08x\n"), getdevname (), request); put_byte (request + 31, 32); return get_byte (request + 31); } put_byte (request + 31, 0); if ((flags & 1) && dev_canquick (dev, request)) { if (dev_do_io (dev, request, 1)) write_log (_T("%s: command %d bug with IO_QUICK\n"), SANA2NAME, command); return get_byte (request + 31); } else { if (command == CMD_WRITE || command == S2_BROADCAST || command == S2_MULTICAST) { struct s2packet *s2p; if (!pdev->copyfrombuff || !pdev->copytobuff) { put_long (request + 32, S2ERR_BAD_ARGUMENT); put_byte (request + 31, S2WERR_BUFF_ERROR); } else { if (command == S2_BROADCAST) { uaecptr dstaddr = request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES; put_byte (dstaddr + 0, 0xff); put_byte (dstaddr + 1, 0xff); put_byte (dstaddr + 2, 0xff); put_byte (dstaddr + 3, 0xff); put_byte (dstaddr + 4, 0xff); put_byte (dstaddr + 5, 0xff); } s2p = createwritepacket (context, request); if (s2p) { uae_sem_wait (&async_sem); add_async_packet (dev, s2p, request); uae_sem_post (&async_sem); } if (!s2p) { put_long (request + 32, S2WERR_BUFF_ERROR); put_byte (request + 31, S2ERR_NO_RESOURCES); } } } put_byte (request + 30, get_byte (request + 30) & ~1); write_comm_pipe_u32 (&dev->requests, request, 1); return 0; } }
/* We simply find the first function in this .obj data, and execute it. */ static uae_u32 REGPARAM2 emulib_ExecuteNativeCode (struct regstruct *regs) { #if 0 uaecptr object_AAM = m68k_areg (regs, 0); uae_u32 d1 = m68k_dreg (regs, 1); uae_u32 d2 = m68k_dreg (regs, 2); uae_u32 d3 = m68k_dreg (regs, 3); uae_u32 d4 = m68k_dreg (regs, 4); uae_u32 d5 = m68k_dreg (regs, 5); uae_u32 d6 = m68k_dreg (regs, 6); uae_u32 d7 = m68k_dreg (regs, 7); uae_u32 a1 = m68k_areg (regs, 1); uae_u32 a2 = m68k_areg (regs, 2); uae_u32 a3 = m68k_areg (regs, 3); uae_u32 a4 = m68k_areg (regs, 4); uae_u32 a5 = m68k_areg (regs, 5); uae_u32 a6 = m68k_areg (regs, 6); uae_u8* object_UAM = NULL; CREATE_NATIVE_FUNC_PTR; if( get_mem_bank( object_AAM ).check( object_AAM, 1 ) ) object_UAM = get_mem_bank( object_AAM).xlateaddr( object_AAM ); if( object_UAM ) { SET_NATIVE_FUNC( FindFunctionInObject( object_UAM ) ); CALL_NATIVE_FUNC( d1, d2, d3, d4, d5, d6, d7, a1, a2, a3, a4, a5, a6); } return 1; #endif return 0; }
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context) { uae_u32 request = m68k_areg (&context->regs, 1); struct priv_devstruct *pdev = getpdevstruct (request); struct devstruct *dev; if (!pdev) return 0; dev = getdevstruct (pdev->unit); if (log_scsi) write_log ("%s:%d close, req=%08.8X\n", getdevname (pdev->type), pdev->unit, request); if (!dev) return 0; dev_close_3 (dev, pdev); put_long (request + 24, 0); put_word (m68k_areg (&context->regs, 6) + 32, get_word (m68k_areg (&context->regs, 6) + 32) - 1); return 0; }
static uae_u32 hardfile_open (void) { uaecptr tmp1 = m68k_areg(regs, 1); /* IOReq */ /* Check unit number */ if (get_hardfile_data (m68k_dreg (regs, 0))) { opencount++; put_word (m68k_areg(regs, 6)+32, get_word (m68k_areg(regs, 6)+32) + 1); put_long (tmp1 + 24, m68k_dreg (regs, 0)); /* io_Unit */ put_byte (tmp1 + 31, 0); /* io_Error */ put_byte (tmp1 + 8, 7); /* ln_type = NT_REPLYMSG */ return 0; } put_long (tmp1 + 20, (uae_u32)-1); put_byte (tmp1 + 31, (uae_u8)-1); return (uae_u32)-1; }
uae_u32 trap_get_areg(TrapContext *ctx, int reg) { if (trap_is_indirect_null(ctx)) { if (!ctx) { write_log(_T("trap_get_areg() without TrapContext!\n")); return 0; } return ctx->saved_regs.regs[reg + 8]; } else { return m68k_areg(regs, reg); } }
static uint32_t REGPARAM2 dev_abortio (TrapContext *context) { uint32_t request = m68k_areg (regs, 1); struct devstruct *dev = getdevstruct (get_long (request + 24)); if (!dev) { put_byte (request + 31, 32); return get_byte (request + 31); } abort_async (dev, request); return 0; }
void trap_set_areg(TrapContext *ctx, int reg, uae_u32 v) { if (trap_is_indirect_null(ctx)) { if (!ctx) { write_log(_T("trap_set_areg() without TrapContext!\n")); return; } ctx->saved_regs.regs[reg + 8] = v; } else { m68k_areg(regs, reg) = v; } }
/* patched DOS: NewLoadSeg call */ static uae_u32 REGPARAM2 NewLoadSeg(TrapContext *ctx) { uaecptr name_addr = m68k_areg(regs,0); // a0 = name (was d1) uaecptr seglist_baddr = m68k_dreg(regs,0); // d0 = seglist uaecptr seglist_addr = seglist_baddr << 2; const char *name = (char *)get_real_address(name_addr); //printf("NewLoadSeg(%s) -> %08x\n",name, seglist_addr); add_seglist(name, seglist_addr); return 0; }
static void do_stack_magic (TrapFunction f, struct extra_stack *s, int has_retval) { switch (setjmp (s->stackswap_env)) { case 0: /* Returning directly */ current_extra_stack = s; if (has_retval == -1) { /*write_log ("finishing m68k mode return\n");*/ longjmp (s->m68kcall_env, 1); } /*write_log ("calling native function\n");*/ transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval); /* not reached */ abort (); case 1: /*write_log ("native function complete\n");*/ /* Returning normally. */ if (stack_has_retval (s, EXTRA_STACK_SIZE)) m68k_dreg (regs, 0) = get_retval_from_stack (s, EXTRA_STACK_SIZE); free_extra_stack (s); break; case 2: { /* Returning to do a m68k call. We're now back on the main stack. */ uaecptr a7 = m68k_areg (regs, 7) -= (sizeof (void *) + 7) & ~3; /* Save stack to restore */ *((void **)get_real_address (a7 + 4)) = s; /* Save special return address: this address contains a * calltrap that will longjmp to the right stack. */ put_long (m68k_areg (regs, 7), RTAREA_BASE + 0xFF00); m68k_setpc (s->m68kcall_addr); fill_prefetch_slow (); /*write_log ("native function calls m68k\n");*/ break; } } current_extra_stack = 0; }
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context) { uae_u32 request = m68k_areg (regs, 1); struct priv_s2devstruct *pdev = getps2devstruct (request); struct s2devstruct *dev; if (!pdev) { write_log (_T("%s close with unknown request %08X!?\n"), SANA2NAME, request); return 0; } dev = gets2devstruct (pdev->unit); if (!dev) { write_log (_T("%s:%d close with unknown request %08X!?\n"), SANA2NAME, pdev->unit, request); return 0; } if (log_net) write_log (_T("%s:%d close, open=%d req=%08X\n"), SANA2NAME, pdev->unit, dev->opencnt, request); put_long (request + 24, 0); dev->opencnt--; pdev->inuse = 0; if (!dev->opencnt) { dev->exclusive = 0; if (pdev->tempbuf) { m68k_areg (regs, 1) = pdev->tempbuf; m68k_dreg (regs, 0) = pdev->td->mtu + ETH_HEADER_SIZE + 2; CallLib (context, get_long (4), -0xD2); /* FreeMem */ pdev->tempbuf = 0; } ethernet_close (pdev->td, dev->sysdata); xfree (dev->sysdata); dev->sysdata = NULL; write_comm_pipe_u32 (&dev->requests, 0, 1); write_log (_T("%s: opencnt == 0, all instances closed\n"), SANA2NAME); } put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1); return 0; }
/* * Handles the return from a 68k call at the emulator's side. */ static uae_u32 REGPARAM2 m68k_return_handler (struct regstruct *regs) { ExtendedTrapContext *context; uae_u32 sp; /* One trap returning at a time, please! */ uae_sem_wait (&trap_mutex); /* Get trap context from 68k stack. */ sp = m68k_areg (regs, 7); context = (struct ExtendedTrapContext *) get_pointer(sp); sp += sizeof (void *); m68k_areg (regs, 7) = sp; /* Get return value from the 68k call. */ context->call68k_retval = m68k_dreg (regs, 0); /* Update trap's working copy of CPU state. */ context->regs = *regs; /* Switch back to trap context. */ uae_sem_post (&context->switch_to_trap_sem); /* Wait for trap context to switch back to us. * * It'll do this when the trap handler is done - or when * the handler wants to call another 68k function. */ uae_sem_wait (&context->switch_to_emu_sem); /* Use trap's modified 68k state. This will reset the PC, so that * execution will resume at either the m68k call handler or the * the exit handler. */ *regs = context->regs; /* Dummy return value. */ return 0; }
static uae_u32 scsidev_open (void) { uaecptr tmp1 = m68k_areg (regs, 1); /* IOReq */ uae_u32 unit = m68k_dreg (regs, 0); struct scsidevdata *sdd; #ifdef DEBUGME printf("scsidev_open(0x%x, %d)\n", tmp1, unit); #endif /* Check unit number */ if ((sdd = get_scsidev_data (unit)) && start_thread (sdd)) { opencount++; put_word (m68k_areg (regs, 6)+32, get_word (m68k_areg (regs, 6)+32) + 1); put_long (tmp1 + 24, unit); /* io_Unit */ put_byte (tmp1 + 31, 0); /* io_Error */ put_byte (tmp1 + 8, 7); /* ln_type = NT_REPLYMSG */ return 0; } put_long (tmp1 + 20, (uae_u32)-1); put_byte (tmp1 + 31, (uae_u8)-1); return (uae_u32)-1; }
static uae_u32 REGPARAM2 res_getfunc (TrapContext *ctx) { uaecptr funcname = m68k_areg (regs, 0); uae_char tmp[256]; uae_u32 p; TCHAR *s; if (funcname == 0) return 0; strcpyah_safe (tmp, funcname, sizeof tmp); s = au (tmp); p = find_trap (s); xfree (s); return p; }
void ersatz_perform (uint16_t what) { switch (what) { case EOP_INIT: ersatz_init (); break; case EOP_SERVEINT: { uint16_t intreq = get_word (0xDFF01E); /* Just reset all the interrupt request bits */ if (intreq & 0x0008) get_byte (0xbfed01); /* possible keyboard interrupt */ put_word (0xDFF09C, intreq & 0x3FFF); break; } case EOP_DOIO: ersatz_doio (); break; case EOP_AVAILMEM: m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x70000; break; case EOP_ALLOCMEM: m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x0F000; break; case EOP_ALLOCABS: m68k_dreg (regs, 0) = m68k_areg (regs, 1); break; case EOP_NIMP: write_log (_T("Unimplemented Kickstart function called\n")); ersatz_failed (); /* fall through */ case EOP_LOOP: m68k_setpc (0xF80010); break; case EOP_OPENLIB: default: write_log (_T("Internal error. Giving up.\n")); ersatz_failed (); } }
void ersatz_perform (uae_u16 what) { switch (what) { case EOP_INIT: ersatz_init (); break; case EOP_SERVEINT: /* Just reset all the interrupt request bits */ put_word (0xDFF09C, get_word (0xDFF01E) & 0x3FFF); break; case EOP_DOIO: ersatz_doio (); break; case EOP_AVAILMEM: m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x70000; break; case EOP_ALLOCMEM: m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x0F000; break; case EOP_ALLOCABS: m68k_dreg (regs, 0) = m68k_areg (regs, 1); break; case EOP_NIMP: printf ("Unimplemented Kickstart function called\n"); ersatz_failed (); break; /* fall through */ case EOP_LOOP: m68k_setpc (0xF80010); break; case EOP_OPENLIB: default: printf ("Internal error. Giving up.\n"); ersatz_failed (); break; } }