/*
* GINGE - GINGE Is Not Gp2x Emulator
- * (C) notaz, 2010-2011
+ * (C) notaz, 2010-2011,2016
*
* This work is licensed under the MAME license, see COPYING file for details.
*/
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;
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);
+ 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)
// 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;
err("warning: uppermem @ %08x overflows by %d bytes\n",
offset, umem + length - umem_end);
- dbg("upper mem @ %08x %d\n", offset, length);
+ dbg("upper mem @ %08x %x = %p\n", offset, length, umem);
return umem;
}
return MAP_FAILED;
}
+int emu_do_munmap(void *addr, unsigned int length)
+{
+ u8 *p = addr;
+
+ // don't allow to unmap upper mem
+ if ((u8 *)mmsp2.umem <= p && p < (u8 *)mmsp2.umem + 0x2000000) {
+ dbg("ignoring munmap: %p %x\n", addr, length);
+ return 0;
+ }
+
+ return -EAGAIN;
+}
+
static void emu_sound_open(int fd)
{
#ifdef PND