Refactor CPU assembly for simplicity and efficiency

- Variables needed in assembly now accessible in a struct pointer that  avoids __PIC__ nastiness
    - Reduces code size and execution time for CPU thread
This commit is contained in:
Aaron Culliney 2018-01-15 13:03:31 -08:00
parent 6e7af373d7
commit e4e0c941d3
39 changed files with 4981 additions and 4896 deletions

View File

@ -125,7 +125,7 @@ if test "x$do_build" = "x1" -o "x$do_release" = "x1" ; then
$CC $CFLAGS -o $apple2_src_path/genfont $apple2_src_path/genfont.c && \ $CC $CFLAGS -o $apple2_src_path/genfont $apple2_src_path/genfont.c && \
$apple2_src_path/genfont < $apple2_src_path/font.txt > $apple2_src_path/font.c $apple2_src_path/genfont < $apple2_src_path/font.txt > $apple2_src_path/font.c
# trampoline generation # bridge trampoline generation
TARGET_ARCH=x86 $apple2_src_path/genglue.sh $glue_srcs > $apple2_src_path/x86/glue.S TARGET_ARCH=x86 $apple2_src_path/genglue.sh $glue_srcs > $apple2_src_path/x86/glue.S
TARGET_ARCH=arm $apple2_src_path/genglue.sh $glue_srcs > $apple2_src_path/arm/glue.S TARGET_ARCH=arm $apple2_src_path/genglue.sh $glue_srcs > $apple2_src_path/arm/glue.S

View File

