First cut at 65c02 implemented on aarch64

This commit is contained in:
Aaron Culliney 2019-10-06 16:32:06 -07:00
parent 4e27c1a322
commit 43d99ec9f4
9 changed files with 809 additions and 572 deletions

View File

@ -1,4 +1,4 @@
APP_ABI := armeabi-v7a x86 x86_64
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
# Do not change APP_PLATFORM if we care about Gingerbread (2.3.3) devices! We must compile against android-10,
# otherwise we may encounter runtime load-library errors from symbols that should have been inlined against older

View File

@ -148,7 +148,7 @@ if test "x$do_build" = "x1" -o "x$do_release" = "x1" ; then
# Symbolicate and move symbols file into location to be deployed on device
SYMFILE=libapple2ix.so.sym
ARCHES_TO_SYMBOLICATE='armeabi-v7a x86 x86_64'
ARCHES_TO_SYMBOLICATE='armeabi-v7a arm64-v8a x86 x86_64'
for arch in $ARCHES_TO_SYMBOLICATE ; do
SYMDIR=../assets/symbols/$arch/libapple2ix.so

View File

@ -63,7 +63,7 @@ APPLE2_MAIN_SRC = \
$(APPLE2_SRC_PATH)/zlib-helpers.c \
$(APPLE2_SRC_PATH)/../externals/jsmn/jsmn.c
APPLE2_OPTIM_CFLAGS := -Os
APPLE2_OPTIM_CFLAGS := -O2 # match the same optimization level as BUILD_MODE=release for ndk-build
APPLE2_BASE_CFLAGS := -DAPPLE2IX=1 -DINTERFACE_TOUCH=1 -DMOBILE_DEVICE=1 -DVIDEO_OPENGL=1 -std=gnu11 -fPIC $(APPLE2_OPTIM_CFLAGS) -I$(APPLE2_SRC_PATH)
APPLE2_BASE_LDLIBS := -Wl,-z,text -Wl,-z,noexecstack -llog -landroid -lGLESv2 -lz -lOpenSLES -latomic

View File

