Small optimization (~2-4%) and whitespace cleanup!

Cleans up a ton of whitespace in cpu.c (like 100KB!) and improves
readability of some massive decode statements.

Added an optimization for PC-relative loads (pool load) in ROM (since
it's read only and cannot possibily change) that directly emits an
immediate load. This is way faster, specially in MIPS/x86, ARM can be
even faster if we rewrite the immediate load macros to also use a pool.
This commit is contained in:
David Guillen Fandos 2021-05-07 20:41:54 +02:00
parent 7877a8888b
commit 37430f22c5
7 changed files with 1980 additions and 2721 deletions

View file

@ -376,6 +376,7 @@ else ifeq ($(platform), mips32)
SHARED := -shared -nostdlib -Wl,--version-script=link.T
fpic := -fPIC -DPIC
CFLAGS += -fomit-frame-pointer -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float
CFLAGS += -fno-caller-saves
HAVE_DYNAREC := 1
CPU_ARCH := mips

View file

@ -319,7 +319,7 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations)
#define generate_load_pc(ireg, new_pc) \
arm_load_imm_32bit(ireg, new_pc) \
arm_load_imm_32bit(ireg, (new_pc)) \
#define generate_load_imm(ireg, imm, imm_ror) \
ARM_MOV_REG_IMM(0, ireg, imm, imm_ror) \
@ -1658,6 +1658,10 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
/* Operation types: imm, mem_reg, mem_imm */
#define thumb_load_pc_pool_const(reg_rd, value) \
generate_load_pc(reg_a0, (value)); \
generate_store_reg(reg_a0, reg_rd)
#define thumb_access_memory_load(mem_type, _rd) \
cycle_count += 2; \
generate_function_call(execute_load_##mem_type); \

610
cpu.c
View file

@ -3188,22 +3188,7 @@ arm_loop:
arm_block_memory(load, up, up, yes);
break;
case 0xA0:
case 0xA1:
case 0xA2:
case 0xA3:
case 0xA4:
case 0xA5:
case 0xA6:
case 0xA7:
case 0xA8:
case 0xA9:
case 0xAA:
case 0xAB:
case 0xAC:
case 0xAD:
case 0xAE:
case 0xAF:
case 0xA0 ... 0xAF:
{
/* B offset */
arm_decode_branch();
@ -3211,22 +3196,7 @@ arm_loop:
break;
}
case 0xB0:
case 0xB1:
case 0xB2:
case 0xB3:
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
case 0xB0 ... 0xBF:
{
/* BL offset */
arm_decode_branch();
@ -3241,22 +3211,7 @@ arm_loop:
break;
#endif
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
case 0xF0 ... 0xFF:
{
/* SWI comment */
u32 swi_comment = opcode & 0x00FFFFFF;
@ -3313,38 +3268,17 @@ thumb_loop:
switch((opcode >> 8) & 0xFF)
{
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x00 ... 0x07:
/* LSL rd, rs, offset */
thumb_shift(shift, lsl, imm);
break;
case 0x08:
case 0x09:
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
case 0x0F:
case 0x08 ... 0x0F:
/* LSR rd, rs, offset */
thumb_shift(shift, lsr, imm);
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x10 ... 0x17:
/* ASR rd, rs, offset */
thumb_shift(shift, asr, imm);
break;
@ -3373,164 +3307,24 @@ thumb_loop:
thumb_sub(add_sub_imm, rd, reg[rs], imm);
break;
case 0x20:
/* MOV r0, imm */
thumb_logic(imm, 0, imm);
case 0x20 ... 0x27:
/* MOV r0..7, imm */
thumb_logic(imm, ((opcode >> 8) & 7), imm);
break;
case 0x21:
/* MOV r1, imm */
thumb_logic(imm, 1, imm);
case 0x28 ... 0x2F:
/* CMP r0..7, imm */
thumb_test_sub(imm, reg[(opcode >> 8) & 7], imm);
break;
case 0x22:
/* MOV r2, imm */
thumb_logic(imm, 2, imm);
case 0x30 ... 0x37:
/* ADD r0..7, imm */
thumb_add(imm, ((opcode >> 8) & 7), reg[(opcode >> 8) & 7], imm);
break;
case 0x23:
/* MOV r3, imm */
thumb_logic(imm, 3, imm);
break;
case 0x24:
/* MOV r4, imm */
thumb_logic(imm, 4, imm);
break;
case 0x25:
/* MOV r5, imm */
thumb_logic(imm, 5, imm);
break;
case 0x26:
/* MOV r6, imm */
thumb_logic(imm, 6, imm);
break;
case 0x27:
/* MOV r7, imm */
thumb_logic(imm, 7, imm);
break;
case 0x28:
/* CMP r0, imm */
thumb_test_sub(imm, reg[0], imm);
break;
case 0x29:
/* CMP r1, imm */
thumb_test_sub(imm, reg[1], imm);
break;
case 0x2A:
/* CMP r2, imm */
thumb_test_sub(imm, reg[2], imm);
break;
case 0x2B:
/* CMP r3, imm */
thumb_test_sub(imm, reg[3], imm);
break;
case 0x2C:
/* CMP r4, imm */
thumb_test_sub(imm, reg[4], imm);
break;
case 0x2D:
/* CMP r5, imm */
thumb_test_sub(imm, reg[5], imm);
break;
case 0x2E:
/* CMP r6, imm */
thumb_test_sub(imm, reg[6], imm);
break;
case 0x2F:
/* CMP r7, imm */
thumb_test_sub(imm, reg[7], imm);
break;
case 0x30:
/* ADD r0, imm */
thumb_add(imm, 0, reg[0], imm);
break;
case 0x31:
/* ADD r1, imm */
thumb_add(imm, 1, reg[1], imm);
break;
case 0x32:
/* ADD r2, imm */
thumb_add(imm, 2, reg[2], imm);
break;
case 0x33:
/* ADD r3, imm */
thumb_add(imm, 3, reg[3], imm);
break;
case 0x34:
/* ADD r4, imm */
thumb_add(imm, 4, reg[4], imm);
break;
case 0x35:
/* ADD r5, imm */
thumb_add(imm, 5, reg[5], imm);
break;
case 0x36:
/* ADD r6, imm */
thumb_add(imm, 6, reg[6], imm);
break;
case 0x37:
/* ADD r7, imm */
thumb_add(imm, 7, reg[7], imm);
break;
case 0x38:
/* SUB r0, imm */
thumb_sub(imm, 0, reg[0], imm);
break;
case 0x39:
/* SUB r1, imm */
thumb_sub(imm, 1, reg[1], imm);
break;
case 0x3A:
/* SUB r2, imm */
thumb_sub(imm, 2, reg[2], imm);
break;
case 0x3B:
/* SUB r3, imm */
thumb_sub(imm, 3, reg[3], imm);
break;
case 0x3C:
/* SUB r4, imm */
thumb_sub(imm, 4, reg[4], imm);
break;
case 0x3D:
/* SUB r5, imm */
thumb_sub(imm, 5, reg[5], imm);
break;
case 0x3E:
/* SUB r6, imm */
thumb_sub(imm, 6, reg[6], imm);
break;
case 0x3F:
/* SUB r7, imm */
thumb_sub(imm, 7, reg[7], imm);
case 0x38 ... 0x3F:
/* SUB r0..7, imm */
thumb_sub(imm, ((opcode >> 8) & 7), reg[(opcode >> 8) & 7], imm);
break;
case 0x40:
@ -3679,44 +3473,9 @@ thumb_loop:
}
break;
case 0x48:
/* LDR r0, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[0], u32);
break;
case 0x49:
/* LDR r1, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[1], u32);
break;
case 0x4A:
/* LDR r2, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[2], u32);
break;
case 0x4B:
/* LDR r3, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[3], u32);
break;
case 0x4C:
/* LDR r4, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[4], u32);
break;
case 0x4D:
/* LDR r5, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[5], u32);
break;
case 0x4E:
/* LDR r6, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[6], u32);
break;
case 0x4F:
/* LDR r7, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[7], u32);
case 0x48 ... 0x4F:
/* LDR r0..7, [pc + imm] */
thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[(opcode >> 8) & 7], u32);
break;
case 0x50:
@ -3767,236 +3526,54 @@ thumb_loop:
thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], s16);
break;
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x60 ... 0x67:
/* STR rd, [rb + imm] */
thumb_access_memory(store, mem_imm, reg[rb] + (imm * 4), reg[rd], u32);
break;
case 0x68:
case 0x69:
case 0x6A:
case 0x6B:
case 0x6C:
case 0x6D:
case 0x6E:
case 0x6F:
case 0x68 ... 0x6F:
/* LDR rd, [rb + imm] */
thumb_access_memory(load, mem_imm, reg[rb] + (imm * 4), reg[rd], u32);
break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x70 ... 0x77:
/* STRB rd, [rb + imm] */
thumb_access_memory(store, mem_imm, reg[rb] + imm, reg[rd], u8);
break;
case 0x78:
case 0x79:
case 0x7A:
case 0x7B:
case 0x7C:
case 0x7D:
case 0x7E:
case 0x7F:
case 0x78 ... 0x7F:
/* LDRB rd, [rb + imm] */
thumb_access_memory(load, mem_imm, reg[rb] + imm, reg[rd], u8);
break;
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x80 ... 0x87:
/* STRH rd, [rb + imm] */
thumb_access_memory(store, mem_imm, reg[rb] + (imm * 2), reg[rd], u16);
break;
case 0x88:
case 0x89:
case 0x8A:
case 0x8B:
case 0x8C:
case 0x8D:
case 0x8E:
case 0x8F:
case 0x88 ... 0x8F:
/* LDRH rd, [rb + imm] */
thumb_access_memory(load, mem_imm, reg[rb] + (imm * 2), reg[rd], u16);
break;
case 0x90:
/* STR r0, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[0], u32);
case 0x90 ... 0x97:
/* STR r0..7, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[(opcode >> 8) & 7], u32);
break;
case 0x91:
/* STR r1, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[1], u32);
case 0x98 ... 0x9F:
/* LDR r0..7, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[(opcode >> 8) & 7], u32);
break;
case 0x92:
/* STR r2, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[2], u32);
case 0xA0 ... 0xA7:
/* ADD r0..7, pc, +imm */
thumb_add_noflags(imm, ((opcode >> 8) & 7), (pc & ~2) + 4, (imm * 4));
break;
case 0x93:
/* STR r3, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[3], u32);
break;
case 0x94:
/* STR r4, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[4], u32);
break;
case 0x95:
/* STR r5, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[5], u32);
break;
case 0x96:
/* STR r6, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[6], u32);
break;
case 0x97:
/* STR r7, [sp + imm] */
thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[7], u32);
break;
case 0x98:
/* LDR r0, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[0], u32);
break;
case 0x99:
/* LDR r1, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[1], u32);
break;
case 0x9A:
/* LDR r2, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[2], u32);
break;
case 0x9B:
/* LDR r3, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[3], u32);
break;
case 0x9C:
/* LDR r4, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[4], u32);
break;
case 0x9D:
/* LDR r5, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[5], u32);
break;
case 0x9E:
/* LDR r6, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[6], u32);
break;
case 0x9F:
/* LDR r7, [sp + imm] */
thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[7], u32);
break;
case 0xA0:
/* ADD r0, pc, +imm */
thumb_add_noflags(imm, 0, (pc & ~2) + 4, (imm * 4));
break;
case 0xA1:
/* ADD r1, pc, +imm */
thumb_add_noflags(imm, 1, (pc & ~2) + 4, (imm * 4));
break;
case 0xA2:
/* ADD r2, pc, +imm */
thumb_add_noflags(imm, 2, (pc & ~2) + 4, (imm * 4));
break;
case 0xA3:
/* ADD r3, pc, +imm */
thumb_add_noflags(imm, 3, (pc & ~2) + 4, (imm * 4));
break;
case 0xA4:
/* ADD r4, pc, +imm */
thumb_add_noflags(imm, 4, (pc & ~2) + 4, (imm * 4));
break;
case 0xA5:
/* ADD r5, pc, +imm */
thumb_add_noflags(imm, 5, (pc & ~2) + 4, (imm * 4));
break;
case 0xA6:
/* ADD r6, pc, +imm */
thumb_add_noflags(imm, 6, (pc & ~2) + 4, (imm * 4));
break;
case 0xA7:
/* ADD r7, pc, +imm */
thumb_add_noflags(imm, 7, (pc & ~2) + 4, (imm * 4));
break;
case 0xA8:
/* ADD r0, sp, +imm */
thumb_add_noflags(imm, 0, reg[REG_SP], (imm * 4));
break;
case 0xA9:
/* ADD r1, sp, +imm */
thumb_add_noflags(imm, 1, reg[REG_SP], (imm * 4));
break;
case 0xAA:
/* ADD r2, sp, +imm */
thumb_add_noflags(imm, 2, reg[REG_SP], (imm * 4));
break;
case 0xAB:
/* ADD r3, sp, +imm */
thumb_add_noflags(imm, 3, reg[REG_SP], (imm * 4));
break;
case 0xAC:
/* ADD r4, sp, +imm */
thumb_add_noflags(imm, 4, reg[REG_SP], (imm * 4));
break;
case 0xAD:
/* ADD r5, sp, +imm */
thumb_add_noflags(imm, 5, reg[REG_SP], (imm * 4));
break;
case 0xAE:
/* ADD r6, sp, +imm */
thumb_add_noflags(imm, 6, reg[REG_SP], (imm * 4));
break;
case 0xAF:
/* ADD r7, sp, +imm */
thumb_add_noflags(imm, 7, reg[REG_SP], (imm * 4));
case 0xA8 ... 0xAF:
/* ADD r0..7, sp, +imm */
thumb_add_noflags(imm, ((opcode >> 8) & 7), reg[REG_SP], (imm * 4));
break;
case 0xB0:
@ -4035,84 +3612,14 @@ thumb_loop:
thumb_block_memory(load, no_op, pop_pc, 13);
break;
case 0xC0:
/* STMIA r0!, rlist */
thumb_block_memory(store, no_op, up, 0);
case 0xC0 ... 0xC7:
/* STMIA r0..7!, rlist */
thumb_block_memory(store, no_op, up, ((opcode >> 8) & 7));
break;
case 0xC1:
/* STMIA r1!, rlist */
thumb_block_memory(store, no_op, up, 1);
break;
case 0xC2:
/* STMIA r2!, rlist */
thumb_block_memory(store, no_op, up, 2);
break;
case 0xC3:
/* STMIA r3!, rlist */
thumb_block_memory(store, no_op, up, 3);
break;
case 0xC4:
/* STMIA r4!, rlist */
thumb_block_memory(store, no_op, up, 4);
break;
case 0xC5:
/* STMIA r5!, rlist */
thumb_block_memory(store, no_op, up, 5);
break;
case 0xC6:
/* STMIA r6!, rlist */
thumb_block_memory(store, no_op, up, 6);
break;
case 0xC7:
/* STMIA r7!, rlist */
thumb_block_memory(store, no_op, up, 7);
break;
case 0xC8:
/* LDMIA r0!, rlist */
thumb_block_memory(load, no_op, up, 0);
break;
case 0xC9:
/* LDMIA r1!, rlist */
thumb_block_memory(load, no_op, up, 1);
break;
case 0xCA:
/* LDMIA r2!, rlist */
thumb_block_memory(load, no_op, up, 2);
break;
case 0xCB:
/* LDMIA r3!, rlist */
thumb_block_memory(load, no_op, up, 3);
break;
case 0xCC:
/* LDMIA r4!, rlist */
thumb_block_memory(load, no_op, up, 4);
break;
case 0xCD:
/* LDMIA r5!, rlist */
thumb_block_memory(load, no_op, up, 5);
break;
case 0xCE:
/* LDMIA r6!, rlist */
thumb_block_memory(load, no_op, up, 6);
break;
case 0xCF:
/* LDMIA r7!, rlist */
thumb_block_memory(load, no_op, up, 7);
case 0xC8 ... 0xCF:
/* LDMIA r0..7!, rlist */
thumb_block_memory(load, no_op, up, ((opcode >> 8) & 7));
break;
case 0xD0:
@ -4205,14 +3712,7 @@ thumb_loop:
break;
}
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
case 0xE0 ... 0xE7:
{
/* B label */
thumb_decode_branch();
@ -4220,14 +3720,7 @@ thumb_loop:
break;
}
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF0 ... 0xF7:
{
/* (low word) BL label */
thumb_decode_branch();
@ -4236,14 +3729,7 @@ thumb_loop:
break;
}
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
case 0xF8 ... 0xFF:
{
/* (high word) BL label */
thumb_decode_branch();

View file

@ -1705,8 +1705,9 @@ void translate_icache_sync() {
last_opcode = opcode; \
opcode = address16(pc_address_block, (pc & 0x7FFF)); \
emit_trace_thumb_instruction(pc); \
u8 hiop = opcode >> 8; \
\
switch((opcode >> 8) & 0xFF) \
switch(hiop) \
{ \
case 0x00 ... 0x07: \
/* LSL rd, rs, imm */ \
@ -1743,165 +1744,45 @@ void translate_icache_sync() {
thumb_data_proc(add_sub_imm, subs, imm, rd, rs, imm); \
break; \
\
case 0x20: \
/* MOV r0, imm */ \
thumb_data_proc_unary(imm, movs, imm, 0, imm); \
break; \
/* MOV r0..7, imm */ \
case 0x20: thumb_data_proc_unary(imm, movs, imm, 0, imm); break; \
case 0x21: thumb_data_proc_unary(imm, movs, imm, 1, imm); break; \
case 0x22: thumb_data_proc_unary(imm, movs, imm, 2, imm); break; \
case 0x23: thumb_data_proc_unary(imm, movs, imm, 3, imm); break; \
case 0x24: thumb_data_proc_unary(imm, movs, imm, 4, imm); break; \
case 0x25: thumb_data_proc_unary(imm, movs, imm, 5, imm); break; \
case 0x26: thumb_data_proc_unary(imm, movs, imm, 6, imm); break; \
case 0x27: thumb_data_proc_unary(imm, movs, imm, 7, imm); break; \
\
case 0x21: \
/* MOV r1, imm */ \
thumb_data_proc_unary(imm, movs, imm, 1, imm); \
break; \
\
case 0x22: \
/* MOV r2, imm */ \
thumb_data_proc_unary(imm, movs, imm, 2, imm); \
break; \
\
case 0x23: \
/* MOV r3, imm */ \
thumb_data_proc_unary(imm, movs, imm, 3, imm); \
break; \
\
case 0x24: \
/* MOV r4, imm */ \
thumb_data_proc_unary(imm, movs, imm, 4, imm); \
break; \
\
case 0x25: \
/* MOV r5, imm */ \
thumb_data_proc_unary(imm, movs, imm, 5, imm); \
break; \
\
case 0x26: \
/* MOV r6, imm */ \
thumb_data_proc_unary(imm, movs, imm, 6, imm); \
break; \
\
case 0x27: \
/* MOV r7, imm */ \
thumb_data_proc_unary(imm, movs, imm, 7, imm); \
break; \
\
case 0x28: \
/* CMP r0, imm */ \
thumb_data_proc_test(imm, cmp, imm, 0, imm); \
break; \
case 0x28: thumb_data_proc_test(imm, cmp, imm, 0, imm); break; \
case 0x29: thumb_data_proc_test(imm, cmp, imm, 1, imm); break; \
case 0x2A: thumb_data_proc_test(imm, cmp, imm, 2, imm); break; \
case 0x2B: thumb_data_proc_test(imm, cmp, imm, 3, imm); break; \
case 0x2C: thumb_data_proc_test(imm, cmp, imm, 4, imm); break; \
case 0x2D: thumb_data_proc_test(imm, cmp, imm, 5, imm); break; \
case 0x2E: thumb_data_proc_test(imm, cmp, imm, 6, imm); break; \
case 0x2F: thumb_data_proc_test(imm, cmp, imm, 7, imm); break; \
\
case 0x29: \
/* CMP r1, imm */ \
thumb_data_proc_test(imm, cmp, imm, 1, imm); \
break; \
/* ADD r0..7, imm */ \
case 0x30: thumb_data_proc(imm, adds, imm, 0, 0, imm); break; \
case 0x31: thumb_data_proc(imm, adds, imm, 1, 1, imm); break; \
case 0x32: thumb_data_proc(imm, adds, imm, 2, 2, imm); break; \
case 0x33: thumb_data_proc(imm, adds, imm, 3, 3, imm); break; \
case 0x34: thumb_data_proc(imm, adds, imm, 4, 4, imm); break; \
case 0x35: thumb_data_proc(imm, adds, imm, 5, 5, imm); break; \
case 0x36: thumb_data_proc(imm, adds, imm, 6, 6, imm); break; \
case 0x37: thumb_data_proc(imm, adds, imm, 7, 7, imm); break; \
\
case 0x2A: \
/* CMP r2, imm */ \
thumb_data_proc_test(imm, cmp, imm, 2, imm); \
break; \
\
case 0x2B: \
/* CMP r3, imm */ \
thumb_data_proc_test(imm, cmp, imm, 3, imm); \
break; \
\
case 0x2C: \
/* CMP r4, imm */ \
thumb_data_proc_test(imm, cmp, imm, 4, imm); \
break; \
\
case 0x2D: \
/* CMP r5, imm */ \
thumb_data_proc_test(imm, cmp, imm, 5, imm); \
break; \
\
case 0x2E: \
/* CMP r6, imm */ \
thumb_data_proc_test(imm, cmp, imm, 6, imm); \
break; \
\
case 0x2F: \
/* CMP r7, imm */ \
thumb_data_proc_test(imm, cmp, imm, 7, imm); \
break; \
\
case 0x30: \
/* ADD r0, imm */ \
thumb_data_proc(imm, adds, imm, 0, 0, imm); \
break; \
\
case 0x31: \
/* ADD r1, imm */ \
thumb_data_proc(imm, adds, imm, 1, 1, imm); \
break; \
\
case 0x32: \
/* ADD r2, imm */ \
thumb_data_proc(imm, adds, imm, 2, 2, imm); \
break; \
\
case 0x33: \
/* ADD r3, imm */ \
thumb_data_proc(imm, adds, imm, 3, 3, imm); \
break; \
\
case 0x34: \
/* ADD r4, imm */ \
thumb_data_proc(imm, adds, imm, 4, 4, imm); \
break; \
\
case 0x35: \
/* ADD r5, imm */ \
thumb_data_proc(imm, adds, imm, 5, 5, imm); \
break; \
\
case 0x36: \
/* ADD r6, imm */ \
thumb_data_proc(imm, adds, imm, 6, 6, imm); \
break; \
\
case 0x37: \
/* ADD r7, imm */ \
thumb_data_proc(imm, adds, imm, 7, 7, imm); \
break; \
\
case 0x38: \
/* SUB r0, imm */ \
thumb_data_proc(imm, subs, imm, 0, 0, imm); \
break; \
\
case 0x39: \
/* SUB r1, imm */ \
thumb_data_proc(imm, subs, imm, 1, 1, imm); \
break; \
\
case 0x3A: \
/* SUB r2, imm */ \
thumb_data_proc(imm, subs, imm, 2, 2, imm); \
break; \
\
case 0x3B: \
/* SUB r3, imm */ \
thumb_data_proc(imm, subs, imm, 3, 3, imm); \
break; \
\
case 0x3C: \
/* SUB r4, imm */ \
thumb_data_proc(imm, subs, imm, 4, 4, imm); \
break; \
\
case 0x3D: \
/* SUB r5, imm */ \
thumb_data_proc(imm, subs, imm, 5, 5, imm); \
break; \
\
case 0x3E: \
/* SUB r6, imm */ \
thumb_data_proc(imm, subs, imm, 6, 6, imm); \
break; \
\
case 0x3F: \
/* SUB r7, imm */ \
thumb_data_proc(imm, subs, imm, 7, 7, imm); \
break; \
/* SUB r0..7, imm */ \
case 0x38: thumb_data_proc(imm, subs, imm, 0, 0, imm); break; \
case 0x39: thumb_data_proc(imm, subs, imm, 1, 1, imm); break; \
case 0x3A: thumb_data_proc(imm, subs, imm, 2, 2, imm); break; \
case 0x3B: thumb_data_proc(imm, subs, imm, 3, 3, imm); break; \
case 0x3C: thumb_data_proc(imm, subs, imm, 4, 4, imm); break; \
case 0x3D: thumb_data_proc(imm, subs, imm, 5, 5, imm); break; \
case 0x3E: thumb_data_proc(imm, subs, imm, 6, 6, imm); break; \
case 0x3F: thumb_data_proc(imm, subs, imm, 7, 7, imm); break; \
\
case 0x40: \
switch((opcode >> 6) & 0x03) \
@ -2023,52 +1904,21 @@ void translate_icache_sync() {
thumb_bx(); \
break; \
\
case 0x48: \
/* LDR r0, [pc + imm] */ \
thumb_access_memory(load, imm, 0, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
break; \
\
case 0x49: \
/* LDR r1, [pc + imm] */ \
thumb_access_memory(load, imm, 1, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
break; \
\
case 0x4A: \
/* LDR r2, [pc + imm] */ \
thumb_access_memory(load, imm, 2, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
break; \
\
case 0x4B: \
/* LDR r3, [pc + imm] */ \
thumb_access_memory(load, imm, 3, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
break; \
\
case 0x4C: \
/* LDR r4, [pc + imm] */ \
thumb_access_memory(load, imm, 4, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
break; \
\
case 0x4D: \
/* LDR r5, [pc + imm] */ \
thumb_access_memory(load, imm, 5, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
break; \
\
case 0x4E: \
/* LDR r6, [pc + imm] */ \
thumb_access_memory(load, imm, 6, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
break; \
\
case 0x4F: \
/* LDR r7, [pc + imm] */ \
thumb_access_memory(load, imm, 7, 0, 0, pc_relative, \
(pc & ~2) + (imm * 4) + 4, u32); \
case 0x48 ... 0x4F: \
/* LDR r0..7, [pc + imm] */ \
{ \
thumb_decode_imm(); \
u32 rdreg = (hiop & 7); \
u32 aoff = (pc & ~2) + (imm*4) + 4; \
/* ROM + same page -> optimize as const load */ \
if (translation_region == TRANSLATION_REGION_ROM && \
(((aoff + 4) >> 15) == (pc >> 15))) { \
u32 value = address32(pc_address_block, (aoff & 0x7FFF)); \
thumb_load_pc_pool_const(rdreg, value); \
} else { \
thumb_access_memory(load, imm, rdreg, 0, 0, pc_relative, aoff, u32);\
} \
} \
break; \
\
case 0x50 ... 0x51: \
@ -2143,165 +1993,77 @@ void translate_icache_sync() {
thumb_access_memory(load, mem_imm, rd, rb, 0, reg_imm, (imm * 2), u16); \
break; \
\
/* STR r0..7, [sp + imm] */ \
case 0x90: \
/* STR r0, [sp + imm] */ \
thumb_access_memory(store, imm, 0, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x91: \
/* STR r1, [sp + imm] */ \
thumb_access_memory(store, imm, 1, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x92: \
/* STR r2, [sp + imm] */ \
thumb_access_memory(store, imm, 2, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x93: \
/* STR r3, [sp + imm] */ \
thumb_access_memory(store, imm, 3, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x94: \
/* STR r4, [sp + imm] */ \
thumb_access_memory(store, imm, 4, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x95: \
/* STR r5, [sp + imm] */ \
thumb_access_memory(store, imm, 5, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x96: \
/* STR r6, [sp + imm] */ \
thumb_access_memory(store, imm, 6, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x97: \
/* STR r7, [sp + imm] */ \
thumb_access_memory(store, imm, 7, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
/* LDR r0..7, [sp + imm] */ \
case 0x98: \
/* LDR r0, [sp + imm] */ \
thumb_access_memory(load, imm, 0, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x99: \
/* LDR r1, [sp + imm] */ \
thumb_access_memory(load, imm, 1, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x9A: \
/* LDR r2, [sp + imm] */ \
thumb_access_memory(load, imm, 2, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x9B: \
/* LDR r3, [sp + imm] */ \
thumb_access_memory(load, imm, 3, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x9C: \
/* LDR r4, [sp + imm] */ \
thumb_access_memory(load, imm, 4, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x9D: \
/* LDR r5, [sp + imm] */ \
thumb_access_memory(load, imm, 5, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x9E: \
/* LDR r6, [sp + imm] */ \
thumb_access_memory(load, imm, 6, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0x9F: \
/* LDR r7, [sp + imm] */ \
thumb_access_memory(load, imm, 7, 13, 0, reg_imm_sp, imm, u32); \
break; \
\
case 0xA0: \
/* ADD r0, pc, +imm */ \
thumb_load_pc(0); \
break; \
/* ADD r0..7, pc, +imm */ \
case 0xA0: thumb_load_pc(0); break; \
case 0xA1: thumb_load_pc(1); break; \
case 0xA2: thumb_load_pc(2); break; \
case 0xA3: thumb_load_pc(3); break; \
case 0xA4: thumb_load_pc(4); break; \
case 0xA5: thumb_load_pc(5); break; \
case 0xA6: thumb_load_pc(6); break; \
case 0xA7: thumb_load_pc(7); break; \
\
case 0xA1: \
/* ADD r1, pc, +imm */ \
thumb_load_pc(1); \
break; \
\
case 0xA2: \
/* ADD r2, pc, +imm */ \
thumb_load_pc(2); \
break; \
\
case 0xA3: \
/* ADD r3, pc, +imm */ \
thumb_load_pc(3); \
break; \
\
case 0xA4: \
/* ADD r4, pc, +imm */ \
thumb_load_pc(4); \
break; \
\
case 0xA5: \
/* ADD r5, pc, +imm */ \
thumb_load_pc(5); \
break; \
\
case 0xA6: \
/* ADD r6, pc, +imm */ \
thumb_load_pc(6); \
break; \
\
case 0xA7: \
/* ADD r7, pc, +imm */ \
thumb_load_pc(7); \
break; \
\
case 0xA8: \
/* ADD r0, sp, +imm */ \
thumb_load_sp(0); \
break; \
\
case 0xA9: \
/* ADD r1, sp, +imm */ \
thumb_load_sp(1); \
break; \
\
case 0xAA: \
/* ADD r2, sp, +imm */ \
thumb_load_sp(2); \
break; \
\
case 0xAB: \
/* ADD r3, sp, +imm */ \
thumb_load_sp(3); \
break; \
\
case 0xAC: \
/* ADD r4, sp, +imm */ \
thumb_load_sp(4); \
break; \
\
case 0xAD: \
/* ADD r5, sp, +imm */ \
thumb_load_sp(5); \
break; \
\
case 0xAE: \
/* ADD r6, sp, +imm */ \
thumb_load_sp(6); \
break; \
\
case 0xAF: \
/* ADD r7, sp, +imm */ \
thumb_load_sp(7); \
break; \
/* ADD r0..7, sp, +imm */ \
case 0xA8: thumb_load_sp(0); break; \
case 0xA9: thumb_load_sp(1); break; \
case 0xAA: thumb_load_sp(2); break; \
case 0xAB: thumb_load_sp(3); break; \
case 0xAC: thumb_load_sp(4); break; \
case 0xAD: thumb_load_sp(5); break; \
case 0xAE: thumb_load_sp(6); break; \
case 0xAF: thumb_load_sp(7); break; \
\
case 0xB0 ... 0xB3: \
if((opcode >> 7) & 0x01) \

View file

@ -872,7 +872,6 @@ bool retro_load_game(const struct retro_game_info* info)
strcpy(filename_bios, main_path);
bool bios_loaded = false;
printf("USE %d\n", (int)selected_bios);
if (selected_bios == auto_detect || selected_bios == official_bios)
{
bios_loaded = true;

View file

@ -535,14 +535,14 @@ u32 arm_to_mips_reg[] =
#define generate_load_pc(ireg, new_pc) \
{ \
s32 pc_delta = new_pc - stored_pc; \
s32 pc_delta = (new_pc) - (stored_pc); \
if((pc_delta >= -32768) && (pc_delta <= 32767)) \
{ \
mips_emit_addiu(ireg, reg_pc, pc_delta); \
} \
else \
{ \
generate_load_imm(ireg, new_pc); \
generate_load_imm(ireg, (new_pc)); \
} \
} \
@ -1697,6 +1697,9 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
arm_psr_##transfer_type(op_type, psr_reg); \
} \
#define thumb_load_pc_pool_const(rd, value) \
generate_load_imm(arm_to_mips_reg[rd], (value)); \
#define arm_access_memory_load(mem_type) \
cycle_count += 2; \
mips_emit_jal(mips_absolute_offset(execute_load_##mem_type)); \

View file

@ -325,7 +325,7 @@ typedef enum
x86_emit_mov_reg_mem(reg_##ireg, reg_base, reg_index * 4); \
#define generate_load_pc(ireg, new_pc) \
x86_emit_mov_reg_imm(reg_##ireg, new_pc) \
x86_emit_mov_reg_imm(reg_##ireg, (new_pc)) \
#define generate_load_imm(ireg, imm) \
x86_emit_mov_reg_imm(reg_##ireg, imm) \
@ -1894,6 +1894,10 @@ u32 function_cc execute_ror_imm_op(u32 value, u32 shift)
// Operation types: imm, mem_reg, mem_imm
#define thumb_load_pc_pool_const(reg_rd, value) \
generate_load_pc(a0, (value)); \
generate_store_reg(a0, reg_rd)
#define thumb_access_memory_load(mem_type, reg_rd) \
cycle_count += 2; \
generate_function_call(execute_load_##mem_type); \