X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=ginge.git;a=blobdiff_plain;f=loader%2Femu.c;h=8dc6d51bae91d97f56963b8bc0ef6f8216128807;hp=dd507ff01c85251ac2dcfb83116e2cdeb6bc0b6f;hb=10c900a1c09d1a3f62dc866df11dcda22c6ec8b7;hpb=7000b522095b21ba16784d02997835d74ecc3375 diff --git a/loader/emu.c b/loader/emu.c index dd507ff..8dc6d51 100644 --- a/loader/emu.c +++ b/loader/emu.c @@ -1,8 +1,18 @@ -// vim:shiftwidth=2:expandtab +/* + * GINGE - GINGE Is Not Gp2x Emulator + * (C) notaz, 2010-2011,2016 + * + * This work is licensed under the MAME license, see COPYING file for details. + */ +// a "gentle" reminder +#ifdef __ARM_EABI__ +#error loader is meant to be OABI! +#endif #include #include #include #include +#include #include #include #include @@ -438,7 +448,8 @@ static u32 xread32_io_cmn(u32 a, u32 *handled) // ???? ???? YXBA DURiLe ???? VdVuMS LR?? ???? // | GPIOC[31:16] | GPIOB[31:16] | case 0xa058: // GPIOBPAD - d = pollux.btn_state & 0x0300; + d = (pollux.btn_state >> 1) & 0x0100; + d |= (pollux.btn_state << 1) & 0x0200; d |= (pollux.btn_state >> 3) & 0x0080; d |= (pollux.btn_state >> 5) & 0x0040; d |= (pollux.btn_state >> 6) & 0x0c00; @@ -720,18 +731,46 @@ static struct op_linkpage *g_linkpage; static u32 *g_code_ptr; static int g_linkpage_count; +enum opcond { + C_EQ, C_NE, C_CS, C_CC, C_MI, C_PL, C_VS, C_VC, + C_HI, C_LS, C_GE, C_LT, C_GT, C_LE, C_AL, +}; +enum cpsr_cond { + CPSR_N = (1u << 31), + CPSR_Z = (1u << 30), + CPSR_C = (1u << 29), + CPSR_V = (1u << 28), +}; + #define BIT_SET(v, b) (v & (1 << (b))) void emu_handle_op(struct op_context *op_ctx, struct op_stackframe *sframe) { u32 *regs = sframe->saved_regs; + u32 cpsr = sframe->cpsr; u32 op = op_ctx->op; u32 t, shift, ret, addr; - int rn, rd; + int i, rn, rd, cond; + cond = (op & 0xf0000000) >> 28; rd = (op & 0x0000f000) >> 12; rn = (op & 0x000f0000) >> 16; + if (cond != 0x0e) { + switch (cond) { + case C_EQ: if ( (cpsr & CPSR_Z)) break; return; + case C_NE: if (!(cpsr & CPSR_Z)) break; return; + case C_CS: if ( (cpsr & CPSR_C)) break; return; + case C_CC: if (!(cpsr & CPSR_C)) break; return; + case C_MI: if ( (cpsr & CPSR_N)) break; return; + case C_PL: if (!(cpsr & CPSR_N)) break; return; + case C_VS: if ( (cpsr & CPSR_V)) break; return; + case C_VC: if (!(cpsr & CPSR_V)) break; return; + default: + goto unhandled; + } + } + if ((op & 0x0f200090) == 0x01000090) { // AM3: LDRH, STRH if (!BIT_SET(op, 5)) // !H goto unhandled; @@ -758,10 +797,12 @@ void emu_handle_op(struct op_context *op_ctx, struct op_stackframe *sframe) else xwrite16(addr, regs[rd]); } - else if ((op & 0x0d200000) == 0x05000000) { // AM2: LDR[B], STR[B] + else if ((op & 0x0c000000) == 0x04000000) { // load/store word/byte + if (BIT_SET(op, 21)) + goto unhandled; // unprivileged if (BIT_SET(op, 25)) { // reg offs if (BIT_SET(op, 4)) - goto unhandled; + goto unhandled; // nah it's media t = regs[op & 0x000f]; shift = (op & 0x0f80) >> 7; @@ -777,7 +818,12 @@ void emu_handle_op(struct op_context *op_ctx, struct op_stackframe *sframe) if (!BIT_SET(op, 23)) t = -t; - addr = regs[rn] + t; + + addr = regs[rn]; + if (BIT_SET(op, 24)) // pre-indexed + addr += t; + if (!BIT_SET(op, 24) || BIT_SET(op, 21)) + regs[rn] += t; // writeback if (BIT_SET(op, 20)) { // Load if (BIT_SET(op, 22)) // Byte @@ -806,6 +852,10 @@ void emu_handle_op(struct op_context *op_ctx, struct op_stackframe *sframe) unhandled: err("unhandled IO op %08x @ %08x\n", op, op_ctx->pc); + for (i = 0; i < 8-1; i++) + err(" r%d=%08x r%-2d=%08x\n", i, regs[i], i+8, regs[i+8]); + err(" r%d=%08x cpsr=%08x\n", i, regs[i], cpsr); + abort(); } static u32 make_offset12(u32 *pc, u32 *target) @@ -870,7 +920,7 @@ static void segv_sigaction(int num, siginfo_t *info, void *ctx) // real crash - time to die err("segv %d %p @ %08x\n", info->si_code, info->si_addr, regs[15]); for (i = 0; i < 8; i++) - dbg(" r%d=%08x r%2d=%08x\n", i, regs[i], i+8, regs[i+8]); + dbg(" r%d=%08x r%-2d=%08x\n", i, regs[i], i+8, regs[i+8]); signal(num, SIG_DFL); raise(num); return; @@ -925,6 +975,14 @@ void emu_init(void *map_bottom) void *pret; int ret; +#ifdef PND + if (geteuid() == 0) { + fprintf(stderr, "don't try to run as root, device registers or memory " + "might get trashed crashing the OS or even damaging the device.\n"); + exit(1); + } +#endif + g_linkpage = (void *)(((u32)map_bottom - LINKPAGE_ALLOC) & ~0xfff); pret = mmap(g_linkpage, LINKPAGE_ALLOC, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); @@ -948,13 +1006,15 @@ void emu_init(void *map_bottom) exit(1); } -#ifdef WIZ - // we are short on memmory on Wiz, need special handling - extern void *host_mmap_upper(void); - mmsp2.umem = host_mmap_upper(); -#else + // TODO: check if this really fails on Wiz.. mmsp2.umem = mmap(NULL, 0x2000000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +#ifdef WIZ + if (mmsp2.umem == MAP_FAILED) { + // we are short on memmory on Wiz, need special handling + extern void *host_mmap_upper(void); + mmsp2.umem = host_mmap_upper(); + } #endif if (mmsp2.umem == MAP_FAILED) { perror(PFX "mmap upper mem"); @@ -1195,24 +1255,27 @@ static const struct { const char *from; const char *to; } path_map[] = { - { "/mnt/tmp/", "/tmp/" }, + { "/mnt/tmp", "./tmp" }, }; static const char *wrap_path(const char *path) { - char *buff; + char *buff, *p; size_t size; int i, len; // do only path mapping for now for (i = 0; i < ARRAY_SIZE(path_map); i++) { - len = strlen(path_map[i].from); - if (strncmp(path, path_map[i].from, len) == 0) { + p = strstr(path, path_map[i].from); + if (p != NULL) { size = strlen(path) + strlen(path_map[i].to) + 1; buff = malloc(size); if (buff == NULL) break; - snprintf(buff, size, "%s%s", path_map[i].to, path + len); + len = p - path; + strncpy(buff, path, len); + snprintf(buff + len, size - len, "%s%s", path_map[i].to, + path + len + strlen(path_map[i].from)); dbg("mapped path \"%s\" -> \"%s\"\n", path, buff); return buff; } @@ -1243,6 +1306,7 @@ void *emu_do_fopen(const char *path, const char *mode) int emu_do_system(const char *command) { static char tmp_path[512]; + int need_ginge = 0; const char *p2; char *p; int ret; @@ -1250,17 +1314,25 @@ int emu_do_system(const char *command) if (command == NULL) return -1; - // pass through stuff in PATH - p = strchr(command, ' '); - p2 = strchr(command, '/'); - if (p2 == NULL || (p != NULL && p2 > p)) - return system(command); + for (p2 = command; *p2 && isspace(*p2); p2++) + ; - make_local_path(tmp_path, sizeof(tmp_path), "ginge_prep"); - p = tmp_path + strlen(tmp_path); + if (*p2 == '.') // relative path? + need_ginge = 1; + else if (*p2 == '/' && strncmp(p2, "/bin", 4) && strncmp(p2, "/lib", 4) + && strncmp(p2, "/sbin", 4) && strncmp(p2, "/usr", 4)) + // absolute path, but not a system command + need_ginge = 1; p2 = wrap_path(command); - snprintf(p, sizeof(tmp_path) - (p - tmp_path), " --nomenu %s", p2); + if (need_ginge) { + make_local_path(tmp_path, sizeof(tmp_path), "ginge_prep"); + p = tmp_path + strlen(tmp_path); + + snprintf(p, sizeof(tmp_path) - (p - tmp_path), " --nomenu %s", p2); + } + else + snprintf(tmp_path, sizeof(tmp_path), "%s", p2); wrap_path_free(p2, command); dbg("system: \"%s\"\n", tmp_path); @@ -1311,3 +1383,4 @@ int emu_do_execve(const char *filename, char *const argv[], char *const envp[]) return ret; } +// vim:shiftwidth=2:expandtab