@ -15,45 +15,107 @@
#include "cpu.h"
#include "glue-offsets.h"
// ARM register mappings
// r0, r1 are scratch regs, with r0 generally as the "important byte"
#define EffectiveAddr r2 /* 16bit Effective address */
#define PC_Reg r3 /* 16bit 6502 Program Counter */
#define SP_Reg r4 /* 16bit 6502 Stack pointer */
#define F_Reg r5 /* 8bit 6502 flags */
#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 "ARM platform register" ... used as a scratch register
#define reg_args r10 /* cpu65_run() args register */
#define reg_vmem_r r11 /* cpu65_vmem_r table address */
// r12 is "ARM Intra-Procedure-call scratch register" ... used as a scratch register
// r13 ARM SP
// r14 ARM return addr
// r15 ARM PC
#ifdef __aarch64__
# error 20150205 ARM 64bit untested!!!
# define PTR_SHIFT #4 // 4<<1 = 8
# define ROR_BIT 0x8000000000000000
#else
# define PTR_SHIFT #2 // 2<<1 = 4
# define ROR_BIT 0x80000000
#endif
#if !defined(__APPLE__)
# define NO_UNDERSCORES 1
# define STRBNE strneb
#endif
// ARM register mappings
#define bz beq
#define bnz bne
#define ROR_BIT 0x80000000
#ifdef __aarch64__
# define DOT_ARM
# define ALIGN .align 2;
# define PTR_SHIFT #3 // 1<<3 = 8
# define BLX blr
# define BX br
// x: 64bit addressing mode
// w: 32bit addressing mode
# define xr0 x0 /* scratch/"important byte" */
# define wr0 w0 /* scratch/"important byte" */
# define xr1 x1 /* scratch */
# define wr1 w1 /* scratch */
# define wr9 w2
// NOTE: ARMv8 Procedure Call Standard indicates that x19-x28 are callee saved ... so we can call back into C without needing to
// first save these ...
# define xEffectiveAddr x19 /* 16bit Effective address */
# define EffectiveAddr w19 /* 16bit Effective address */
# define PC_Reg w20 /* 16bit 6502 Program Counter */
# define xSP_Reg x21 /* 16bit 6502 Stack pointer */
# define SP_Reg w21 /* 16bit 6502 Stack pointer */
# define xF_Reg x22 /* 8bit 6502 flags */
# define F_Reg w22 /* 8bit 6502 flags */
# define Y_Reg w23 /* 8bit 6502 Y register */
# define X_Reg w24 /* 8bit 6502 X register */
# define A_Reg w25 /* 8bit 6502 A register */
# define xA_Reg x25 /* 8bit 6502 A register */
# define reg_args x26 /* cpu65_run() args register */
# define reg_vmem_r x27 /* cpu65_vmem_r table address */
# define xr12 x28 /* scratch */
# define wr12 w28 /* scratch */
// x29 : frame pointer (callee-saved)
// x30 : return address
// xzr/wzr : zero register
// sp : stack pointer
// pc : instruction pointer
#else
# define STRBNE strbne
# define DOT_ARM .arm;
# define ALIGN .balign 4;
# define PTR_SHIFT #2 // 1<<2 = 4
# define BLX blx
# define BX bx
// r0, r1 are scratch regs, with r0 generally as the "important byte"
# define xr0 r0 /* scratch/"important byte" */
# define wr0 r0 /* scratch/"important byte" */
# define xr1 r1 /* scratch */
# define wr1 r1 /* scratch */
# define wr9 r9 /* scratch */
// r12 is "ARM Intra-Procedure-call scratch register" ... used as a scratch register
# define xr12 r12 /* scratch */
# define wr12 r12 /* scratch */
// NOTE: these need to be preserved in subroutine (C) invocations ... */
# define EffectiveAddr r2 /* 16bit Effective address */
# define xEffectiveAddr r2 /* 16bit Effective address */
# define PC_Reg r3 /* 16bit 6502 Program Counter */
// NOTE: ARMv7 PCS states : "A subroutine must preserve the contents of the registers r4-r8, r10, r11 and SP [...]"
# define xSP_Reg r4 /* 16bit 6502 Stack pointer */
# define SP_Reg r4 /* 16bit 6502 Stack pointer */
# define xF_Reg r5 /* 8bit 6502 flags */
# define F_Reg r5 /* 8bit 6502 flags */
# define Y_Reg r6 /* 8bit 6502 Y register */
# define X_Reg r7 /* 8bit 6502 X register */
# define A_Reg r8 /* 8bit 6502 A register */
# define xA_Reg r8 /* 8bit 6502 A register */
// r9 is "ARM platform register" ... used as a scratch register
# define reg_args r10 /* cpu65_run() args register */
# define reg_vmem_r r11 /* cpu65_vmem_r table address */
// r13 ARM SP
// r14 ARM LR (return addr)
// r15 ARM PC
#endif
#if NO_UNDERSCORES
# define ENTRY(x) .globl x; .arm; .balign 4; x##:
# define ENTRY(x) .global x; DOT_ARM ALIGN x##:
# define CALL(x) x
#else
# define ENTRY(x) .globl _##x; .arm; .balign 4; _##x##:
# define ENTRY(x) .global _##x; DOT_ARM ALIGN _##x##:
# define CALL(x) _##x
#endif

File diff suppressed because it is too large Load Diff

53
src/arm/glue-offsets64.h Normal file
View File

@ -0,0 +1,53 @@
/* This file is auto-generated for a specific architecture ABI */
#define UNUSED0 0
#define CPU65_TRACE_PROLOGUE 8
#define CPU65_TRACE_ARG 16
#define UNUSED1 24
#define UNUSED2 32
#define CPU65_TRACE_EPILOGUE 40
#define CPU65_TRACE_IRQ 48
#define DEBUG_ILLEGAL_BCD 56
#define CPU65_VMEM_R 64
#define CPU65_VMEM_W 72
#define CPU65_FLAGS_ENCODE 80
#define CPU65_FLAGS_DECODE 88
#define CPU65__OPCODES 96
#define CPU65__OPCYCLES 104
#define BASE_RAMRD 112
#define BASE_RAMWRT 120
#define BASE_TEXTRD 128
#define BASE_TEXTWRT 136
#define BASE_HGRRD 144
#define BASE_HGRWRT 152
#define BASE_STACKZP 160
#define BASE_D000_RD 168
#define BASE_E000_RD 176
#define BASE_D000_WRT 184
#define BASE_E000_WRT 192
#define BASE_C3ROM 200
#define BASE_C4ROM 208
#define BASE_C5ROM 216
#define BASE_CXROM 224
#define SOFTSWITCHES 232
#define GC_CYCLES_TIMER_0 236
#define GC_CYCLES_TIMER_1 240
#define CPU65_CYCLES_TO_EXECUTE 244
#define CPU65_CYCLE_COUNT 248
#define UNUSED3 252
#define INTERRUPT_VECTOR 256
#define RESET_VECTOR 258
#define CPU65_PC 260
#define CPU65_EA 262
#define CPU65_A 264
#define CPU65_F 265
#define CPU65_X 266
#define CPU65_Y 267
#define CPU65_SP 268
#define CPU65_D 269
#define CPU65_RW 270
#define CPU65_OPCODE 271
#define CPU65_OPCYCLES 272
#define CPU65__SIGNAL 273
#define JOY_BUTTON0 274
#define JOY_BUTTON1 275
#define EMUL_REINITIALIZE 276

