bool mapped_malloc (addrbank *ab) { if (ab->allocated_size) { write_log(_T("mapped_malloc with memory bank '%s' already allocated!?\n"), ab->name); } ab->allocated_size = 0; if (ab->label && ab->label[0] == '*') { if (ab->start == 0 || ab->start == 0xffffffff) { write_log(_T("mapped_malloc(*) without start address!\n")); return false; } } struct uae_mman_data md = { 0 }; uaecptr start = ab->start; if (uae_mman_info(ab, &md)) { start = md.start; ab->baseaddr = regs.natmem_offset + start; } if (ab->baseaddr) { if (md.hasbarrier) { // fill end of ram with ILLEGAL to catch direct PC falling out of RAM. put_long_host(ab->baseaddr + ab->reserved_size, 0x4afc4afc); } ab->allocated_size = ab->reserved_size; write_log("mapped_malloc(): 0x%08x - 0x%08x (0x%08x - 0x%08x) -> %s (%s)\n", ab->baseaddr - regs.natmem_offset, ab->baseaddr - regs.natmem_offset + ab->allocated_size, ab->baseaddr, ab->baseaddr + ab->allocated_size, ab->name, ab->label); } ab->flags |= ABFLAG_DIRECTMAP; return (ab->baseaddr != NULL); }
TrapContext *alloc_host_thread_trap_context(void) { if (trap_is_indirect()) { int trap_slot = RTAREA_TRAP_DATA_NUM; TrapContext *ctx = alloc_host_main_trap_context(); ctx->host_trap_data = rtarea_bank.baseaddr + RTAREA_TRAP_DATA + trap_slot * RTAREA_TRAP_DATA_SLOT_SIZE; ctx->amiga_trap_data = rtarea_base + RTAREA_TRAP_DATA + trap_slot * RTAREA_TRAP_DATA_SLOT_SIZE; ctx->host_trap_status = rtarea_bank.baseaddr + RTAREA_TRAP_STATUS + trap_slot * RTAREA_TRAP_STATUS_SIZE; ctx->amiga_trap_status = rtarea_base + RTAREA_TRAP_STATUS + trap_slot * RTAREA_TRAP_STATUS_SIZE; ctx->trap_mode = 1; // Set status to allocated, we are skipping hwtrap_entry() put_long_host(ctx->host_trap_status + 4, 0x00000000); put_long_host(ctx->host_trap_status, 0x00000080); return ctx; } else { return NULL; } }
uae_u32 trap_call_func(TrapContext *ctx, uaecptr func) { uae_u32 v; if (trap_is_indirect_null(ctx)) { uae_u8 *p = ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA; for (int i = 0; i < 16; i++) { if (ctx->calllib_reg_inuse[i]) { put_long_host(p, ctx->calllib_regs[i]); ctx->calllib_reg_inuse[i] = 0; } else { put_long_host(p, ctx->saved_regs.regs[i]); } p += 4; } v = call_hardware_trap_back(ctx, TRAPCMD_CALL_FUNC, func, ctx->amiga_trap_data + RTAREA_TRAP_DATA_EXTRA, 0, 0); } else { uae_u32 storedregs[16]; bool storedregsused[16]; for (int i = 0; i < 16; i++) { storedregsused[i] = false; if (ctx->calllib_reg_inuse[i]) { if ((i & 7) >= 2) { storedregsused[i] = true; storedregs[i] = regs.regs[i]; } regs.regs[i] = ctx->calllib_regs[i]; } ctx->calllib_reg_inuse[i] = 0; } v = CallFunc(ctx, func); for (int i = 0; i < 16; i++) { if (storedregsused[i]) { regs.regs[i] = storedregs[i]; } } } return v; }
// Executes trap from C-code void trap_callback(TRAP_CALLBACK cb, void *ud) { if (trap_is_indirect()) { int trap_slot = RTAREA_TRAP_DATA_NUM; TrapContext *ctx = xcalloc(TrapContext, 1); ctx->host_trap_data = rtarea_bank.baseaddr + RTAREA_TRAP_DATA + trap_slot * RTAREA_TRAP_DATA_SLOT_SIZE; ctx->amiga_trap_data = rtarea_base + RTAREA_TRAP_DATA + trap_slot * RTAREA_TRAP_DATA_SLOT_SIZE; ctx->host_trap_status = rtarea_bank.baseaddr + RTAREA_TRAP_STATUS + trap_slot * RTAREA_TRAP_STATUS_SIZE; ctx->amiga_trap_status = rtarea_base + RTAREA_TRAP_STATUS + trap_slot * RTAREA_TRAP_STATUS_SIZE; ctx->trap_mode = 1; ctx->trap_slot = trap_slot; // Set status to allocated, we are skipping hwtrap_entry() put_long_host(ctx->host_trap_status + 4, 0x00000000); put_long_host(ctx->host_trap_status + 0, 0x00000080); ctx->callback = cb; ctx->callback_ud = ud; write_comm_pipe_pvoid(&trap_thread_pipe[trap_slot], ctx, 1); } else { cb(NULL, ud); } }
void trap_put_longs(TrapContext *ctx, uae_u32 *haddr, uaecptr addr, int cnt) { if (cnt <= 0) return; if (trap_is_indirect_null(ctx)) { while (cnt > 0) { int max = cnt > RTAREA_TRAP_DATA_EXTRA_SIZE / sizeof(uae_u32) ? RTAREA_TRAP_DATA_EXTRA_SIZE / sizeof(uae_u32) : cnt; for (int i = 0; i < max; i++) { put_long_host(ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA + i * sizeof(uae_u32), *haddr++); } call_hardware_trap_back(ctx, TRAPCMD_PUT_LONGS, ctx->amiga_trap_data + RTAREA_TRAP_DATA_EXTRA, addr, max, 0); addr += max * sizeof(uae_u32); cnt -= max; } } else { uae_u32 *p = (uae_u32*)haddr; for (int i = 0; i < cnt; i++) { put_long(addr, *p++); addr += 4; } } }
static uae_u32 call_hardware_trap_back(TrapContext *ctx, uae_u16 cmd, uae_u32 p1, uae_u32 p2, uae_u32 p3, uae_u32 p4) { int trap_slot = ((ctx->amiga_trap_data & 0xffff) - RTAREA_TRAP_DATA) / RTAREA_TRAP_DATA_SLOT_SIZE; uae_u8 *data = ctx->host_trap_data + RTAREA_TRAP_DATA_SECOND; uae_u8 *status = ctx->host_trap_status + RTAREA_TRAP_STATUS_SECOND; #if NEW_TRAP_DEBUG write_log(_T("TRAP BACK SLOT %d: CMD=%d P=%08x %08x %08x %08x TASK=%08x\n"), trap_slot, cmd, p1, p2, p3, p4, get_long_host(ctx->host_trap_data + RTAREA_TRAP_DATA_TASKWAIT)); #endif if (trap_slot != ctx->trap_slot) write_log(_T("Trap trap slot mismatch %d <> %d!\n"), trap_slot, ctx->trap_slot); if (trap_in_use2[trap_slot]) write_log(_T("Trap slot %d already in use2!\n"), trap_slot); trap_in_use2[trap_slot] = true; put_long_host(data + 4, p1); put_long_host(data + 8, p2); put_long_host(data + 12, p3); put_long_host(data + 16, p4); put_word_host(status, cmd); volatile uae_u8 *d = status + 3; if (ctx->trap_mode == 2) { *d = 0xfe; // signal rtarea_bget wait uae_sem_post(&hardware_trap_event2[trap_slot]); } else if (ctx->trap_mode == 0) { *d = 0xfe; } else { atomic_inc(&hwtrap_waiting); atomic_or(&uae_int_requested, 0x2000); set_special_exter(SPCFLAG_UAEINT); *d = 0xff; } for (;;) { if (hardware_trap_kill[trap_slot] < 0) return 0; uae_u8 v = *d; if (v == 0x01 || v == 0x02 || v == 0x03) break; if (hardware_trap_kill[trap_slot] == 0) { hardware_trap_kill[trap_slot] = 2; return 0; } if (uae_sem_trywait_delay(&hardware_trap_event[trap_slot], 100) == -2) { hardware_trap_kill[trap_slot] = 3; return 0; } } // get result uae_u32 v = get_long_host(data + 4); if (!trap_in_use2[trap_slot]) write_log(_T("Trap slot %d in use2 unexpected release!\n"), trap_slot); trap_in_use2[trap_slot] = false; put_long_host(status, 0); #if NEW_TRAP_DEBUG write_log(_T("TRAP BACK SLOT %d: RET = %08x TASK = %08x\n"), trap_slot, v, get_long_host(ctx->host_trap_data + RTAREA_TRAP_DATA_TASKWAIT)); #endif return v; }
static void *hardware_trap_thread(void *arg) { int tid = (uae_u32)arg; for (;;) { TrapContext *ctx = (TrapContext*)read_comm_pipe_pvoid_blocking(&trap_thread_pipe[tid]); if (!ctx) break; if (trap_in_use[ctx->trap_slot]) { write_log(_T("TRAP SLOT %d ALREADY IN USE!\n")); } trap_in_use[ctx->trap_slot] = true; uae_u8 *data = ctx->host_trap_data; uae_u8 *status = ctx->host_trap_status; ctx->tindex = tid; ctx->tcnt = ++trap_cnt; for (int i = 0; i < 15; i++) { uae_u32 v = get_long_host(data + 4 + i * 4); ctx->saved_regs.regs[i] = v; } put_long_host(status + RTAREA_TRAP_STATUS_SECOND, 0); #if NEW_TRAP_DEBUG //if (_tcscmp(trap->name, _T("exter_int_helper"))) write_log(_T("TRAP SLOT %d: NUM %d\n"), ctx->trap_slot, trap_num); #endif uae_u32 ret; struct Trap *trap = NULL; if (ctx->trap_done) write_log(_T("hardware_trap_thread #1: trap_done set!")); if (ctx->callback) { ret = ctx->callback(ctx, ctx->callback_ud); } else { int trap_num = get_word_host(status); trap = &traps[trap_num]; ret = trap->handler(ctx); } if (ctx->trap_done) write_log(_T("hardware_trap_thread #2: trap_done set!")); if (!ctx->trap_background) { for (int i = 0; i < 15; i++) { uae_u32 v = ctx->saved_regs.regs[i]; put_long_host(data + 4 + i * 4, v); } if (trap && (trap->flags & TRAPFLAG_NO_RETVAL) == 0) { put_long_host(data + 4, ret); } hardware_trap_ack(ctx); } else { ctx->trap_done = true; } } hardware_trap_kill[tid] = -1; return 0; }
void trap_multi(TrapContext *ctx, struct trapmd *data, int items) { if (trap_is_indirect_null(ctx)) { uae_u8 *p = ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA; for (int i = 0; i < items; i++) { struct trapmd *md = &data[i]; put_word_host(p + 0, md->cmd); put_byte_host(p + 2, md->trapmd_index); put_byte_host(p + 3, md->parm_num); put_long_host(p + 4, md->params[0]); put_long_host(p + 8, md->params[1]); put_long_host(p + 12, md->params[2]); put_long_host(p + 16, md->params[3]); p += 5 * 4; } call_hardware_trap_back(ctx, TRAPCMD_MULTI, ctx->amiga_trap_data + RTAREA_TRAP_DATA_EXTRA, items, 0, 0); p = ctx->host_trap_data + RTAREA_TRAP_DATA_EXTRA; for (int i = 0; i < items; i++) { struct trapmd *md = &data[i]; md->params[0] = get_long_host(p + 4); p += 5 * 4; } } else { uae_u32 v = 0; for (int i = 0; i < items; i++) { struct trapmd *md = &data[i]; switch (md->cmd) { case TRAPCMD_PUT_LONG: trap_put_long(ctx, md->params[0], md->params[1]); break; case TRAPCMD_PUT_WORD: trap_put_word(ctx, md->params[0], md->params[1]); break; case TRAPCMD_PUT_BYTE: trap_put_byte(ctx, md->params[0], md->params[1]); break; case TRAPCMD_GET_LONG: v = md->params[0] = trap_get_long(ctx, md->params[0]); break; case TRAPCMD_GET_WORD: v = md->params[0] = trap_get_word(ctx, md->params[0]); break; case TRAPCMD_GET_BYTE: v = md->params[0] = trap_get_byte(ctx, md->params[0]); break; case TRAPCMD_PUT_BYTES: trap_put_bytes(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_BYTES: trap_get_bytes(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_PUT_WORDS: trap_put_words(ctx, (uae_u16*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_WORDS: trap_get_words(ctx, (uae_u16*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_PUT_LONGS: trap_put_longs(ctx, (uae_u32*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_LONGS: trap_get_longs(ctx, (uae_u32*)md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_PUT_STRING: trap_put_string(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_GET_STRING: trap_get_string(ctx, md->haddr, md->params[0], md->params[1]); break; case TRAPCMD_SET_LONGS: trap_set_longs(ctx, md->params[0], md->params[1], md->params[2]); break; case TRAPCMD_SET_WORDS: trap_set_words(ctx, md->params[0], md->params[1], md->params[2]); break; case TRAPCMD_SET_BYTES: trap_set_bytes(ctx, md->params[0], md->params[1], md->params[2]); break; case TRAPCMD_NOP: break; } if (md->trapmd_index) { data[md->trapmd_index].params[md->parm_num] = v; } } } }