@ -294,11 +294,11 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeReboot(JNIEnv *env, jclass
if (resetState) { if (resetState) {
// joystick button settings should be balanced by c_joystick_reset() triggered on CPU thread // joystick button settings should be balanced by c_joystick_reset() triggered on CPU thread
if (resetState == 1) { if (resetState == 1) {
joy_button0 = 0xff; run_args.joy_button0 = 0xff;
joy_button1 = 0x0; run_args.joy_button1 = 0x0;
} else { } else {
joy_button0 = 0x0; run_args.joy_button0 = 0x0;
joy_button1 = 0xff; run_args.joy_button1 = 0xff;
} }
} }
cpu65_interrupt(ResetSig); cpu65_interrupt(ResetSig);

View File

@ -14,13 +14,14 @@ noinst_HEADERS = src/common.h src/cpu.h src/disk.h src/glue.h src/vm.h \
src/timing.h src/uthash.h src/video/video.h src/zlib-helpers.h \ src/timing.h src/uthash.h src/video/video.h src/zlib-helpers.h \
\ \
src/x86/glue-prologue.h \ src/x86/glue-prologue.h \
src/x86/glue-offsets.h src/x86/glue-offsets32.h src/x86/glue-offsets64.h \
src/meta/debug.h src/meta/log.h src/meta/trace.h \ src/meta/debug.h src/meta/log.h src/meta/trace.h \
\ \
src/audio/alhelpers.h src/audio/AY8910.h src/audio/mockingboard.h \ src/audio/alhelpers.h src/audio/AY8910.h src/audio/mockingboard.h \
src/audio/peripherals.h src/audio/soundcore.h src/audio/speaker.h \ src/audio/peripherals.h src/audio/soundcore.h src/audio/speaker.h \
src/audio/SSI263Phonemes.h src/audio/SSI263Phonemes.h
noinst_PROGRAMS = genfont genrom noinst_PROGRAMS = genfont genrom glue_offsets
############################################################################### ###############################################################################
# Apple //ix and supporting sources # Apple //ix and supporting sources
@ -87,6 +88,8 @@ genfont_SOURCES = src/genfont.c
genrom_SOURCES = src/genrom.c genrom_SOURCES = src/genrom.c
glue_offsets_SOURCES = src/glue-offsets.c
src/font.c: src/font.txt genfont src/font.c: src/font.txt genfont
./genfont < $< > $@ ./genfont < $< > $@

View File

@ -13,6 +13,7 @@
#define _CPU_REGS_H_ #define _CPU_REGS_H_
#include "cpu.h" #include "cpu.h"
#include "glue-offsets.h"
// ARM register mappings // ARM register mappings
@ -25,7 +26,7 @@
#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 "ARM platform register" ... used as a scratch register // r9 is "ARM platform register" ... used as a scratch register
// r10 is another scratch variable #define reg_args r10 /* cpu65_run() args register */
#define reg_vmem_r r11 /* cpu65_vmem_r table address */ #define reg_vmem_r r11 /* cpu65_vmem_r table address */
// r12 is "ARM Intra-Procedure-call scratch register" ... used as a scratch register // r12 is "ARM Intra-Procedure-call scratch register" ... used as a scratch register
// r13 ARM SP // r13 ARM SP
@ -41,7 +42,6 @@
# define ROR_BIT 0x80000000 # define ROR_BIT 0x80000000
#endif #endif
#if !defined(__APPLE__) #if !defined(__APPLE__)
# define NO_UNDERSCORES 1 # define NO_UNDERSCORES 1
# define STRBNE strneb # define STRBNE strneb
@ -57,48 +57,5 @@
# define CALL(x) _##x # define CALL(x) _##x
#endif #endif
// 2015/11/08 NOTE : Android requires all apps targeting API 23 (AKA Marshmallow) to use Position Independent Code (PIC)
// that does not have TEXT segment relocations
#if !defined(__COUNTER__)
#error __COUNTER__ macro should be available in modern compilers
#endif
#if __PIC__ && !__APPLE__
// 2016/07/15 : TODO FIXME : this PIC code does not work on ARM-Darwin
# define _SYM_ADDR_PRE(reg) \
ldr reg, 5f;
# define _SYM_ADDR_OFF_THUMB(reg,ct) \
4: add reg, pc; \
ldr reg, [reg];
# define _SYM_ADDR_OFF_ARM(reg,ct) \
4: ldr reg, [pc, reg];
# define _SYM_ADDR_POST(var,poff) \
b 6f; \
.align 2; \
5: .word var(GOT_PREL)+(. - (4b + poff)); \
6:
# if defined(THUMB)
# define SYM(reg,var) \
_SYM_ADDR_PRE(reg) \
_SYM_ADDR_OFF_THUMB(reg, __COUNTER__); \
_SYM_ADDR_POST(var,4)
# else
# define SYM(reg,var) \
_SYM_ADDR_PRE(reg) \
_SYM_ADDR_OFF_ARM(reg, __COUNTER__); \
_SYM_ADDR_POST(var,8)
# endif
#else
# if NO_UNDERSCORES
# define SYM(reg,var) \
ldr reg, =var
# else
# define SYM(reg,var) \
ldr reg, =_##var
# endif
#endif
#endif // whole file #endif // whole file

View File

@ -18,39 +18,32 @@
#define DecodeFlags \ #define DecodeFlags \
SYM(r1, cpu65_flags_decode); \ ldr r1, [reg_args, #CPU65_FLAGS_DECODE]; \
ldrb F_Reg, [r1, r0]; ldrb F_Reg, [r1, r0];
#define EncodeFlags \ #define EncodeFlags \
SYM(r1, cpu65_flags_encode); \ ldr r1, [reg_args, #CPU65_FLAGS_ENCODE]; \
ldrb r0, [r1, F_Reg]; ldrb r0, [r1, F_Reg];
#define CommonSaveCPUState \ #define CommonSaveCPUState \
/* save EA */ \ /* save EA */ \
SYM(r0, cpu65_ea); \ strh EffectiveAddr, [reg_args, #CPU65_EA]; \
strh EffectiveAddr, [r0]; \
/* save stack pointer */ \ /* save stack pointer */ \
SYM(r0, cpu65_sp); \ strb SP_Reg, [reg_args, #CPU65_SP]; \
strb SP_Reg, [r0]; \
/* save X */ \ /* save X */ \
SYM(r0, cpu65_x); \ strb X_Reg, [reg_args, #CPU65_X]; \
strb X_Reg, [r0]; \
/* save Y */ \ /* save Y */ \
SYM(r0, cpu65_y); \ strb Y_Reg, [reg_args, #CPU65_Y]; \
strb Y_Reg, [r0]; \
/* save A */ \ /* save A */ \
SYM(r0, cpu65_a); \ strb A_Reg, [reg_args, #CPU65_A]; \
strb A_Reg, [r0]; \
/* save flags */ \ /* save flags */ \
EncodeFlags \ EncodeFlags \
SYM(r1, cpu65_f); \ strb r0, [reg_args, #CPU65_F]
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 \
SYM(r1, cpu65_pc); \ strh PC_Reg, [reg_args, #CPU65_PC]; \
strh PC_Reg, [r1]; \
bl CALL(cpu65_trace_prologue); bl CALL(cpu65_trace_prologue);
# define TRACE_ARG \ # define TRACE_ARG \
bl CALL(cpu65_trace_arg); bl CALL(cpu65_trace_arg);
@ -74,25 +67,20 @@
#define CPUStatsReset \ #define CPUStatsReset \
eor r9, r9, r9; \ eor r1, r1, r1; \
SYM(r1, cpu65_opcycles); \ strb r1, [reg_args, #CPU65_OPCYCLES]; \
strb r9, [r1]; \ strb r1, [reg_args, #CPU65_RW];
SYM(r1, cpu65_rw); \
strb r9, [r1];
#define CPUStatsSetRead \ #define CPUStatsSetRead \
SYM(r1, cpu65_rw); \ ldrb r1, [reg_args, #CPU65_RW]; \
ldrb r9, [r1]; \ orr r1, r1, #1; \
orr r9, r9, #1; \ strb r1, [reg_args, #CPU65_RW];
strb r9, [r1];
#define CPUStatsSetWrite \ #define CPUStatsSetWrite \
SYM(r1, cpu65_rw); \ strb r0, [reg_args, #CPU65_D]; \
ldrb r9, [r1]; \ ldrb r1, [reg_args, #CPU65_RW]; \
orr r9, r9, #2; \ orr r1, r1, #2; \
strb r9, [r1]; \ strb r1, [reg_args, #CPU65_RW];
SYM(r1, cpu65_d); \
strb r0, [r1];
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// CPU (6502) helper macros // CPU (6502) helper macros
@ -152,9 +140,8 @@
#define JumpNextInstruction \ #define JumpNextInstruction \
TRACE_PROLOGUE \ TRACE_PROLOGUE \
GetFromPC_B \ GetFromPC_B \
SYM(r1, cpu65_opcode); \ strb r0, [reg_args, #CPU65_OPCODE]; /* r0 should be next opcode */ \
strb r0, [r1]; /* r0 should be next opcode */ \ ldr r1, [reg_args, #CPU65__OPCODES]; \
SYM(r1, cpu65__opcodes); \
ldr r1, [r1, r0, LSL PTR_SHIFT]; \ ldr r1, [r1, r0, LSL PTR_SHIFT]; \
bx r1; bx r1;
@ -175,7 +162,7 @@
#define PutToEA_B \ #define PutToEA_B \
CPUStatsSetWrite \ CPUStatsSetWrite \
SYM(r1, cpu65_vmem_w); \ ldr r1, [reg_args, #CPU65_VMEM_W]; \
ldr r1, [r1, EffectiveAddr, LSL PTR_SHIFT]; \ ldr r1, [r1, EffectiveAddr, LSL PTR_SHIFT]; \
blx r1; blx r1;
@ -197,17 +184,14 @@
mov r0, r0, ASR #24; mov r0, r0, ASR #24;
#define _IncOpCycles \ #define _IncOpCycles \
SYM(mem_cycle_count, cpu65_opcycles); \ ldrb scratch_count, [reg_args, #CPU65_OPCYCLES]; \
ldrb scratch_count, [mem_cycle_count]; \
add scratch_count, scratch_count, #1; add scratch_count, scratch_count, #1;
#define IncOpCycles \ #define IncOpCycles \
_IncOpCycles \ _IncOpCycles \
strb scratch_count, [mem_cycle_count]; strb scratch_count, [reg_args, #CPU65_OPCYCLES];
#define pc_hi_byte r9 #define scratch_count r1
#define mem_cycle_count r1
#define scratch_count r12
#define pc_hi_prev r9 #define pc_hi_prev r9
#define pc_hi_next r0 #define pc_hi_next r0
#define BranchXCycles \ #define BranchXCycles \
@ -220,7 +204,7 @@
mov pc_hi_next, PC_Reg, LSR #8; \ mov pc_hi_next, PC_Reg, LSR #8; \
teq pc_hi_next, pc_hi_prev; \ teq pc_hi_next, pc_hi_prev; \
addne scratch_count, scratch_count, #1; /* +1 branch taken */ \ addne scratch_count, scratch_count, #1; /* +1 branch taken */ \
strb scratch_count, [mem_cycle_count]; strb scratch_count, [reg_args, #CPU65_OPCYCLES];
#define arm_flags r12 #define arm_flags r12
#define lahf \ #define lahf \
@ -287,13 +271,12 @@
#define stack_loc r1 #define stack_loc r1
#ifdef APPLE2_VM #ifdef APPLE2_VM
#define RestoreAltZP \ # define RestoreAltZP \
SYM(stack_loc, base_stackzp); \ ldr stack_loc, [reg_args, #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
#define RestoreAltZP # error FIXME TODO ...
#endif #endif
#define Push(x) \ #define Push(x) \
@ -1189,8 +1172,7 @@ ENTRY(op_BRK)
EncodeFlags EncodeFlags
Push(r0) Push(r0)
orr F_Reg, F_Reg, #I_Flag orr F_Reg, F_Reg, #I_Flag
SYM(EffectiveAddr, interrupt_vector) ldrh EffectiveAddr, [reg_args, #INTERRUPT_VECTOR]
ldrh EffectiveAddr, [EffectiveAddr]
GetFromEA_W GetFromEA_W
mov PC_Reg, r0 mov PC_Reg, r0
Continue Continue
@ -2406,59 +2388,53 @@ ENTRY(op_WAI_65c02)
#define cycles_exe r0 #define cycles_exe r0
continue: continue:
SYM(r1, cpu65__opcycles) ldr r1, [reg_args, #CPU65__OPCYCLES]
SYM(r0, cpu65_opcode) ldrb r0, [reg_args, #CPU65_OPCODE]
ldrb r0, [r0]
ldrb cycles_exe, [r1, r0] ldrb cycles_exe, [r1, r0]
SYM(r1, cpu65_opcycles) ldrb r1, [reg_args, #CPU65_OPCYCLES]
ldrb r9, [r1] add cycles_exe, cycles_exe, r1
add cycles_exe, cycles_exe, r9 strb cycles_exe, [reg_args, #CPU65_OPCYCLES]
strb cycles_exe, [r1]
TRACE_EPILOGUE TRACE_EPILOGUE
SYM(r1, gc_cycles_timer_0) ldr r1, [reg_args, #GC_CYCLES_TIMER_0]
ldr r9, [r1] sub r1, r1, cycles_exe
sub r9, r9, cycles_exe str r1, [reg_args, #GC_CYCLES_TIMER_0]
str r9, [r1]
SYM(r1, gc_cycles_timer_1) ldr r1, [reg_args, #GC_CYCLES_TIMER_1]
ldr r9, [r1] sub r1, r1, cycles_exe
sub r9, r9, cycles_exe str r1, [reg_args, #GC_CYCLES_TIMER_1]
str r9, [r1]
SYM(r1, cpu65_cycle_count) ldr r1, [reg_args, #CPU65_CYCLE_COUNT]
ldr r9, [r1] add r1, r1, cycles_exe
add r9, r9, cycles_exe str r1, [reg_args, #CPU65_CYCLE_COUNT]
str r9, [r1]
#if CONFORMANT_IRQ_CHECKPOINT #if CONFORMANT_IRQ_CHECKPOINT
SYM(r1, irqCheckTimeout) // AppleWin : CheckInterruptSources() # error 2018/01/15 untested ...
ldr r9, [r1] ldr r1, [reg_args, #CPU_IRQCHECK] // AppleWin : CheckInterruptSources()
subs r9, r9, cycles_exe subs r1, r1, cycles_exe
str r9, [r1] str r1, [reg_args, #CPU_IRQCHECK]
bmi irq_checkpoint bmi irq_checkpoint
#endif #endif
continue1: SYM(r1, cpu65_cycles_to_execute) continue1: ldr r1, [reg_args, #CPU65_CYCLES_TO_EXECUTE]
ldr r9, [r1] subs r1, r1, cycles_exe
subs r9, r9, cycles_exe str r1, [reg_args, #CPU65_CYCLES_TO_EXECUTE]
str r9, [r1]
bmi exit_cpu65_run bmi exit_cpu65_run
beq exit_cpu65_run beq exit_cpu65_run
continue2: SYM(r1, cpu65__signal) continue2: ldrb r0, [reg_args, #CPU65__SIGNAL]
ldrb r0, [r1]
orrs r0, r0, r0 orrs r0, r0, r0
bne exception bne exception
CPUStatsReset CPUStatsReset
JumpNextInstruction JumpNextInstruction
#if CONFORMANT_IRQ_CHECKPOINT #if CONFORMANT_IRQ_CHECKPOINT
# error 2018/01/15 untested ...
irq_checkpoint: irq_checkpoint:
bl CALL(cpu_irqCheck); bl CALL(cpu_irqCheck);
SYM(r1, irqCheckTimeout) //eor r1, r1, r1
eor r9, r9, r9 mov r1, #IRQ_CHECK_CYCLES
str r9, [r1] str r1, [reg_args, #CPU_IRQCHECK]
b continue1 b continue1
#endif #endif
@ -2468,20 +2444,16 @@ irq_checkpoint:
exception: tst r0, #ResetSig exception: tst r0, #ResetSig
beq ex_irq beq ex_irq
SYM(r1, joy_button0) // OpenApple ldrb r0, [reg_args, #JOY_BUTTON0] // OpenApple
ldrb r0, [r1]
tst r0, #0xFF tst r0, #0xFF
bne exit_reinit bne exit_reinit
SYM(r1, joy_button1) // ClosedApple ldr r0, [reg_args, #JOY_BUTTON1] // ClosedApple
ldrb r0, [r1]
tst r0, #0xFF tst r0, #0xFF
bne exit_reinit bne exit_reinit
ex_reset: eor r0, r0, r0 ex_reset: eor r0, r0, r0
SYM(r1, cpu65__signal) strb r0, [reg_args, #CPU65__SIGNAL]
strb r0, [r1] ldrh EffectiveAddr, [reg_args, #RESET_VECTOR]
SYM(EffectiveAddr, reset_vector)
ldrh EffectiveAddr, [EffectiveAddr]
GetFromEA_W GetFromEA_W
mov PC_Reg, r0 mov PC_Reg, r0
CPUStatsReset CPUStatsReset
@ -2502,15 +2474,13 @@ ex_irq: tst F_Reg, #I_Flag // Already interrupt
Push(r0) Push(r0)
orr F_Reg, F_Reg, #BI_Flags orr F_Reg, F_Reg, #BI_Flags
//bic F_Reg, F_Reg, #D_Flag // AppleWin clears Decimal bit? //bic F_Reg, F_Reg, #D_Flag // AppleWin clears Decimal bit?
SYM(EffectiveAddr, interrupt_vector) ldrh EffectiveAddr, [reg_args, #INTERRUPT_VECTOR]
ldrh EffectiveAddr, [EffectiveAddr]
GetFromEA_W GetFromEA_W
mov PC_Reg, r0 mov PC_Reg, r0
CPUStatsReset CPUStatsReset
SYM(r1, cpu65_opcycles) ldrb r0, [reg_args, #CPU65_OPCYCLES]
ldrb r0, [r1]
add r0, r0, #7 // IRQ handling will take additional 7 cycles add r0, r0, #7 // IRQ handling will take additional 7 cycles
strb r0, [r1] strb r0, [reg_args, #CPU65_OPCYCLES]
JumpNextInstruction JumpNextInstruction
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
@ -2520,27 +2490,20 @@ 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} 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.
SYM(reg_vmem_r, cpu65_vmem_r) mov reg_args, r0
SYM(r1, cpu65_ea) ldr reg_vmem_r, [reg_args, #CPU65_VMEM_R]
ldrh EffectiveAddr, [r1] ldrh EffectiveAddr, [reg_args, #CPU65_EA]
SYM(r1, cpu65_pc) ldrh PC_Reg, [reg_args, #CPU65_PC]
ldrh PC_Reg, [r1] ldrb A_Reg, [reg_args, #CPU65_A]
SYM(r1, cpu65_a) ldrb r0, [reg_args, #CPU65_F]
ldrb A_Reg, [r1]
SYM(r1, cpu65_f)
ldrb r0, [r1]
DecodeFlags DecodeFlags
SYM(r1, cpu65_x) ldrb X_Reg, [reg_args, #CPU65_X]
ldrb X_Reg, [r1] ldrb Y_Reg, [reg_args, #CPU65_Y]
SYM(r1, cpu65_y) ldrb SP_Reg, [reg_args, #CPU65_SP]
ldrb Y_Reg, [r1] ldrb r0, [reg_args, #EMUL_REINITIALIZE]
SYM(r1, cpu65_sp)
ldrb SP_Reg, [r1]
SYM(r1, emul_reinitialize)
ldrb r0, [r1]
teq r0, #0 teq r0, #0
eorne r0, r0, r0 eorne r0, r0, r0
STRBNE r0, [r1] STRBNE r0, [reg_args, #EMUL_REINITIALIZE]
bne ex_reset bne ex_reset
b continue2 b continue2
@ -2550,17 +2513,14 @@ ENTRY(cpu65_run)
exit_cpu65_run: exit_cpu65_run:
// Save CPU state when returning from being called from C // Save CPU state when returning from being called from C
SYM(r1, cpu65_pc) strh PC_Reg, [reg_args, #CPU65_PC]
strh PC_Reg, [r1]
CommonSaveCPUState CommonSaveCPUState
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
exit_reinit: SYM(r1, cpu65__signal) exit_reinit: mov r0, #0
mov r0, #0 strb r0, [reg_args, #CPU65__SIGNAL]
strb r0, [r1]
SYM(r1, emul_reinitialize)
mov r0, #1 mov r0, #1
strb r0, [r1] strb r0, [reg_args, #EMUL_REINITIALIZE]
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
@ -2573,16 +2533,5 @@ ENTRY(cpu65_direct_write)
ldr r0, [r0] // segfault ldr r0, [r0] // segfault
mov pc, lr mov pc, lr
# local data ...
.global interrupt_vector
.global reset_vector
#if NO_UNDERSCORES
interrupt_vector: .hword 0xFFFE
reset_vector: .hword 0xFFFC
#else
_interrupt_vector: .hword 0xFFFE
_reset_vector: .hword 0xFFFC
#endif
.ltorg .ltorg

5
src/arm/glue-offsets.h Normal file
View File

@ -0,0 +1,5 @@
#if __aarch64__
# include "glue-offsets64.h"
#else
# include "glue-offsets32.h"
#endif

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

@ -0,0 +1,53 @@
/* This file is auto-generated for a specific architecture ABI */
#define CPU_IRQCHECK 0
#define CPU65_TRACE_PROLOGUE 4
#define CPU65_TRACE_ARG 8
#define CPU65_TRACE_ARG1 12
#define CPU65_TRACE_ARG2 16
#define CPU65_TRACE_EPILOGUE 20
#define CPU65_TRACE_IRQ 24
#define DEBUG_ILLEGAL_BCD 28
#define CPU65_VMEM_R 32
#define CPU65_VMEM_W 36
#define CPU65_FLAGS_ENCODE 40
#define CPU65_FLAGS_DECODE 44
#define CPU65__OPCODES 48
#define CPU65__OPCYCLES 52
#define BASE_RAMRD 56
#define BASE_RAMWRT 60
#define BASE_TEXTRD 64
#define BASE_TEXTWRT 68
#define BASE_HGRRD 72
#define BASE_HGRWRT 76
#define BASE_STACKZP 80
#define BASE_D000_RD 84
#define BASE_E000_RD 88
#define BASE_D000_WRT 92
#define BASE_E000_WRT 96
#define BASE_C3ROM 100
#define BASE_C4ROM 104
#define BASE_C5ROM 108
#define BASE_CXROM 112
#define SOFTSWITCHES 116
#define GC_CYCLES_TIMER_0 120
#define GC_CYCLES_TIMER_1 124
#define CPU65_CYCLES_TO_EXECUTE 128
#define CPU65_CYCLE_COUNT 132
#define IRQ_CHECK_TIMEOUT 136
#define INTERRUPT_VECTOR 140
#define RESET_VECTOR 142
#define CPU65_PC 144
#define CPU65_EA 146
#define CPU65_A 148
#define CPU65_F 149
#define CPU65_X 150
#define CPU65_Y 151
#define CPU65_SP 152
#define CPU65_D 153
#define CPU65_RW 154
#define CPU65_OPCODE 155
#define CPU65_OPCYCLES 156
#define CPU65__SIGNAL 157
#define JOY_BUTTON0 158
#define JOY_BUTTON1 159
#define EMUL_REINITIALIZE 160

View File

@ -14,70 +14,78 @@
#define GLUE_EXTERN_C_READ(func) #define GLUE_EXTERN_C_READ(func)
#define GLUE_BANK_MAYBE_READ_CX(func,pointer) \ #define _GLUE_BANK_MAYBE_READ_CX(func,x,pointer) \
ENTRY(func) SYM(r1, softswitches); \ ENTRY(func) ldr r0, [reg_args, #SOFTSWITCHES]; \
ldr r0, [r1]; \ ldr r1, [reg_args, x ## pointer]; \
SYM(r1, pointer); \
tst r0, $SS_CXROM; \ tst r0, $SS_CXROM; \
bne 1f; \ bne 1f; \
push {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ lr}; \ push {EffectiveAddr, PC_Reg, lr}; \
ldr r1, [r1]; \
blx r1; \ blx r1; \
pop {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ pc}; \ pop {EffectiveAddr, PC_Reg, pc}; \
1: ldr r1, [r1]; \ 1: ldrb r0, [r1, EffectiveAddr]; \
ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr; mov pc, lr;
#define GLUE_BANK_MAYBE_READ_C3(func,pointer) \ #define GLUE_BANK_MAYBE_READ_CX(func,pointer) _GLUE_BANK_MAYBE_READ_CX(func,#,pointer)
ENTRY(func) SYM(r1, softswitches); \
ldr r0, [r1]; \
SYM(r1, 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; \ tst r0, $SS_CXROM; \
bne 1f; \ bne 1f; \
tst r0, $SS_C3ROM; \ tst r0, $SS_C3ROM; \
bne 1f; \ bne 1f; \
push {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ lr}; \ push {EffectiveAddr, PC_Reg, lr}; \
ldr r1, [r1]; \
blx r1; \ blx r1; \
pop {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ pc}; \ pop {EffectiveAddr, PC_Reg, pc}; \
1: ldr r1, [r1]; \ 1: ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr;
#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]; \ ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr; mov pc, lr;
#define GLUE_BANK_READ(func,pointer) _GLUE_BANK_READ(func,#,pointer)
#define GLUE_BANK_READ(func,pointer) \ #define _GLUE_BANK_WRITE(func,x,pointer) \
ENTRY(func) SYM(r1, pointer); \ ENTRY(func) ldr r1, [reg_args, x ## pointer]; \
ldr r1, [r1]; \
ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr;
#define GLUE_BANK_WRITE(func,pointer) \
ENTRY(func) SYM(r1, pointer); \
ldr r1, [r1]; \
strb r0, [r1, EffectiveAddr]; \ strb r0, [r1, EffectiveAddr]; \
mov pc, lr; mov pc, lr;
#define GLUE_BANK_WRITE(func,pointer) _GLUE_BANK_WRITE(func,#,pointer)
#define GLUE_BANK_MAYBEWRITE(func,pointer) \
ENTRY(func) SYM(r1, pointer); \ #define _GLUE_BANK_MAYBEWRITE(func,x,pointer) \
ldr r1, [r1]; \ ENTRY(func) ldr r1, [reg_args, x ## pointer]; \
teq r1, #0; \ teq r1, #0; \
STRBNE r0, [r1, EffectiveAddr]; \ STRBNE r0, [r1, EffectiveAddr]; \
mov pc, lr; mov pc, lr;
#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;
#define GLUE_INLINE_READ(func,off) _GLUE_INLINE_READ(func,#,off)
#define GLUE_C_WRITE(func) \ #define GLUE_C_WRITE(func) \
ENTRY(func) push {r0, EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ lr}; \ ENTRY(func) push {r0, EffectiveAddr, PC_Reg, lr}; \
and r0, r0, #0xff; \ and r0, r0, #0xff; \
mov r1, r0; \ mov r1, r0; \
mov r0, EffectiveAddr; \ mov r0, EffectiveAddr; \
bl CALL(c_##func); \ bl CALL(c_##func); \
pop {r0, EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ pc}; pop {r0, EffectiveAddr, PC_Reg, pc};
#define GLUE_C_READ(func) \ #define GLUE_C_READ(func) \
ENTRY(func) push {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ lr}; \ ENTRY(func) push {EffectiveAddr, PC_Reg, lr}; \
mov r0, EffectiveAddr; \ mov r0, EffectiveAddr; \
bl CALL(c_##func); \ bl CALL(c_##func); \
pop {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ pc}; pop {EffectiveAddr, PC_Reg, pc};
#define GLUE_C_READ_ALTZP(FUNC) GLUE_C_READ(FUNC) #define GLUE_C_READ_ALTZP(FUNC) GLUE_C_READ(FUNC)

View File

@ -22,20 +22,7 @@
#include "common.h" #include "common.h"
uint16_t cpu65_pc; cpu65_run_args_s run_args = { 0 };
uint8_t cpu65_a;
uint8_t cpu65_f;
uint8_t cpu65_x;
uint8_t cpu65_y;
uint8_t cpu65_sp;
uint16_t cpu65_ea;
uint8_t cpu65_d;
uint8_t cpu65_rw;
uint8_t cpu65_opcode;
uint8_t cpu65_opcycles;
uint8_t cpu65__signal = 0;
static pthread_mutex_t irq_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t irq_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -57,7 +44,7 @@ static FILE *cpu_trace_fp = NULL;
extern void op_BRK(), op_ORA_ind_x(), op_UNK_65c02(), op_TSB_zpage(), op_ORA_zpage(), op_ASL_zpage(), op_RMB0_65c02(), op_PHP(), op_ORA_imm(), op_ASL_acc(), op_TSB_abs(), op_ORA_abs(), op_ASL_abs(), op_BBR0_65c02(), op_BPL(), op_ORA_ind_y(), op_ORA_ind_zpage(), op_TRB_zpage(), op_ORA_zpage_x(), op_ASL_zpage_x(), op_RMB1_65c02(), op_CLC(), op_ORA_abs_y(), op_INA(), op_TRB_abs(), op_ORA_abs_x(), op_ASL_abs_x(), op_BBR1_65c02(), op_JSR(), op_AND_ind_x(), op_BIT_zpage(), op_AND_zpage(), op_ROL_zpage(), op_RMB2_65c02(), op_PLP(), op_AND_imm(), op_ROL_acc(), op_BIT_abs(), op_AND_abs(), op_ROL_abs(), op_BBR2_65c02(), op_BMI(), op_AND_ind_y(), op_AND_ind_zpage(), op_BIT_zpage_x(), op_AND_zpage_x(), op_ROL_zpage_x(), op_RMB3_65c02(), op_SEC(), op_AND_abs_y(), op_DEA(), op_BIT_abs_x(), op_AND_abs_x(), op_ROL_abs_x(), op_BBR3_65c02(), op_RTI(), op_EOR_ind_x(), op_EOR_zpage(), op_LSR_zpage(), op_RMB4_65c02(), op_PHA(), op_EOR_imm(), op_LSR_acc(), op_JMP_abs(), op_EOR_abs(), op_LSR_abs(), op_BBR4_65c02(), op_BVC(), op_EOR_ind_y(), op_EOR_ind_zpage(), op_EOR_zpage_x(), op_LSR_zpage_x(), op_RMB5_65c02(), op_CLI(), op_EOR_abs_y(), op_PHY(), op_EOR_abs_x(), op_LSR_abs_x(), op_BBR5_65c02(), op_RTS(), op_ADC_ind_x(), op_STZ_zpage(), op_ADC_zpage(), op_ROR_zpage(), op_RMB6_65c02(), op_PLA(), op_ADC_imm(), op_ROR_acc(), op_JMP_ind(), op_ADC_abs(), op_ROR_abs(), op_BBR6_65c02(), op_BVS(), op_ADC_ind_y(), op_ADC_ind_zpage(), op_STZ_zpage_x(), op_ADC_zpage_x(), op_ROR_zpage_x(), op_RMB7_65c02(), op_SEI(), op_ADC_abs_y(), op_PLY(), op_JMP_abs_ind_x(), op_ADC_abs_x(), op_ROR_abs_x(), op_BBR7_65c02(), op_BRA(), op_STA_ind_x(), op_STY_zpage(), op_STA_zpage(), op_STX_zpage(), op_SMB0_65c02(), op_DEY(), op_BIT_imm(), op_TXA(), op_STY_abs(), op_STA_abs(), op_STX_abs(), op_BBS0_65c02(), op_BCC(), op_STA_ind_y(), op_STA_ind_zpage(), op_STY_zpage_x(), op_STA_zpage_x(), op_STX_zpage_y(), op_SMB1_65c02(), op_TYA(), op_STA_abs_y(), op_TXS(), op_STZ_abs(), op_STA_abs_x(), op_STZ_abs_x(), op_BBS1_65c02(), op_LDY_imm(), op_LDA_ind_x(), op_LDX_imm(), op_LDY_zpage(), op_LDA_zpage(), op_LDX_zpage(), op_SMB2_65c02(), op_TAY(), op_LDA_imm(), op_TAX(), op_LDY_abs(), op_LDA_abs(), op_LDX_abs(), op_BBS2_65c02(), op_BCS(), op_LDA_ind_y(), op_LDA_ind_zpage(), op_LDY_zpage_x(), op_LDA_zpage_x(), op_LDX_zpage_y(), op_SMB3_65c02(), op_CLV(), op_LDA_abs_y(), op_TSX(), op_LDY_abs_x(), op_LDA_abs_x(), op_LDX_abs_y(), op_BBS3_65c02(), op_CPY_imm(), op_CMP_ind_x(), op_CPY_zpage(), op_CMP_zpage(), op_DEC_zpage(), op_SMB4_65c02(), op_INY(), op_CMP_imm(), op_DEX(), op_WAI_65c02(), op_CPY_abs(), op_CMP_abs(), op_DEC_abs(), op_BBS4_65c02(), op_BNE(), op_CMP_ind_y(), op_CMP_ind_zpage(), op_CMP_zpage_x(), op_DEC_zpage_x(), op_SMB5_65c02(), op_CLD(), op_CMP_abs_y(), op_PHX(), op_STP_65c02(), op_CMP_abs_x(), op_DEC_abs_x(), op_BBS5_65c02(), op_CPX_imm(), op_SBC_ind_x(), op_CPX_zpage(), op_SBC_zpage(), op_INC_zpage(), op_SMB6_65c02(), op_INX(), op_SBC_imm(), op_NOP(), op_CPX_abs(), op_SBC_abs(), op_INC_abs(), op_BBS6_65c02(), op_BEQ(), op_SBC_ind_y(), op_SBC_ind_zpage(), op_SBC_zpage_x(), op_INC_zpage_x(), op_SMB7_65c02(), op_SED(), op_SBC_abs_y(), op_PLX(), op_SBC_abs_x(), op_INC_abs_x(), op_BBS7_65c02(); extern void op_BRK(), op_ORA_ind_x(), op_UNK_65c02(), op_TSB_zpage(), op_ORA_zpage(), op_ASL_zpage(), op_RMB0_65c02(), op_PHP(), op_ORA_imm(), op_ASL_acc(), op_TSB_abs(), op_ORA_abs(), op_ASL_abs(), op_BBR0_65c02(), op_BPL(), op_ORA_ind_y(), op_ORA_ind_zpage(), op_TRB_zpage(), op_ORA_zpage_x(), op_ASL_zpage_x(), op_RMB1_65c02(), op_CLC(), op_ORA_abs_y(), op_INA(), op_TRB_abs(), op_ORA_abs_x(), op_ASL_abs_x(), op_BBR1_65c02(), op_JSR(), op_AND_ind_x(), op_BIT_zpage(), op_AND_zpage(), op_ROL_zpage(), op_RMB2_65c02(), op_PLP(), op_AND_imm(), op_ROL_acc(), op_BIT_abs(), op_AND_abs(), op_ROL_abs(), op_BBR2_65c02(), op_BMI(), op_AND_ind_y(), op_AND_ind_zpage(), op_BIT_zpage_x(), op_AND_zpage_x(), op_ROL_zpage_x(), op_RMB3_65c02(), op_SEC(), op_AND_abs_y(), op_DEA(), op_BIT_abs_x(), op_AND_abs_x(), op_ROL_abs_x(), op_BBR3_65c02(), op_RTI(), op_EOR_ind_x(), op_EOR_zpage(), op_LSR_zpage(), op_RMB4_65c02(), op_PHA(), op_EOR_imm(), op_LSR_acc(), op_JMP_abs(), op_EOR_abs(), op_LSR_abs(), op_BBR4_65c02(), op_BVC(), op_EOR_ind_y(), op_EOR_ind_zpage(), op_EOR_zpage_x(), op_LSR_zpage_x(), op_RMB5_65c02(), op_CLI(), op_EOR_abs_y(), op_PHY(), op_EOR_abs_x(), op_LSR_abs_x(), op_BBR5_65c02(), op_RTS(), op_ADC_ind_x(), op_STZ_zpage(), op_ADC_zpage(), op_ROR_zpage(), op_RMB6_65c02(), op_PLA(), op_ADC_imm(), op_ROR_acc(), op_JMP_ind(), op_ADC_abs(), op_ROR_abs(), op_BBR6_65c02(), op_BVS(), op_ADC_ind_y(), op_ADC_ind_zpage(), op_STZ_zpage_x(), op_ADC_zpage_x(), op_ROR_zpage_x(), op_RMB7_65c02(), op_SEI(), op_ADC_abs_y(), op_PLY(), op_JMP_abs_ind_x(), op_ADC_abs_x(), op_ROR_abs_x(), op_BBR7_65c02(), op_BRA(), op_STA_ind_x(), op_STY_zpage(), op_STA_zpage(), op_STX_zpage(), op_SMB0_65c02(), op_DEY(), op_BIT_imm(), op_TXA(), op_STY_abs(), op_STA_abs(), op_STX_abs(), op_BBS0_65c02(), op_BCC(), op_STA_ind_y(), op_STA_ind_zpage(), op_STY_zpage_x(), op_STA_zpage_x(), op_STX_zpage_y(), op_SMB1_65c02(), op_TYA(), op_STA_abs_y(), op_TXS(), op_STZ_abs(), op_STA_abs_x(), op_STZ_abs_x(), op_BBS1_65c02(), op_LDY_imm(), op_LDA_ind_x(), op_LDX_imm(), op_LDY_zpage(), op_LDA_zpage(), op_LDX_zpage(), op_SMB2_65c02(), op_TAY(), op_LDA_imm(), op_TAX(), op_LDY_abs(), op_LDA_abs(), op_LDX_abs(), op_BBS2_65c02(), op_BCS(), op_LDA_ind_y(), op_LDA_ind_zpage(), op_LDY_zpage_x(), op_LDA_zpage_x(), op_LDX_zpage_y(), op_SMB3_65c02(), op_CLV(), op_LDA_abs_y(), op_TSX(), op_LDY_abs_x(), op_LDA_abs_x(), op_LDX_abs_y(), op_BBS3_65c02(), op_CPY_imm(), op_CMP_ind_x(), op_CPY_zpage(), op_CMP_zpage(), op_DEC_zpage(), op_SMB4_65c02(), op_INY(), op_CMP_imm(), op_DEX(), op_WAI_65c02(), op_CPY_abs(), op_CMP_abs(), op_DEC_abs(), op_BBS4_65c02(), op_BNE(), op_CMP_ind_y(), op_CMP_ind_zpage(), op_CMP_zpage_x(), op_DEC_zpage_x(), op_SMB5_65c02(), op_CLD(), op_CMP_abs_y(), op_PHX(), op_STP_65c02(), op_CMP_abs_x(), op_DEC_abs_x(), op_BBS5_65c02(), op_CPX_imm(), op_SBC_ind_x(), op_CPX_zpage(), op_SBC_zpage(), op_INC_zpage(), op_SMB6_65c02(), op_INX(), op_SBC_imm(), op_NOP(), op_CPX_abs(), op_SBC_abs(), op_INC_abs(), op_BBS6_65c02(), op_BEQ(), op_SBC_ind_y(), op_SBC_ind_zpage(), op_SBC_zpage_x(), op_INC_zpage_x(), op_SMB7_65c02(), op_SED(), op_SBC_abs_y(), op_PLX(), op_SBC_abs_x(), op_INC_abs_x(), op_BBS7_65c02();
void *const cpu65__opcodes[256] = { void *cpu65__opcodes[256] = {
op_BRK, // 00 op_BRK, // 00
op_ORA_ind_x, op_ORA_ind_x,
op_UNK_65c02, op_UNK_65c02,
@ -620,35 +607,69 @@ static void init_flags_conversion_tables(void) {
} }
} }
void cpu65_init(void) static __attribute__((constructor)) void __init_cpu65(void) {
{ // emulator_registerStartupCallback(CTOR_PRIORITY_LATE, &_init_cpu65); -- 2018/01/15 NOTE : too late for testcpu.c
init_flags_conversion_tables();
cpu65__signal = 0; extern void (*cpu_irqCheck)(uint16_t, uint8_t);
cpu65_pc = 0x0; run_args.cpu_irqCheck = cpu_irqCheck;
cpu65_ea = 0x0;
cpu65_a = 0xFF; run_args.cpu65_vmem_r = &cpu65_vmem_r[0];
cpu65_x = 0xFF; run_args.cpu65_vmem_w = &cpu65_vmem_w[0];
cpu65_y = 0xFF; run_args.cpu65_flags_encode = &cpu65_flags_encode[0];
cpu65_f = (C_Flag_6502|X_Flag_6502|I_Flag_6502|V_Flag_6502|B_Flag_6502|Z_Flag_6502|N_Flag_6502); run_args.cpu65_flags_decode = &cpu65_flags_decode[0];
cpu65_sp = 0xFC; run_args.cpu65__opcodes = &cpu65__opcodes[0];
run_args.cpu65__opcycles = &cpu65__opcycles[0];
run_args.interrupt_vector = 0xFFFE;
run_args.reset_vector = 0xFFFC;
#if CPU_TRACING
extern void (*cpu65_trace_prologue)(uint16_t, uint8_t);
run_args.cpu65_trace_prologue = cpu65_trace_prologue;
extern void (*cpu65_trace_arg)(uint16_t, uint8_t);
run_args.cpu65_trace_arg = cpu65_trace_arg;
extern void (*cpu65_trace_arg1)(uint16_t, uint8_t);
run_args.cpu65_trace_arg1 = cpu65_trace_arg1;
extern void (*cpu65_trace_arg2)(uint16_t, uint8_t);
run_args.cpu65_trace_arg2 = cpu65_trace_arg2;
extern void (*cpu65_trace_epilogue)(uint16_t, uint8_t);
run_args.cpu65_trace_epilogue = cpu65_trace_epilogue;
extern void (*cpu65_trace_irq)(uint16_t, uint8_t);
run_args.cpu65_trace_irq = cpu65_trace_irq;
#endif
#ifndef NDEBUG
extern uint8_t (*debug_illegal_bcd)(uint16_t);
run_args.debug_illegal_bcd = debug_illegal_bcd;
#endif
} }
void cpu65_interrupt(int reason) void cpu65_init(void) {
{ init_flags_conversion_tables();
run_args.cpu65__signal = 0;
run_args.cpu65_pc = 0x0;
run_args.cpu65_ea = 0x0;
run_args.cpu65_a = 0xFF;
run_args.cpu65_x = 0xFF;
run_args.cpu65_y = 0xFF;
run_args.cpu65_f = (C_Flag_6502|X_Flag_6502|I_Flag_6502|V_Flag_6502|B_Flag_6502|Z_Flag_6502|N_Flag_6502);
run_args.cpu65_sp = 0xFC;
}
void cpu65_interrupt(int reason) {
pthread_mutex_lock(&irq_mutex); pthread_mutex_lock(&irq_mutex);
cpu65__signal |= reason; run_args.cpu65__signal |= reason;
pthread_mutex_unlock(&irq_mutex); pthread_mutex_unlock(&irq_mutex);
} }
void cpu65_uninterrupt(int reason) void cpu65_uninterrupt(int reason) {
{
pthread_mutex_lock(&irq_mutex); pthread_mutex_lock(&irq_mutex);
cpu65__signal &= ~reason; run_args.cpu65__signal &= ~reason;
pthread_mutex_unlock(&irq_mutex); pthread_mutex_unlock(&irq_mutex);
} }
void cpu65_reboot(void) { void cpu65_reboot(void) {
joy_button0 = 0xff; // OpenApple -- should be balanced by c_joystick_reset() triggers on CPU thread run_args.joy_button0 = 0xff; // OpenApple -- should be balanced by c_joystick_reset() triggers on CPU thread
cpu65_interrupt(ResetSig); cpu65_interrupt(ResetSig);
} }
@ -660,40 +681,33 @@ bool cpu65_saveState(StateHelper_s *helper) {
uint8_t serialized[4] = { 0 }; uint8_t serialized[4] = { 0 };
// save CPU state // save CPU state
serialized[0] = ((cpu65_pc & 0xFF00) >> 8); serialized[0] = ((run_args.cpu65_pc & 0xFF00) >> 8);
serialized[1] = ((cpu65_pc & 0xFF ) >> 0); serialized[1] = ((run_args.cpu65_pc & 0xFF ) >> 0);
if (!helper->save(fd, serialized, sizeof(cpu65_pc))) { if (!helper->save(fd, serialized, sizeof(run_args.cpu65_pc))) {
break; break;
} }
LOG("SAVE cpu65_pc = %04x", cpu65_pc);
serialized[0] = ((cpu65_ea & 0xFF00) >> 8); serialized[0] = ((run_args.cpu65_ea & 0xFF00) >> 8);
serialized[1] = ((cpu65_ea & 0xFF ) >> 0); serialized[1] = ((run_args.cpu65_ea & 0xFF ) >> 0);
if (!helper->save(fd, serialized, sizeof(cpu65_ea))) { if (!helper->save(fd, serialized, sizeof(run_args.cpu65_ea))) {
break; break;
} }
LOG("SAVE cpu65_ea = %04x", cpu65_ea);
if (!helper->save(fd, &cpu65_a, sizeof(cpu65_a))) { if (!helper->save(fd, &run_args.cpu65_a, sizeof(run_args.cpu65_a))) {
break; break;
} }
LOG("SAVE cpu65_a = %02x", cpu65_a); if (!helper->save(fd, &run_args.cpu65_f, sizeof(run_args.cpu65_f))) {
if (!helper->save(fd, &cpu65_f, sizeof(cpu65_f))) {
break; break;
} }
LOG("SAVE cpu65_f = %02x", cpu65_f); if (!helper->save(fd, &run_args.cpu65_x, sizeof(run_args.cpu65_x))) {
if (!helper->save(fd, &cpu65_x, sizeof(cpu65_x))) {
break; break;
} }
LOG("SAVE cpu65_x = %02x", cpu65_x); if (!helper->save(fd, &run_args.cpu65_y, sizeof(run_args.cpu65_y))) {
if (!helper->save(fd, &cpu65_y, sizeof(cpu65_y))) {
break; break;
} }
LOG("SAVE cpu65_y = %02x", cpu65_y); if (!helper->save(fd, &run_args.cpu65_sp, sizeof(run_args.cpu65_sp))) {
if (!helper->save(fd, &cpu65_sp, sizeof(cpu65_sp))) {
break; break;
} }
LOG("SAVE cpu65_sp = %02x", cpu65_sp);
saved = true; saved = true;
} while (0); } while (0);
@ -713,37 +727,30 @@ bool cpu65_loadState(StateHelper_s *helper) {
if (!helper->load(fd, serialized, sizeof(uint16_t))) { if (!helper->load(fd, serialized, sizeof(uint16_t))) {
break; break;
} }
cpu65_pc = (serialized[0] << 8); run_args.cpu65_pc = (serialized[0] << 8);
cpu65_pc |= serialized[1]; run_args.cpu65_pc |= serialized[1];
LOG("LOAD cpu65_pc = %04x", cpu65_pc);
if (!helper->load(fd, serialized, sizeof(uint16_t))) { if (!helper->load(fd, serialized, sizeof(uint16_t))) {
break; break;
} }
cpu65_ea = (serialized[0] << 8); run_args.cpu65_ea = (serialized[0] << 8);
cpu65_ea |= serialized[1]; run_args.cpu65_ea |= serialized[1];
LOG("LOAD cpu65_ea = %04x", cpu65_ea);
if (!helper->load(fd, &cpu65_a, sizeof(cpu65_a))) { if (!helper->load(fd, &run_args.cpu65_a, sizeof(run_args.cpu65_a))) {
break; break;
} }
LOG("LOAD cpu65_a = %02x", cpu65_a); if (!helper->load(fd, &run_args.cpu65_f, sizeof(run_args.cpu65_f))) {
if (!helper->load(fd, &cpu65_f, sizeof(cpu65_f))) {
break; break;
} }
LOG("LOAD cpu65_f = %02x", cpu65_f); if (!helper->load(fd, &run_args.cpu65_x, sizeof(run_args.cpu65_x))) {
if (!helper->load(fd, &cpu65_x, sizeof(cpu65_x))) {
break; break;
} }
LOG("LOAD cpu65_x = %02x", cpu65_x); if (!helper->load(fd, &run_args.cpu65_y, sizeof(run_args.cpu65_y))) {
if (!helper->load(fd, &cpu65_y, sizeof(cpu65_y))) {
break; break;
} }
LOG("LOAD cpu65_y = %02x", cpu65_y); if (!helper->load(fd, &run_args.cpu65_sp, sizeof(run_args.cpu65_sp))) {
if (!helper->load(fd, &cpu65_sp, sizeof(cpu65_sp))) {
break; break;
} }
LOG("LOAD cpu65_sp = %02x", cpu65_sp);
loaded = true; loaded = true;
} while (0); } while (0);
@ -782,7 +789,7 @@ void cpu65_trace_toggle(const char *trace_file) {
GLUE_C_WRITE(cpu65_trace_prologue) GLUE_C_WRITE(cpu65_trace_prologue)
{ {
nargs = 0; nargs = 0;
current_pc = cpu65_pc; current_pc = run_args.cpu65_pc;
} }
GLUE_C_WRITE(cpu65_trace_arg) GLUE_C_WRITE(cpu65_trace_arg)
@ -816,14 +823,14 @@ GLUE_C_WRITE(cpu65_trace_epilogue)
assert(nargs > 0); assert(nargs > 0);
assert(nargs <= 3); assert(nargs <= 3);
if (nargs != opcodes_65c02_numargs[cpu65_opcode]+1) { if (nargs != opcodes_65c02_numargs[run_args.cpu65_opcode]+1) {
assert(false && "OOPS, most likely some cpu.S routine is not properly setting the arg value"); assert(false && "OOPS, most likely some cpu.S routine is not properly setting the arg value");
} }
switch (opcodes_65c02[cpu65_opcode].mode) { switch (opcodes_65c02[run_args.cpu65_opcode].mode) {
case addr_implied: case addr_implied:
case addr_accumulator: case addr_accumulator:
fprintf(cpu_trace_fp, "%04X:%02X ", current_pc, cpu65_opcode); fprintf(cpu_trace_fp, "%04X:%02X ", current_pc, run_args.cpu65_opcode);
break; break;
case addr_immediate: case addr_immediate:
case addr_zeropage: case addr_zeropage:
@ -833,64 +840,63 @@ GLUE_C_WRITE(cpu65_trace_epilogue)
case addr_indirect_x: case addr_indirect_x:
case addr_indirect_y: case addr_indirect_y:
case addr_relative: case addr_relative:
fprintf(cpu_trace_fp, "%04X:%02X%02X ", current_pc, cpu65_opcode, (uint8_t)arg1); fprintf(cpu_trace_fp, "%04X:%02X%02X ", current_pc, run_args.cpu65_opcode, (uint8_t)arg1);
break; break;
case addr_absolute: case addr_absolute:
case addr_absolute_x: case addr_absolute_x:
case addr_absolute_y: case addr_absolute_y:
case addr_j_indirect: case addr_j_indirect:
case addr_j_indirect_x: case addr_j_indirect_x:
fprintf(cpu_trace_fp, "%04X:%02X%02X%02X", current_pc, cpu65_opcode, (uint8_t)arg2, (uint8_t)arg1); fprintf(cpu_trace_fp, "%04X:%02X%02X%02X", current_pc, run_args.cpu65_opcode, (uint8_t)arg2, (uint8_t)arg1);
break; break;
default: default:
fprintf(cpu_trace_fp, "invalid opcode mode"); fprintf(cpu_trace_fp, "invalid opcode mode");
break; break;
} }
fprintf(cpu_trace_fp, " SP:%02X X:%02X Y:%02X A:%02X", cpu65_sp, cpu65_x, cpu65_y, cpu65_a); fprintf(cpu_trace_fp, " SP:%02X X:%02X Y:%02X A:%02X", run_args.cpu65_sp, run_args.cpu65_x, run_args.cpu65_y, run_args.cpu65_a);
#define FLAGS_BUFSZ 9 #define FLAGS_BUFSZ 9
char flags_buf[FLAGS_BUFSZ]; char flags_buf[FLAGS_BUFSZ];
memset(flags_buf, '-', FLAGS_BUFSZ); memset(flags_buf, '-', FLAGS_BUFSZ);
if (cpu65_f & C_Flag_6502) { if (run_args.cpu65_f & C_Flag_6502) {
flags_buf[0]='C'; flags_buf[0]='C';
} }
if (cpu65_f & X_Flag_6502) { if (run_args.cpu65_f & X_Flag_6502) {
flags_buf[1]='X'; flags_buf[1]='X';
} }
if (cpu65_f & I_Flag_6502) { if (run_args.cpu65_f & I_Flag_6502) {
flags_buf[2]='I'; flags_buf[2]='I';
} }
if (cpu65_f & V_Flag_6502) { if (run_args.cpu65_f & V_Flag_6502) {
flags_buf[3]='V'; flags_buf[3]='V';
} }
if (cpu65_f & B_Flag_6502) { if (run_args.cpu65_f & B_Flag_6502) {
flags_buf[4]='B'; flags_buf[4]='B';
} }
if (cpu65_f & D_Flag_6502) { if (run_args.cpu65_f & D_Flag_6502) {
flags_buf[5]='D'; flags_buf[5]='D';
} }
if (cpu65_f & Z_Flag_6502) { if (run_args.cpu65_f & Z_Flag_6502) {
flags_buf[6]='Z'; flags_buf[6]='Z';
} }
if (cpu65_f & N_Flag_6502) { if (run_args.cpu65_f & N_Flag_6502) {
flags_buf[7]='N'; flags_buf[7]='N';
} }
flags_buf[8] = '\0'; flags_buf[8] = '\0';
char fmt[64]; char fmt[64];
if (UNLIKELY(cpu65_opcycles >= 10)) { if (UNLIKELY(run_args.cpu65_opcycles >= 10)) {
// occurs rarely for interrupt + opcode // occurs rarely for interrupt + opcode
snprintf(fmt, 64, "%s", " %s CY:%u irqChk:%d totCyc:%d EA:%04X"); snprintf(fmt, 64, "%s", " %s CY:%u irqChk:%d totCyc:%d EA:%04X");
} else { } else {
snprintf(fmt, 64, "%s", " %s CYC:%u irqChk:%d totCyc:%d EA:%04X"); snprintf(fmt, 64, "%s", " %s CYC:%u irqChk:%d totCyc:%d EA:%04X");
} }
extern int32_t irqCheckTimeout; fprintf(cpu_trace_fp, fmt, flags_buf, run_args.cpu65_opcycles, (run_args.irq_check_timeout - run_args.cpu65_opcycles), (cycles_count_total + run_args.cpu65_opcycles), run_args.cpu65_ea);
fprintf(cpu_trace_fp, fmt, flags_buf, cpu65_opcycles, (irqCheckTimeout - cpu65_opcycles), (cycles_count_total + cpu65_opcycles), cpu65_ea);
sprintf(fmt, " %s %s", opcodes_65c02[cpu65_opcode].mnemonic, disasm_templates[opcodes_65c02[cpu65_opcode].mode]); sprintf(fmt, " %s %s", opcodes_65c02[run_args.cpu65_opcode].mnemonic, disasm_templates[opcodes_65c02[run_args.cpu65_opcode].mode]);
switch (opcodes_65c02[cpu65_opcode].mode) { switch (opcodes_65c02[run_args.cpu65_opcode].mode) {
case addr_implied: case addr_implied:
case addr_accumulator: case addr_accumulator:
fprintf(cpu_trace_fp, "%s", fmt); fprintf(cpu_trace_fp, "%s", fmt);
@ -928,7 +934,7 @@ GLUE_C_WRITE(cpu65_trace_epilogue)
GLUE_C_WRITE(cpu65_trace_irq) GLUE_C_WRITE(cpu65_trace_irq)
{ {
if (cpu_trace_fp) { if (cpu_trace_fp) {
fprintf(cpu_trace_fp, "IRQ:%02X\n", cpu65__signal); fprintf(cpu_trace_fp, "IRQ:%02X\n", run_args.cpu65__signal);
} }
} }

View File

@ -23,23 +23,14 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdint.h> #include <stdint.h>
#include "glue.h"
/* types */ /* types */
#define MEM_READ_FLAG (1<<0) #define MEM_READ_FLAG (1<<0)
#define MEM_WRITE_FLAG (1<<1) #define MEM_WRITE_FLAG (1<<1)
extern uint16_t cpu65_pc; // Program counter extern cpu65_run_args_s run_args;
extern uint8_t cpu65_a; // Accumulator
extern uint8_t cpu65_f; // Flags (host-order)
extern uint8_t cpu65_x; // X Index register
extern uint8_t cpu65_y; // Y Index register
extern uint8_t cpu65_sp; // Stack Pointer
extern uint16_t cpu65_ea; // Last effective address
extern uint8_t cpu65_d; // Last data byte written
extern uint8_t cpu65_rw; // MEM_READ_FLAG = read occured, MEM_WRITE_FLAG = write
extern uint8_t cpu65_opcode; // Last opcode
extern uint8_t cpu65_opcycles; // Last opcode extra cycles
/* Set up the processor for a new run. Sets up opcode table. */ /* Set up the processor for a new run. Sets up opcode table. */
extern void cpu65_init(); extern void cpu65_init();
@ -48,7 +39,7 @@ extern void cpu65_init();
extern void cpu65_interrupt(int reason); extern void cpu65_interrupt(int reason);
extern void cpu65_uninterrupt(int reason); extern void cpu65_uninterrupt(int reason);
extern void cpu65_run(void); extern void cpu65_run(void *args);
extern void cpu65_reboot(void); extern void cpu65_reboot(void);
extern bool cpu65_saveState(StateHelper_s *helper); extern bool cpu65_saveState(StateHelper_s *helper);
@ -59,10 +50,8 @@ extern void cpu65_direct_write(int ea,int data);
extern void *cpu65_vmem_r[65536]; extern void *cpu65_vmem_r[65536];
extern void *cpu65_vmem_w[65536]; extern void *cpu65_vmem_w[65536];
extern unsigned char cpu65_flags_encode[256]; extern uint8_t cpu65_flags_encode[256];
extern unsigned char cpu65_flags_decode[256]; extern uint8_t cpu65_flags_decode[256];
extern int32_t cpu65_cycle_count;
#if CPU_TRACING #if CPU_TRACING
void cpu65_trace_begin(const char *trace_file); void cpu65_trace_begin(const char *trace_file);

View File

@ -836,48 +836,48 @@ static inline drawpage_mode_t _currentMixedMode(uint32_t currswitches) {
GLUE_C_WRITE(video__write_2e_text0) GLUE_C_WRITE(video__write_2e_text0)
{ {
base_textwrt[ea] = b; run_args.base_textwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches); drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) { if (mode == DRAWPAGE_HIRES) {
return; return;
} }
if (!(softswitches & SS_PAGE2)) { if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_text0_mixed) GLUE_C_WRITE(video__write_2e_text0_mixed)
{ {
base_textwrt[ea] = b; run_args.base_textwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches); drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) { if (mode == DRAWPAGE_HIRES) {
return; return;
} }
if (!(softswitches & SS_PAGE2)) { if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_text1) GLUE_C_WRITE(video__write_2e_text1)
{ {
base_ramwrt[ea] = b; run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches); drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) { if (mode == DRAWPAGE_HIRES) {
return; return;
} }
if (softswitches & SS_PAGE2) { if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_text1_mixed) GLUE_C_WRITE(video__write_2e_text1_mixed)
{ {
base_ramwrt[ea] = b; run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches); drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) { if (mode == DRAWPAGE_HIRES) {
return; return;
} }
if (softswitches & SS_PAGE2) { if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
@ -1161,96 +1161,96 @@ static void (*_hirespage_plotter(uint32_t currswitches))(uint16_t, int, int, boo
GLUE_C_WRITE(video__write_2e_even0) GLUE_C_WRITE(video__write_2e_even0)
{ {
base_hgrwrt[ea] = b; run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches); drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (!(softswitches & SS_PAGE2)) { if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_even0_mixed) GLUE_C_WRITE(video__write_2e_even0_mixed)
{ {
base_hgrwrt[ea] = b; run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches); drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (!(softswitches & SS_PAGE2)) { if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_odd0) GLUE_C_WRITE(video__write_2e_odd0)
{ {
base_hgrwrt[ea] = b; run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches); drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (!(softswitches & SS_PAGE2)) { if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_odd0_mixed) GLUE_C_WRITE(video__write_2e_odd0_mixed)
{ {
base_hgrwrt[ea] = b; run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches); drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (!(softswitches & SS_PAGE2)) { if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_even1) GLUE_C_WRITE(video__write_2e_even1)
{ {
base_ramwrt[ea] = b; run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches); drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (softswitches & SS_PAGE2) { if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_even1_mixed) GLUE_C_WRITE(video__write_2e_even1_mixed)
{ {
base_ramwrt[ea] = b; run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches); drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (softswitches & SS_PAGE2) { if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_odd1) GLUE_C_WRITE(video__write_2e_odd1)
{ {
base_ramwrt[ea] = b; run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches); drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (softswitches & SS_PAGE2) { if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
GLUE_C_WRITE(video__write_2e_odd1_mixed) GLUE_C_WRITE(video__write_2e_odd1_mixed)
{ {
base_ramwrt[ea] = b; run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches); drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) { if (mode == DRAWPAGE_TEXT) {
return; return;
} }
if (softswitches & SS_PAGE2) { if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
} }
} }
@ -1294,7 +1294,7 @@ void display_renderStagingFramebuffer(uint8_t *stagingFB) {
int page = 0; int page = 0;
int bank = 0; int bank = 0;
const uint32_t mainswitches = softswitches; const uint32_t mainswitches = run_args.softswitches;
// render main portion of screen ... // render main portion of screen ...
@ -1323,7 +1323,7 @@ void display_renderStagingFramebuffer(uint8_t *stagingFB) {
} }
// resample current switches ... and render mixed portion of screen // resample current switches ... and render mixed portion of screen
const uint32_t mixedswitches = softswitches; const uint32_t mixedswitches = run_args.softswitches;
drawpage_mode_t mixedDrawPageMode = _currentMixedMode(mixedswitches); drawpage_mode_t mixedDrawPageMode = _currentMixedMode(mixedswitches);
_currentPageAndBank(mixedswitches, mixedDrawPageMode, &page, &bank); _currentPageAndBank(mixedswitches, mixedDrawPageMode, &page, &bank);
@ -1361,7 +1361,7 @@ void display_flashText(void) {
normal = !normal; normal = !normal;
// flash only if it's text or mixed modes. // flash only if it's text or mixed modes.
if (softswitches & (SS_TEXT|SS_MIXED)) { if (run_args.softswitches & (SS_TEXT|SS_MIXED)) {
if (normal) { if (normal) {
colormap[ COLOR_FLASHING_BLACK].red = 0; colormap[ COLOR_FLASHING_BLACK].red = 0;
colormap[ COLOR_FLASHING_BLACK].green = 0; colormap[ COLOR_FLASHING_BLACK].green = 0;
@ -1407,12 +1407,11 @@ unsigned long video_clearDirty(unsigned long flags) {
extern unsigned int CpuGetCyclesThisVideoFrame(void); extern unsigned int CpuGetCyclesThisVideoFrame(void);
uint16_t video_scanner_get_address(bool *vblBarOut) { uint16_t video_scanner_get_address(bool *vblBarOut) {
const bool SW_HIRES = (run_args.softswitches & SS_HIRES);
const bool SW_HIRES = (softswitches & SS_HIRES); const bool SW_TEXT = (run_args.softswitches & SS_TEXT);
const bool SW_TEXT = (softswitches & SS_TEXT); const bool SW_PAGE2 = (run_args.softswitches & SS_PAGE2);
const bool SW_PAGE2 = (softswitches & SS_PAGE2); const bool SW_80STORE = (run_args.softswitches & SS_80STORE);
const bool SW_80STORE = (softswitches & SS_80STORE); const bool SW_MIXED = (run_args.softswitches & SS_MIXED);
const bool SW_MIXED = (softswitches & SS_MIXED);
// get video scanner position // get video scanner position
unsigned int nCycles = CpuGetCyclesThisVideoFrame(); unsigned int nCycles = CpuGetCyclesThisVideoFrame();

View File

@ -1,6 +1,7 @@
#!/bin/sh #!/bin/sh
echo "#include \"$TARGET_ARCH/glue-prologue.h\"" echo "#include \"$TARGET_ARCH/glue-prologue.h\""
echo "#include \"$TARGET_ARCH/glue-offsets.h\""
while test "x$1" != "x" ; do while test "x$1" != "x" ; do
grep -E -h '(GLUE_)|(#[ ]*if)|(#[ ]*endif)|(#[ ]*else)|(#[ ]*elif)' "$1" grep -E -h '(GLUE_)|(#[ ]*if)|(#[ ]*endif)|(#[ ]*else)|(#[ ]*elif)' "$1"

95
src/glue-offsets.c Normal file
View File

@ -0,0 +1,95 @@
/*
* Apple // emulator for *ix
*
* This software package is subject to the GNU General Public License
* version 3 or later (your choice) as published by the Free Software
* Foundation.
*
* Copyright 2017+ Aaron Culliney
*
*/
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include "glue.h"
int main (int argc, char **argv) {
printf("/* This file is auto-generated for a specific architecture ABI */\n");
OUTPUT_CPU_IRQCHECK();
OUTPUT_CPU65_TRACE_PROLOGUE();
OUTPUT_CPU65_TRACE_ARG();
OUTPUT_CPU65_TRACE_ARG1();
OUTPUT_CPU65_TRACE_ARG2();
OUTPUT_CPU65_TRACE_EPILOGUE();
OUTPUT_CPU65_TRACE_IRQ();
OUTPUT_DEBUG_ILLEGAL_BCD();
OUTPUT_CPU65_VMEM_R();
OUTPUT_CPU65_VMEM_W();
OUTPUT_CPU65_FLAGS_ENCODE();
OUTPUT_CPU65_FLAGS_DECODE();
OUTPUT_CPU65__OPCODES();
OUTPUT_CPU65__OPCYCLES();
OUTPUT_BASE_RAMRD();
OUTPUT_BASE_RAMWRT();
OUTPUT_BASE_TEXTRD();
OUTPUT_BASE_TEXTWRT();
OUTPUT_BASE_HGRRD();
OUTPUT_BASE_HGRWRT();
OUTPUT_BASE_STACKZP();
OUTPUT_BASE_D000_RD();
OUTPUT_BASE_E000_RD();
OUTPUT_BASE_D000_WRT();
OUTPUT_BASE_E000_WRT();
OUTPUT_BASE_C3ROM();
OUTPUT_BASE_C4ROM();
OUTPUT_BASE_C5ROM();
OUTPUT_BASE_CXROM();
OUTPUT_SOFTSWITCHES();
OUTPUT_GC_CYCLES_TIMER_0();
OUTPUT_GC_CYCLES_TIMER_1();
OUTPUT_CPU65_CYCLES_TO_EXECUTE();
OUTPUT_CPU65_CYCLE_COUNT();
OUTPUT_IRQ_CHECK_TIMEOUT();
OUTPUT_INTERRUPT_VECTOR();
OUTPUT_RESET_VECTOR();
OUTPUT_CPU65_PC();
OUTPUT_CPU65_EA();
OUTPUT_CPU65_A();
OUTPUT_CPU65_F();
OUTPUT_CPU65_X();
OUTPUT_CPU65_Y();
OUTPUT_CPU65_SP();
OUTPUT_CPU65_D();
OUTPUT_CPU65_RW();
OUTPUT_CPU65_OPCODE();
OUTPUT_CPU65_OPCYCLES();
OUTPUT_CPU65__SIGNAL();
OUTPUT_JOY_BUTTON0();
OUTPUT_JOY_BUTTON1();
OUTPUT_EMUL_REINITIALIZE();
fflush(stdout);
return 0;
}

View File

@ -13,6 +13,9 @@
* *
*/ */
#ifndef _GLUE_H_
#define _GLUE_H_
#if defined(__ASSEMBLER__) #if defined(__ASSEMBLER__)
# error assembler-specific glue code should be in the arch-specific area # error assembler-specific glue code should be in the arch-specific area
#endif #endif
@ -23,6 +26,8 @@
#define GLUE_BANK_WRITE(func,pointer) extern void func(void) #define GLUE_BANK_WRITE(func,pointer) extern void func(void)
#define GLUE_BANK_MAYBEWRITE(func,pointer) extern void func(void) #define GLUE_BANK_MAYBEWRITE(func,pointer) extern void func(void)
#define GLUE_INLINE_READ(func,arg) extern uint8_t func(uint16_t)
#define GLUE_EXTERN_C_READ(func) extern uint8_t func(uint16_t) #define GLUE_EXTERN_C_READ(func) extern uint8_t func(uint16_t)
#if VM_TRACING #if VM_TRACING
@ -68,3 +73,131 @@
#define GLUE_C_READ_ALTZP(func, ...) GLUE_C_READ(func) #define GLUE_C_READ_ALTZP(func, ...) GLUE_C_READ(func)
// Stack struct assembly bridge (avoiding all PIC nastiness)
typedef struct cpu65_run_args_s {
void (*cpu_irqCheck)(uint16_t, uint8_t);
#define OUTPUT_CPU_IRQCHECK() printf("#define CPU_IRQCHECK %ld\n", offsetof(cpu65_run_args_s, cpu_irqCheck))
void (*cpu65_trace_prologue)(uint16_t, uint8_t);
#define OUTPUT_CPU65_TRACE_PROLOGUE() printf("#define CPU65_TRACE_PROLOGUE %ld\n", offsetof(cpu65_run_args_s, cpu65_trace_prologue))
void (*cpu65_trace_arg)(uint16_t, uint8_t);
#define OUTPUT_CPU65_TRACE_ARG() printf("#define CPU65_TRACE_ARG %ld\n", offsetof(cpu65_run_args_s, cpu65_trace_arg))
void (*cpu65_trace_arg1)(uint16_t, uint8_t);
#define OUTPUT_CPU65_TRACE_ARG1() printf("#define CPU65_TRACE_ARG1 %ld\n", offsetof(cpu65_run_args_s, cpu65_trace_arg1))
void (*cpu65_trace_arg2)(uint16_t, uint8_t);
#define OUTPUT_CPU65_TRACE_ARG2() printf("#define CPU65_TRACE_ARG2 %ld\n", offsetof(cpu65_run_args_s, cpu65_trace_arg2))
void (*cpu65_trace_epilogue)(uint16_t, uint8_t);
#define OUTPUT_CPU65_TRACE_EPILOGUE() printf("#define CPU65_TRACE_EPILOGUE %ld\n", offsetof(cpu65_run_args_s, cpu65_trace_epilogue))
void (*cpu65_trace_irq)(uint16_t, uint8_t);
#define OUTPUT_CPU65_TRACE_IRQ() printf("#define CPU65_TRACE_IRQ %ld\n", offsetof(cpu65_run_args_s, cpu65_trace_irq))
uint8_t (*debug_illegal_bcd)(uint16_t);
#define OUTPUT_DEBUG_ILLEGAL_BCD() printf("#define DEBUG_ILLEGAL_BCD %ld\n", offsetof(cpu65_run_args_s, debug_illegal_bcd))
void *cpu65_vmem_r;
#define OUTPUT_CPU65_VMEM_R() printf("#define CPU65_VMEM_R %ld\n", offsetof(cpu65_run_args_s, cpu65_vmem_r))
void *cpu65_vmem_w;
#define OUTPUT_CPU65_VMEM_W() printf("#define CPU65_VMEM_W %ld\n", offsetof(cpu65_run_args_s, cpu65_vmem_w))
void *cpu65_flags_encode;
#define OUTPUT_CPU65_FLAGS_ENCODE() printf("#define CPU65_FLAGS_ENCODE %ld\n", offsetof(cpu65_run_args_s, cpu65_flags_encode))
void *cpu65_flags_decode;
#define OUTPUT_CPU65_FLAGS_DECODE() printf("#define CPU65_FLAGS_DECODE %ld\n", offsetof(cpu65_run_args_s, cpu65_flags_decode))
void *cpu65__opcodes;
#define OUTPUT_CPU65__OPCODES() printf("#define CPU65__OPCODES %ld\n", offsetof(cpu65_run_args_s, cpu65__opcodes))
uint8_t *cpu65__opcycles;
#define OUTPUT_CPU65__OPCYCLES() printf("#define CPU65__OPCYCLES %ld\n", offsetof(cpu65_run_args_s, cpu65__opcycles))
uint8_t *base_ramrd;
#define OUTPUT_BASE_RAMRD() printf("#define BASE_RAMRD %ld\n", offsetof(cpu65_run_args_s, base_ramrd))
uint8_t *base_ramwrt;
#define OUTPUT_BASE_RAMWRT() printf("#define BASE_RAMWRT %ld\n", offsetof(cpu65_run_args_s, base_ramwrt))
uint8_t *base_textrd;
#define OUTPUT_BASE_TEXTRD() printf("#define BASE_TEXTRD %ld\n", offsetof(cpu65_run_args_s, base_textrd))
uint8_t *base_textwrt;
#define OUTPUT_BASE_TEXTWRT() printf("#define BASE_TEXTWRT %ld\n", offsetof(cpu65_run_args_s, base_textwrt))
uint8_t *base_hgrrd;
#define OUTPUT_BASE_HGRRD() printf("#define BASE_HGRRD %ld\n", offsetof(cpu65_run_args_s, base_hgrrd))
uint8_t *base_hgrwrt;
#define OUTPUT_BASE_HGRWRT() printf("#define BASE_HGRWRT %ld\n", offsetof(cpu65_run_args_s, base_hgrwrt))
uint8_t *base_stackzp;
#define OUTPUT_BASE_STACKZP() printf("#define BASE_STACKZP %ld\n", offsetof(cpu65_run_args_s, base_stackzp))
uint8_t *base_d000_rd;
#define OUTPUT_BASE_D000_RD() printf("#define BASE_D000_RD %ld\n", offsetof(cpu65_run_args_s, base_d000_rd))
uint8_t *base_e000_rd;
#define OUTPUT_BASE_E000_RD() printf("#define BASE_E000_RD %ld\n", offsetof(cpu65_run_args_s, base_e000_rd))
uint8_t *base_d000_wrt;
#define OUTPUT_BASE_D000_WRT() printf("#define BASE_D000_WRT %ld\n", offsetof(cpu65_run_args_s, base_d000_wrt))
uint8_t *base_e000_wrt;
#define OUTPUT_BASE_E000_WRT() printf("#define BASE_E000_WRT %ld\n", offsetof(cpu65_run_args_s, base_e000_wrt))
uint8_t *base_c3rom;
#define OUTPUT_BASE_C3ROM() printf("#define BASE_C3ROM %ld\n", offsetof(cpu65_run_args_s, base_c3rom))
uint8_t *base_c4rom;
#define OUTPUT_BASE_C4ROM() printf("#define BASE_C4ROM %ld\n", offsetof(cpu65_run_args_s, base_c4rom))
uint8_t *base_c5rom;
#define OUTPUT_BASE_C5ROM() printf("#define BASE_C5ROM %ld\n", offsetof(cpu65_run_args_s, base_c5rom))
uint8_t *base_cxrom;
#define OUTPUT_BASE_CXROM() printf("#define BASE_CXROM %ld\n", offsetof(cpu65_run_args_s, base_cxrom))
uint32_t softswitches;
#define OUTPUT_SOFTSWITCHES() printf("#define SOFTSWITCHES %ld\n", offsetof(cpu65_run_args_s, softswitches))
int32_t gc_cycles_timer_0; // joystick timer values
#define OUTPUT_GC_CYCLES_TIMER_0() printf("#define GC_CYCLES_TIMER_0 %ld\n", offsetof(cpu65_run_args_s, gc_cycles_timer_0))
int32_t gc_cycles_timer_1;
#define OUTPUT_GC_CYCLES_TIMER_1() printf("#define GC_CYCLES_TIMER_1 %ld\n", offsetof(cpu65_run_args_s, gc_cycles_timer_1))
int32_t cpu65_cycles_to_execute; // cycles-to-execute by cpu65_run()
#define OUTPUT_CPU65_CYCLES_TO_EXECUTE() printf("#define CPU65_CYCLES_TO_EXECUTE %ld\n", offsetof(cpu65_run_args_s, cpu65_cycles_to_execute))
int32_t cpu65_cycle_count; // cycles currently excuted by cpu65_run()
#define OUTPUT_CPU65_CYCLE_COUNT() printf("#define CPU65_CYCLE_COUNT %ld\n", offsetof(cpu65_run_args_s, cpu65_cycle_count))
int32_t irq_check_timeout; // cycles to check for raised IRQ
#define OUTPUT_IRQ_CHECK_TIMEOUT() printf("#define IRQ_CHECK_TIMEOUT %ld\n", offsetof(cpu65_run_args_s, irq_check_timeout))
uint16_t interrupt_vector;
#define OUTPUT_INTERRUPT_VECTOR() printf("#define INTERRUPT_VECTOR %ld\n", offsetof(cpu65_run_args_s, interrupt_vector))
uint16_t reset_vector;
#define OUTPUT_RESET_VECTOR() printf("#define RESET_VECTOR %ld\n", offsetof(cpu65_run_args_s, reset_vector))
uint16_t cpu65_pc; // Program counter
#define OUTPUT_CPU65_PC() printf("#define CPU65_PC %ld\n", offsetof(cpu65_run_args_s, cpu65_pc))
uint16_t cpu65_ea; // Last effective address
#define OUTPUT_CPU65_EA() printf("#define CPU65_EA %ld\n", offsetof(cpu65_run_args_s, cpu65_ea))
uint8_t cpu65_a; // Accumulator
#define OUTPUT_CPU65_A() printf("#define CPU65_A %ld\n", offsetof(cpu65_run_args_s, cpu65_a))
uint8_t cpu65_f; // Flags (host-order)
#define OUTPUT_CPU65_F() printf("#define CPU65_F %ld\n", offsetof(cpu65_run_args_s, cpu65_f))
uint8_t cpu65_x; // X Index register
#define OUTPUT_CPU65_X() printf("#define CPU65_X %ld\n", offsetof(cpu65_run_args_s, cpu65_x))
uint8_t cpu65_y; // Y Index register
#define OUTPUT_CPU65_Y() printf("#define CPU65_Y %ld\n", offsetof(cpu65_run_args_s, cpu65_y))
uint8_t cpu65_sp; // Stack Pointer
#define OUTPUT_CPU65_SP() printf("#define CPU65_SP %ld\n", offsetof(cpu65_run_args_s, cpu65_sp))
uint8_t cpu65_d; // Last data byte written
#define OUTPUT_CPU65_D() printf("#define CPU65_D %ld\n", offsetof(cpu65_run_args_s, cpu65_d))
uint8_t cpu65_rw; // MEM_READ_FLAG = read occured, MEM_WRITE_FLAG = write
#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
#define OUTPUT_CPU65_OPCYCLES() printf("#define CPU65_OPCYCLES %ld\n", offsetof(cpu65_run_args_s, cpu65_opcycles))
uint8_t cpu65__signal;
#define OUTPUT_CPU65__SIGNAL() printf("#define CPU65__SIGNAL %ld\n", offsetof(cpu65_run_args_s, cpu65__signal))
uint8_t joy_button0;
#define OUTPUT_JOY_BUTTON0() printf("#define JOY_BUTTON0 %ld\n", offsetof(cpu65_run_args_s, joy_button0))
uint8_t joy_button1;
#define OUTPUT_JOY_BUTTON1() printf("#define JOY_BUTTON1 %ld\n", offsetof(cpu65_run_args_s, joy_button1))
uint8_t emul_reinitialize;
#define OUTPUT_EMUL_REINITIALIZE() printf("#define EMUL_REINITIALIZE %ld\n", offsetof(cpu65_run_args_s, emul_reinitialize))
} cpu65_run_args_s;
#endif // whole file

View File

@ -25,8 +25,6 @@ joystick_mode_t joy_mode = JOY_PCJOY;
/* parameters for generic and keyboard-simulated joysticks */ /* parameters for generic and keyboard-simulated joysticks */
uint16_t joy_x = HALF_JOY_RANGE; uint16_t joy_x = HALF_JOY_RANGE;
uint16_t joy_y = HALF_JOY_RANGE; uint16_t joy_y = HALF_JOY_RANGE;
uint8_t joy_button0 = 0;
uint8_t joy_button1 = 0;
bool joy_clip_to_radius = false; bool joy_clip_to_radius = false;
#ifdef KEYPAD_JOYSTICK #ifdef KEYPAD_JOYSTICK
@ -114,8 +112,8 @@ static void c_calibrate_pc_joystick()
x_last = x_plot; x_last = x_plot;
y_last = y_plot; y_last = y_plot;
joymenu[CALIBRATE_JOYMENU_H-4][8] = joy_button0 ? 'X' : ' '; joymenu[CALIBRATE_JOYMENU_H-4][8] = run_args.joy_button0 ? 'X' : ' ';
joymenu[CALIBRATE_JOYMENU_H-4][15] = joy_button1 ? 'X' : ' '; joymenu[CALIBRATE_JOYMENU_H-4][15] = run_args.joy_button1 ? 'X' : ' ';
snprintf(temp, TEMPSIZE, "%04x", (short)(joy_x)); snprintf(temp, TEMPSIZE, "%04x", (short)(joy_x));
copy_and_pad_string(&joymenu[CALIBRATE_JOYMENU_H-4][24], temp, ' ', 5, ' '); copy_and_pad_string(&joymenu[CALIBRATE_JOYMENU_H-4][24], temp, ' ', 5, ' ');
@ -182,8 +180,8 @@ static void c_calibrate_keypad_joystick()
char temp[TEMPSIZE]; char temp[TEMPSIZE];
for (;;) for (;;)
{ {
submenu[KEYPAD_SUBMENU_H-2][12] = joy_button0 ? 'X' : ' '; submenu[KEYPAD_SUBMENU_H-2][12] = run_args.joy_button0 ? 'X' : ' ';
submenu[KEYPAD_SUBMENU_H-2][23] = joy_button1 ? 'X' : ' '; submenu[KEYPAD_SUBMENU_H-2][23] = run_args.joy_button1 ? 'X' : ' ';
snprintf(temp, TEMPSIZE, "%02x", (uint8_t)joy_x); snprintf(temp, TEMPSIZE, "%02x", (uint8_t)joy_x);
copy_and_pad_string(&submenu[KEYPAD_SUBMENU_H-2][31], temp, ' ', 3, ' '); copy_and_pad_string(&submenu[KEYPAD_SUBMENU_H-2][31], temp, ' ', 3, ' ');
@ -272,8 +270,8 @@ static void *_joystick_resetDelayed(void *ctx) {
// delay // delay
sleep(1); sleep(1);
joy_button0 = 0x0; run_args.joy_button0 = 0x0;
joy_button1 = 0x0; run_args.joy_button1 = 0x0;
return NULL; return NULL;
} }
@ -286,8 +284,8 @@ void c_joystick_reset(void)
#if TESTING #if TESTING
// For "testdisk" determinism, these need to be reset immediately // For "testdisk" determinism, these need to be reset immediately
joy_button0 = 0x0; run_args.joy_button0 = 0x0;
joy_button1 = 0x0; run_args.joy_button1 = 0x0;
#else #else
pthread_t pid; pthread_t pid;
pthread_create(&pid, NULL, (void *)&_joystick_resetDelayed, (void *)NULL); pthread_create(&pid, NULL, (void *)&_joystick_resetDelayed, (void *)NULL);
@ -339,11 +337,11 @@ uint8_t joydriver_getAxisY(void) {
// set button 0 pressed // set button 0 pressed
void joydriver_setButton0Pressed(bool pressed) { void joydriver_setButton0Pressed(bool pressed) {
joy_button0 = (pressed) ? 0x80 : 0x0; run_args.joy_button0 = (pressed) ? 0x80 : 0x0;
} }
// set button 1 pressed // set button 1 pressed
void joydriver_setButton1Pressed(bool pressed) { void joydriver_setButton1Pressed(bool pressed) {
joy_button1 = (pressed) ? 0x80 : 0x0; run_args.joy_button1 = (pressed) ? 0x80 : 0x0;
} }

View File

@ -28,8 +28,6 @@ extern joystick_mode_t joy_mode;
extern uint16_t joy_x; extern uint16_t joy_x;
extern uint16_t joy_y; extern uint16_t joy_y;
extern uint8_t joy_button0;
extern uint8_t joy_button1;
extern bool joy_clip_to_radius; extern bool joy_clip_to_radius;
#ifdef KEYPAD_JOYSTICK #ifdef KEYPAD_JOYSTICK

View File

@ -148,7 +148,7 @@ uint8_t keys_apple2ASCII(uint8_t c, OUTPARM font_mode_t *mode) {
*mode = FONT_MODE_INVERSE; *mode = FONT_MODE_INVERSE;
return c; // Apple //e (0x20-0x3F) -> ASCII (0x20-0x3F) return c; // Apple //e (0x20-0x3F) -> ASCII (0x20-0x3F)
} else if (c < 0x60) { } else if (c < 0x60) {
if (/*altchar on:*/(softswitches & SS_ALTCHAR)) { if (/*altchar on:*/(run_args.softswitches & SS_ALTCHAR)) {
*mode = FONT_MODE_MOUSETEXT; *mode = FONT_MODE_MOUSETEXT;
return c+0x40; return c+0x40;
} else { } else {
@ -156,7 +156,7 @@ uint8_t keys_apple2ASCII(uint8_t c, OUTPARM font_mode_t *mode) {
return c; // Apple //e (0x40-0x5F) -> ASCII (0x40-0x5F) return c; // Apple //e (0x40-0x5F) -> ASCII (0x40-0x5F)
} }
} else if (c < 0x80) { } else if (c < 0x80) {
if (/*altchar on:*/(softswitches & SS_ALTCHAR)) { if (/*altchar on:*/(run_args.softswitches & SS_ALTCHAR)) {
*mode = FONT_MODE_INVERSE; *mode = FONT_MODE_INVERSE;
return c; // Apple //e (0x60-0x7F) -> ASCII (0x60-0x7F) return c; // Apple //e (0x60-0x7F) -> ASCII (0x60-0x7F)
} else { } else {
@ -238,10 +238,10 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
switch (keymap[ scancode ]) switch (keymap[ scancode ])
{ {
case JB0: case JB0:
joy_button0 = 0xff; /* open apple */ run_args.joy_button0 = 0xff; /* open apple */
break; break;
case JB1: case JB1:
joy_button1 = 0xff; /* closed apple */ run_args.joy_button1 = 0xff; /* closed apple */
break; break;
default: default:
next_key = keymap[scancode]; next_key = keymap[scancode];
@ -254,10 +254,10 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
switch (keymap[ scancode ]) switch (keymap[ scancode ])
{ {
case JB0: case JB0:
joy_button0 = 0x00; run_args.joy_button0 = 0x00;
break; break;
case JB1: case JB1:
joy_button1 = 0x00; run_args.joy_button1 = 0x00;
break; break;
default: default:
break; break;

View File

@ -1491,7 +1491,7 @@ YY_RULE_SETUP
++debugtext; ++debugtext;
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
dump_mem(cpu65_pc, arg1, 0, do_ascii, -1); dump_mem(run_args.cpu65_pc, arg1, 0, do_ascii, -1);
return MEM; return MEM;
} }
YY_BREAK YY_BREAK
@ -1505,7 +1505,7 @@ YY_RULE_SETUP
if (tolower(debugtext[0]) == 'a') if (tolower(debugtext[0]) == 'a')
do_ascii = 1; do_ascii = 1;
dump_mem(cpu65_pc, 256, 0, do_ascii, -1); dump_mem(run_args.cpu65_pc, 256, 0, do_ascii, -1);
return MEM; return MEM;
} }
YY_BREAK YY_BREAK
@ -1646,7 +1646,7 @@ YY_RULE_SETUP
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
arg2 = 256; arg2 = 256;
if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_pc; if ((arg1 < 0) || (arg1 > 65535)) arg1 = run_args.cpu65_pc;
disasm(arg1, arg2, 0, -1); disasm(arg1, arg2, 0, -1);
return DIS; return DIS;
@ -1665,7 +1665,7 @@ YY_RULE_SETUP
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
arg2 = 256; arg2 = 256;
if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_pc; if ((arg1 < 0) || (arg1 > 65535)) arg1 = run_args.cpu65_pc;
disasm(arg1, arg2, 0, arg3); disasm(arg1, arg2, 0, arg3);
return DIS; return DIS;
@ -1681,7 +1681,7 @@ YY_RULE_SETUP
++debugtext; ++debugtext;
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
disasm(cpu65_pc, arg1, 0, -1); disasm(run_args.cpu65_pc, arg1, 0, -1);
return DIS; return DIS;
} }
YY_BREAK YY_BREAK
@ -1691,7 +1691,7 @@ YY_RULE_SETUP
#line 331 "src/meta/debug.l" #line 331 "src/meta/debug.l"
{ {
/* disassemble current location */ /* disassemble current location */
disasm(cpu65_pc, 256, 0, -1); disasm(run_args.cpu65_pc, 256, 0, -1);
return DIS; return DIS;
} }
YY_BREAK YY_BREAK
@ -1959,7 +1959,7 @@ YY_RULE_SETUP
stepping_struct_t s = { stepping_struct_t s = {
.step_type = UNTILING, .step_type = UNTILING,
.step_pc = cpu65_pc + delta .step_pc = run_args.cpu65_pc + delta
}; };
debugger_go(s); debugger_go(s);
@ -1975,7 +1975,7 @@ YY_RULE_SETUP
while (!isspace(*debugtext)) ++debugtext; while (!isspace(*debugtext)) ++debugtext;
/* DANGEROUS! */ /* DANGEROUS! */
cpu65_pc = (int)strtol(debugtext, (char**)NULL, 16); run_args.cpu65_pc = (int)strtol(debugtext, (char**)NULL, 16);
stepping_struct_t s = { stepping_struct_t s = {
.step_type = GOING .step_type = GOING
@ -2004,7 +2004,7 @@ YY_RULE_SETUP
#line 584 "src/meta/debug.l" #line 584 "src/meta/debug.l"
{ {
/* set watchpoint */ /* set watchpoint */
set_halt(watchpoints, cpu65_pc); set_halt(watchpoints, run_args.cpu65_pc);
return WATCH; return WATCH;
} }
YY_BREAK YY_BREAK
@ -2032,7 +2032,7 @@ YY_RULE_SETUP
#line 605 "src/meta/debug.l" #line 605 "src/meta/debug.l"
{ {
/* set breakpoint */ /* set breakpoint */
set_halt(breakpoints, cpu65_pc); set_halt(breakpoints, run_args.cpu65_pc);
return BREAK; return BREAK;
} }
YY_BREAK YY_BREAK

View File

@ -174,7 +174,7 @@ ADDRS [0-9a-fA-F]+
++debugtext; ++debugtext;
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
dump_mem(cpu65_pc, arg1, 0, do_ascii, -1); dump_mem(run_args.cpu65_pc, arg1, 0, do_ascii, -1);
return MEM; return MEM;
} }
@ -184,7 +184,7 @@ ADDRS [0-9a-fA-F]+
if (tolower(debugtext[0]) == 'a') if (tolower(debugtext[0]) == 'a')
do_ascii = 1; do_ascii = 1;
dump_mem(cpu65_pc, 256, 0, do_ascii, -1); dump_mem(run_args.cpu65_pc, 256, 0, do_ascii, -1);
return MEM; return MEM;
} }
@ -297,7 +297,7 @@ ADDRS [0-9a-fA-F]+
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
arg2 = 256; arg2 = 256;
if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_pc; if ((arg1 < 0) || (arg1 > 65535)) arg1 = run_args.cpu65_pc;
disasm(arg1, arg2, 0, -1); disasm(arg1, arg2, 0, -1);
return DIS; return DIS;
@ -312,7 +312,7 @@ ADDRS [0-9a-fA-F]+
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
arg2 = 256; arg2 = 256;
if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_pc; if ((arg1 < 0) || (arg1 > 65535)) arg1 = run_args.cpu65_pc;
disasm(arg1, arg2, 0, arg3); disasm(arg1, arg2, 0, arg3);
return DIS; return DIS;
@ -324,13 +324,13 @@ ADDRS [0-9a-fA-F]+
++debugtext; ++debugtext;
arg1 = (int)strtol(debugtext, &debugtext, 16); arg1 = (int)strtol(debugtext, &debugtext, 16);
disasm(cpu65_pc, arg1, 0, -1); disasm(run_args.cpu65_pc, arg1, 0, -1);
return DIS; return DIS;
} }
{BOS}di?s?{EOS} { {BOS}di?s?{EOS} {
/* disassemble current location */ /* disassemble current location */
disasm(cpu65_pc, 256, 0, -1); disasm(run_args.cpu65_pc, 256, 0, -1);
return DIS; return DIS;
} }
@ -550,7 +550,7 @@ ADDRS [0-9a-fA-F]+
stepping_struct_t s = { stepping_struct_t s = {
.step_type = UNTILING, .step_type = UNTILING,
.step_pc = cpu65_pc + delta .step_pc = run_args.cpu65_pc + delta
}; };
debugger_go(s); debugger_go(s);
@ -562,7 +562,7 @@ ADDRS [0-9a-fA-F]+
while (!isspace(*debugtext)) ++debugtext; while (!isspace(*debugtext)) ++debugtext;
/* DANGEROUS! */ /* DANGEROUS! */
cpu65_pc = (int)strtol(debugtext, (char**)NULL, 16); run_args.cpu65_pc = (int)strtol(debugtext, (char**)NULL, 16);
stepping_struct_t s = { stepping_struct_t s = {
.step_type = GOING .step_type = GOING
@ -583,7 +583,7 @@ ADDRS [0-9a-fA-F]+
{BOS}wa?t?c?h?{EOS} { {BOS}wa?t?c?h?{EOS} {
/* set watchpoint */ /* set watchpoint */
set_halt(watchpoints, cpu65_pc); set_halt(watchpoints, run_args.cpu65_pc);
return WATCH; return WATCH;
} }
@ -604,7 +604,7 @@ ADDRS [0-9a-fA-F]+
{BOS}br?e?a?k?{EOS} { {BOS}br?e?a?k?{EOS} {
/* set breakpoint */ /* set breakpoint */
set_halt(breakpoints, cpu65_pc); set_halt(breakpoints, run_args.cpu65_pc);
return BREAK; return BREAK;
} }

View File

@ -126,7 +126,7 @@ int c_get_current_rambank(int addrs) {
/* if SLOTCXROM, then internal rom (regardless of /* if SLOTCXROM, then internal rom (regardless of
SLOTC3ROM setting). */ SLOTC3ROM setting). */
if (softswitches & SS_CXROM) if (run_args.softswitches & SS_CXROM)
{ {
return 1; return 1;
} }
@ -134,7 +134,7 @@ int c_get_current_rambank(int addrs) {
/* slot 3 rom */ /* slot 3 rom */
if ((addrs >= 0xC300) && (addrs < 0xC400)) if ((addrs >= 0xC300) && (addrs < 0xC400))
{ {
return !!(softswitches & SS_C3ROM); return !!(run_args.softswitches & SS_C3ROM);
} }
return 0; /* peripheral rom */ return 0; /* peripheral rom */
@ -143,28 +143,28 @@ int c_get_current_rambank(int addrs) {
/* text page 1 */ /* text page 1 */
if ((addrs >= 0x400) && (addrs < 0x800)) if ((addrs >= 0x400) && (addrs < 0x800))
{ {
return !!(softswitches & SS_TEXTRD); return !!(run_args.softswitches & SS_TEXTRD);
} }
/* hires page 1 with 80STORE and HIRES on */ /* hires page 1 with 80STORE and HIRES on */
if ((addrs >= 0x2000) && (addrs < 0x4000)) if ((addrs >= 0x2000) && (addrs < 0x4000))
{ {
return !!(softswitches & SS_HGRRD); return !!(run_args.softswitches & SS_HGRRD);
} }
/* otherwise return RAMRD flag */ /* otherwise return RAMRD flag */
return !!(softswitches & SS_RAMRD); return !!(run_args.softswitches & SS_RAMRD);
} }
/* executing in ALTZP space. */ /* executing in ALTZP space. */
return !!(softswitches & SS_ALTZP); return !!(run_args.softswitches & SS_ALTZP);
} }
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
get_last_opcode () - returns the last executed opcode get_last_opcode () - returns the last executed opcode
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
uint8_t get_last_opcode() { uint8_t get_last_opcode() {
return cpu65_opcode; return run_args.cpu65_opcode;
} }
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
@ -172,41 +172,41 @@ uint8_t get_last_opcode() {
the PC is currently reading from. the PC is currently reading from.
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
uint8_t get_current_opcode() { uint8_t get_current_opcode() {
int bank = c_get_current_rambank(cpu65_pc); int bank = c_get_current_rambank(run_args.cpu65_pc);
int lcbank = 0; int lcbank = 0;
/* main RAM */ /* main RAM */
if (cpu65_pc < 0xD000) if (run_args.cpu65_pc < 0xD000)
{ {
return apple_ii_64k[bank][cpu65_pc]; return apple_ii_64k[bank][run_args.cpu65_pc];
} }
/* LC RAM */ /* LC RAM */
if (cpu65_pc >= 0xE000) if (run_args.cpu65_pc >= 0xE000)
{ {
if (softswitches & SS_LCRAM) if (run_args.softswitches & SS_LCRAM)
{ {
return language_card[bank][cpu65_pc-0xE000]; return language_card[bank][run_args.cpu65_pc-0xE000];
} }
else else
{ {
return apple_ii_64k[bank][cpu65_pc]; return apple_ii_64k[bank][run_args.cpu65_pc];
} }
} }
/* LC BANK RAM */ /* LC BANK RAM */
if (softswitches & SS_BANK2) if (run_args.softswitches & SS_BANK2)
{ {
lcbank = 0x1000; lcbank = 0x1000;
} }
if (softswitches & SS_LCRAM) if (run_args.softswitches & SS_LCRAM)
{ {
return language_banks[bank][cpu65_pc-0xD000+lcbank]; return language_banks[bank][run_args.cpu65_pc-0xD000+lcbank];
} }
else else
{ {
return apple_ii_64k[bank][cpu65_pc]; return apple_ii_64k[bank][run_args.cpu65_pc];
} }
} }
@ -226,15 +226,15 @@ void dump_mem(int addrs, int len, int lc, int do_ascii, int rambank) {
rambank = c_get_current_rambank(addrs); rambank = c_get_current_rambank(addrs);
} }
if (!lc && (softswitches & SS_LCRAM) && (addrs >= 0xd000)) if (!lc && (run_args.softswitches & SS_LCRAM) && (addrs >= 0xd000))
{ {
/* read lc anyway */ /* read lc anyway */
lc = 1 + !!(softswitches & SS_BANK2); lc = 1 + !!(run_args.softswitches & SS_BANK2);
} }
if ((addrs < 0) || (addrs > 0xffff)) if ((addrs < 0) || (addrs > 0xffff))
{ {
addrs = cpu65_pc; addrs = run_args.cpu65_pc;
orig_addrs = addrs; orig_addrs = addrs;
} }
@ -334,7 +334,7 @@ void search_mem(char *hexstr, int lc, int rambank) {
/* check which rambank for cpu65_pc */ /* check which rambank for cpu65_pc */
if (rambank == -1) if (rambank == -1)
{ {
rambank = c_get_current_rambank(cpu65_pc); rambank = c_get_current_rambank(run_args.cpu65_pc);
} }
/* iterate over memory */ /* iterate over memory */
@ -531,16 +531,16 @@ void disasm(int addrs, int len, int lc, int rambank) {
rambank = c_get_current_rambank(addrs); rambank = c_get_current_rambank(addrs);
} }
if (!lc && (softswitches & SS_LCRAM) && (addrs >= 0xd000)) if (!lc && (run_args.softswitches & SS_LCRAM) && (addrs >= 0xd000))
{ {
/* read lc anyway */ /* read lc anyway */
lc = 1 + !!(softswitches & SS_BANK2); lc = 1 + !!(run_args.softswitches & SS_BANK2);
} }
/* handle invalid address request */ /* handle invalid address request */
if ((addrs < 0) || (addrs > 0xffff)) if ((addrs < 0) || (addrs > 0xffff))
{ {
addrs = cpu65_pc; addrs = run_args.cpu65_pc;
orig_addrs = addrs; orig_addrs = addrs;
} }
@ -682,46 +682,46 @@ void disasm(int addrs, int len, int lc, int rambank) {
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void show_regs() { void show_regs() {
sprintf(second_buf[num_buffer_lines++], "PC = %04X EA = %04X SP = %04X", cpu65_pc, cpu65_ea, cpu65_sp + 0x0100); sprintf(second_buf[num_buffer_lines++], "PC = %04X EA = %04X SP = %04X", run_args.cpu65_pc, run_args.cpu65_ea, run_args.cpu65_sp + 0x0100);
sprintf(second_buf[num_buffer_lines++], "X = %02X Y = %02X A = %02X F = %02X", cpu65_x, cpu65_y, cpu65_a, cpu65_f); sprintf(second_buf[num_buffer_lines++], "X = %02X Y = %02X A = %02X F = %02X", run_args.cpu65_x, run_args.cpu65_y, run_args.cpu65_a, run_args.cpu65_f);
memset(second_buf[num_buffer_lines], ' ', BUF_X); memset(second_buf[num_buffer_lines], ' ', BUF_X);
if (cpu65_f & C_Flag_6502) if (run_args.cpu65_f & C_Flag_6502)
{ {
second_buf[num_buffer_lines][0]='C'; second_buf[num_buffer_lines][0]='C';
} }
if (cpu65_f & X_Flag_6502) if (run_args.cpu65_f & X_Flag_6502)
{ {
second_buf[num_buffer_lines][1]='X'; second_buf[num_buffer_lines][1]='X';
} }
if (cpu65_f & I_Flag_6502) if (run_args.cpu65_f & I_Flag_6502)
{ {
second_buf[num_buffer_lines][2]='I'; second_buf[num_buffer_lines][2]='I';
} }
if (cpu65_f & V_Flag_6502) if (run_args.cpu65_f & V_Flag_6502)
{ {
second_buf[num_buffer_lines][3]='V'; second_buf[num_buffer_lines][3]='V';
} }
if (cpu65_f & B_Flag_6502) if (run_args.cpu65_f & B_Flag_6502)
{ {
second_buf[num_buffer_lines][4]='B'; second_buf[num_buffer_lines][4]='B';
} }
if (cpu65_f & D_Flag_6502) if (run_args.cpu65_f & D_Flag_6502)
{ {
second_buf[num_buffer_lines][5]='D'; second_buf[num_buffer_lines][5]='D';
} }
if (cpu65_f & Z_Flag_6502) if (run_args.cpu65_f & Z_Flag_6502)
{ {
second_buf[num_buffer_lines][6]='Z'; second_buf[num_buffer_lines][6]='Z';
} }
if (cpu65_f & N_Flag_6502) if (run_args.cpu65_f & N_Flag_6502)
{ {
second_buf[num_buffer_lines][7]='N'; second_buf[num_buffer_lines][7]='N';
} }
@ -744,23 +744,23 @@ static int will_branch() {
switch (op) switch (op)
{ {
case 0x10: /* BPL */ case 0x10: /* BPL */
return (int) !(cpu65_f & N_Flag_6502); return (int) !(run_args.cpu65_f & N_Flag_6502);
case 0x30: /* BMI */ case 0x30: /* BMI */
return (int) (cpu65_f & N_Flag_6502); return (int) (run_args.cpu65_f & N_Flag_6502);
case 0x50: /* BVC */ case 0x50: /* BVC */
return (int) !(cpu65_f & V_Flag_6502); return (int) !(run_args.cpu65_f & V_Flag_6502);
case 0x70: /* BVS */ case 0x70: /* BVS */
return (int) (cpu65_f & V_Flag_6502); return (int) (run_args.cpu65_f & V_Flag_6502);
case 0x80: /* BRA */ case 0x80: /* BRA */
return 1; return 1;
case 0x90: /* BCC */ case 0x90: /* BCC */
return (int) !(cpu65_f & C_Flag_6502); return (int) !(run_args.cpu65_f & C_Flag_6502);
case 0xb0: /* BCS */ case 0xb0: /* BCS */
return (int) (cpu65_f & C_Flag_6502); return (int) (run_args.cpu65_f & C_Flag_6502);
case 0xd0: /* BNE */ case 0xd0: /* BNE */
return (int) !(cpu65_f & Z_Flag_6502); return (int) !(run_args.cpu65_f & Z_Flag_6502);
case 0xf0: /* BEQ */ case 0xf0: /* BEQ */
return (int) (cpu65_f & Z_Flag_6502); return (int) (run_args.cpu65_f & Z_Flag_6502);
} }
return BRANCH_NA; return BRANCH_NA;
@ -877,28 +877,28 @@ int at_haltpt() {
uint8_t op = get_last_opcode(); uint8_t op = get_last_opcode();
if (op_breakpoints[op]) if (op_breakpoints[op])
{ {
sprintf(second_buf[num_buffer_lines++], "stopped at %04X bank %d instruction %02X", cpu65_pc, c_get_current_rambank(cpu65_pc), op); sprintf(second_buf[num_buffer_lines++], "stopped at %04X bank %d instruction %02X", run_args.cpu65_pc, c_get_current_rambank(run_args.cpu65_pc), op);
++count; ++count;
} }
for (int i = 0; i < MAX_BRKPTS; i++) for (int i = 0; i < MAX_BRKPTS; i++)
{ {
if (cpu65_pc == breakpoints[i]) if (run_args.cpu65_pc == breakpoints[i])
{ {
sprintf(second_buf[num_buffer_lines++], "stopped at %04X bank %d", breakpoints[i], c_get_current_rambank(cpu65_pc)); sprintf(second_buf[num_buffer_lines++], "stopped at %04X bank %d", breakpoints[i], c_get_current_rambank(run_args.cpu65_pc));
++count; ++count;
} }
} }
if (cpu65_rw) /* only check watchpoints if read/write occured */ if (run_args.cpu65_rw) /* only check watchpoints if read/write occured */
{ {
for (int i = 0; i < MAX_BRKPTS; i++) for (int i = 0; i < MAX_BRKPTS; i++)
{ {
if (cpu65_ea == watchpoints[i]) if (run_args.cpu65_ea == watchpoints[i])
{ {
if (cpu65_rw & 0x2) if (run_args.cpu65_rw & 0x2)
{ {
sprintf(second_buf[num_buffer_lines++], "wrote: %04X: %02X", watchpoints[i], cpu65_d); sprintf(second_buf[num_buffer_lines++], "wrote: %04X: %02X", watchpoints[i], run_args.cpu65_d);
++count; ++count;
} }
else else
@ -907,7 +907,7 @@ int at_haltpt() {
++count; ++count;
} }
cpu65_rw = 0; /* only allow WP to trip once */ run_args.cpu65_rw = 0; /* only allow WP to trip once */
} }
} }
} }
@ -981,29 +981,29 @@ void show_opcode_breakpts() {
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void show_lc_info() { void show_lc_info() {
int i = num_buffer_lines; int i = num_buffer_lines;
sprintf(second_buf[i++], "lc bank = %d", 1 + !!(softswitches & SS_BANK2)); sprintf(second_buf[i++], "lc bank = %d", 1 + !!(run_args.softswitches & SS_BANK2));
(softswitches & SS_LCWRT) ? sprintf(second_buf[i++], "write LC") : sprintf(second_buf[i++], "LC write protected"); (run_args.softswitches & SS_LCWRT) ? sprintf(second_buf[i++], "write LC") : sprintf(second_buf[i++], "LC write protected");
(softswitches & SS_LCRAM) ? sprintf(second_buf[i++], "read LC") : sprintf(second_buf[i++], "read ROM"); (run_args.softswitches & SS_LCRAM) ? sprintf(second_buf[i++], "read LC") : sprintf(second_buf[i++], "read ROM");
sprintf(second_buf[i++], "second = %d", !!(softswitches & SS_LCSEC)); sprintf(second_buf[i++], "second = %d", !!(run_args.softswitches & SS_LCSEC));
num_buffer_lines = i; num_buffer_lines = i;
} }
void show_misc_info() { void show_misc_info() {
int i = num_buffer_lines; int i = num_buffer_lines;
sprintf(second_buf[i++], "TEXT (%04X): %s", SW_TEXT + !!(softswitches & SS_TEXT), (softswitches & SS_TEXT) ? "on" : "off"); sprintf(second_buf[i++], "TEXT (%04X): %s", SW_TEXT + !!(run_args.softswitches & SS_TEXT), (run_args.softswitches & SS_TEXT) ? "on" : "off");
sprintf(second_buf[i++], "MIXED (%04X): %s", SW_MIXED + !!(softswitches & SS_MIXED), (softswitches & SS_MIXED) ? "on" : "off"); sprintf(second_buf[i++], "MIXED (%04X): %s", SW_MIXED + !!(run_args.softswitches & SS_MIXED), (run_args.softswitches & SS_MIXED) ? "on" : "off");
sprintf(second_buf[i++], "PAGE2 (%04X): %s", SW_PAGE2 + !!(softswitches & SS_PAGE2), (softswitches & SS_PAGE2) ? "on" : "off"); sprintf(second_buf[i++], "PAGE2 (%04X): %s", SW_PAGE2 + !!(run_args.softswitches & SS_PAGE2), (run_args.softswitches & SS_PAGE2) ? "on" : "off");
sprintf(second_buf[i++], "HIRES (%04X): %s", SW_HIRES + !!(softswitches & SS_HIRES), (softswitches & SS_HIRES) ? "on" : "off"); sprintf(second_buf[i++], "HIRES (%04X): %s", SW_HIRES + !!(run_args.softswitches & SS_HIRES), (run_args.softswitches & SS_HIRES) ? "on" : "off");
sprintf(second_buf[i++], "80STORE (%04X): %s", SW_80STORE + !!(softswitches & SS_80STORE), (softswitches & SS_80STORE) ? "on" : "off"); sprintf(second_buf[i++], "80STORE (%04X): %s", SW_80STORE + !!(run_args.softswitches & SS_80STORE), (run_args.softswitches & SS_80STORE) ? "on" : "off");
sprintf(second_buf[i++], "RAMRD (%04X): %s", SW_RAMRD + !!(softswitches & SS_RAMRD), (softswitches & SS_RAMRD) ? "on" : "off"); sprintf(second_buf[i++], "RAMRD (%04X): %s", SW_RAMRD + !!(run_args.softswitches & SS_RAMRD), (run_args.softswitches & SS_RAMRD) ? "on" : "off");
sprintf(second_buf[i++], "RAMWRT (%04X): %s", SW_RAMWRT + !!(softswitches & SS_RAMWRT), (softswitches & SS_RAMWRT) ? "on" : "off"); sprintf(second_buf[i++], "RAMWRT (%04X): %s", SW_RAMWRT + !!(run_args.softswitches & SS_RAMWRT), (run_args.softswitches & SS_RAMWRT) ? "on" : "off");
sprintf(second_buf[i++], "ALTZP (%04X): %s", SW_ALTZP + !!(softswitches & SS_ALTZP), (softswitches & SS_ALTZP) ? "on" : "off"); sprintf(second_buf[i++], "ALTZP (%04X): %s", SW_ALTZP + !!(run_args.softswitches & SS_ALTZP), (run_args.softswitches & SS_ALTZP) ? "on" : "off");
sprintf(second_buf[i++], "80COL (%04X): %s", SW_80COL + !!(softswitches & SS_80COL), (softswitches & SS_80COL) ? "on" : "off"); sprintf(second_buf[i++], "80COL (%04X): %s", SW_80COL + !!(run_args.softswitches & SS_80COL), (run_args.softswitches & SS_80COL) ? "on" : "off");
sprintf(second_buf[i++], "ALTCHAR (%04X): %s", SW_ALTCHAR + !!(softswitches & SS_ALTCHAR), (softswitches & SS_ALTCHAR) ? "on" : "off"); sprintf(second_buf[i++], "ALTCHAR (%04X): %s", SW_ALTCHAR + !!(run_args.softswitches & SS_ALTCHAR), (run_args.softswitches & SS_ALTCHAR) ? "on" : "off");
sprintf(second_buf[i++], "SLOTC3ROM (%04X): %s", SW_SLOTC3ROM -/*anomaly*/ !!(softswitches & SS_C3ROM), (softswitches & SS_C3ROM) ? "on" : "off"); sprintf(second_buf[i++], "SLOTC3ROM (%04X): %s", SW_SLOTC3ROM -/*anomaly*/ !!(run_args.softswitches & SS_C3ROM), (run_args.softswitches & SS_C3ROM) ? "on" : "off");
sprintf(second_buf[i++], "SLOTCXROM (%04X): %s", SW_SLOTCXROM + !!(softswitches & SS_CXROM), (softswitches & SS_CXROM) ? "on" : "off"); sprintf(second_buf[i++], "SLOTCXROM (%04X): %s", SW_SLOTCXROM + !!(run_args.softswitches & SS_CXROM), (run_args.softswitches & SS_CXROM) ? "on" : "off");
sprintf(second_buf[i++], "DHIRES (%04X): %s", SW_DHIRES + !!(softswitches & SS_DHIRES), (softswitches & SS_DHIRES) ? "on" : "off"); sprintf(second_buf[i++], "DHIRES (%04X): %s", SW_DHIRES + !!(run_args.softswitches & SS_DHIRES), (run_args.softswitches & SS_DHIRES) ? "on" : "off");
sprintf(second_buf[i++], "IOUDIS (%04X): %s", SW_IOUDIS + !!(softswitches & SS_IOUDIS), (softswitches & SS_IOUDIS) ? "on" : "off"); sprintf(second_buf[i++], "IOUDIS (%04X): %s", SW_IOUDIS + !!(run_args.softswitches & SS_IOUDIS), (run_args.softswitches & SS_IOUDIS) ? "on" : "off");
/* sprintf(second_buf[i++], "RDVBLBAR: %s", (SLOTCXROM & 0x80) */ /* sprintf(second_buf[i++], "RDVBLBAR: %s", (SLOTCXROM & 0x80) */
/* ? "on" : "off"); */ /* ? "on" : "off"); */
@ -1228,7 +1228,7 @@ bool c_debugger_should_break() {
case UNTILING: case UNTILING:
{ {
if (stepping_struct.step_pc == cpu65_pc) { if (stepping_struct.step_pc == run_args.cpu65_pc) {
stepping_struct.should_break = true; stepping_struct.should_break = true;
} }
} }
@ -1275,7 +1275,7 @@ int debugger_go(stepping_struct_t s) {
#if !TESTING #if !TESTING
if (stepping_struct.step_type != LOADING) { if (stepping_struct.step_type != LOADING) {
clear_debugger_screen(); clear_debugger_screen();
disasm(cpu65_pc, 1, 0, -1); disasm(run_args.cpu65_pc, 1, 0, -1);
int branch = will_branch(); int branch = will_branch();
if (branch != BRANCH_NA) { if (branch != BRANCH_NA) {
sprintf(second_buf[num_buffer_lines++], "%s", (branch) ? "will branch" : "will not branch"); sprintf(second_buf[num_buffer_lines++], "%s", (branch) ? "will branch" : "will not branch");

View File

@ -87,7 +87,7 @@ static inline int BOOT_TO_DOS(void) {
static inline void REBOOT_TO_DOS(void) { static inline void REBOOT_TO_DOS(void) {
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00; apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
apple_ii_64k[0][TESTOUT_ADDR] = 0x00; apple_ii_64k[0][TESTOUT_ADDR] = 0x00;
joy_button0 = 0xff; run_args.joy_button0 = 0xff;
cpu65_interrupt(ResetSig); cpu65_interrupt(ResetSig);
} }

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ static void testdisk_setup(void *arg) {
apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00; apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00;
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00; apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
apple_ii_64k[0][TESTOUT_ADDR] = 0x00; apple_ii_64k[0][TESTOUT_ADDR] = 0x00;
joy_button0 = 0xff; // OpenApple run_args.joy_button0 = 0xff; // OpenApple
test_setup_boot_disk(TESTING_DISK, 1); test_setup_boot_disk(TESTING_DISK, 1);
if (test_do_reboot) { if (test_do_reboot) {
cpu65_interrupt(ResetSig); cpu65_interrupt(ResetSig);

View File

@ -19,7 +19,7 @@ static void testdisplay_setup(void *arg) {
test_common_setup(); test_common_setup();
apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00; apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00;
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00; apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
joy_button0 = 0xff; // OpenApple run_args.joy_button0 = 0xff; // OpenApple
if (test_do_reboot) { if (test_do_reboot) {
cpu65_interrupt(ResetSig); cpu65_interrupt(ResetSig);
} }

View File

@ -23,7 +23,7 @@ static void testui_setup(void *arg) {
apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00; apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00;
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00; apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
if (test_do_reboot) { if (test_do_reboot) {
joy_button0 = 0xff; // OpenApple run_args.joy_button0 = 0xff; // OpenApple
cpu65_interrupt(ResetSig); cpu65_interrupt(ResetSig);
} }
} }
@ -69,32 +69,32 @@ static int _assert_blank_boot(void) {
ASSERT(disk6.disk[0].skew_table == skew_table_6_do); ASSERT(disk6.disk[0].skew_table == skew_table_6_do);
// VM ... // VM ...
ASSERT(softswitches == 0x000140d1); ASSERT(run_args.softswitches == 0x000140d1);
ASSERT_SHA_BIN("97AADDDF5D20B793C4558A8928227F0B52565A98", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k)); ASSERT_SHA_BIN("97AADDDF5D20B793C4558A8928227F0B52565A98", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k));
ASSERT_SHA_BIN("2C82E33E964936187CA1DABF71AE6148916BD131", language_card[0], /*len:*/sizeof(language_card)); ASSERT_SHA_BIN("2C82E33E964936187CA1DABF71AE6148916BD131", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks)); ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]); ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]); ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]); ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]); ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]); ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]); ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]); ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]); ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card); ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == apple_ii_64k[0]); ASSERT(run_args.base_d000_rd == apple_ii_64k[0]);
ASSERT(base_d000_wrt == language_banks[0] - 0xD000); ASSERT(run_args.base_d000_wrt == language_banks[0] - 0xD000);
ASSERT(base_e000_rd == apple_ii_64k[0]); ASSERT(run_args.base_e000_rd == apple_ii_64k[0]);
ASSERT(base_e000_wrt == language_card[0] - 0xE000); ASSERT(run_args.base_e000_wrt == language_card[0] - 0xE000);
// CPU ... // CPU ...
ASSERT(cpu65_pc == 0xE783); ASSERT(run_args.cpu65_pc == 0xE783);
ASSERT(cpu65_ea == 0x1F33); ASSERT(run_args.cpu65_ea == 0x1F33);
ASSERT(cpu65_a == 0xFF); ASSERT(run_args.cpu65_a == 0xFF);
ASSERT(cpu65_f == 0x37); ASSERT(run_args.cpu65_f == 0x37);
ASSERT(cpu65_x == 0xFF); ASSERT(run_args.cpu65_x == 0xFF);
ASSERT(cpu65_y == 0x00); ASSERT(run_args.cpu65_y == 0x00);
ASSERT(cpu65_sp == 0xF6); ASSERT(run_args.cpu65_sp == 0xF6);
PASS(); PASS();
} }
@ -126,6 +126,8 @@ static int _get_fds(JSON_ref jsonData, int *fdA, int *fdB) {
TEMP_FAILURE_RETRY(*fdB = open(pathB, readOnlyB ? O_RDONLY : O_RDWR)); TEMP_FAILURE_RETRY(*fdB = open(pathB, readOnlyB ? O_RDONLY : O_RDWR));
FREE(pathB); FREE(pathB);
} }
return 0;
} }
TEST test_save_state_1() { TEST test_save_state_1() {
@ -275,32 +277,32 @@ TEST test_load_A2VM_good1() {
//ASSERT(disk6.disk[0].skew_table == skew_table_6_do); //ASSERT(disk6.disk[0].skew_table == skew_table_6_do);
// VM ... // VM ...
ASSERT(softswitches == 0x000343d1); ASSERT(run_args.softswitches == 0x000343d1);
ASSERT_SHA_BIN("2E3C6163EEAA817B02B00766B9E118D3197D16AF", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k)); ASSERT_SHA_BIN("2E3C6163EEAA817B02B00766B9E118D3197D16AF", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k));
ASSERT_SHA_BIN("2C82E33E964936187CA1DABF71AE6148916BD131", language_card[0], /*len:*/sizeof(language_card)); ASSERT_SHA_BIN("2C82E33E964936187CA1DABF71AE6148916BD131", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks)); ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]); ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]); ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]); ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]); ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]); ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]); ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]); ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]); ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card); ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == apple_ii_64k[0]); ASSERT(run_args.base_d000_rd == apple_ii_64k[0]);
ASSERT(base_d000_wrt == language_banks[0] - 0xD000); ASSERT(run_args.base_d000_wrt == language_banks[0] - 0xD000);
ASSERT(base_e000_rd == apple_ii_64k[0]); ASSERT(run_args.base_e000_rd == apple_ii_64k[0]);
ASSERT(base_e000_wrt == language_card[0] - 0xE000); ASSERT(run_args.base_e000_wrt == language_card[0] - 0xE000);
// CPU ... // CPU ...
ASSERT(cpu65_pc == 0xC83D); ASSERT(run_args.cpu65_pc == 0xC83D);
ASSERT(cpu65_ea == 0x004E); ASSERT(run_args.cpu65_ea == 0x004E);
ASSERT(cpu65_a == 0x0D); ASSERT(run_args.cpu65_a == 0x0D);
ASSERT(cpu65_f == 0x35); ASSERT(run_args.cpu65_f == 0x35);
ASSERT(cpu65_x == 0x09); ASSERT(run_args.cpu65_x == 0x09);
ASSERT(cpu65_y == 0x01); ASSERT(run_args.cpu65_y == 0x01);
ASSERT(cpu65_sp == 0xEA); ASSERT(run_args.cpu65_sp == 0xEA);
TEMP_FAILURE_RETRY(close(fdState)); TEMP_FAILURE_RETRY(close(fdState));
TEMP_FAILURE_RETRY(close(fdA)); TEMP_FAILURE_RETRY(close(fdA));
@ -389,32 +391,32 @@ TEST test_load_A2V2_good1() {
//ASSERT(disk6.disk[0].skew_table == skew_table_6_do); //ASSERT(disk6.disk[0].skew_table == skew_table_6_do);
// VM ... // VM ...
ASSERT(softswitches == 0x000140f5); ASSERT(run_args.softswitches == 0x000140f5);
ASSERT_SHA_BIN("3B41CCC86A7FCE2A95F1D7A5C4BF7E2AC7A11323", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k)); ASSERT_SHA_BIN("3B41CCC86A7FCE2A95F1D7A5C4BF7E2AC7A11323", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k));
ASSERT_SHA_BIN("54C8611AA3FD1813B1BEE45EF7F4B2303C51C679", language_card[0], /*len:*/sizeof(language_card)); ASSERT_SHA_BIN("54C8611AA3FD1813B1BEE45EF7F4B2303C51C679", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks)); ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]); ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]); ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]); ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]); ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]); ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]); ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]); ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]); ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card); ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == language_banks[0]-0xD000); ASSERT(run_args.base_d000_rd == language_banks[0]-0xD000);
ASSERT(base_d000_wrt == language_banks[0]-0xD000); ASSERT(run_args.base_d000_wrt == language_banks[0]-0xD000);
ASSERT(base_e000_rd == language_card[0]-0xE000); ASSERT(run_args.base_e000_rd == language_card[0]-0xE000);
ASSERT(base_e000_wrt == language_card[0]-0xE000); ASSERT(run_args.base_e000_wrt == language_card[0]-0xE000);
// CPU ... // CPU ...
ASSERT(cpu65_pc == 0xF6EA); ASSERT(run_args.cpu65_pc == 0xF6EA);
ASSERT(cpu65_ea == 0x0018); ASSERT(run_args.cpu65_ea == 0x0018);
ASSERT(cpu65_a == 0x05); ASSERT(run_args.cpu65_a == 0x05);
ASSERT(cpu65_f == 0x33); ASSERT(run_args.cpu65_f == 0x33);
ASSERT(cpu65_x == 0x10); ASSERT(run_args.cpu65_x == 0x10);
ASSERT(cpu65_y == 0x02); ASSERT(run_args.cpu65_y == 0x02);
ASSERT(cpu65_sp == 0xFA); ASSERT(run_args.cpu65_sp == 0xFA);
// Timing ... // Timing ...
long scaleFactor = (long)(cpu_scale_factor * 100.); long scaleFactor = (long)(cpu_scale_factor * 100.);
@ -515,32 +517,32 @@ TEST test_load_A2V2_good2() {
//ASSERT(disk6.disk[0].skew_table == skew_table_6_do); //ASSERT(disk6.disk[0].skew_table == skew_table_6_do);
// VM ... // VM ...
ASSERT(softswitches == 0x000140f4); ASSERT(run_args.softswitches == 0x000140f4);
ASSERT_SHA_BIN("CAD59B53F04DE501A76E0C04750155C838EADAE2", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k)); ASSERT_SHA_BIN("CAD59B53F04DE501A76E0C04750155C838EADAE2", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k));
ASSERT_SHA_BIN("B3268356F9F4F4ACAE2F4FF49D4FED1D36535DDA", language_card[0], /*len:*/sizeof(language_card)); ASSERT_SHA_BIN("B3268356F9F4F4ACAE2F4FF49D4FED1D36535DDA", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("0B6E45306506F92554102485CE9B500C6779D145", language_banks[0], /*len:*/sizeof(language_banks)); ASSERT_SHA_BIN("0B6E45306506F92554102485CE9B500C6779D145", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]); ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]); ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]); ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]); ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]); ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]); ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]); ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]); ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card); ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == language_banks[0]-0xD000); ASSERT(run_args.base_d000_rd == language_banks[0]-0xD000);
ASSERT(base_d000_wrt == language_banks[0]-0xD000); ASSERT(run_args.base_d000_wrt == language_banks[0]-0xD000);
ASSERT(base_e000_rd == language_card[0]-0xE000); ASSERT(run_args.base_e000_rd == language_card[0]-0xE000);
ASSERT(base_e000_wrt == language_card[0]-0xE000); ASSERT(run_args.base_e000_wrt == language_card[0]-0xE000);
// CPU ... // CPU ...
ASSERT(cpu65_pc == 0x8474); ASSERT(run_args.cpu65_pc == 0x8474);
ASSERT(cpu65_ea == 0x8474); ASSERT(run_args.cpu65_ea == 0x8474);
ASSERT(cpu65_a == 0x00); ASSERT(run_args.cpu65_a == 0x00);
ASSERT(cpu65_f == 0x73); ASSERT(run_args.cpu65_f == 0x73);
ASSERT(cpu65_x == 0x04); ASSERT(run_args.cpu65_x == 0x04);
ASSERT(cpu65_y == 0x21); ASSERT(run_args.cpu65_y == 0x21);
ASSERT(cpu65_sp == 0xF1); ASSERT(run_args.cpu65_sp == 0xF1);
// Timing ... // Timing ...
long scaleFactor = (long)(cpu_scale_factor * 100.); long scaleFactor = (long)(cpu_scale_factor * 100.);
@ -637,32 +639,32 @@ TEST test_load_A2V2_good3() {
ASSERT(!disk6.disk[1].track_dirty); ASSERT(!disk6.disk[1].track_dirty);
// VM ... // VM ...
ASSERT(softswitches == 0x000140f4); ASSERT(run_args.softswitches == 0x000140f4);
ASSERT_SHA_BIN("16A730D3E709F096B693EA4029FC68672CE454B8", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k)); ASSERT_SHA_BIN("16A730D3E709F096B693EA4029FC68672CE454B8", apple_ii_64k[0], /*len:*/sizeof(apple_ii_64k));
ASSERT_SHA_BIN("DF3EE367193484A6A1C28C2BAE0EFEF42E6D19BB", language_card[0], /*len:*/sizeof(language_card)); ASSERT_SHA_BIN("DF3EE367193484A6A1C28C2BAE0EFEF42E6D19BB", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("343C30374074AB3AEE22581A6477736121390B18", language_banks[0], /*len:*/sizeof(language_banks)); ASSERT_SHA_BIN("343C30374074AB3AEE22581A6477736121390B18", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]); ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]); ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]); ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]); ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]); ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]); ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]); ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]); ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card); ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == language_banks[0]-0xD000); ASSERT(run_args.base_d000_rd == language_banks[0]-0xD000);
ASSERT(base_d000_wrt == language_banks[0]-0xD000); ASSERT(run_args.base_d000_wrt == language_banks[0]-0xD000);
ASSERT(base_e000_rd == language_card[0]-0xE000); ASSERT(run_args.base_e000_rd == language_card[0]-0xE000);
ASSERT(base_e000_wrt == language_card[0]-0xE000); ASSERT(run_args.base_e000_wrt == language_card[0]-0xE000);
// CPU ... // CPU ...
ASSERT(cpu65_pc == 0x0E9C); ASSERT(run_args.cpu65_pc == 0x0E9C);
ASSERT(cpu65_ea == 0x0EB9); ASSERT(run_args.cpu65_ea == 0x0EB9);
ASSERT(cpu65_a == 0x00); ASSERT(run_args.cpu65_a == 0x00);
ASSERT(cpu65_f == 0xB0); ASSERT(run_args.cpu65_f == 0xB0);
ASSERT(cpu65_x == 0x05); ASSERT(run_args.cpu65_x == 0x05);
ASSERT(cpu65_y == 0x04); ASSERT(run_args.cpu65_y == 0x04);
ASSERT(cpu65_sp == 0xE0); ASSERT(run_args.cpu65_sp == 0xE0);
// Timing ... // Timing ...
long scaleFactor = (long)(cpu_scale_factor * 100.); long scaleFactor = (long)(cpu_scale_factor * 100.);