View File

@ -12,79 +12,120 @@
#include "vm.h"
#include "cpu-regs.h"
#if __aarch64__
# define _GLUE_REG_SAVE \
stp x29, x30, [sp, -16]!;
# define _GLUE_REG_RESTORE \
ldp x29, x30, [sp], 16; \
ret
# define _GLUE_REG_SAVE0 \
stp x0, x30, [sp, -16]!;
# define _GLUE_REG_RESTORE0 \
ldp x0, x30, [sp], 16; \
ret
# define _GLUE_RET \
ret
#else
# define _GLUE_REG_SAVE \
push {EffectiveAddr, PC_Reg, lr};
# define _GLUE_REG_RESTORE \
pop {EffectiveAddr, PC_Reg, pc};
# define _GLUE_REG_SAVE0 \
push {r0, EffectiveAddr, PC_Reg, lr};
# define _GLUE_REG_RESTORE0 \
pop {r0, EffectiveAddr, PC_Reg, pc};
# define _GLUE_RET \
mov pc, lr;
#endif
#define GLUE_EXTERN_C_READ(func)
#define _GLUE_BANK_MAYBE_READ_CX(func,x,pointer) \
ENTRY(func) ldr r0, [reg_args, #SOFTSWITCHES]; \
ldr r1, [reg_args, x ## pointer]; \
tst r0, $SS_CXROM; \
bne 1f; \
push {EffectiveAddr, PC_Reg, lr}; \
blx r1; \
pop {EffectiveAddr, PC_Reg, pc}; \
1: ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr;
ENTRY(func) ldr wr0, [reg_args, #SOFTSWITCHES]; \
ldr xr1, [reg_args, x ## pointer]; \
tst wr0, #SS_CXROM; \
bnz 1f; \
_GLUE_REG_SAVE; \
BLX xr1; \
_GLUE_REG_RESTORE; \
1: ldrb wr0, [xr1, xEffectiveAddr]; \
_GLUE_RET
#define GLUE_BANK_MAYBE_READ_CX(func,pointer) _GLUE_BANK_MAYBE_READ_CX(func,#,pointer)
#define _GLUE_BANK_MAYBE_READ_C3(func,x,pointer) \
ENTRY(func) ldr r0, [reg_args, #SOFTSWITCHES]; \
ldr r1, [reg_args, x ## pointer]; \
tst r0, $SS_CXROM; \
bne 1f; \
tst r0, $SS_C3ROM; \
bne 1f; \
push {EffectiveAddr, PC_Reg, lr}; \
blx r1; \
pop {EffectiveAddr, PC_Reg, pc}; \
1: ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr;
ENTRY(func) ldr wr0, [reg_args, #SOFTSWITCHES]; \
ldr xr1, [reg_args, x ## pointer]; \
tst wr0, #SS_CXROM; \
bnz 1f; \
tst wr0, #SS_C3ROM; \
bnz 1f; \
_GLUE_REG_SAVE; \
BLX xr1; \
_GLUE_REG_RESTORE; \
1: ldrb wr0, [xr1, xEffectiveAddr]; \
_GLUE_RET
#define GLUE_BANK_MAYBE_READ_C3(func,pointer) _GLUE_BANK_MAYBE_READ_C3(func,#,pointer)
#define _GLUE_BANK_READ(func,x,pointer) \
ENTRY(func) ldr r1, [reg_args, x ## pointer]; \
ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr;
ENTRY(func) ldr xr1, [reg_args, x ## pointer]; \
ldrb wr0, [xr1, xEffectiveAddr]; \
_GLUE_RET
#define GLUE_BANK_READ(func,pointer) _GLUE_BANK_READ(func,#,pointer)
#define _GLUE_BANK_WRITE(func,x,pointer) \
ENTRY(func) ldr r1, [reg_args, x ## pointer]; \
strb r0, [r1, EffectiveAddr]; \
mov pc, lr;
ENTRY(func) ldr xr1, [reg_args, x ## pointer]; \
strb wr0, [xr1, xEffectiveAddr]; \
_GLUE_RET
#define GLUE_BANK_WRITE(func,pointer) _GLUE_BANK_WRITE(func,#,pointer)
#define _GLUE_BANK_MAYBEWRITE(func,x,pointer) \
ENTRY(func) ldr r1, [reg_args, x ## pointer]; \
teq r1, #0; \
STRBNE r0, [r1, EffectiveAddr]; \
mov pc, lr;
ENTRY(func) ldr xr1, [reg_args, x ## pointer]; \
eor xr12, xr12, xr12; \
eor xr1, xr1, xr12; \
cmp xr1, #0; \
bz 1f; \
strb wr0, [xr1, xEffectiveAddr]; \
1: _GLUE_RET
#define GLUE_BANK_MAYBEWRITE(func,pointer) _GLUE_BANK_MAYBEWRITE(func,#,pointer)
#define _GLUE_INLINE_READ(func,x,off) \
ENTRY(func) ldrb r0, [reg_args, x ## off]; \
mov pc, lr;
ENTRY(func) ldrb wr0, [reg_args, x ## off]; \
_GLUE_RET
#define GLUE_INLINE_READ(func,off) _GLUE_INLINE_READ(func,#,off)
#define GLUE_C_WRITE(func) \
ENTRY(func) push {r0, EffectiveAddr, PC_Reg, lr}; \
and r0, r0, #0xff; \
mov r1, r0; \
mov r0, EffectiveAddr; \
ENTRY(func) _GLUE_REG_SAVE0; \
and wr0, wr0, #0xff; \
mov wr1, wr0; \
mov wr0, EffectiveAddr; \
bl CALL(c_##func); \
pop {r0, EffectiveAddr, PC_Reg, pc};
_GLUE_REG_RESTORE0;
#define GLUE_C_READ(func) \
ENTRY(func) push {EffectiveAddr, PC_Reg, lr}; \
mov r0, EffectiveAddr; \
ENTRY(func) _GLUE_REG_SAVE; \
mov wr0, EffectiveAddr; \
bl CALL(c_##func); \
pop {EffectiveAddr, PC_Reg, pc};
_GLUE_REG_RESTORE;
#define GLUE_C_READ_ALTZP(FUNC) GLUE_C_READ(FUNC)

View File

@ -87,7 +87,7 @@ void cpu65_trace_checkpoint(void);
# define D_Flag 0x20 /* 6502 Decimal mode */
# define Z_Flag 0x40 /* 6502 Zero */
# define N_Flag 0x80 /* 6502 Negative */
#elif defined(__arm__)
#elif defined(__arm__) || defined(__aarch64__)
// VCZN positions match positions of shifted status register
# define V_Flag 0x1
# define C_Flag 0x2
@ -101,10 +101,7 @@ void cpu65_trace_checkpoint(void);
# define I_Flag 0x20
# define B_Flag 0x40
# define D_Flag 0x80
# define BX_Flags 0x50
# define BI_Flags 0x60
#elif defined(__aarch64__)
# error soon ...
#else
# error unknown machine architecture
#endif

View File

@ -186,7 +186,7 @@ typedef struct cpu65_run_args_s {
#define OUTPUT_CPU65_RW() printf("#define CPU65_RW %ld\n", offsetof(cpu65_run_args_s, cpu65_rw))
uint8_t cpu65_opcode; // Last opcode
#define OUTPUT_CPU65_OPCODE() printf("#define CPU65_OPCODE %ld\n", offsetof(cpu65_run_args_s, cpu65_opcode))
uint8_t cpu65_opcycles; // Last opcode extra cycles
uint8_t cpu65_opcycles; // Last opcode cycles
#define OUTPUT_CPU65_OPCYCLES() printf("#define CPU65_OPCYCLES %ld\n", offsetof(cpu65_run_args_s, cpu65_opcycles))
uint8_t cpu65__signal;