Get some CPU tests passing on ARM/Android

This commit is contained in:
Aaron Culliney 2015-02-18 23:08:16 -08:00
parent 43fa9c9357
commit 3149914741
3 changed files with 88 additions and 96 deletions

View File

@ -24,10 +24,10 @@
#define Y_Reg r6 /* 8bit 6502 Y register */ #define Y_Reg r6 /* 8bit 6502 Y register */
#define X_Reg r7 /* 8bit 6502 X register */ #define X_Reg r7 /* 8bit 6502 X register */
#define A_Reg r8 /* 8bit 6502 A register */ #define A_Reg r8 /* 8bit 6502 A register */
// r9 is another scratch variable // r9 is "ARM platform register" ... used as a scratch register
#define reg_64k r10 /* apple_ii_64k table address */ // r10 is another scratch variable
#define reg_vmem_r r11 /* cpu65_vmem_r table address */ #define reg_vmem_r r11 /* cpu65_vmem_r table address */
// r12 unused // r12 is "ARM Intra-Procedure-call scratch register" ... used as a scratch register
// r13 ARM SP // r13 ARM SP
// r14 ARM return addr // r14 ARM return addr
// r15 ARM PC // r15 ARM PC
@ -36,10 +36,6 @@
#define ARM_AF_Bit ... #define ARM_AF_Bit ...
// x86-ish instruction macros for legibility =P
#define ret mov pc, r14
#ifdef __aarch64__ #ifdef __aarch64__
# error 20150205 ARM 64bit untested!!! # error 20150205 ARM 64bit untested!!!
# define PTR_SHIFT #4 // 4<<1 = 8 # define PTR_SHIFT #4 // 4<<1 = 8

View File

