-// 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!
#include <stdlib.h>
#include <string.h>
#include <alloca.h>
+#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
u32 *regs = sframe->saved_regs;
u32 op = op_ctx->op;
u32 t, shift, ret, addr;
- int rn, rd;
+ int rn, rd, cond;
+ cond = (op & 0xf0000000) >> 28;
rd = (op & 0x0000f000) >> 12;
rn = (op & 0x000f0000) >> 16;
+ if (cond != 0x0e)
+ goto unhandled; // TODO
+
if ((op & 0x0f200090) == 0x01000090) { // AM3: LDRH, STRH
if (!BIT_SET(op, 5)) // !H
goto unhandled;
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;
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
unhandled:
err("unhandled IO op %08x @ %08x\n", op, op_ctx->pc);
+ abort();
}
static u32 make_offset12(u32 *pc, u32 *target)
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");
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;
}
int emu_do_system(const char *command)
{
static char tmp_path[512];
+ int need_ginge = 0;
const char *p2;
char *p;
int ret;
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);
return ret;
}
+// vim:shiftwidth=2:expandtab