File diff suppressed because it is too large Load Diff

View File

@ -52,9 +52,6 @@
double cycles_persec_target = CLK_6502; double cycles_persec_target = CLK_6502;
unsigned long cycles_count_total = 0; // Running at spec ~1MHz, this will approach overflow in ~4000secs (for 32bit architectures) unsigned long cycles_count_total = 0; // Running at spec ~1MHz, this will approach overflow in ~4000secs (for 32bit architectures)
int cycles_speaker_feedback = 0; int cycles_speaker_feedback = 0;
int32_t cpu65_cycles_to_execute = 0; // cycles-to-execute by cpu65_run()
int32_t cpu65_cycle_count = 0; // cycles currently excuted by cpu65_run()
int32_t irqCheckTimeout = IRQ_CHECK_CYCLES;
static int32_t cycles_checkpoint_count = 0; static int32_t cycles_checkpoint_count = 0;
static unsigned int g_dwCyclesThisFrame = 0; static unsigned int g_dwCyclesThisFrame = 0;
@ -71,7 +68,6 @@ bool is_fullspeed = false;
bool alt_speed_enabled = false; bool alt_speed_enabled = false;
// misc // misc
volatile uint8_t emul_reinitialize = 1;
static bool emul_reinitialize_audio = false; static bool emul_reinitialize_audio = false;
static bool emul_pause_audio = false; static bool emul_pause_audio = false;
static bool emul_resume_audio = false; static bool emul_resume_audio = false;
@ -149,7 +145,7 @@ void reinitialize(void) {
cycles_count_total = 0; cycles_count_total = 0;
g_dwCyclesThisFrame = 0; g_dwCyclesThisFrame = 0;
irqCheckTimeout = IRQ_CHECK_CYCLES; run_args.irq_check_timeout = IRQ_CHECK_CYCLES;
#if TESTING #if TESTING
extern unsigned long (*testing_getCyclesCount)(void); extern unsigned long (*testing_getCyclesCount)(void);
if (testing_getCyclesCount) { if (testing_getCyclesCount) {
@ -159,8 +155,6 @@ void reinitialize(void) {
vm_initialize(); vm_initialize();
softswitches = SS_TEXT | SS_IOUDIS | SS_C3ROM | SS_LCWRT | SS_LCSEC;
video_setDirty(A2_DIRTY_FLAG); video_setDirty(A2_DIRTY_FLAG);
cpu65_init(); cpu65_init();
@ -277,9 +271,10 @@ static void *cpu_thread(void *dummyptr) {
speaker_init(); speaker_init();
MB_Initialize(); MB_Initialize();
run_args.emul_reinitialize = 1;
cpu_runloop: cpu_runloop:
do do {
{
LOG("CPUTHREAD %lu LOCKING FOR MAYBE INITIALIZING AUDIO ...", (unsigned long)cpu_thread_id); LOG("CPUTHREAD %lu LOCKING FOR MAYBE INITIALIZING AUDIO ...", (unsigned long)cpu_thread_id);
pthread_mutex_lock(&interface_mutex); pthread_mutex_lock(&interface_mutex);
if (emul_reinitialize_audio) { if (emul_reinitialize_audio) {
@ -298,7 +293,7 @@ cpu_runloop:
pthread_mutex_unlock(&interface_mutex); pthread_mutex_unlock(&interface_mutex);
LOG("UNLOCKING FOR MAYBE INITIALIZING AUDIO ..."); LOG("UNLOCKING FOR MAYBE INITIALIZING AUDIO ...");
if (emul_reinitialize) { if (run_args.emul_reinitialize) {
reinitialize(); reinitialize();
} }
@ -321,8 +316,7 @@ cpu_runloop:
clock_gettime(CLOCK_MONOTONIC, &ti); clock_gettime(CLOCK_MONOTONIC, &ti);
deltat = timespec_diff(t0, ti, &negative); deltat = timespec_diff(t0, ti, &negative);
if (deltat.tv_sec) if (deltat.tv_sec) {
{
if (!is_fullspeed) { if (!is_fullspeed) {
TIMING_LOG("NOTE : serious divergence from target time ..."); TIMING_LOG("NOTE : serious divergence from target time ...");
} }
@ -333,35 +327,36 @@ cpu_runloop:
drift_adj_nsecs = negative ? ~deltat.tv_nsec : deltat.tv_nsec; drift_adj_nsecs = negative ? ~deltat.tv_nsec : deltat.tv_nsec;
// set up increment & decrement counters // set up increment & decrement counters
cpu65_cycles_to_execute = (cycles_persec_target / 1000); // cycles_persec_target * EXECUTION_PERIOD_NSECS / NANOSECONDS_PER_SECOND run_args.cpu65_cycles_to_execute = (cycles_persec_target / 1000); // cycles_persec_target * EXECUTION_PERIOD_NSECS / NANOSECONDS_PER_SECOND
if (!is_fullspeed) { if (!is_fullspeed) {
cpu65_cycles_to_execute += cycles_speaker_feedback; run_args.cpu65_cycles_to_execute += cycles_speaker_feedback;
} }
if (cpu65_cycles_to_execute < 0) if (run_args.cpu65_cycles_to_execute < 0) {
{ run_args.cpu65_cycles_to_execute = 0;
cpu65_cycles_to_execute = 0;
} }
MB_StartOfCpuExecute(); MB_StartOfCpuExecute();
if (is_debugging) { if (is_debugging) {
debugging_cycles = cpu65_cycles_to_execute; debugging_cycles = run_args.cpu65_cycles_to_execute;
} }
do { do {
if (is_debugging) { if (is_debugging) {
cpu65_cycles_to_execute = 1; run_args.cpu65_cycles_to_execute = 1;
} }
cpu65_cycle_count = 0; run_args.cpu65_cycle_count = 0;
cycles_checkpoint_count = 0; cycles_checkpoint_count = 0;
cpu65_run(); // run emulation for cpu65_cycles_to_execute cycles ...
cpu65_run(&run_args); // run emulation for cpu65_cycles_to_execute cycles ...
#if DEBUG_TIMING #if DEBUG_TIMING
dbg_cycles_executed += cpu65_cycle_count; dbg_cycles_executed += run_args.cpu65_cycle_count;
#endif #endif
g_dwCyclesThisFrame += cpu65_cycle_count; g_dwCyclesThisFrame += run_args.cpu65_cycle_count;
if (is_debugging) { if (is_debugging) {
debugging_cycles -= cpu65_cycle_count; debugging_cycles -= run_args.cpu65_cycle_count;
timing_checkpoint_cycles(); timing_checkpoint_cycles();
if (c_debugger_should_break() || (debugging_cycles <= 0)) { if (c_debugger_should_break() || (debugging_cycles <= 0)) {
@ -377,7 +372,7 @@ cpu_runloop:
} }
} }
if (emul_reinitialize) { if (run_args.emul_reinitialize) {
pthread_mutex_unlock(&interface_mutex); pthread_mutex_unlock(&interface_mutex);
goto cpu_runloop; goto cpu_runloop;
} }
@ -489,7 +484,7 @@ cpu_runloop:
} }
#endif #endif
if (UNLIKELY(emul_reinitialize)) { if (UNLIKELY(run_args.emul_reinitialize)) {
break; break;
} }
@ -549,7 +544,7 @@ unsigned int CpuGetCyclesThisVideoFrame(void) {
void timing_checkpoint_cycles(void) { void timing_checkpoint_cycles(void) {
assert(pthread_self() == cpu_thread_id); assert(pthread_self() == cpu_thread_id);
const int32_t d = cpu65_cycle_count - cycles_checkpoint_count; const int32_t d = run_args.cpu65_cycle_count - cycles_checkpoint_count;
assert(d >= 0); assert(d >= 0);
#if !TESTING #if !TESTING
cycles_count_total += d; cycles_count_total += d;
@ -563,7 +558,7 @@ void timing_checkpoint_cycles(void) {
} }
} }
#endif #endif
cycles_checkpoint_count = cpu65_cycle_count; cycles_checkpoint_count = run_args.cpu65_cycle_count;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -55,8 +55,8 @@ static inline void _reset_axis_state(void) {
} }
static inline void _reset_buttons_state(void) { static inline void _reset_buttons_state(void) {
joy_button0 = 0x0; run_args.joy_button0 = 0x0;
joy_button1 = 0x0; run_args.joy_button1 = 0x0;
} }
static void touchjoy_resetState(void) { static void touchjoy_resetState(void) {
@ -135,8 +135,8 @@ static void *_button_tap_delayed_thread(void *dummyptr) {
assert(timedOut); assert(timedOut);
// touch-down-and-hold // touch-down-and-hold
TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] long touch ..."); TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] long touch ...");
joy_button0 = touchPrevEvent->currJoyButtonValue0; run_args.joy_button0 = touchPrevEvent->currJoyButtonValue0;
joy_button1 = touchPrevEvent->currJoyButtonValue1; run_args.joy_button1 = touchPrevEvent->currJoyButtonValue1;
joys.buttonDrawCallback(touchPrevEvent->currButtonDisplayChar); joys.buttonDrawCallback(touchPrevEvent->currButtonDisplayChar);
continue; continue;
} }
@ -145,16 +145,16 @@ static void *_button_tap_delayed_thread(void *dummyptr) {
if (touchCurrEvent->event == TOUCH_MOVE) { if (touchCurrEvent->event == TOUCH_MOVE) {
// dragging ... // dragging ...
TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] move ..."); TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] move ...");
joy_button0 = touchCurrEvent->currJoyButtonValue0; run_args.joy_button0 = touchCurrEvent->currJoyButtonValue0;
joy_button1 = touchCurrEvent->currJoyButtonValue1; run_args.joy_button1 = touchCurrEvent->currJoyButtonValue1;
joys.buttonDrawCallback(touchCurrEvent->currButtonDisplayChar); joys.buttonDrawCallback(touchCurrEvent->currButtonDisplayChar);
FREE(touchPrevEvent); FREE(touchPrevEvent);
touchPrevEvent = touchCurrEvent; touchPrevEvent = touchCurrEvent;
} else if (touchCurrEvent->event == TOUCH_UP) { } else if (touchCurrEvent->event == TOUCH_UP) {
// tap // tap
TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] touch up ..."); TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] touch up ...");
joy_button0 = touchPrevEvent->currJoyButtonValue0; run_args.joy_button0 = touchPrevEvent->currJoyButtonValue0;
joy_button1 = touchPrevEvent->currJoyButtonValue1; run_args.joy_button1 = touchPrevEvent->currJoyButtonValue1;
joys.buttonDrawCallback(touchPrevEvent->currButtonDisplayChar); joys.buttonDrawCallback(touchPrevEvent->currButtonDisplayChar);
timedOut = 0; timedOut = 0;
break; break;

View File

@ -161,7 +161,6 @@ static void _rerender_character(int col, int row) {
const unsigned int dstPointStride = pixelSize * glyphScale; const unsigned int dstPointStride = pixelSize * glyphScale;
const unsigned int dstRowStride = fb_w * dstPointStride; const unsigned int dstRowStride = fb_w * dstPointStride;
const unsigned int texSubRowStride = dstRowStride + (dstRowStride * (glyphScale-1)); const unsigned int texSubRowStride = dstRowStride + (dstRowStride * (glyphScale-1));
const unsigned int indexedIdx = (row * fb_w * FONT_HEIGHT_PIXELS) + (col * FONT80_WIDTH_PIXELS);
unsigned int texIdx = ((row * fb_w * FONT_HEIGHT_PIXELS * /*1 row:*/glyphScale) + (col * FONT80_WIDTH_PIXELS)) * dstPointStride; unsigned int texIdx = ((row * fb_w * FONT_HEIGHT_PIXELS * /*1 row:*/glyphScale) + (col * FONT80_WIDTH_PIXELS)) * dstPointStride;
for (unsigned int i=0; i<FONT_HEIGHT_PIXELS; i++, texIdx+=texSubRowStride) { for (unsigned int i=0; i<FONT_HEIGHT_PIXELS; i++, texIdx+=texSubRowStride) {
@ -317,8 +316,8 @@ static inline int64_t _tap_key_at_point(float x, float y) {
_rerender_selected(kbd.selectedCol, kbd.selectedRow); _rerender_selected(kbd.selectedCol, kbd.selectedRow);
if (!_is_point_on_keyboard(x, y)) { if (!_is_point_on_keyboard(x, y)) {
joy_button0 = 0x0; run_args.joy_button0 = 0x0;
joy_button1 = 0x0; run_args.joy_button1 = 0x0;
kbd.selectedCol = -1; kbd.selectedCol = -1;
kbd.selectedRow = -1; kbd.selectedRow = -1;
return false; return false;
@ -408,12 +407,12 @@ static inline int64_t _tap_key_at_point(float x, float y) {
break; break;
case MOUSETEXT_OPENAPPLE: case MOUSETEXT_OPENAPPLE:
joy_button0 = joy_button0 ? 0x0 : 0x80; run_args.joy_button0 = run_args.joy_button0 ? 0x0 : 0x80;
scancode = SCODE_L_ALT; scancode = SCODE_L_ALT;
break; break;
case MOUSETEXT_CLOSEDAPPLE: case MOUSETEXT_CLOSEDAPPLE:
joy_button1 = joy_button1 ? 0x0 : 0x80; run_args.joy_button1 = run_args.joy_button1 ? 0x0 : 0x80;
scancode = SCODE_R_ALT; scancode = SCODE_R_ALT;
break; break;
@ -737,14 +736,13 @@ static void _loadAltKbd(const char *kbdPath) {
json_unescapeSlashes((char **)&kbdPath); json_unescapeSlashes((char **)&kbdPath);
int tokCount = json_createFromFile(kbdPath, &jsonRef); int tokCount = json_createFromFile(kbdPath, &jsonRef);
JSON_s parsedData = { 0 };
do { do {
if (tokCount < 0) { if (tokCount < 0) {
break; break;
} }
parsedData = (JSON_s)(*jsonRef); JSON_s parsedData = (JSON_s)(*jsonRef);
// we are expecting a very specific layout ... abort if anything is not correct // we are expecting a very specific layout ... abort if anything is not correct
int idx=0; int idx=0;

View File

@ -179,11 +179,11 @@ static void gldriver_joystick_callback(unsigned int buttonMask, int x, int y, in
#endif #endif
// sample buttons only if apple keys aren't pressed. keys get set to 0xff, and js buttons are set to 0x80. // sample buttons only if apple keys aren't pressed. keys get set to 0xff, and js buttons are set to 0x80.
if (!(joy_button0 & 0x7f)) { if (!(run_args.joy_button0 & 0x7f)) {
joy_button0 = (buttonMask & 0x01) ? 0x80 : 0x0; run_args.joy_button0 = (buttonMask & 0x01) ? 0x80 : 0x0;
} }
if (!(joy_button1 & 0x7f)) { if (!(run_args.joy_button1 & 0x7f)) {
joy_button1 = (buttonMask & 0x02) ? 0x80 : 0x0; run_args.joy_button1 = (buttonMask & 0x02) ? 0x80 : 0x0;
} }
// normalize GLUT range // normalize GLUT range

View File

@ -721,7 +721,7 @@ static void _nc_modeChange(pixel_delta_t pixel) {
} }
WINDOW *winPrev = winCurr; WINDOW *winPrev = winCurr;
uint32_t currswitches = softswitches; uint32_t currswitches = run_args.softswitches;
if ((currswitches & SS_TEXT) && !(currswitches & SS_MIXED)) { if ((currswitches & SS_TEXT) && !(currswitches & SS_MIXED)) {
winCurr = (currswitches & SS_80COL) ? winTxt80 : winTxt40; winCurr = (currswitches & SS_80COL) ? winTxt80 : winTxt40;
} else { } else {

840
src/vm.c

File diff suppressed because it is too large Load Diff

View File

@ -123,26 +123,6 @@ extern uint8_t apple_ii_64k[2][65536];
extern uint8_t language_card[2][8192]; extern uint8_t language_card[2][8192];
extern uint8_t language_banks[2][8192]; extern uint8_t language_banks[2][8192];
extern uint32_t softswitches;
extern uint8_t *base_ramrd;
extern uint8_t *base_ramwrt;
extern uint8_t *base_textrd;
extern uint8_t *base_textwrt;
extern uint8_t *base_hgrrd;
extern uint8_t *base_hgrwrt;
extern uint8_t *base_stackzp;
extern uint8_t *base_d000_rd;
extern uint8_t *base_e000_rd;
extern uint8_t *base_d000_wrt;
extern uint8_t *base_e000_wrt;
extern uint8_t *base_c3rom;
extern uint8_t *base_c4rom; // points to function or memory vector
extern uint8_t *base_c5rom; // points to function or memory vector
extern uint8_t *base_cxrom;
void vm_initialize(void); void vm_initialize(void);
void vm_reinitializeAudio(void); void vm_reinitializeAudio(void);

View File

@ -17,13 +17,12 @@
#endif #endif
#include "cpu.h" #include "cpu.h"
#include "glue-offsets.h"
#define X_Reg %bl /* 6502 X register in %bl */ #define X_Reg %bl /* 6502 X register in %bl */
#define Y_Reg %bh /* 6502 Y register in %bh */ #define Y_Reg %bh /* 6502 Y register in %bh */
#define A_Reg %cl /* 6502 A register in %cl */ #define A_Reg %cl /* 6502 A register in %cl */
#define F_Reg %ch /* 6502 flags in %ch */ #define F_Reg %ch /* 6502 flags in %ch */
#define SP_Reg_L %dl /* 6502 Stack pointer low */
#define SP_Reg_H %dh /* 6502 Stack pointer high */
#define PC_Reg %si /* 6502 Program Counter */ #define PC_Reg %si /* 6502 Program Counter */
#define PC_Reg_L %sil /* 6502 PC low */ #define PC_Reg_L %sil /* 6502 PC low */
#define PC_Reg_H %sih /* 6502 PC high */ #define PC_Reg_H %sih /* 6502 PC high */
@ -34,28 +33,20 @@
#define X86_CF_Bit 0x0 /* x86 carry */ #define X86_CF_Bit 0x0 /* x86 carry */
#define X86_AF_Bit 0x4 /* x86 adj (nybble carry) */ #define X86_AF_Bit 0x4 /* x86 adj (nybble carry) */
#define RestoreAltZP \
/* Apple //e set stack point to ALTZP (or not) */ \
MEM2REG(movLQ, base_stackzp, _XAX); \
MEM2REG(subLQ, base_vmem, _XAX); \
orLQ $0x0100, SP_Reg_X; \
orLQ _XAX, SP_Reg_X;
#if __LP64__ #if __LP64__
# define SZ_PTR 8 # define SZ_PTR 8
# define ROR_BIT 63 # define ROR_BIT 63
// x86_64 registers // x86_64 registers
# define _XBP %rbp /* x86_64 base pointer */ # define _XBP %rbp /* x86_64 base ptr/ scratch*/
# define _XSP %rsp /* x86_64 stack pointer */ # define _XSP %rsp /* x86_64 stack pointer */
# define _XDI %rdi # define _XDI %rdi
# define _XSI %rsi # define _XSI %rsi
# define _XAX %rax /* scratch */ # define _XAX %rax /* scratch */
# define _XBX %rbx /* scratch2 */ # define _XBX %rbx /* scratch2 */
# define _X8 %r8
// full-length Apple ][ registers // full-length Apple ][ registers
# define XY_Reg_X %rbx /* 6502 X&Y flags */ # define XY_Reg_X %rbx /* 6502 X&Y flags */
# define AF_Reg_X %rcx /* 6502 F&A flags */ # define AF_Reg_X %rcx /* 6502 F&A flags */
# define SP_Reg_X %rdx /* 6502 Stack pointer */ # define reg_args %rdx
# define PC_Reg_X %rsi /* 6502 Program Counter */ # define PC_Reg_X %rsi /* 6502 Program Counter */
# define EffectiveAddr_X %rdi /* Effective address */ # define EffectiveAddr_X %rdi /* Effective address */
// full-length assembly instructions // full-length assembly instructions
@ -83,18 +74,16 @@
# define SZ_PTR 4 # define SZ_PTR 4
# define ROR_BIT 31 # define ROR_BIT 31
// x86 registers // x86 registers
# define _XBP %ebp /* x86 base pointer */ # define _XBP %ebp /* x86 base ptr / scratch */
# define _PICREG %ebp /* used for accessing GOT */
# define _XSP %esp /* x86 stack pointer */ # define _XSP %esp /* x86 stack pointer */
# define _XDI %edi # define _XDI %edi
# define _XSI %esi # define _XSI %esi
# define _XAX %eax /* scratch */ # define _XAX %eax /* scratch */
# define _XBX %ebx /* scratch2 */ # define _XBX %ebx /* scratch2 */
# define _X8 %eax // WRONG!!! FIXMENOW
// full-length Apple ][ registers // full-length Apple ][ registers
# define XY_Reg_X %ebx /* 6502 X&Y flags */ # define XY_Reg_X %ebx /* 6502 X&Y flags */
# define AF_Reg_X %ecx /* 6502 F&A flags */ # define AF_Reg_X %ecx /* 6502 F&A flags */
# define SP_Reg_X %edx /* 6502 Stack pointer */ # define reg_args %edx
# define PC_Reg_X %esi /* 6502 Program Counter */ # define PC_Reg_X %esi /* 6502 Program Counter */
# define EffectiveAddr_X %edi /* Effective address */ # define EffectiveAddr_X %edi /* Effective address */
// full-length assembly instructions // full-length assembly instructions
@ -122,92 +111,24 @@
/* Symbol naming issues */ /* Symbol naming issues */
#if NO_UNDERSCORES #if NO_UNDERSCORES
# define _UNDER(x) x # define ENTRY(x) .globl x; .balign 16; x##:
# define CALL(x) x
#else #else
# define _UNDER(x) _##x # define ENTRY(x) .globl _##x##; .balign 16; _##x##:
# define CALL(x) _##x
#endif #endif
#define ENTRY(x) .globl _UNDER(x); .balign 16; _UNDER(x)##: #define MOVB_IND(BASE,OFF,REG) \
movLQ BASE(reg_args), _XBP; \
movb (_XBP,OFF,1), REG;
#if !__PIC__ || (__APPLE__ && !__LP64__) #define CALL_IND(BASE,OFF) \
movLQ BASE(reg_args), _XBP; \
callLQ *(_XBP,OFF,SZ_PTR);
// For non-Position Independent Code, the assembly is relatively simple... #define JUMP_IND(BASE,OFF) \
movLQ BASE(reg_args), _XBP; \
# define CALL_FN(op,fn,stk) op _UNDER(fn) jmp *(_XBP,OFF,SZ_PTR);
# define JUMP_FN(op,fn) op _UNDER(fn)
# define CALL_IND0(sym) callLQ *_UNDER(sym)
# define CALL_IND(sym,off,sz) callLQ *_UNDER(sym)(,off,sz)
# define JUMP_IND(sym,off,sz) jmp *_UNDER(sym)(,off,sz)
# define MEM2REG_IND(op,sym,off,sz,x) op _UNDER(sym)(,off,sz), x
# define REG2MEM_IND(op,x,sym,off,sz) op x, _UNDER(sym)(,off,sz)
# define _2MEM(op,sym) op _UNDER(sym) // op to-memory
# define REG2MEM(op,x,sym) op x, _UNDER(sym) // op register-to-memory
# define MEM2REG(op,sym,x) op _UNDER(sym), x // op memory-to-register
#else
// For PIC code, the assembly is more convoluted, because we have to access symbols only indirectly through the Global
// Offset Table and the Procedure Linkage Table. There is some redundancy in the codegen from these macros (e.g.,
// access to the same symbol back-to-back results in duplicate register loads, when we could keep using the previously
// calculated value).
# if __APPLE__
# if !__LP64__
# error unsure of __PIC__ code on i386 Mac
# endif
# define _AT_PLT
# define _LEA(sym) leaq _UNDER(sym)(%rip), _X8
# define CALL_IND0(fn) callq *_UNDER(fn)(%rip)
# define _2MEM(op,sym) op _UNDER(sym)(%rip) // op to-memory
# define REG2MEM(op,x,sym) op x, _UNDER(sym)(%rip) // op register-to-memory
# define MEM2REG(op,sym,x) op _UNDER(sym)(%rip), x // op memory-to-register
# elif __LP64__
# define _AT_PLT @PLT
# define _LEA(sym) movq _UNDER(sym)@GOTPCREL(%rip), _X8
# define CALL_IND0(fn) callq *_UNDER(fn)_AT_PLT
# define _2MEM(op,sym) _LEA(sym); op (_X8) // op to-memory
# define REG2MEM(op,x,sym) _LEA(sym); op x, (_X8) // op register-to-memory
# define MEM2REG(op,sym,x) _LEA(sym); op (_X8), x // op memory-to-register
# endif
# if __LP64__
# define CALL_FN(op,fn,stk) op _UNDER(fn)_AT_PLT
# define JUMP_FN(op,fn) op _UNDER(fn)_AT_PLT
# define CALL_IND(sym,off,sz) _LEA(sym); callq *(_X8,off,sz)
# define JUMP_IND(sym,off,sz) _LEA(sym); jmp *(_X8,off,sz)
# define MEM2REG_IND(op,sym,off,sz,x) _LEA(sym); op (_X8,off,sz), x
# define REG2MEM_IND(op,x,sym,off,sz) _LEA(sym); op x, (_X8,off,sz)
# else
# if !__i386__
# error what architecture is this?!
# endif
// http://ewontfix.com/18/ -- "32-bit x86 Position Independent Code - It's that bad"
// 2016/05/01 : Strategy here is to (ab)use _PICREG in cpu65_run() to contain the offset to the GOT for symbol access.
// %ebx is used only for actual calls to the fn@PLT (per ABI convention). Similar to x64 PIC, use of these macros does
// result in some code duplication...
# define CALL_FN(op,fn,stk) movl stk(%esp), %ebx; \
op _UNDER(fn)@PLT;
# define _GOT_PRE(sym,reg) movl _A2_PIC_GOT(%esp), reg; \
movl _UNDER(sym)@GOT(reg), reg;
# define CALL_IND0(fn) _GOT_PRE(fn, _PICREG); calll *(_PICREG);
# define CALL_IND(sym,off,sz) _GOT_PRE(sym,_PICREG); calll *(_PICREG,off,sz);
# define JUMP_FN(op,fn) op _UNDER(fn)
# define JUMP_IND(sym,off,sz) _GOT_PRE(sym,_PICREG); jmp *(_PICREG,off,sz);
# define MEM2REG_IND(op,sym,off,sz,x) _GOT_PRE(sym,_PICREG); op (_PICREG,off,sz), x;
# define REG2MEM_IND(op,x,sym,off,sz) _GOT_PRE(sym,_PICREG); op x, (_PICREG,off,sz);
# define _2MEM(op,sym) _GOT_PRE(sym,_PICREG); op (_PICREG); // op to-memory
# define REG2MEM(op,x,sym) _GOT_PRE(sym,_PICREG); op x, (_PICREG); // op register-to-memory
# define MEM2REG(op,sym,x) _GOT_PRE(sym,_PICREG); op (_PICREG), x; // op memory-to-register
# endif
#endif
#endif // whole file #endif // whole file

View File

@ -16,50 +16,36 @@
#include "cpu-regs.h" #include "cpu-regs.h"
#include "vm.h" #include "vm.h"
#if !__PIC__ || (__APPLE__ && !__LP64__) #define SAVE_Y_REG() \
# define SAVE_Y_REG() \ movb Y_Reg, CPU65_Y(reg_args)
REG2MEM(movb, Y_Reg, cpu65_y)
# define _POP_PICREG()
#else
# define SAVE_Y_REG() \
movb Y_Reg, %al; \
REG2MEM(movb, %al, cpu65_y)
# if __i386__
# define _A2_PIC_GOT(reg) 0x0(reg) // Assumes GOT pointer is at head of stack
# define _POP_PICREG() popl _PICREG
# else
# define _POP_PICREG()
# endif
#endif
#define CommonSaveCPUState \ #define CommonSaveCPUState \
REG2MEM(movw, EffectiveAddr, cpu65_ea); \ movw EffectiveAddr, CPU65_EA(reg_args); \
REG2MEM(movb, A_Reg, cpu65_a); \ movb A_Reg, CPU65_A(reg_args); \
xorw %ax, %ax; \ xorw %ax, %ax; \
movb F_Reg, %al; \ movb F_Reg, %al; \
MEM2REG_IND(movb,cpu65_flags_encode,_XAX,1,%al); \ MOVB_IND(CPU65_FLAGS_ENCODE,_XAX,%al); \
REG2MEM(movb, %al, cpu65_f); \ movb %al, CPU65_F(reg_args); \
REG2MEM(movb, X_Reg, cpu65_x); \ movb X_Reg, CPU65_X(reg_args); \
SAVE_Y_REG(); \ SAVE_Y_REG();
REG2MEM(movb, SP_Reg_L, cpu65_sp)
#if CPU_TRACING #if CPU_TRACING
# define TRACE_PROLOGUE \ # define TRACE_PROLOGUE \
REG2MEM(movw, PC_Reg, cpu65_pc); \ movw PC_Reg, CPU65_PC(reg_args); \
CALL_FN(callLQ, cpu65_trace_prologue, 0x4); callLQ *CPU65_TRACE_PROLOGUE(reg_args);
# define TRACE_ARG \ # define TRACE_ARG \
CALL_FN(callLQ, cpu65_trace_arg, 0x4); callLQ *CPU65_TRACE_ARG(reg_args);
# define TRACE_ARG1 \ # define TRACE_ARG1 \
CALL_FN(callLQ, cpu65_trace_arg1, 0x4); callLQ *CPU65_TRACE_ARG1(reg_args);
# define TRACE_ARG2 \ # define TRACE_ARG2 \
CALL_FN(callLQ, cpu65_trace_arg2, 0x4); callLQ *CPU65_TRACE_ARG2(reg_args);
# define TRACE_EPILOGUE \ # define TRACE_EPILOGUE \
pushLQ _XAX; \ pushLQ _XAX; \
CommonSaveCPUState; \ CommonSaveCPUState; \
popLQ _XAX; \ popLQ _XAX; \
CALL_FN(callLQ, cpu65_trace_epilogue, 0x4); callLQ *CPU65_TRACE_EPILOGUE(reg_args);
# define TRACE_IRQ \ # define TRACE_IRQ \
CALL_FN(callLQ, cpu65_trace_irq, 0x4); callLQ *CPU65_TRACE_IRQ(reg_args);
#else #else
# define TRACE_PROLOGUE # define TRACE_PROLOGUE
# define TRACE_ARG # define TRACE_ARG
@ -76,49 +62,49 @@
#define GetFromPC_B \ #define GetFromPC_B \
movLQ PC_Reg_X, EffectiveAddr_X; \ movLQ PC_Reg_X, EffectiveAddr_X; \
incw PC_Reg; \ incw PC_Reg; \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); \ CALL_IND(CPU65_VMEM_R,EffectiveAddr_X); \
TRACE_ARG; TRACE_ARG;
#define GetFromPC_W \ #define GetFromPC_W \
movLQ PC_Reg_X, EffectiveAddr_X; \ movLQ PC_Reg_X, EffectiveAddr_X; \
incw EffectiveAddr; \ incw EffectiveAddr; \
addw $2, PC_Reg; \ addw $2, PC_Reg; \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); \ CALL_IND(CPU65_VMEM_R,EffectiveAddr_X); \
decw EffectiveAddr; \ decw EffectiveAddr; \
TRACE_ARG2; \ TRACE_ARG2; \
movb %al, %ah; \ movb %al, %ah; \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); \ CALL_IND(CPU65_VMEM_R,EffectiveAddr_X); \
TRACE_ARG1; TRACE_ARG1;
#define CPUStatsReset \ #define CPUStatsReset \
REG2MEM(movb, $0, cpu65_opcycles); \ movb $0, CPU65_OPCYCLES(reg_args); \
REG2MEM(movb, $0, cpu65_rw); movb $0, CPU65_RW(reg_args);
#define JumpNextInstruction \ #define JumpNextInstruction \
TRACE_PROLOGUE; \ TRACE_PROLOGUE; \
GetFromPC_B \ GetFromPC_B \
REG2MEM(movb, %al, cpu65_opcode); \ movb %al, CPU65_OPCODE(reg_args); \
JUMP_IND(cpu65__opcodes,_XAX,SZ_PTR); JUMP_IND(CPU65__OPCODES,_XAX)
#define GetFromEA_B \ #define GetFromEA_B \
REG2MEM(orb, $1, cpu65_rw); \ orb $1, CPU65_RW(reg_args); \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); CALL_IND(CPU65_VMEM_R,EffectiveAddr_X);
#define GetFromEA_W \ #define GetFromEA_W \
incw EffectiveAddr; \ incw EffectiveAddr; \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); \ CALL_IND(CPU65_VMEM_R,EffectiveAddr_X); \
decw EffectiveAddr; \ decw EffectiveAddr; \
movb %al, %ah; \ movb %al, %ah; \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); CALL_IND(CPU65_VMEM_R,EffectiveAddr_X);
#define PutToEA_B \ #define PutToEA_B \
REG2MEM(orb, $2, cpu65_rw); \ orb $2, CPU65_RW(reg_args); \
REG2MEM(movb, %al, cpu65_d); \ movb %al, CPU65_D(reg_args); \
CALL_IND(cpu65_vmem_w,EffectiveAddr_X,SZ_PTR); CALL_IND(CPU65_VMEM_W,EffectiveAddr_X);
#define GetFromMem_B(x) \ #define GetFromMem_B(x) \
movLQ x, EffectiveAddr_X; \ movLQ x, EffectiveAddr_X; \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); CALL_IND(CPU65_VMEM_R,EffectiveAddr_X);
#define GetFromMem_W(x) \ #define GetFromMem_W(x) \
movLQ x, EffectiveAddr_X; \ movLQ x, EffectiveAddr_X; \
@ -128,7 +114,7 @@
jmp continue; jmp continue;
#define BranchXCycles \ #define BranchXCycles \
_2MEM(incb, cpu65_opcycles); /* +1 branch taken */ \ incb CPU65_OPCYCLES(reg_args); /* +1 branch taken */ \
shlLQ $16, _XBX; \ shlLQ $16, _XBX; \
movw PC_Reg, %bx; \ movw PC_Reg, %bx; \
cbw; \ cbw; \
@ -136,7 +122,7 @@
movw %ax, PC_Reg; \ movw %ax, PC_Reg; \
cmpb %ah, %bh; \ cmpb %ah, %bh; \
je 9f; \ je 9f; \
_2MEM(incb, cpu65_opcycles); /* +1 branch new page */ \ incb CPU65_OPCYCLES(reg_args); /* +1 branch new page */ \
9: shrLQ $16, _XBX; 9: shrLQ $16, _XBX;
#define FlagC \ #define FlagC \
@ -184,13 +170,24 @@
orb %ah, F_Reg; \ orb %ah, F_Reg; \
orb %al, F_Reg; orb %al, F_Reg;
#ifdef APPLE2_VM
# define _GetStkOff \
movzbLQ CPU65_SP(reg_args), _XBP; \
addLQ BASE_STACKZP(reg_args), _XBP; \
addLQ $0x0100, _XBP;
#else
# error FIXME TODO ...
#endif
#define Push(x) \ #define Push(x) \
REG2MEM_IND(movb,x,apple_ii_64k,SP_Reg_X,1); \ _GetStkOff \
decb SP_Reg_L; movb x, (_XBP); \
decb CPU65_SP(reg_args);
#define Pop(x) \ #define Pop(x) \
incb SP_Reg_L; \ incb CPU65_SP(reg_args); \
MEM2REG_IND(movb,apple_ii_64k,SP_Reg_X,1,x); _GetStkOff \
movb (_XBP), x;
/* Immediate Addressing - the operand is contained in the second byte of the /* Immediate Addressing - the operand is contained in the second byte of the
instruction. */ instruction. */
@ -200,7 +197,7 @@
#if CPU_TRACING #if CPU_TRACING
#define GetImm \ #define GetImm \
_GetImm \ _GetImm \
CALL_IND(cpu65_vmem_r,EffectiveAddr_X,SZ_PTR); \ CALL_IND(CPU65_VMEM_R,EffectiveAddr_X); \
TRACE_ARG; TRACE_ARG;
#else #else
#define GetImm \ #define GetImm \
@ -245,7 +242,7 @@
#define GetAbs_X \ #define GetAbs_X \
_GetAbs_X \ _GetAbs_X \
_2MEM(incb, cpu65_opcycles); /* +1 cycle on page boundary */ \ incb CPU65_OPCYCLES(reg_args); /* +1 cycle on page boundary */ \
9: movLQ _XAX, EffectiveAddr_X; 9: movLQ _XAX, EffectiveAddr_X;
#define GetAbs_X_STx \ #define GetAbs_X_STx \
@ -260,7 +257,7 @@
#define GetAbs_Y \ #define GetAbs_Y \
_GetAbs_Y \ _GetAbs_Y \
_2MEM(incb, cpu65_opcycles); /* +1 cycle on page boundary */ \ incb CPU65_OPCYCLES(reg_args); /* +1 cycle on page boundary */ \
9: movLQ _XAX, EffectiveAddr_X; 9: movLQ _XAX, EffectiveAddr_X;
#define GetAbs_Y_STA \ #define GetAbs_Y_STA \
@ -323,7 +320,7 @@
#define GetIndZPage_Y \ #define GetIndZPage_Y \
_GetIndZPage_Y \ _GetIndZPage_Y \
adcb $0, %ah; \ adcb $0, %ah; \
_2MEM(incb, cpu65_opcycles); /* +1 cycle on page boundary */ \ incb CPU65_OPCYCLES(reg_args); /* +1 cycle on page boundary */ \
9: movLQ _XAX, EffectiveAddr_X; 9: movLQ _XAX, EffectiveAddr_X;
#define GetIndZPage_Y_STA \ #define GetIndZPage_Y_STA \
@ -342,22 +339,22 @@
jz 6f; \ jz 6f; \
testb $0x60, A_Reg; \ testb $0x60, A_Reg; \
jz 6f; \ jz 6f; \
CALL_FN(callLQ, debug_illegal_bcd, 0x4); \ callLQ *DEBUG_ILLEGAL_BCD(reg_args); \
6: testb $0x08, A_Reg; \ 6: testb $0x08, A_Reg; \
jz 7f; \ jz 7f; \
testb $0x06, A_Reg; \ testb $0x06, A_Reg; \
jz 7f; \ jz 7f; \
CALL_FN(callLQ, debug_illegal_bcd, 0x4); \ callLQ *DEBUG_ILLEGAL_BCD(reg_args); \
7: testb $0x80, %al; \ 7: testb $0x80, %al; \
jz 8f; \ jz 8f; \
testb $0x60, %al; \ testb $0x60, %al; \
jz 8f; \ jz 8f; \
CALL_FN(callLQ, debug_illegal_bcd, 0x4); \ callLQ *DEBUG_ILLEGAL_BCD(reg_args); \
8: testb $0x08, %al; \ 8: testb $0x08, %al; \
jz 9f; \ jz 9f; \
testb $0x06, %al; \ testb $0x06, %al; \
jz 9f; \ jz 9f; \
CALL_FN(callLQ, debug_illegal_bcd, 0x4); \ callLQ *DEBUG_ILLEGAL_BCD(reg_args); \
9: 9:
#else #else
#define DebugBCDCheck #define DebugBCDCheck
@ -534,7 +531,7 @@
// Decimal mode // Decimal mode
ENTRY(op_ADC_dec) ENTRY(op_ADC_dec)
_2MEM(incb, cpu65_opcycles) // +1 cycle incb CPU65_OPCYCLES(reg_args) // +1 cycle
GetFromEA_B GetFromEA_B
DebugBCDCheck DebugBCDCheck
bt $C_Flag_Bit, AF_Reg_X bt $C_Flag_Bit, AF_Reg_X
@ -555,19 +552,18 @@ ENTRY(op_ADC_dec)
// al = al + 60h // al = al + 60h
// CF set // CF set
// ENDIF // ENDIF
pushq _XBX
pushfq pushfq
popq _XBX popq _XBP
andb $~(N_Flag|V_Flag|Z_Flag|C_Flag), F_Reg andb $~(N_Flag|V_Flag|Z_Flag|C_Flag), F_Reg
movb %al, %ah movb %al, %ah
andb $0x0f, %ah andb $0x0f, %ah
cmpb $9, %ah cmpb $9, %ah
jg _daa_lo_nyb jg _daa_lo_nyb
btq $X86_AF_Bit, _XBX btq $X86_AF_Bit, _XBP
jnc _daa_next0 jnc _daa_next0
_daa_lo_nyb: addb $6, %al // adjust lo nybble _daa_lo_nyb: addb $6, %al // adjust lo nybble
jc _daa_hi_nyb jc _daa_hi_nyb
_daa_next0: btq $X86_CF_Bit, _XBX _daa_next0: btq $X86_CF_Bit, _XBP
jc _daa_hi_nyb jc _daa_hi_nyb
xorb %ah, %ah xorb %ah, %ah
cmpw $0x99, %ax cmpw $0x99, %ax
@ -580,14 +576,13 @@ _daa_next1: testq $0x80, %rax
_daa_next2: testq $0xFF, %rax _daa_next2: testq $0xFF, %rax
jnz _daa_finish jnz _daa_finish
orb $Z_Flag, F_Reg // FlagZ orb $Z_Flag, F_Reg // FlagZ
_daa_finish: popq _XBX _daa_finish: movb %al, A_Reg
movb %al, A_Reg
#endif #endif
Continue Continue
#define maybe_DoADC_d \ #define maybe_DoADC_d \
testb $D_Flag, F_Reg; /* Decimal mode? */ \ testb $D_Flag, F_Reg; /* Decimal mode? */ \
JUMP_FN(jnz, op_ADC_dec) /* Yes, jump to decimal version */ jnz CALL(op_ADC_dec) /* Yes, jump to decimal version */
ENTRY(op_ADC_imm) // 0x69 ENTRY(op_ADC_imm) // 0x69
GetImm GetImm
@ -609,7 +604,7 @@ ENTRY(op_ADC_zpage_x) // 0x75
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_ADC_zpage_y) ENTRY(op_ADC_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_ADC_abs) // 0x6d ENTRY(op_ADC_abs) // 0x6d
GetAbs GetAbs
@ -670,7 +665,7 @@ ENTRY(op_AND_zpage_x) // 0x35
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_AND_zpage_y) ENTRY(op_AND_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_AND_abs) // 0x2d ENTRY(op_AND_abs) // 0x2d
GetAbs GetAbs
@ -939,7 +934,7 @@ ENTRY(op_BRK)
orb $(B_Flag|X_Flag), F_Reg orb $(B_Flag|X_Flag), F_Reg
xorw %ax, %ax xorw %ax, %ax
movb F_Reg, %al movb F_Reg, %al
MEM2REG_IND(movb,cpu65_flags_encode,_XAX,1,%al) MOVB_IND(CPU65_FLAGS_ENCODE,_XAX,%al)
Push(%al) Push(%al)
orb $I_Flag, F_Reg orb $I_Flag, F_Reg
movw $0xFFFE, EffectiveAddr // ROM interrupt vector movw $0xFFFE, EffectiveAddr // ROM interrupt vector
@ -1027,7 +1022,7 @@ ENTRY(op_CMP_zpage_x) // 0xd5
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_CMP_zpage_y) ENTRY(op_CMP_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_CMP_abs) // 0xcd ENTRY(op_CMP_abs) // 0xcd
GetAbs GetAbs
@ -1172,7 +1167,7 @@ ENTRY(op_EOR_zpage_x) // 0x55
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_EOR_zpage_y) ENTRY(op_EOR_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_EOR_abs) // 0x4d ENTRY(op_EOR_abs) // 0x4d
GetAbs GetAbs
@ -1335,7 +1330,7 @@ ENTRY(op_LDA_zpage_x) // 0xb5
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_LDA_zpage_y) ENTRY(op_LDA_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_LDA_abs) // 0xad ENTRY(op_LDA_abs) // 0xad
GetAbs GetAbs
@ -1482,7 +1477,7 @@ ENTRY(op_ORA_zpage_x) // 0x15
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_ORA_zpage_y) ENTRY(op_ORA_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_ORA_abs) // 0x0d ENTRY(op_ORA_abs) // 0x0d
GetAbs GetAbs
@ -1529,7 +1524,7 @@ ENTRY(op_PHA) // 0x48
ENTRY(op_PHP) // 0x08 ENTRY(op_PHP) // 0x08
movb F_Reg, %al movb F_Reg, %al
MEM2REG_IND(movb,cpu65_flags_encode,_XAX,1,%al) MOVB_IND(CPU65_FLAGS_ENCODE,_XAX,%al)
Push(%al) Push(%al)
Continue Continue
@ -1572,12 +1567,7 @@ ENTRY(op_PLA) // 0x68
ENTRY(op_PLP) // 0x28 ENTRY(op_PLP) // 0x28
Pop(%al) Pop(%al)
#if __PIC__ MOVB_IND(CPU65_FLAGS_DECODE,_XAX,F_Reg)
MEM2REG_IND(movb,cpu65_flags_decode,_XAX,1,%al)
movb %al, F_Reg
#else
MEM2REG_IND(movb,cpu65_flags_decode,_XAX,1,F_Reg)
#endif
orb $(B_Flag|X_Flag), F_Reg orb $(B_Flag|X_Flag), F_Reg
Continue Continue
@ -1674,10 +1664,10 @@ ENTRY(op_ROR_abs_x) // 0x7e
ENTRY(op_RTI) // 0x40 ENTRY(op_RTI) // 0x40
Pop(%al) Pop(%al)
#if __PIC__ #if __PIC__
MEM2REG_IND(movb,cpu65_flags_decode,_XAX,1,%al) MOVB_IND(CPU65_FLAGS_DECODE,_XAX,%al)
movb %al, F_Reg movb %al, F_Reg
#else #else
MEM2REG_IND(movb,cpu65_flags_decode,_XAX,1,F_Reg) MOVB_IND(CPU65_FLAGS_DECODE,_XAX,F_Reg)
#endif #endif
orb $(B_Flag|X_Flag), F_Reg orb $(B_Flag|X_Flag), F_Reg
Pop(%al) Pop(%al)
@ -1714,7 +1704,7 @@ ENTRY(op_RTS) // 0x60
---------------------------------- */ ---------------------------------- */
ENTRY(op_SBC_dec) ENTRY(op_SBC_dec)
_2MEM(incb, cpu65_opcycles) // +1 cycle incb CPU65_OPCYCLES(reg_args) // +1 cycle
GetFromEA_B GetFromEA_B
DebugBCDCheck DebugBCDCheck
bt $C_Flag_Bit, AF_Reg_X bt $C_Flag_Bit, AF_Reg_X
@ -1739,20 +1729,19 @@ ENTRY(op_SBC_dec)
// al = al - 60h // al = al - 60h
// ^CF set // ^CF set
// ENDIF // ENDIF
pushq _XBX
pushfq pushfq
popq _XBX popq _XBP
andb $~(N_Flag|V_Flag|Z_Flag), F_Reg andb $~(N_Flag|V_Flag|Z_Flag), F_Reg
orb $C_Flag, F_Reg orb $C_Flag, F_Reg
movb %al, %ah movb %al, %ah
andb $0x0f, %ah andb $0x0f, %ah
cmpb $9, %ah cmpb $9, %ah
jg _das_lo_nyb jg _das_lo_nyb
btq $X86_AF_Bit, _XBX btq $X86_AF_Bit, _XBP
jnc _das_next0 jnc _das_next0
_das_lo_nyb: subb $6, %al // adjust lo nybble _das_lo_nyb: subb $6, %al // adjust lo nybble
jc _das_hi_nyb jc _das_hi_nyb
_das_next0: btq $X86_CF_Bit, _XBX _das_next0: btq $X86_CF_Bit, _XBP
jc _das_hi_nyb jc _das_hi_nyb
xorb %ah, %ah xorb %ah, %ah
cmpw $0x99, %ax cmpw $0x99, %ax
@ -1765,14 +1754,13 @@ _das_next1: testq $0x80, %rax
_das_next2: testq $0xFF, %rax _das_next2: testq $0xFF, %rax
jnz _das_finish jnz _das_finish
orb $Z_Flag, F_Reg // FlagZ orb $Z_Flag, F_Reg // FlagZ
_das_finish: popq _XBX _das_finish: movb %al, A_Reg
movb %al, A_Reg
#endif #endif
Continue Continue
#define maybe_DoSBC_d \ #define maybe_DoSBC_d \
testb $D_Flag, F_Reg; /* Decimal mode? */ \ testb $D_Flag, F_Reg; /* Decimal mode? */ \
JUMP_FN(jnz, op_SBC_dec) /* Yes, jump to decimal version */ jnz CALL(op_SBC_dec) /* Yes, jump to decimal version */
ENTRY(op_SBC_imm) // 0xe9 ENTRY(op_SBC_imm) // 0xe9
GetImm GetImm
@ -1794,7 +1782,7 @@ ENTRY(op_SBC_zpage_x) // 0xf5
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_SBC_zpage_y) ENTRY(op_SBC_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_SBC_abs) // 0xed ENTRY(op_SBC_abs) // 0xed
GetAbs GetAbs
@ -1902,7 +1890,7 @@ ENTRY(op_STA_zpage_x) // 0x95
// UNIMPLEMENTED : W65C02S datasheet // UNIMPLEMENTED : W65C02S datasheet
ENTRY(op_STA_zpage_y) ENTRY(op_STA_zpage_y)
JUMP_FN(jmp, op_NOP) jmp CALL(op_NOP)
ENTRY(op_STA_abs) // 0x8d ENTRY(op_STA_abs) // 0x8d
GetAbs GetAbs
@ -2098,7 +2086,7 @@ ENTRY(op_TSB_zpage)
---------------------------------- */ ---------------------------------- */
ENTRY(op_TSX) // 0xba ENTRY(op_TSX) // 0xba
movb SP_Reg_L, X_Reg movb CPU65_SP(reg_args), X_Reg
orb X_Reg, X_Reg orb X_Reg, X_Reg
FlagNZ FlagNZ
Continue Continue
@ -2118,7 +2106,7 @@ ENTRY(op_TXA) // 0x8a
---------------------------------- */ ---------------------------------- */
ENTRY(op_TXS) // 0x9a ENTRY(op_TXS) // 0x9a
movb X_Reg, SP_Reg_L movb X_Reg, CPU65_SP(reg_args)
Continue Continue
/* ---------------------------------- /* ----------------------------------
@ -2154,36 +2142,38 @@ ENTRY(op_WAI_65c02)
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
continue: continue:
MEM2REG(movzbLQ, cpu65_opcode, _XAX) movzbLQ CPU65_OPCODE(reg_args), _XAX
MEM2REG_IND(movb,cpu65__opcycles,_XAX,1,%al) MOVB_IND(CPU65__OPCYCLES,_XAX,%al)
MEM2REG(addb, cpu65_opcycles, %al) addb CPU65_OPCYCLES(reg_args), %al
REG2MEM(movb, %al, cpu65_opcycles) movb %al, CPU65_OPCYCLES(reg_args)
TRACE_EPILOGUE TRACE_EPILOGUE
REG2MEM(addl, %eax, cpu65_cycle_count) addl %eax, CPU65_CYCLE_COUNT(reg_args)
REG2MEM(subl, %eax, gc_cycles_timer_0) subl %eax, GC_CYCLES_TIMER_0(reg_args)
REG2MEM(subl, %eax, gc_cycles_timer_1) subl %eax, GC_CYCLES_TIMER_1(reg_args)
#if CONFORMANT_IRQ_CHECKPOINT #if CONFORMANT_IRQ_CHECKPOINT
REG2MEM(subl, %eax, irqCheckTimeout) # error 2018/01/15 untested ...
subl %eax, IRQ_CHECK_TIMEOUT(reg_args)
jl irq_checkpoint // AppleWin : CheckInterruptSources() jl irq_checkpoint // AppleWin : CheckInterruptSources()
#endif #endif
continue1: REG2MEM(subl, %eax, cpu65_cycles_to_execute) continue1: subl %eax, CPU65_CYCLES_TO_EXECUTE(reg_args)
jle exit_cpu65_run jle exit_cpu65_run
continue2: xorLQ _XAX, _XAX continue2: xorLQ _XAX, _XAX
MEM2REG(orb, cpu65__signal, %al) orb CPU65__SIGNAL(reg_args), %al
jnz exception jnz exception
CPUStatsReset CPUStatsReset
JumpNextInstruction JumpNextInstruction
#if CONFORMANT_IRQ_CHECKPOINT #if CONFORMANT_IRQ_CHECKPOINT
# error 2018/01/15 untested ...
irq_checkpoint: irq_checkpoint:
#if __PIC__ && __i386__ #if __PIC__ && __i386__
pushl %ebx pushl %ebx
#endif #endif
CALL_FN(callLQ, cpu_irqCheck, 0x8) callLQ *CPU_IRQCHECK(reg_args)
#if __PIC__ && __i386__ #if __PIC__ && __i386__
popl %ebx popl %ebx
#endif #endif
REG2MEM(movl, $IRQ_CHECK_CYCLES, irqCheckTimeout) movl $IRQ_CHECK_CYCLES, IRQ_CHECK_TIMEOUT(reg_args)
jmp continue1 jmp continue1
#endif #endif
@ -2193,12 +2183,12 @@ irq_checkpoint:
exception: testb $ResetSig, %al exception: testb $ResetSig, %al
jz ex_irq jz ex_irq
REG2MEM(testb, $0xff, joy_button0) // OpenApple testb $0xff, JOY_BUTTON0(reg_args) // OpenApple
jnz exit_reinit jnz exit_reinit
REG2MEM(testb, $0xff, joy_button1) // ClosedApple testb $0xff, JOY_BUTTON1(reg_args) // ClosedApple
jnz exit_reinit jnz exit_reinit
ex_reset: REG2MEM(movb, $0, cpu65__signal) ex_reset: movb $0, CPU65__SIGNAL(reg_args)
movw $0xFFFC, EffectiveAddr // ROM reset vector movw $0xFFFC, EffectiveAddr // ROM reset vector
GetFromEA_W GetFromEA_W
movw %ax, PC_Reg movw %ax, PC_Reg
@ -2223,16 +2213,16 @@ ex_irq: testb $I_Flag, F_Reg // Already interrupt
orb $X_Flag, F_Reg orb $X_Flag, F_Reg
xorw %ax, %ax xorw %ax, %ax
movb F_Reg, %al movb F_Reg, %al
MEM2REG_IND(movb,cpu65_flags_encode,_XAX,1,%al) MOVB_IND(CPU65_FLAGS_ENCODE,_XAX,%al)
Push(%al) Push(%al)
orb $(B_Flag | I_Flag), F_Reg orb $(B_Flag | I_Flag), F_Reg
//andb $~D_Flag, F_Reg // AppleWin clears Decimal bit? //andb $~D_Flag, F_Reg // AppleWin clears Decimal bit?
movLQ $0xFFFE, EffectiveAddr_X// HACK FIXME : there is a bug somewhere that is occasionally corrupting EffectiveAddr_X movLQ $0xFFFE, EffectiveAddr_X
GetFromEA_W GetFromEA_W
movw %ax, PC_Reg movw %ax, PC_Reg
xorb %ah, %ah xorb %ah, %ah
CPUStatsReset CPUStatsReset
REG2MEM(addb, $7, cpu65_opcycles); // IRQ handling will take additional 7 cycles addb $7, CPU65_OPCYCLES(reg_args); // IRQ handling will take additional 7 cycles
JumpNextInstruction JumpNextInstruction
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
@ -2241,47 +2231,30 @@ ex_irq: testb $I_Flag, F_Reg // Already interrupt
ENTRY(cpu65_run) ENTRY(cpu65_run)
pushLQ _XBP pushLQ _XBP
movLQ _XSP, _XBP
pushLQ _XDI pushLQ _XDI
pushLQ _XSI pushLQ _XSI
pushLQ _XBX pushLQ _XBX
#if __LP64__ #if __LP64__
// NOTE: should we be also preserving r12-r15? movLQ %rdi, reg_args
#endif #else
movLQ 4(%esp), reg_args
#if __PIC__ && __i386__ && !__APPLE__
calll .Lget_pc_thunk0
.Lget_pc_thunk0:
_POP_PICREG()
.Lget_pc_thunk1:
addl $_GLOBAL_OFFSET_TABLE_+(.Lget_pc_thunk1 - .Lget_pc_thunk0), _PICREG
pushl _PICREG
#endif #endif
// Restore CPU state when being called from C. // Restore CPU state when being called from C.
MEM2REG(movzwLQ, cpu65_ea, EffectiveAddr_X) movzwLQ CPU65_EA(reg_args), EffectiveAddr_X
MEM2REG(movzwLQ, cpu65_pc, PC_Reg_X) movzwLQ CPU65_PC(reg_args), PC_Reg_X
MEM2REG(movzbLQ, cpu65_a, AF_Reg_X) movzbLQ CPU65_A(reg_args), AF_Reg_X
MEM2REG(movzbLQ, cpu65_x, XY_Reg_X) movzbLQ CPU65_X(reg_args), XY_Reg_X
MEM2REG(movzbLQ, cpu65_f, _XAX) movb CPU65_Y(reg_args), Y_Reg
#if __PIC__
MEM2REG_IND(movb,cpu65_flags_decode,_XAX,1,%al) movzbLQ CPU65_F(reg_args), _XAX
movb %al, F_Reg MOVB_IND(CPU65_FLAGS_DECODE,_XAX,F_Reg)
MEM2REG(movb, cpu65_y, %al)
movb %al, Y_Reg cmpb $0, EMUL_REINITIALIZE(reg_args)
#else
MEM2REG_IND(movb,cpu65_flags_decode,_XAX,1,F_Reg)
MEM2REG(movb, cpu65_y, Y_Reg)
#endif
MEM2REG(movzbLQ, cpu65_sp, SP_Reg_X)
#ifdef APPLE2_VM
RestoreAltZP
#endif
REG2MEM(cmpb, $0, emul_reinitialize)
jnz enter_reinit jnz enter_reinit
jmp continue2 jmp continue2
enter_reinit: REG2MEM(movb, $0, emul_reinitialize) enter_reinit: movb $0, EMUL_REINITIALIZE(reg_args)
jmp ex_reset jmp ex_reset
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
@ -2290,18 +2263,16 @@ enter_reinit: REG2MEM(movb, $0, emul_reinitialize)
exit_cpu65_run: exit_cpu65_run:
// Save CPU state when returning from being called from C // Save CPU state when returning from being called from C
REG2MEM(movw, PC_Reg, cpu65_pc) movw PC_Reg, CPU65_PC(reg_args)
CommonSaveCPUState CommonSaveCPUState
_POP_PICREG()
popLQ _XBX popLQ _XBX
popLQ _XSI popLQ _XSI
popLQ _XDI popLQ _XDI
popLQ _XBP popLQ _XBP
ret ret
exit_reinit: REG2MEM(movb, $0, cpu65__signal) exit_reinit: movb $0, CPU65__SIGNAL(reg_args)
REG2MEM(movb, $1, emul_reinitialize) movb $1, EMUL_REINITIALIZE(reg_args)
_POP_PICREG()
popLQ _XBX popLQ _XBX
popLQ _XSI popLQ _XSI
popLQ _XDI popLQ _XDI
@ -2316,7 +2287,8 @@ ENTRY(cpu65_direct_write)
pushLQ EffectiveAddr_X pushLQ EffectiveAddr_X
movLQ 8(_XSP),EffectiveAddr_X movLQ 8(_XSP),EffectiveAddr_X
movLQ 12(_XSP),_XAX movLQ 12(_XSP),_XAX
CALL_IND(cpu65_vmem_w,EffectiveAddr_X,SZ_PTR) movLQ CPU65_VMEM_W(reg_args), _XBP;
callLQ *(_XBP,EffectiveAddr_X,SZ_PTR)
popLQ EffectiveAddr_X popLQ EffectiveAddr_X
ret ret

5
src/x86/glue-offsets.h Normal file
View File

@ -0,0 +1,5 @@
#if __LP64__
# include "glue-offsets64.h"
#else
# include "glue-offsets32.h"
#endif

53
src/x86/glue-offsets32.h Normal file
View File

@ -0,0 +1,53 @@
/* This file is auto-generated for a specific architecture ABI */
#define CPU_IRQCHECK 0
#define CPU65_TRACE_PROLOGUE 4
#define CPU65_TRACE_ARG 8
#define CPU65_TRACE_ARG1 12
#define CPU65_TRACE_ARG2 16
#define CPU65_TRACE_EPILOGUE 20
#define CPU65_TRACE_IRQ 24
#define DEBUG_ILLEGAL_BCD 28
#define CPU65_VMEM_R 32
#define CPU65_VMEM_W 36
#define CPU65_FLAGS_ENCODE 40
#define CPU65_FLAGS_DECODE 44
#define CPU65__OPCODES 48
#define CPU65__OPCYCLES 52
#define BASE_RAMRD 56
#define BASE_RAMWRT 60
#define BASE_TEXTRD 64
#define BASE_TEXTWRT 68
#define BASE_HGRRD 72
#define BASE_HGRWRT 76
#define BASE_STACKZP 80
#define BASE_D000_RD 84
#define BASE_E000_RD 88
#define BASE_D000_WRT 92
#define BASE_E000_WRT 96
#define BASE_C3ROM 100
#define BASE_C4ROM 104
#define BASE_C5ROM 108
#define BASE_CXROM 112
#define SOFTSWITCHES 116
#define GC_CYCLES_TIMER_0 120
#define GC_CYCLES_TIMER_1 124
#define CPU65_CYCLES_TO_EXECUTE 128
#define CPU65_CYCLE_COUNT 132
#define IRQ_CHECK_TIMEOUT 136
#define INTERRUPT_VECTOR 140
#define RESET_VECTOR 142
#define CPU65_PC 144
#define CPU65_EA 146
#define CPU65_A 148
#define CPU65_F 149
#define CPU65_X 150
#define CPU65_Y 151
#define CPU65_SP 152
#define CPU65_D 153
#define CPU65_RW 154
#define CPU65_OPCODE 155
#define CPU65_OPCYCLES 156
#define CPU65__SIGNAL 157
#define JOY_BUTTON0 158
#define JOY_BUTTON1 159
#define EMUL_REINITIALIZE 160

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

@ -0,0 +1,53 @@
/* This file is auto-generated for a specific architecture ABI */
#define CPU_IRQCHECK 0
#define CPU65_TRACE_PROLOGUE 8
#define CPU65_TRACE_ARG 16
#define CPU65_TRACE_ARG1 24
#define CPU65_TRACE_ARG2 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 IRQ_CHECK_TIMEOUT 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

@ -21,53 +21,52 @@
* to make calls back into C that conform with the x86 and x86_64 calling ABIs. * to make calls back into C that conform with the x86 and x86_64 calling ABIs.
*/ */
#if __PIC__ && __i386__
# define _A2_PIC_GOT(reg) 0x4(reg) // Stack offset assumes a CALL has been made that pushed %eip
#endif
#define _PUSH_COUNT ((/*args:*/7+/*ret:*/1) * SZ_PTR)
#define GLUE_EXTERN_C_READ(func) #define GLUE_EXTERN_C_READ(func)
#define GLUE_BANK_MAYBE_READ_CX(func,pointer) \ #define GLUE_BANK_MAYBE_READ_CX(func,pointer) \
ENTRY(func) REG2MEM(testLQ, $SS_CXROM, softswitches); \ ENTRY(func) testLQ $SS_CXROM, SOFTSWITCHES(reg_args); \
jnz 1f; \ jnz 1f; \
CALL_IND0(pointer); \ callLQ *pointer(reg_args); \
ret; \ ret; \
1: MEM2REG(addLQ, pointer, EffectiveAddr_X); \ 1: addLQ pointer(reg_args), EffectiveAddr_X; \
movb (EffectiveAddr_X),%al; \ movb (EffectiveAddr_X),%al; \
MEM2REG(subLQ, pointer, EffectiveAddr_X); \ subLQ pointer(reg_args), EffectiveAddr_X; \
ret; ret;
#define GLUE_BANK_MAYBE_READ_C3(func,pointer) \ #define GLUE_BANK_MAYBE_READ_C3(func,pointer) \
ENTRY(func) REG2MEM(testLQ, $SS_CXROM, softswitches); \ ENTRY(func) testLQ $SS_CXROM, SOFTSWITCHES(reg_args); \
jnz 1f; \ jnz 1f; \
REG2MEM(testLQ, $SS_C3ROM, softswitches); \ testLQ $SS_C3ROM, SOFTSWITCHES(reg_args); \
jnz 1f; \ jnz 1f; \
CALL_IND0(pointer); \ callLQ *pointer(reg_args); \
ret; \ ret; \
1: MEM2REG(addLQ, pointer, EffectiveAddr_X); \ 1: addLQ pointer(reg_args), EffectiveAddr_X; \
movb (EffectiveAddr_X),%al; \ movb (EffectiveAddr_X),%al; \
MEM2REG(subLQ, pointer, EffectiveAddr_X); \ subLQ pointer(reg_args), EffectiveAddr_X; \
ret; ret;
#define GLUE_BANK_READ(func,pointer) \ #define GLUE_BANK_READ(func,pointer) \
ENTRY(func) MEM2REG(addLQ, pointer, EffectiveAddr_X); \ ENTRY(func) addLQ pointer(reg_args), EffectiveAddr_X; \
movb (EffectiveAddr_X),%al; \ movb (EffectiveAddr_X),%al; \
MEM2REG(subLQ, pointer, EffectiveAddr_X); \ subLQ pointer(reg_args), EffectiveAddr_X; \
ret; ret;
#define GLUE_BANK_WRITE(func,pointer) \ #define GLUE_BANK_WRITE(func,pointer) \
ENTRY(func) MEM2REG(addLQ, pointer, EffectiveAddr_X); \ ENTRY(func) addLQ pointer(reg_args), EffectiveAddr_X; \
movb %al,(EffectiveAddr_X); \ movb %al,(EffectiveAddr_X); \
MEM2REG(subLQ, pointer, EffectiveAddr_X); \ subLQ pointer(reg_args), EffectiveAddr_X; \
ret; ret;
#define GLUE_BANK_MAYBEWRITE(func,pointer) \ #define GLUE_BANK_MAYBEWRITE(func,pointer) \
ENTRY(func) MEM2REG(addLQ, pointer, EffectiveAddr_X); \ ENTRY(func) addLQ pointer(reg_args), EffectiveAddr_X; \
REG2MEM(cmpl, $0, pointer); \ cmpl $0, pointer(reg_args); \
jz 1f; \ jz 1f; \
movb %al,(EffectiveAddr_X); \ movb %al,(EffectiveAddr_X); \
1: MEM2REG(subLQ, pointer, EffectiveAddr_X); \ 1: subLQ pointer(reg_args), EffectiveAddr_X; \
ret;
#define GLUE_INLINE_READ(func,off) \
ENTRY(func) movb off(reg_args), %al; \
ret; ret;
@ -86,57 +85,38 @@ ENTRY(func) MEM2REG(addLQ, pointer, EffectiveAddr_X); \
ENTRY(func) pushLQ _XAX; \ ENTRY(func) pushLQ _XAX; \
pushLQ XY_Reg_X; \ pushLQ XY_Reg_X; \
pushLQ AF_Reg_X; \ pushLQ AF_Reg_X; \
pushLQ SP_Reg_X; \ pushLQ reg_args; \
pushLQ PC_Reg_X; \ pushLQ PC_Reg_X; \
andLQ $0xff,_XAX; \ andLQ $0xff,_XAX; \
_PUSH_ARGS \ _PUSH_ARGS \
CALL_FN(callLQ, c_##func, _PUSH_COUNT); \ callLQ CALL(c_##func); \
_POP_ARGS \ _POP_ARGS \
popLQ PC_Reg_X; \ popLQ PC_Reg_X; \
popLQ SP_Reg_X; \ popLQ reg_args; \
popLQ AF_Reg_X; \ popLQ AF_Reg_X; \
popLQ XY_Reg_X; \ popLQ XY_Reg_X; \
popLQ _XAX; \ popLQ _XAX; \
ret; ret;
#if __PIC__ && __i386__ #define _GLUE_C_READ(func) \
# define _PUSH_GOT() movl _A2_PIC_GOT(%esp), _PICREG; \
pushl _PICREG;
# define _POP_GOT() addl $4, %esp
#else
# define _PUSH_GOT()
# define _POP_GOT()
#endif
// TODO FIXME : implement CDECL prologue/epilogues...
#define _GLUE_C_READ(func, ...) \
ENTRY(func) pushLQ XY_Reg_X; \ ENTRY(func) pushLQ XY_Reg_X; \
pushLQ AF_Reg_X; \ pushLQ AF_Reg_X; \
pushLQ SP_Reg_X; \ pushLQ reg_args; \
pushLQ PC_Reg_X; \ pushLQ PC_Reg_X; \
pushLQ _XAX; /* HACK: works around mysterious issue with generated mov(_XAX), _XAX ... */ \ pushLQ _XAX; /* HACK: works around mysterious issue with generated mov(_XAX), _XAX ... */ \
pushLQ EffectiveAddr_X; /* ea is arg0 (and preserved) */ \ pushLQ EffectiveAddr_X; /* ea is arg0 (and preserved) */ \
CALL_FN(callLQ, c_##func, _PUSH_COUNT); \ callLQ CALL(c_##func); \
popLQ EffectiveAddr_X; /* restore ea */ \ popLQ EffectiveAddr_X; /* restore ea */ \
movb %al, %dl; \ movb %al, %dl; \
popLQ _XAX; /* ... ugh */ \ popLQ _XAX; /* ... ugh */ \
movb %dl, %al; \ movb %dl, %al; \
popLQ PC_Reg_X; \ popLQ PC_Reg_X; \
popLQ SP_Reg_X; \ popLQ reg_args; \
popLQ AF_Reg_X; \ popLQ AF_Reg_X; \
popLQ XY_Reg_X; \ popLQ XY_Reg_X; \
_PUSH_GOT(); \
__VA_ARGS__ \
_POP_GOT(); \
ret; ret;
// TODO FIXME : implement CDECL prologue/epilogues...
#define GLUE_C_READ(FUNC) _GLUE_C_READ(FUNC) #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)
pushLQ _XAX; \
andLQ $0xFFFF, SP_Reg_X; \
RestoreAltZP \
popLQ _XAX; \
)