@ -17,11 +17,6 @@
#include "misc.h" #include "misc.h"
// debugging is necessary for running CPU test suite and to use the 65c02 debugger
#ifndef NDEBUG
#define CPU_DEBUGGING 1
#endif
#define DecodeFlags \ #define DecodeFlags \
ldr r1, SYM(cpu65_flags_decode); \ ldr r1, SYM(cpu65_flags_decode); \
ldrb F_Reg, [r1, r0]; ldrb F_Reg, [r1, r0];
@ -51,7 +46,6 @@
ldr r1, SYM(cpu65_f); \ ldr r1, SYM(cpu65_f); \
strb r0, [r1] strb r0, [r1]
// Tracing is necessary for some CPU tests and to verify operation against other emulators // Tracing is necessary for some CPU tests and to verify operation against other emulators
#if CPU_TRACING #if CPU_TRACING
# define TRACE_PROLOGUE \ # define TRACE_PROLOGUE \
@ -65,10 +59,10 @@
# define TRACE_ARG2 \ # define TRACE_ARG2 \
bl CALL(cpu65_trace_arg2); bl CALL(cpu65_trace_arg2);
# define TRACE_EPILOGUE \ # define TRACE_EPILOGUE \
push {r0}; \
CommonSaveCPUState; \ CommonSaveCPUState; \
push {r0, EffectiveAddr, PC_Reg, lr}; \
bl CALL(cpu65_trace_epilogue); \ bl CALL(cpu65_trace_epilogue); \
pop {r0}; pop {r0, EffectiveAddr, PC_Reg, lr};
#else #else
# define TRACE_PROLOGUE # define TRACE_PROLOGUE
# define TRACE_ARG # define TRACE_ARG
@ -78,50 +72,57 @@
#endif #endif
#if CPU_DEBUGGING #define CPUStatsReset \
# define CPU_DEBUGGING_RESET \
ldr r1, SYM(cpu65_opcode); \ ldr r1, SYM(cpu65_opcode); \
strb r0, [r1]; /* r0 should be next opcode */ \ strb r0, [r1]; /* r0 should be next opcode */ \
eor r9, r9, r9; \ eor r9, r9, r9; \
ldr r1, SYM(cpu65_opcycles); \ ldr r1, SYM(cpu65_opcycles); \
strb r9, [r1]; \ strb r9, [r1]; \
/*ldr r1, SYM(cpu65_rw);*/ \ ldr r1, SYM(cpu65_rw); \
strb r9, [r1]; strb r9, [r1];
# define CPU_DEBUGGING_SET_READ \ #define CPUStatsSetRead \
/*ldr r1, SYM(cpu65_rw);*/ \ ldr r1, SYM(cpu65_rw); \
ldrb r9, [r1]; \ ldrb r9, [r1]; \
orr r9, r9, #1; \ orr r9, r9, #1; \
strb r9, [r1]; strb r9, [r1];
# define CPU_DEBUGGING_SET_WRITE \
/*ldr r1, SYM(cpu65_rw);*/ \ #define CPUStatsSetWrite \
ldr r1, SYM(cpu65_rw); \
ldrb r9, [r1]; \ ldrb r9, [r1]; \
orr r9, r9, #2; \ orr r9, r9, #2; \
strb r9, [r1]; \ strb r9, [r1]; \
ldr r1, SYM(cpu65_d); \ ldr r1, SYM(cpu65_d); \
strb r0, [r1]; strb r0, [r1];
#else
# define CPU_DEBUGGING_SET_READ
# define CPU_DEBUGGING_RESET
# define CPU_DEBUGGING_SET_WRITE
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// CPU (6502) helper macros // CPU (6502) helper macros
// Add 16bit x with <=16bit amt
#define AddUint16(x, amt) \ #define AddUint16(x, amt) \
add x, x, amt; \ add x, x, amt; \
bic x, #0x10000; bic x, #0x10000;
// Increment 16bit x
#define IncUint16(x) \ #define IncUint16(x) \
AddUint16(x, #1) AddUint16(x, #1)
#define SubUint16(x, amt) \ // Add 8bit x with <=8bit amt
sub x, x, amt; \ #define AddUint8(x, amt) \
mov x, x, LSL #16; \ add x, x, amt; \
mov x, x, LSR #16; bic SP_Reg, #0x0100;
#define DecUint16(x) \ // Increment 8bit x
SubUint16(x, #1) #define IncUint8(x) \
AddUint8(x, #1)
// Subtract 8bit x by <=8bit amt
#define SubUint8(x, amt) \
subs x, x, amt; \
movmi x, #0xFF;
// Decrement 8bit x
#define DecUint8(x) \
SubUint8(x, #1)
#define GetFromPC_B \ #define GetFromPC_B \
mov EffectiveAddr, PC_Reg; \ mov EffectiveAddr, PC_Reg; \
@ -150,13 +151,13 @@
#define JumpNextInstruction \ #define JumpNextInstruction \
TRACE_PROLOGUE \ TRACE_PROLOGUE \
GetFromPC_B \ GetFromPC_B \
CPU_DEBUGGING_RESET \ CPUStatsReset \
ldr r1, SYM(cpu65__opcodes); \ ldr r1, SYM(cpu65__opcodes); \
ldr r1, [r1, r0, LSL PTR_SHIFT]; \ ldr r1, [r1, r0, LSL PTR_SHIFT]; \
bx r1; bx r1;
#define GetFromEA_B \ #define GetFromEA_B \
CPU_DEBUGGING_SET_READ \ CPUStatsSetRead \
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \ ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
blx r1; blx r1;
@ -171,7 +172,7 @@
orr r0, hi_byte, lo_byte; orr r0, hi_byte, lo_byte;
#define PutToEA_B \ #define PutToEA_B \
CPU_DEBUGGING_SET_WRITE \ CPUStatsSetWrite \
ldr r1, SYM(cpu65_vmem_w); \ ldr r1, SYM(cpu65_vmem_w); \
ldr r1, [r1, EffectiveAddr, LSL PTR_SHIFT]; \ ldr r1, [r1, EffectiveAddr, LSL PTR_SHIFT]; \
blx r1; blx r1;
@ -200,15 +201,14 @@
#define pc_hi_next r0 #define pc_hi_next r0
#define BranchXCycles \ #define BranchXCycles \
ldr mem_cycle_count, SYM(cpu65_opcycles); \ ldr mem_cycle_count, SYM(cpu65_opcycles); \
eor scratch_count, scratch_count, scratch_count; /* HACK FIXME TODO VERIFY IN GDB : is this necessary? */ \
ldrb scratch_count, [mem_cycle_count]; \ ldrb scratch_count, [mem_cycle_count]; \
add scratch_count, scratch_count, #1; /* +1 branch taken */ \ add scratch_count, scratch_count, #1; /* +1 branch taken */ \
mov pc_hi_prev, PC_Reg; \ mov pc_hi_prev, PC_Reg; \
mov pc_hi_prev, pc_hi_prev, LSR #8; \ mov pc_hi_prev, pc_hi_prev, LSR #8; \
cbw; \ cbw; \
add PC_Reg, PC_Reg, r0; /* branch PC */ \ add PC_Reg, PC_Reg, r0; /* branch PC */ \
mov PC_Reg, PC_Reg, LSL #24; /* 16bit under/overflow protection */ \ mov PC_Reg, PC_Reg, LSL #16; /* 16bit under/overflow protection */ \
mov PC_Reg, PC_Reg, LSR #24; \ mov PC_Reg, PC_Reg, LSR #16; \
mov pc_hi_next, PC_Reg; \ mov pc_hi_next, PC_Reg; \
mov pc_hi_next, pc_hi_next, LSR #8; \ mov pc_hi_next, pc_hi_next, LSR #8; \
teq pc_hi_next, pc_hi_prev; \ teq pc_hi_next, pc_hi_prev; \
@ -266,6 +266,7 @@
#ifdef APPLE2_VM #ifdef APPLE2_VM
#define RestoreAltZP \ #define RestoreAltZP \
ldr stack_loc, SYM(base_stackzp); \ ldr stack_loc, SYM(base_stackzp); \
ldr stack_loc, [stack_loc]; \
add stack_loc, stack_loc, #0x100; \ add stack_loc, stack_loc, #0x100; \
add stack_loc, stack_loc, SP_Reg; add stack_loc, stack_loc, SP_Reg;
#else #else
@ -275,16 +276,14 @@
#define Push(x) \ #define Push(x) \
RestoreAltZP \ RestoreAltZP \
strb x, [stack_loc]; \ strb x, [stack_loc]; \
subs SP_Reg, SP_Reg, #1; \ DecUint8(SP_Reg)
movmi SP_Reg, #0xFF; #warning TODO FIXME ... need to write a 65c02 stack underflow vm test ... also how does AppleWin handle 65c02 underflow?
#warning TODO FIXME ... need to write a 65c02 stack_loc underflow vm test ... also how does AppleWin handle 65c02 underflow?
#define Pop(x) \ #define Pop(x) \
add SP_Reg, SP_Reg, #1; \ IncUint8(SP_Reg) \
bic SP_Reg, #0x0100; \
RestoreAltZP \ RestoreAltZP \
ldrb x, [stack_loc]; ldrb x, [stack_loc];
#warning TODO FIXME ... need to write a 65c02 stack overflow vm test ... also how does AppleWin handle 65c02 underflow? #warning TODO FIXME ... need to write a 65c02 stack overflow vm test ... also how does AppleWin handle 65c02 overflow?
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// addressing macros // addressing macros
@ -799,9 +798,6 @@ ENTRY(op_ADC_ind_zpage)
DoADC_b DoADC_b
Continue Continue
mask_FFFF: .hword 0xFFFF
interrupt_vector: .hword 0xFFFE
reset_vector: .hword 0xFFFC
.ltorg .ltorg
/* ---------------------------------- /* ----------------------------------
@ -1088,7 +1084,6 @@ ENTRY(op_BRA)
ENTRY(op_UNK) /* make undefined opcodes fault */ ENTRY(op_UNK) /* make undefined opcodes fault */
ENTRY(op_BRK) ENTRY(op_BRK)
#warning TODO FIXME ... write test for overflow in op_BRK
IncUint16(PC_Reg) IncUint16(PC_Reg)
mov r0, PC_Reg mov r0, PC_Reg
mov r0, r0, ROR #8 mov r0, r0, ROR #8
@ -1465,7 +1460,6 @@ ENTRY(op_JMP_abs_ind_x)
add EffectiveAddr, r0 add EffectiveAddr, r0
mov EffectiveAddr, EffectiveAddr, LSL #24 // 16bit under/overflow protection mov EffectiveAddr, EffectiveAddr, LSL #24 // 16bit under/overflow protection
mov EffectiveAddr, EffectiveAddr, LSR #24 mov EffectiveAddr, EffectiveAddr, LSR #24
#warning FIXME TODO write test for op_JMP_abs_ind_x under/overflow protection
GetFromMem_W(EffectiveAddr) GetFromMem_W(EffectiveAddr)
mov PC_Reg, r0 mov PC_Reg, r0
Continue Continue
@ -1475,11 +1469,10 @@ ENTRY(op_JMP_abs_ind_x)
---------------------------------- */ ---------------------------------- */
ENTRY(op_JSR) // 0x20 ENTRY(op_JSR) // 0x20
#warning TODO FIXME write test for op_JSR underflow ...
GetAbs GetAbs
mov r0, PC_Reg mov r0, PC_Reg
subs r0, r0, #1 sub r0, r0, #1
mov r0, r0, LSL #16 // handle underflow mov r0, r0, LSL #16 // handle underflow -- can this happen in second mem page?
mov r0, r0, ROR #24 mov r0, r0, ROR #24
Push(r0) // push hi_byte Push(r0) // push hi_byte
mov r0, r0, LSR #24 mov r0, r0, LSR #24
@ -1849,7 +1842,6 @@ ENTRY(op_RTI) // 0x40
---------------------------------- */ ---------------------------------- */
ENTRY(op_RTS) // 0x60 ENTRY(op_RTS) // 0x60
#warning TODO FIXME write test for this overflow ...
Pop(lo_byte) Pop(lo_byte)
Pop(hi_byte) Pop(hi_byte)
mov hi_byte, hi_byte, LSL #8 mov hi_byte, hi_byte, LSL #8
@ -2323,37 +2315,36 @@ continue:
ldrb r0, [r0] ldrb r0, [r0]
ldrb cycles_exe, [r1, r0] ldrb cycles_exe, [r1, r0]
ldr r1, SYM(cpu65_opcycles) ldr r1, SYM(cpu65_opcycles)
ldrb r2, [r1] ldrb r9, [r1]
add cycles_exe, cycles_exe, r2 add cycles_exe, cycles_exe, r9
strb cycles_exe, [r1] strb cycles_exe, [r1]
TRACE_EPILOGUE TRACE_EPILOGUE
ldr r1, SYM(gc_cycles_timer_0) ldr r1, SYM(gc_cycles_timer_0)
ldr r2, [r1] ldr r9, [r1]
sub r2, r2, cycles_exe sub r9, r9, cycles_exe
str r2, [r1] str r9, [r1]
ldr r1, SYM(gc_cycles_timer_1) ldr r1, SYM(gc_cycles_timer_1)
ldr r2, [r1] ldr r9, [r1]
sub r2, r2, cycles_exe sub r9, r9, cycles_exe
str r2, [r1] str r9, [r1]
ldr r1, SYM(cpu65_cycle_count) ldr r1, SYM(cpu65_cycle_count)
ldr r2, [r1] ldr r9, [r1]
add r2, r2, cycles_exe add r9, r9, cycles_exe
str r2, [r1] str r9, [r1]
ldr r1, SYM(cpu65_cycles_to_execute) ldr r1, SYM(cpu65_cycles_to_execute)
ldr r2, [r1] ldr r9, [r1]
subs r2, r2, cycles_exe subs r9, r9, cycles_exe
str r2, [r1] str r9, [r1]
bmi exit_cpu65_run bmi exit_cpu65_run
beq exit_cpu65_run beq exit_cpu65_run
continue1: eor r0, r0, r0 continue1: ldr r1, SYM(cpu65__signal)
ldr r1, SYM(cpu65__signal)
ldrb r0, [r1] ldrb r0, [r1]
orr r0, r0, r0 orrs r0, r0, r0
bne exception bne exception
JumpNextInstruction JumpNextInstruction
@ -2405,8 +2396,9 @@ ex_irq: tst F_Reg, #I_Flag // Already interrupt
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
ENTRY(cpu65_run) ENTRY(cpu65_run)
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
// Restore CPU state when being called from C. // Restore CPU state when being called from C.
#warning FIXME TODO ... do all the ldrb's zero-out the high-24bits of the destination reg? ldr reg_vmem_r, SYM(cpu65_vmem_r)
ldr r1, SYM(cpu65_ea) ldr r1, SYM(cpu65_ea)
ldrh EffectiveAddr, [r1] ldrh EffectiveAddr, [r1]
ldr r1, SYM(cpu65_pc) ldr r1, SYM(cpu65_pc)
@ -2439,7 +2431,7 @@ exit_cpu65_run:
ldr r1, SYM(cpu65_pc) ldr r1, SYM(cpu65_pc)
strh PC_Reg, [r1] strh PC_Reg, [r1]
CommonSaveCPUState CommonSaveCPUState
ret pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
exit_reinit: ldr r1, SYM(cpu65__signal) exit_reinit: ldr r1, SYM(cpu65__signal)
mov r0, #0 mov r0, #0
@ -2447,7 +2439,7 @@ exit_reinit: ldr r1, SYM(cpu65__signal)
ldr r1, SYM(emul_reinitialize) ldr r1, SYM(emul_reinitialize)
mov r0, #1 mov r0, #1
strb r0, [r1] strb r0, [r1]
ret pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Debugger hooks Debugger hooks
@ -2457,5 +2449,9 @@ ENTRY(cpu65_direct_write)
#warning FIXME TODO implement cpu65_direct_write ... #warning FIXME TODO implement cpu65_direct_write ...
mov r0, #42 mov r0, #42
ldr r0, [r0] // segfault ldr r0, [r0] // segfault
ret mov pc, lr
interrupt_vector: .hword 0xFFFE
reset_vector: .hword 0xFFFC
.ltorg

View File

@ -16,49 +16,49 @@
ENTRY(func) ldr r1, SYM(softswitches); \ ENTRY(func) ldr r1, SYM(softswitches); \
ldr r0, [r1]; \ ldr r0, [r1]; \
tst r0, $SS_CXROM; \ tst r0, $SS_CXROM; \
bne 1f; \ beq 1f; \
ldr r1, SYM(pointer); \ ldr r1, SYM(pointer); \
blx r1; \ ldr r1, [r1]; \
ret; \
1: ldr r1, SYM(pointer); \
ldrb r0, [r1, EffectiveAddr]; \ ldrb r0, [r1, EffectiveAddr]; \
ret; mov pc, lr; \
1: ldr r1, SYM(pointer); \
push {lr}; \
blx r1; \
pop {pc}; \
#define GLUE_BANK_READ(func,pointer) \ #define GLUE_BANK_READ(func,pointer) \
ENTRY(func) ldr r1, SYM(pointer); \ ENTRY(func) ldr r1, SYM(pointer); \
ldr r1, [r1]; \
ldrb r0, [r1, EffectiveAddr]; \ ldrb r0, [r1, EffectiveAddr]; \
ret; mov pc, lr;
#define GLUE_BANK_WRITE(func,pointer) \ #define GLUE_BANK_WRITE(func,pointer) \
ENTRY(func) ldr r1, SYM(pointer); \ ENTRY(func) ldr r1, SYM(pointer); \
ldr r1, [r1]; \
strb r0, [r1, EffectiveAddr]; \ strb r0, [r1, EffectiveAddr]; \
ret; mov pc, lr;
#define GLUE_BANK_MAYBEWRITE(func,pointer) \ #define GLUE_BANK_MAYBEWRITE(func,pointer) \
ENTRY(func) ldr r1, SYM(pointer); \ ENTRY(func) ldr r1, SYM(pointer); \
cmp r1, #0; \ ldr r1, [r1]; \
beq 1f; \ tst r1, #0; \
strb r0, [r1, EffectiveAddr]; \ strneb r0, [r1, EffectiveAddr]; \
1: ret; mov pc, lr;
#define GLUE_C_WRITE(func) \ #define GLUE_C_WRITE(func) \
ENTRY(func) push {r0, PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg}; \ ENTRY(func) push {r0, PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg, lr}; \
and r0, #0xff; \ and r0, #0xff; \
mov r1, r0; \ mov r1, r0; \
mov r0, EffectiveAddr; \ mov r0, EffectiveAddr; \
bl CALL(c_##func); \ bl CALL(c_##func); \
pop {r0, PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg}; \ pop {r0, PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg, pc};
ret;
#define _GLUE_C_READ(func, ...) \ #define GLUE_C_READ(func) \
ENTRY(func) push {PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg}; \ ENTRY(func) push {PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg, lr}; \
mov r0, EffectiveAddr; \ mov r0, EffectiveAddr; \
bl CALL(c_##func); \ bl CALL(c_##func); \
pop {PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg}; \ pop {PC_Reg, SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg, pc};
__VA_ARGS__ \
ret;
#define GLUE_C_READ(FUNC) _GLUE_C_READ(FUNC) #define GLUE_C_READ_ALTZP(FUNC) GLUE_C_READ(FUNC)
#define GLUE_C_READ_ALTZP(FUNC) _GLUE_C_READ(FUNC)