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 X_Reg r7 /* 8bit 6502 X register */
#define A_Reg r8 /* 8bit 6502 A register */
// r9 is another scratch variable
#define reg_64k r10 /* apple_ii_64k table address */
// r9 is "ARM platform register" ... used as a scratch register
// r10 is another scratch variable
#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
// r14 ARM return addr
// r15 ARM PC
@ -36,10 +36,6 @@
#define ARM_AF_Bit ...
// x86-ish instruction macros for legibility =P
#define ret mov pc, r14
#ifdef __aarch64__
# error 20150205 ARM 64bit untested!!!
# define PTR_SHIFT #4 // 4<<1 = 8

View File

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