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 && \
$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=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) {
// joystick button settings should be balanced by c_joystick_reset() triggered on CPU thread
if (resetState == 1) {
joy_button0 = 0xff;
joy_button1 = 0x0;
run_args.joy_button0 = 0xff;
run_args.joy_button1 = 0x0;
} else {
joy_button0 = 0x0;
joy_button1 = 0xff;
run_args.joy_button0 = 0x0;
run_args.joy_button1 = 0xff;
}
}
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/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/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/SSI263Phonemes.h
noinst_PROGRAMS = genfont genrom
noinst_PROGRAMS = genfont genrom glue_offsets
###############################################################################
# Apple //ix and supporting sources
@ -87,6 +88,8 @@ genfont_SOURCES = src/genfont.c
genrom_SOURCES = src/genrom.c
glue_offsets_SOURCES = src/glue-offsets.c
src/font.c: src/font.txt genfont
./genfont < $< > $@

View File

@ -13,6 +13,7 @@
#define _CPU_REGS_H_
#include "cpu.h"
#include "glue-offsets.h"
// ARM register mappings
@ -25,7 +26,7 @@
#define X_Reg r7 /* 8bit 6502 X register */
#define A_Reg r8 /* 8bit 6502 A register */
// r9 is "ARM platform register" ... used as a scratch register
// r10 is another scratch variable
#define reg_args r10 /* cpu65_run() args register */
#define reg_vmem_r r11 /* cpu65_vmem_r table address */
// r12 is "ARM Intra-Procedure-call scratch register" ... used as a scratch register
// r13 ARM SP
@ -41,7 +42,6 @@
# define ROR_BIT 0x80000000
#endif
#if !defined(__APPLE__)
# define NO_UNDERSCORES 1
# define STRBNE strneb
@ -57,48 +57,5 @@
# define CALL(x) _##x
#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

View File

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

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_BANK_MAYBE_READ_CX(func,pointer) \
ENTRY(func) SYM(r1, softswitches); \
ldr r0, [r1]; \
SYM(r1, pointer); \
#define _GLUE_BANK_MAYBE_READ_CX(func,x,pointer) \
ENTRY(func) ldr r0, [reg_args, #SOFTSWITCHES]; \
ldr r1, [reg_args, x ## pointer]; \
tst r0, $SS_CXROM; \
bne 1f; \
push {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ lr}; \
ldr r1, [r1]; \
push {EffectiveAddr, PC_Reg, lr}; \
blx r1; \
pop {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ pc}; \
1: ldr r1, [r1]; \
ldrb r0, [r1, EffectiveAddr]; \
pop {EffectiveAddr, PC_Reg, pc}; \
1: ldrb r0, [r1, EffectiveAddr]; \
mov pc, lr;
#define GLUE_BANK_MAYBE_READ_C3(func,pointer) \
ENTRY(func) SYM(r1, softswitches); \
ldr r0, [r1]; \
SYM(r1, pointer); \
#define GLUE_BANK_MAYBE_READ_CX(func,pointer) _GLUE_BANK_MAYBE_READ_CX(func,#,pointer)
#define _GLUE_BANK_MAYBE_READ_C3(func,x,pointer) \
ENTRY(func) ldr r0, [reg_args, #SOFTSWITCHES]; \
ldr r1, [reg_args, x ## pointer]; \
tst r0, $SS_CXROM; \
bne 1f; \
tst r0, $SS_C3ROM; \
bne 1f; \
push {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ lr}; \
ldr r1, [r1]; \
push {EffectiveAddr, PC_Reg, lr}; \
blx r1; \
pop {EffectiveAddr, PC_Reg, /*SP_Reg, F_Reg, Y_Reg, X_Reg, A_Reg,*/ pc}; \
1: ldr r1, [r1]; \
pop {EffectiveAddr, PC_Reg, pc}; \
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]; \
mov pc, lr;
#define GLUE_BANK_READ(func,pointer) _GLUE_BANK_READ(func,#,pointer)
#define GLUE_BANK_READ(func,pointer) \
ENTRY(func) SYM(r1, 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]; \
#define _GLUE_BANK_WRITE(func,x,pointer) \
ENTRY(func) ldr r1, [reg_args, x ## pointer]; \
strb r0, [r1, EffectiveAddr]; \
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); \
ldr r1, [r1]; \
#define _GLUE_BANK_MAYBEWRITE(func,x,pointer) \
ENTRY(func) ldr r1, [reg_args, x ## pointer]; \
teq r1, #0; \
STRBNE r0, [r1, EffectiveAddr]; \
mov pc, lr;
#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) \
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; \
mov r1, r0; \
mov r0, EffectiveAddr; \
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) \
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; \
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)

View File

@ -22,20 +22,7 @@
#include "common.h"
uint16_t cpu65_pc;
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;
cpu65_run_args_s run_args = { 0 };
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();
void *const cpu65__opcodes[256] = {
void *cpu65__opcodes[256] = {
op_BRK, // 00
op_ORA_ind_x,
op_UNK_65c02,
@ -620,35 +607,69 @@ static void init_flags_conversion_tables(void) {
}
}
void cpu65_init(void)
{
init_flags_conversion_tables();
cpu65__signal = 0;
cpu65_pc = 0x0;
cpu65_ea = 0x0;
cpu65_a = 0xFF;
cpu65_x = 0xFF;
cpu65_y = 0xFF;
cpu65_f = (C_Flag_6502|X_Flag_6502|I_Flag_6502|V_Flag_6502|B_Flag_6502|Z_Flag_6502|N_Flag_6502);
cpu65_sp = 0xFC;
static __attribute__((constructor)) void __init_cpu65(void) {
// emulator_registerStartupCallback(CTOR_PRIORITY_LATE, &_init_cpu65); -- 2018/01/15 NOTE : too late for testcpu.c
extern void (*cpu_irqCheck)(uint16_t, uint8_t);
run_args.cpu_irqCheck = cpu_irqCheck;
run_args.cpu65_vmem_r = &cpu65_vmem_r[0];
run_args.cpu65_vmem_w = &cpu65_vmem_w[0];
run_args.cpu65_flags_encode = &cpu65_flags_encode[0];
run_args.cpu65_flags_decode = &cpu65_flags_decode[0];
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);
cpu65__signal |= reason;
run_args.cpu65__signal |= reason;
pthread_mutex_unlock(&irq_mutex);
}
void cpu65_uninterrupt(int reason)
{
void cpu65_uninterrupt(int reason) {
pthread_mutex_lock(&irq_mutex);
cpu65__signal &= ~reason;
run_args.cpu65__signal &= ~reason;
pthread_mutex_unlock(&irq_mutex);
}
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);
}
@ -660,40 +681,33 @@ bool cpu65_saveState(StateHelper_s *helper) {
uint8_t serialized[4] = { 0 };
// save CPU state
serialized[0] = ((cpu65_pc & 0xFF00) >> 8);
serialized[1] = ((cpu65_pc & 0xFF ) >> 0);
if (!helper->save(fd, serialized, sizeof(cpu65_pc))) {
serialized[0] = ((run_args.cpu65_pc & 0xFF00) >> 8);
serialized[1] = ((run_args.cpu65_pc & 0xFF ) >> 0);
if (!helper->save(fd, serialized, sizeof(run_args.cpu65_pc))) {
break;
}
LOG("SAVE cpu65_pc = %04x", cpu65_pc);
serialized[0] = ((cpu65_ea & 0xFF00) >> 8);
serialized[1] = ((cpu65_ea & 0xFF ) >> 0);
if (!helper->save(fd, serialized, sizeof(cpu65_ea))) {
serialized[0] = ((run_args.cpu65_ea & 0xFF00) >> 8);
serialized[1] = ((run_args.cpu65_ea & 0xFF ) >> 0);
if (!helper->save(fd, serialized, sizeof(run_args.cpu65_ea))) {
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;
}
LOG("SAVE cpu65_a = %02x", cpu65_a);
if (!helper->save(fd, &cpu65_f, sizeof(cpu65_f))) {
if (!helper->save(fd, &run_args.cpu65_f, sizeof(run_args.cpu65_f))) {
break;
}
LOG("SAVE cpu65_f = %02x", cpu65_f);
if (!helper->save(fd, &cpu65_x, sizeof(cpu65_x))) {
if (!helper->save(fd, &run_args.cpu65_x, sizeof(run_args.cpu65_x))) {
break;
}
LOG("SAVE cpu65_x = %02x", cpu65_x);
if (!helper->save(fd, &cpu65_y, sizeof(cpu65_y))) {
if (!helper->save(fd, &run_args.cpu65_y, sizeof(run_args.cpu65_y))) {
break;
}
LOG("SAVE cpu65_y = %02x", cpu65_y);
if (!helper->save(fd, &cpu65_sp, sizeof(cpu65_sp))) {
if (!helper->save(fd, &run_args.cpu65_sp, sizeof(run_args.cpu65_sp))) {
break;
}
LOG("SAVE cpu65_sp = %02x", cpu65_sp);
saved = true;
} while (0);
@ -713,37 +727,30 @@ bool cpu65_loadState(StateHelper_s *helper) {
if (!helper->load(fd, serialized, sizeof(uint16_t))) {
break;
}
cpu65_pc = (serialized[0] << 8);
cpu65_pc |= serialized[1];
LOG("LOAD cpu65_pc = %04x", cpu65_pc);
run_args.cpu65_pc = (serialized[0] << 8);
run_args.cpu65_pc |= serialized[1];
if (!helper->load(fd, serialized, sizeof(uint16_t))) {
break;
}
cpu65_ea = (serialized[0] << 8);
cpu65_ea |= serialized[1];
LOG("LOAD cpu65_ea = %04x", cpu65_ea);
run_args.cpu65_ea = (serialized[0] << 8);
run_args.cpu65_ea |= serialized[1];
if (!helper->load(fd, &cpu65_a, sizeof(cpu65_a))) {
if (!helper->load(fd, &run_args.cpu65_a, sizeof(run_args.cpu65_a))) {
break;
}
LOG("LOAD cpu65_a = %02x", cpu65_a);
if (!helper->load(fd, &cpu65_f, sizeof(cpu65_f))) {
if (!helper->load(fd, &run_args.cpu65_f, sizeof(run_args.cpu65_f))) {
break;
}
LOG("LOAD cpu65_f = %02x", cpu65_f);
if (!helper->load(fd, &cpu65_x, sizeof(cpu65_x))) {
if (!helper->load(fd, &run_args.cpu65_x, sizeof(run_args.cpu65_x))) {
break;
}
LOG("LOAD cpu65_x = %02x", cpu65_x);
if (!helper->load(fd, &cpu65_y, sizeof(cpu65_y))) {
if (!helper->load(fd, &run_args.cpu65_y, sizeof(run_args.cpu65_y))) {
break;
}
LOG("LOAD cpu65_y = %02x", cpu65_y);
if (!helper->load(fd, &cpu65_sp, sizeof(cpu65_sp))) {
if (!helper->load(fd, &run_args.cpu65_sp, sizeof(run_args.cpu65_sp))) {
break;
}
LOG("LOAD cpu65_sp = %02x", cpu65_sp);
loaded = true;
} while (0);
@ -782,7 +789,7 @@ void cpu65_trace_toggle(const char *trace_file) {
GLUE_C_WRITE(cpu65_trace_prologue)
{
nargs = 0;
current_pc = cpu65_pc;
current_pc = run_args.cpu65_pc;
}
GLUE_C_WRITE(cpu65_trace_arg)
@ -816,14 +823,14 @@ GLUE_C_WRITE(cpu65_trace_epilogue)
assert(nargs > 0);
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");
}
switch (opcodes_65c02[cpu65_opcode].mode) {
switch (opcodes_65c02[run_args.cpu65_opcode].mode) {
case addr_implied:
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;
case addr_immediate:
case addr_zeropage:
@ -833,64 +840,63 @@ GLUE_C_WRITE(cpu65_trace_epilogue)
case addr_indirect_x:
case addr_indirect_y:
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;
case addr_absolute:
case addr_absolute_x:
case addr_absolute_y:
case addr_j_indirect:
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;
default:
fprintf(cpu_trace_fp, "invalid opcode mode");
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
char 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';
}
if (cpu65_f & X_Flag_6502) {
if (run_args.cpu65_f & X_Flag_6502) {
flags_buf[1]='X';
}
if (cpu65_f & I_Flag_6502) {
if (run_args.cpu65_f & I_Flag_6502) {
flags_buf[2]='I';
}
if (cpu65_f & V_Flag_6502) {
if (run_args.cpu65_f & V_Flag_6502) {
flags_buf[3]='V';
}
if (cpu65_f & B_Flag_6502) {
if (run_args.cpu65_f & B_Flag_6502) {
flags_buf[4]='B';
}
if (cpu65_f & D_Flag_6502) {
if (run_args.cpu65_f & D_Flag_6502) {
flags_buf[5]='D';
}
if (cpu65_f & Z_Flag_6502) {
if (run_args.cpu65_f & Z_Flag_6502) {
flags_buf[6]='Z';
}
if (cpu65_f & N_Flag_6502) {
if (run_args.cpu65_f & N_Flag_6502) {
flags_buf[7]='N';
}
flags_buf[8] = '\0';
char fmt[64];
if (UNLIKELY(cpu65_opcycles >= 10)) {
if (UNLIKELY(run_args.cpu65_opcycles >= 10)) {
// occurs rarely for interrupt + opcode
snprintf(fmt, 64, "%s", " %s CY:%u irqChk:%d totCyc:%d EA:%04X");
} else {
snprintf(fmt, 64, "%s", " %s CYC:%u irqChk:%d totCyc:%d EA:%04X");
}
extern int32_t irqCheckTimeout;
fprintf(cpu_trace_fp, fmt, flags_buf, cpu65_opcycles, (irqCheckTimeout - cpu65_opcycles), (cycles_count_total + cpu65_opcycles), cpu65_ea);
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);
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_accumulator:
fprintf(cpu_trace_fp, "%s", fmt);
@ -928,7 +934,7 @@ GLUE_C_WRITE(cpu65_trace_epilogue)
GLUE_C_WRITE(cpu65_trace_irq)
{
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 <stdint.h>
#include "glue.h"
/* types */
#define MEM_READ_FLAG (1<<0)
#define MEM_WRITE_FLAG (1<<1)
extern uint16_t cpu65_pc; // Program counter
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
extern cpu65_run_args_s run_args;
/* Set up the processor for a new run. Sets up opcode table. */
extern void cpu65_init();
@ -48,7 +39,7 @@ extern void cpu65_init();
extern void cpu65_interrupt(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 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_w[65536];
extern unsigned char cpu65_flags_encode[256];
extern unsigned char cpu65_flags_decode[256];
extern int32_t cpu65_cycle_count;
extern uint8_t cpu65_flags_encode[256];
extern uint8_t cpu65_flags_decode[256];
#if CPU_TRACING
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)
{
base_textwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches);
run_args.base_textwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) {
return;
}
if (!(softswitches & SS_PAGE2)) {
if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_text0_mixed)
{
base_textwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches);
run_args.base_textwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) {
return;
}
if (!(softswitches & SS_PAGE2)) {
if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_text1)
{
base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches);
run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) {
return;
}
if (softswitches & SS_PAGE2) {
if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_text1_mixed)
{
base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches);
run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_HIRES) {
return;
}
if (softswitches & SS_PAGE2) {
if (run_args.softswitches & SS_PAGE2) {
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)
{
base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches);
run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (!(softswitches & SS_PAGE2)) {
if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_even0_mixed)
{
base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches);
run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (!(softswitches & SS_PAGE2)) {
if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_odd0)
{
base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches);
run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (!(softswitches & SS_PAGE2)) {
if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_odd0_mixed)
{
base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches);
run_args.base_hgrwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (!(softswitches & SS_PAGE2)) {
if (!(run_args.softswitches & SS_PAGE2)) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_even1)
{
base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches);
run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (softswitches & SS_PAGE2) {
if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_even1_mixed)
{
base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches);
run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (softswitches & SS_PAGE2) {
if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_odd1)
{
base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(softswitches);
run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMainMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (softswitches & SS_PAGE2) {
if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG);
}
}
GLUE_C_WRITE(video__write_2e_odd1_mixed)
{
base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(softswitches);
run_args.base_ramwrt[ea] = b;
drawpage_mode_t mode = _currentMixedMode(run_args.softswitches);
if (mode == DRAWPAGE_TEXT) {
return;
}
if (softswitches & SS_PAGE2) {
if (run_args.softswitches & SS_PAGE2) {
video_setDirty(A2_DIRTY_FLAG);
}
}
@ -1294,7 +1294,7 @@ void display_renderStagingFramebuffer(uint8_t *stagingFB) {
int page = 0;
int bank = 0;
const uint32_t mainswitches = softswitches;
const uint32_t mainswitches = run_args.softswitches;
// render main portion of screen ...
@ -1323,7 +1323,7 @@ void display_renderStagingFramebuffer(uint8_t *stagingFB) {
}
// 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);
_currentPageAndBank(mixedswitches, mixedDrawPageMode, &page, &bank);
@ -1361,7 +1361,7 @@ void display_flashText(void) {
normal = !normal;
// 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) {
colormap[ COLOR_FLASHING_BLACK].red = 0;
colormap[ COLOR_FLASHING_BLACK].green = 0;
@ -1407,12 +1407,11 @@ unsigned long video_clearDirty(unsigned long flags) {
extern unsigned int CpuGetCyclesThisVideoFrame(void);
uint16_t video_scanner_get_address(bool *vblBarOut) {
const bool SW_HIRES = (softswitches & SS_HIRES);
const bool SW_TEXT = (softswitches & SS_TEXT);
const bool SW_PAGE2 = (softswitches & SS_PAGE2);
const bool SW_80STORE = (softswitches & SS_80STORE);
const bool SW_MIXED = (softswitches & SS_MIXED);
const bool SW_HIRES = (run_args.softswitches & SS_HIRES);
const bool SW_TEXT = (run_args.softswitches & SS_TEXT);
const bool SW_PAGE2 = (run_args.softswitches & SS_PAGE2);
const bool SW_80STORE = (run_args.softswitches & SS_80STORE);
const bool SW_MIXED = (run_args.softswitches & SS_MIXED);
// get video scanner position
unsigned int nCycles = CpuGetCyclesThisVideoFrame();

View File

@ -1,6 +1,7 @@
#!/bin/sh
echo "#include \"$TARGET_ARCH/glue-prologue.h\""
echo "#include \"$TARGET_ARCH/glue-offsets.h\""
while test "x$1" != "x" ; do
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__)
# error assembler-specific glue code should be in the arch-specific area
#endif
@ -23,6 +26,8 @@
#define GLUE_BANK_WRITE(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)
#if VM_TRACING
@ -68,3 +73,131 @@
#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 */
uint16_t joy_x = 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;
#ifdef KEYPAD_JOYSTICK
@ -114,8 +112,8 @@ static void c_calibrate_pc_joystick()
x_last = x_plot;
y_last = y_plot;
joymenu[CALIBRATE_JOYMENU_H-4][8] = joy_button0 ? 'X' : ' ';
joymenu[CALIBRATE_JOYMENU_H-4][15] = joy_button1 ? 'X' : ' ';
joymenu[CALIBRATE_JOYMENU_H-4][8] = run_args.joy_button0 ? 'X' : ' ';
joymenu[CALIBRATE_JOYMENU_H-4][15] = run_args.joy_button1 ? 'X' : ' ';
snprintf(temp, TEMPSIZE, "%04x", (short)(joy_x));
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];
for (;;)
{
submenu[KEYPAD_SUBMENU_H-2][12] = joy_button0 ? 'X' : ' ';
submenu[KEYPAD_SUBMENU_H-2][23] = joy_button1 ? 'X' : ' ';
submenu[KEYPAD_SUBMENU_H-2][12] = run_args.joy_button0 ? 'X' : ' ';
submenu[KEYPAD_SUBMENU_H-2][23] = run_args.joy_button1 ? 'X' : ' ';
snprintf(temp, TEMPSIZE, "%02x", (uint8_t)joy_x);
copy_and_pad_string(&submenu[KEYPAD_SUBMENU_H-2][31], temp, ' ', 3, ' ');
@ -272,8 +270,8 @@ static void *_joystick_resetDelayed(void *ctx) {
// delay
sleep(1);
joy_button0 = 0x0;
joy_button1 = 0x0;
run_args.joy_button0 = 0x0;
run_args.joy_button1 = 0x0;
return NULL;
}
@ -286,8 +284,8 @@ void c_joystick_reset(void)
#if TESTING
// For "testdisk" determinism, these need to be reset immediately
joy_button0 = 0x0;
joy_button1 = 0x0;
run_args.joy_button0 = 0x0;
run_args.joy_button1 = 0x0;
#else
pthread_t pid;
pthread_create(&pid, NULL, (void *)&_joystick_resetDelayed, (void *)NULL);
@ -339,11 +337,11 @@ uint8_t joydriver_getAxisY(void) {
// set button 0 pressed
void joydriver_setButton0Pressed(bool pressed) {
joy_button0 = (pressed) ? 0x80 : 0x0;
run_args.joy_button0 = (pressed) ? 0x80 : 0x0;
}
// set button 1 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_y;
extern uint8_t joy_button0;
extern uint8_t joy_button1;
extern bool joy_clip_to_radius;
#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;
return c; // Apple //e (0x20-0x3F) -> ASCII (0x20-0x3F)
} else if (c < 0x60) {
if (/*altchar on:*/(softswitches & SS_ALTCHAR)) {
if (/*altchar on:*/(run_args.softswitches & SS_ALTCHAR)) {
*mode = FONT_MODE_MOUSETEXT;
return c+0x40;
} 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)
}
} else if (c < 0x80) {
if (/*altchar on:*/(softswitches & SS_ALTCHAR)) {
if (/*altchar on:*/(run_args.softswitches & SS_ALTCHAR)) {
*mode = FONT_MODE_INVERSE;
return c; // Apple //e (0x60-0x7F) -> ASCII (0x60-0x7F)
} else {
@ -238,10 +238,10 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
switch (keymap[ scancode ])
{
case JB0:
joy_button0 = 0xff; /* open apple */
run_args.joy_button0 = 0xff; /* open apple */
break;
case JB1:
joy_button1 = 0xff; /* closed apple */
run_args.joy_button1 = 0xff; /* closed apple */
break;
default:
next_key = keymap[scancode];
@ -254,10 +254,10 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked)
switch (keymap[ scancode ])
{
case JB0:
joy_button0 = 0x00;
run_args.joy_button0 = 0x00;
break;
case JB1:
joy_button1 = 0x00;
run_args.joy_button1 = 0x00;
break;
default:
break;

View File

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

View File

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

View File

@ -126,7 +126,7 @@ int c_get_current_rambank(int addrs) {
/* if SLOTCXROM, then internal rom (regardless of
SLOTC3ROM setting). */
if (softswitches & SS_CXROM)
if (run_args.softswitches & SS_CXROM)
{
return 1;
}
@ -134,7 +134,7 @@ int c_get_current_rambank(int addrs) {
/* slot 3 rom */
if ((addrs >= 0xC300) && (addrs < 0xC400))
{
return !!(softswitches & SS_C3ROM);
return !!(run_args.softswitches & SS_C3ROM);
}
return 0; /* peripheral rom */
@ -143,28 +143,28 @@ int c_get_current_rambank(int addrs) {
/* text page 1 */
if ((addrs >= 0x400) && (addrs < 0x800))
{
return !!(softswitches & SS_TEXTRD);
return !!(run_args.softswitches & SS_TEXTRD);
}
/* hires page 1 with 80STORE and HIRES on */
if ((addrs >= 0x2000) && (addrs < 0x4000))
{
return !!(softswitches & SS_HGRRD);
return !!(run_args.softswitches & SS_HGRRD);
}
/* otherwise return RAMRD flag */
return !!(softswitches & SS_RAMRD);
return !!(run_args.softswitches & SS_RAMRD);
}
/* executing in ALTZP space. */
return !!(softswitches & SS_ALTZP);
return !!(run_args.softswitches & SS_ALTZP);
}
/* -------------------------------------------------------------------------
get_last_opcode () - returns the last executed 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.
------------------------------------------------------------------------- */
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;
/* 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 */
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
{
return apple_ii_64k[bank][cpu65_pc];
return apple_ii_64k[bank][run_args.cpu65_pc];
}
}
/* LC BANK RAM */
if (softswitches & SS_BANK2)
if (run_args.softswitches & SS_BANK2)
{
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
{
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);
}
if (!lc && (softswitches & SS_LCRAM) && (addrs >= 0xd000))
if (!lc && (run_args.softswitches & SS_LCRAM) && (addrs >= 0xd000))
{
/* read lc anyway */
lc = 1 + !!(softswitches & SS_BANK2);
lc = 1 + !!(run_args.softswitches & SS_BANK2);
}
if ((addrs < 0) || (addrs > 0xffff))
{
addrs = cpu65_pc;
addrs = run_args.cpu65_pc;
orig_addrs = addrs;
}
@ -334,7 +334,7 @@ void search_mem(char *hexstr, int lc, int rambank) {
/* check which rambank for cpu65_pc */
if (rambank == -1)
{
rambank = c_get_current_rambank(cpu65_pc);
rambank = c_get_current_rambank(run_args.cpu65_pc);
}
/* iterate over memory */
@ -531,16 +531,16 @@ void disasm(int addrs, int len, int lc, int rambank) {
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 */
lc = 1 + !!(softswitches & SS_BANK2);
lc = 1 + !!(run_args.softswitches & SS_BANK2);
}
/* handle invalid address request */
if ((addrs < 0) || (addrs > 0xffff))
{
addrs = cpu65_pc;
addrs = run_args.cpu65_pc;
orig_addrs = addrs;
}
@ -682,46 +682,46 @@ void disasm(int addrs, int len, int lc, int rambank) {
------------------------------------------------------------------------- */
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++], "X = %02X Y = %02X A = %02X F = %02X", cpu65_x, cpu65_y, cpu65_a, cpu65_f);
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", run_args.cpu65_x, run_args.cpu65_y, run_args.cpu65_a, run_args.cpu65_f);
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';
}
if (cpu65_f & X_Flag_6502)
if (run_args.cpu65_f & X_Flag_6502)
{
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';
}
if (cpu65_f & V_Flag_6502)
if (run_args.cpu65_f & V_Flag_6502)
{
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';
}
if (cpu65_f & D_Flag_6502)
if (run_args.cpu65_f & D_Flag_6502)
{
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';
}
if (cpu65_f & N_Flag_6502)
if (run_args.cpu65_f & N_Flag_6502)
{
second_buf[num_buffer_lines][7]='N';
}
@ -744,23 +744,23 @@ static int will_branch() {
switch (op)
{
case 0x10: /* BPL */
return (int) !(cpu65_f & N_Flag_6502);
return (int) !(run_args.cpu65_f & N_Flag_6502);
case 0x30: /* BMI */
return (int) (cpu65_f & N_Flag_6502);
return (int) (run_args.cpu65_f & N_Flag_6502);
case 0x50: /* BVC */
return (int) !(cpu65_f & V_Flag_6502);
return (int) !(run_args.cpu65_f & V_Flag_6502);
case 0x70: /* BVS */
return (int) (cpu65_f & V_Flag_6502);
return (int) (run_args.cpu65_f & V_Flag_6502);
case 0x80: /* BRA */
return 1;
case 0x90: /* BCC */
return (int) !(cpu65_f & C_Flag_6502);
return (int) !(run_args.cpu65_f & C_Flag_6502);
case 0xb0: /* BCS */
return (int) (cpu65_f & C_Flag_6502);
return (int) (run_args.cpu65_f & C_Flag_6502);
case 0xd0: /* BNE */
return (int) !(cpu65_f & Z_Flag_6502);
return (int) !(run_args.cpu65_f & Z_Flag_6502);
case 0xf0: /* BEQ */
return (int) (cpu65_f & Z_Flag_6502);
return (int) (run_args.cpu65_f & Z_Flag_6502);
}
return BRANCH_NA;
@ -877,28 +877,28 @@ int at_haltpt() {
uint8_t op = get_last_opcode();
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;
}
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;
}
}
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++)
{
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;
}
else
@ -907,7 +907,7 @@ int at_haltpt() {
++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() {
int i = num_buffer_lines;
sprintf(second_buf[i++], "lc bank = %d", 1 + !!(softswitches & SS_BANK2));
(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");
sprintf(second_buf[i++], "second = %d", !!(softswitches & SS_LCSEC));
sprintf(second_buf[i++], "lc bank = %d", 1 + !!(run_args.softswitches & SS_BANK2));
(run_args.softswitches & SS_LCWRT) ? sprintf(second_buf[i++], "write LC") : sprintf(second_buf[i++], "LC write protected");
(run_args.softswitches & SS_LCRAM) ? sprintf(second_buf[i++], "read LC") : sprintf(second_buf[i++], "read ROM");
sprintf(second_buf[i++], "second = %d", !!(run_args.softswitches & SS_LCSEC));
num_buffer_lines = i;
}
void show_misc_info() {
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++], "MIXED (%04X): %s", SW_MIXED + !!(softswitches & SS_MIXED), (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++], "HIRES (%04X): %s", SW_HIRES + !!(softswitches & SS_HIRES), (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++], "RAMRD (%04X): %s", SW_RAMRD + !!(softswitches & SS_RAMRD), (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++], "ALTZP (%04X): %s", SW_ALTZP + !!(softswitches & SS_ALTZP), (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++], "ALTCHAR (%04X): %s", SW_ALTCHAR + !!(softswitches & SS_ALTCHAR), (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++], "SLOTCXROM (%04X): %s", SW_SLOTCXROM + !!(softswitches & SS_CXROM), (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++], "IOUDIS (%04X): %s", SW_IOUDIS + !!(softswitches & SS_IOUDIS), (softswitches & SS_IOUDIS) ? "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 + !!(run_args.softswitches & SS_MIXED), (run_args.softswitches & SS_MIXED) ? "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 + !!(run_args.softswitches & SS_HIRES), (run_args.softswitches & SS_HIRES) ? "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 + !!(run_args.softswitches & SS_RAMRD), (run_args.softswitches & SS_RAMRD) ? "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 + !!(run_args.softswitches & SS_ALTZP), (run_args.softswitches & SS_ALTZP) ? "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 + !!(run_args.softswitches & SS_ALTCHAR), (run_args.softswitches & SS_ALTCHAR) ? "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 + !!(run_args.softswitches & SS_CXROM), (run_args.softswitches & SS_CXROM) ? "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 + !!(run_args.softswitches & SS_IOUDIS), (run_args.softswitches & SS_IOUDIS) ? "on" : "off");
/* sprintf(second_buf[i++], "RDVBLBAR: %s", (SLOTCXROM & 0x80) */
/* ? "on" : "off"); */
@ -1228,7 +1228,7 @@ bool c_debugger_should_break() {
case UNTILING:
{
if (stepping_struct.step_pc == cpu65_pc) {
if (stepping_struct.step_pc == run_args.cpu65_pc) {
stepping_struct.should_break = true;
}
}
@ -1275,7 +1275,7 @@ int debugger_go(stepping_struct_t s) {
#if !TESTING
if (stepping_struct.step_type != LOADING) {
clear_debugger_screen();
disasm(cpu65_pc, 1, 0, -1);
disasm(run_args.cpu65_pc, 1, 0, -1);
int branch = will_branch();
if (branch != BRANCH_NA) {
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) {
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
apple_ii_64k[0][TESTOUT_ADDR] = 0x00;
joy_button0 = 0xff;
run_args.joy_button0 = 0xff;
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][WATCHPOINT_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);
if (test_do_reboot) {
cpu65_interrupt(ResetSig);

View File

@ -19,7 +19,7 @@ static void testdisplay_setup(void *arg) {
test_common_setup();
apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00;
apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00;
joy_button0 = 0xff; // OpenApple
run_args.joy_button0 = 0xff; // OpenApple
if (test_do_reboot) {
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][WATCHPOINT_ADDR] = 0x00;
if (test_do_reboot) {
joy_button0 = 0xff; // OpenApple
run_args.joy_button0 = 0xff; // OpenApple
cpu65_interrupt(ResetSig);
}
}
@ -69,32 +69,32 @@ static int _assert_blank_boot(void) {
ASSERT(disk6.disk[0].skew_table == skew_table_6_do);
// 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("2C82E33E964936187CA1DABF71AE6148916BD131", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == apple_ii_64k[0]);
ASSERT(base_d000_wrt == language_banks[0] - 0xD000);
ASSERT(base_e000_rd == apple_ii_64k[0]);
ASSERT(base_e000_wrt == language_card[0] - 0xE000);
ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(run_args.base_d000_rd == apple_ii_64k[0]);
ASSERT(run_args.base_d000_wrt == language_banks[0] - 0xD000);
ASSERT(run_args.base_e000_rd == apple_ii_64k[0]);
ASSERT(run_args.base_e000_wrt == language_card[0] - 0xE000);
// CPU ...
ASSERT(cpu65_pc == 0xE783);
ASSERT(cpu65_ea == 0x1F33);
ASSERT(cpu65_a == 0xFF);
ASSERT(cpu65_f == 0x37);
ASSERT(cpu65_x == 0xFF);
ASSERT(cpu65_y == 0x00);
ASSERT(cpu65_sp == 0xF6);
ASSERT(run_args.cpu65_pc == 0xE783);
ASSERT(run_args.cpu65_ea == 0x1F33);
ASSERT(run_args.cpu65_a == 0xFF);
ASSERT(run_args.cpu65_f == 0x37);
ASSERT(run_args.cpu65_x == 0xFF);
ASSERT(run_args.cpu65_y == 0x00);
ASSERT(run_args.cpu65_sp == 0xF6);
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));
FREE(pathB);
}
return 0;
}
TEST test_save_state_1() {
@ -275,32 +277,32 @@ TEST test_load_A2VM_good1() {
//ASSERT(disk6.disk[0].skew_table == skew_table_6_do);
// 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("2C82E33E964936187CA1DABF71AE6148916BD131", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == apple_ii_64k[0]);
ASSERT(base_d000_wrt == language_banks[0] - 0xD000);
ASSERT(base_e000_rd == apple_ii_64k[0]);
ASSERT(base_e000_wrt == language_card[0] - 0xE000);
ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(run_args.base_d000_rd == apple_ii_64k[0]);
ASSERT(run_args.base_d000_wrt == language_banks[0] - 0xD000);
ASSERT(run_args.base_e000_rd == apple_ii_64k[0]);
ASSERT(run_args.base_e000_wrt == language_card[0] - 0xE000);
// CPU ...
ASSERT(cpu65_pc == 0xC83D);
ASSERT(cpu65_ea == 0x004E);
ASSERT(cpu65_a == 0x0D);
ASSERT(cpu65_f == 0x35);
ASSERT(cpu65_x == 0x09);
ASSERT(cpu65_y == 0x01);
ASSERT(cpu65_sp == 0xEA);
ASSERT(run_args.cpu65_pc == 0xC83D);
ASSERT(run_args.cpu65_ea == 0x004E);
ASSERT(run_args.cpu65_a == 0x0D);
ASSERT(run_args.cpu65_f == 0x35);
ASSERT(run_args.cpu65_x == 0x09);
ASSERT(run_args.cpu65_y == 0x01);
ASSERT(run_args.cpu65_sp == 0xEA);
TEMP_FAILURE_RETRY(close(fdState));
TEMP_FAILURE_RETRY(close(fdA));
@ -389,32 +391,32 @@ TEST test_load_A2V2_good1() {
//ASSERT(disk6.disk[0].skew_table == skew_table_6_do);
// 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("54C8611AA3FD1813B1BEE45EF7F4B2303C51C679", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("36F1699537024EC6017A22641FF0EC277AFFD49D", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == language_banks[0]-0xD000);
ASSERT(base_d000_wrt == language_banks[0]-0xD000);
ASSERT(base_e000_rd == language_card[0]-0xE000);
ASSERT(base_e000_wrt == language_card[0]-0xE000);
ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(run_args.base_d000_rd == language_banks[0]-0xD000);
ASSERT(run_args.base_d000_wrt == language_banks[0]-0xD000);
ASSERT(run_args.base_e000_rd == language_card[0]-0xE000);
ASSERT(run_args.base_e000_wrt == language_card[0]-0xE000);
// CPU ...
ASSERT(cpu65_pc == 0xF6EA);
ASSERT(cpu65_ea == 0x0018);
ASSERT(cpu65_a == 0x05);
ASSERT(cpu65_f == 0x33);
ASSERT(cpu65_x == 0x10);
ASSERT(cpu65_y == 0x02);
ASSERT(cpu65_sp == 0xFA);
ASSERT(run_args.cpu65_pc == 0xF6EA);
ASSERT(run_args.cpu65_ea == 0x0018);
ASSERT(run_args.cpu65_a == 0x05);
ASSERT(run_args.cpu65_f == 0x33);
ASSERT(run_args.cpu65_x == 0x10);
ASSERT(run_args.cpu65_y == 0x02);
ASSERT(run_args.cpu65_sp == 0xFA);
// Timing ...
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);
// 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("B3268356F9F4F4ACAE2F4FF49D4FED1D36535DDA", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("0B6E45306506F92554102485CE9B500C6779D145", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == language_banks[0]-0xD000);
ASSERT(base_d000_wrt == language_banks[0]-0xD000);
ASSERT(base_e000_rd == language_card[0]-0xE000);
ASSERT(base_e000_wrt == language_card[0]-0xE000);
ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(run_args.base_d000_rd == language_banks[0]-0xD000);
ASSERT(run_args.base_d000_wrt == language_banks[0]-0xD000);
ASSERT(run_args.base_e000_rd == language_card[0]-0xE000);
ASSERT(run_args.base_e000_wrt == language_card[0]-0xE000);
// CPU ...
ASSERT(cpu65_pc == 0x8474);
ASSERT(cpu65_ea == 0x8474);
ASSERT(cpu65_a == 0x00);
ASSERT(cpu65_f == 0x73);
ASSERT(cpu65_x == 0x04);
ASSERT(cpu65_y == 0x21);
ASSERT(cpu65_sp == 0xF1);
ASSERT(run_args.cpu65_pc == 0x8474);
ASSERT(run_args.cpu65_ea == 0x8474);
ASSERT(run_args.cpu65_a == 0x00);
ASSERT(run_args.cpu65_f == 0x73);
ASSERT(run_args.cpu65_x == 0x04);
ASSERT(run_args.cpu65_y == 0x21);
ASSERT(run_args.cpu65_sp == 0xF1);
// Timing ...
long scaleFactor = (long)(cpu_scale_factor * 100.);
@ -637,32 +639,32 @@ TEST test_load_A2V2_good3() {
ASSERT(!disk6.disk[1].track_dirty);
// 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("DF3EE367193484A6A1C28C2BAE0EFEF42E6D19BB", language_card[0], /*len:*/sizeof(language_card));
ASSERT_SHA_BIN("343C30374074AB3AEE22581A6477736121390B18", language_banks[0], /*len:*/sizeof(language_banks));
ASSERT(base_ramrd == apple_ii_64k[0]);
ASSERT(base_ramwrt == apple_ii_64k[0]);
ASSERT(base_textrd == apple_ii_64k[0]);
ASSERT(base_textwrt == apple_ii_64k[0]);
ASSERT(base_hgrrd == apple_ii_64k[0]);
ASSERT(base_hgrwrt == apple_ii_64k[0]);
ASSERT(base_stackzp == apple_ii_64k[0]);
ASSERT(base_c3rom == apple_ii_64k[1]);
ASSERT(base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(base_d000_rd == language_banks[0]-0xD000);
ASSERT(base_d000_wrt == language_banks[0]-0xD000);
ASSERT(base_e000_rd == language_card[0]-0xE000);
ASSERT(base_e000_wrt == language_card[0]-0xE000);
ASSERT(run_args.base_ramrd == apple_ii_64k[0]);
ASSERT(run_args.base_ramwrt == apple_ii_64k[0]);
ASSERT(run_args.base_textrd == apple_ii_64k[0]);
ASSERT(run_args.base_textwrt == apple_ii_64k[0]);
ASSERT(run_args.base_hgrrd == apple_ii_64k[0]);
ASSERT(run_args.base_hgrwrt == apple_ii_64k[0]);
ASSERT(run_args.base_stackzp == apple_ii_64k[0]);
ASSERT(run_args.base_c3rom == apple_ii_64k[1]);
ASSERT(run_args.base_cxrom == (void *)&iie_read_peripheral_card);
ASSERT(run_args.base_d000_rd == language_banks[0]-0xD000);
ASSERT(run_args.base_d000_wrt == language_banks[0]-0xD000);
ASSERT(run_args.base_e000_rd == language_card[0]-0xE000);
ASSERT(run_args.base_e000_wrt == language_card[0]-0xE000);
// CPU ...
ASSERT(cpu65_pc == 0x0E9C);
ASSERT(cpu65_ea == 0x0EB9);
ASSERT(cpu65_a == 0x00);
ASSERT(cpu65_f == 0xB0);
ASSERT(cpu65_x == 0x05);
ASSERT(cpu65_y == 0x04);
ASSERT(cpu65_sp == 0xE0);
ASSERT(run_args.cpu65_pc == 0x0E9C);
ASSERT(run_args.cpu65_ea == 0x0EB9);
ASSERT(run_args.cpu65_a == 0x00);
ASSERT(run_args.cpu65_f == 0xB0);
ASSERT(run_args.cpu65_x == 0x05);
ASSERT(run_args.cpu65_y == 0x04);
ASSERT(run_args.cpu65_sp == 0xE0);
// Timing ...
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;
unsigned long cycles_count_total = 0; // Running at spec ~1MHz, this will approach overflow in ~4000secs (for 32bit architectures)
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 unsigned int g_dwCyclesThisFrame = 0;
@ -71,7 +68,6 @@ bool is_fullspeed = false;
bool alt_speed_enabled = false;
// misc
volatile uint8_t emul_reinitialize = 1;
static bool emul_reinitialize_audio = false;
static bool emul_pause_audio = false;
static bool emul_resume_audio = false;
@ -149,7 +145,7 @@ void reinitialize(void) {
cycles_count_total = 0;
g_dwCyclesThisFrame = 0;
irqCheckTimeout = IRQ_CHECK_CYCLES;
run_args.irq_check_timeout = IRQ_CHECK_CYCLES;
#if TESTING
extern unsigned long (*testing_getCyclesCount)(void);
if (testing_getCyclesCount) {
@ -159,8 +155,6 @@ void reinitialize(void) {
vm_initialize();
softswitches = SS_TEXT | SS_IOUDIS | SS_C3ROM | SS_LCWRT | SS_LCSEC;
video_setDirty(A2_DIRTY_FLAG);
cpu65_init();
@ -277,9 +271,10 @@ static void *cpu_thread(void *dummyptr) {
speaker_init();
MB_Initialize();
run_args.emul_reinitialize = 1;
cpu_runloop:
do
{
do {
LOG("CPUTHREAD %lu LOCKING FOR MAYBE INITIALIZING AUDIO ...", (unsigned long)cpu_thread_id);
pthread_mutex_lock(&interface_mutex);
if (emul_reinitialize_audio) {
@ -298,7 +293,7 @@ cpu_runloop:
pthread_mutex_unlock(&interface_mutex);
LOG("UNLOCKING FOR MAYBE INITIALIZING AUDIO ...");
if (emul_reinitialize) {
if (run_args.emul_reinitialize) {
reinitialize();
}
@ -321,8 +316,7 @@ cpu_runloop:
clock_gettime(CLOCK_MONOTONIC, &ti);
deltat = timespec_diff(t0, ti, &negative);
if (deltat.tv_sec)
{
if (deltat.tv_sec) {
if (!is_fullspeed) {
TIMING_LOG("NOTE : serious divergence from target time ...");
}
@ -333,35 +327,36 @@ cpu_runloop:
drift_adj_nsecs = negative ? ~deltat.tv_nsec : deltat.tv_nsec;
// 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) {
cpu65_cycles_to_execute += cycles_speaker_feedback;
run_args.cpu65_cycles_to_execute += cycles_speaker_feedback;
}
if (cpu65_cycles_to_execute < 0)
{
cpu65_cycles_to_execute = 0;
if (run_args.cpu65_cycles_to_execute < 0) {
run_args.cpu65_cycles_to_execute = 0;
}
MB_StartOfCpuExecute();
if (is_debugging) {
debugging_cycles = cpu65_cycles_to_execute;
debugging_cycles = run_args.cpu65_cycles_to_execute;
}
do {
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;
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
dbg_cycles_executed += cpu65_cycle_count;
dbg_cycles_executed += run_args.cpu65_cycle_count;
#endif
g_dwCyclesThisFrame += cpu65_cycle_count;
g_dwCyclesThisFrame += run_args.cpu65_cycle_count;
if (is_debugging) {
debugging_cycles -= cpu65_cycle_count;
debugging_cycles -= run_args.cpu65_cycle_count;
timing_checkpoint_cycles();
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);
goto cpu_runloop;
}
@ -489,7 +484,7 @@ cpu_runloop:
}
#endif
if (UNLIKELY(emul_reinitialize)) {
if (UNLIKELY(run_args.emul_reinitialize)) {
break;
}
@ -549,7 +544,7 @@ unsigned int CpuGetCyclesThisVideoFrame(void) {
void timing_checkpoint_cycles(void) {
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);
#if !TESTING
cycles_count_total += d;
@ -563,7 +558,7 @@ void timing_checkpoint_cycles(void) {
}
}
#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) {
joy_button0 = 0x0;
joy_button1 = 0x0;
run_args.joy_button0 = 0x0;
run_args.joy_button1 = 0x0;
}
static void touchjoy_resetState(void) {
@ -135,8 +135,8 @@ static void *_button_tap_delayed_thread(void *dummyptr) {
assert(timedOut);
// touch-down-and-hold
TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] long touch ...");
joy_button0 = touchPrevEvent->currJoyButtonValue0;
joy_button1 = touchPrevEvent->currJoyButtonValue1;
run_args.joy_button0 = touchPrevEvent->currJoyButtonValue0;
run_args.joy_button1 = touchPrevEvent->currJoyButtonValue1;
joys.buttonDrawCallback(touchPrevEvent->currButtonDisplayChar);
continue;
}
@ -145,16 +145,16 @@ static void *_button_tap_delayed_thread(void *dummyptr) {
if (touchCurrEvent->event == TOUCH_MOVE) {
// dragging ...
TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] move ...");
joy_button0 = touchCurrEvent->currJoyButtonValue0;
joy_button1 = touchCurrEvent->currJoyButtonValue1;
run_args.joy_button0 = touchCurrEvent->currJoyButtonValue0;
run_args.joy_button1 = touchCurrEvent->currJoyButtonValue1;
joys.buttonDrawCallback(touchCurrEvent->currButtonDisplayChar);
FREE(touchPrevEvent);
touchPrevEvent = touchCurrEvent;
} else if (touchCurrEvent->event == TOUCH_UP) {
// tap
TOUCH_JOY_GESTURE_LOG(">>> [DELAYEDTAP] touch up ...");
joy_button0 = touchPrevEvent->currJoyButtonValue0;
joy_button1 = touchPrevEvent->currJoyButtonValue1;
run_args.joy_button0 = touchPrevEvent->currJoyButtonValue0;
run_args.joy_button1 = touchPrevEvent->currJoyButtonValue1;
joys.buttonDrawCallback(touchPrevEvent->currButtonDisplayChar);
timedOut = 0;
break;

View File

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

View File

@ -179,11 +179,11 @@ static void gldriver_joystick_callback(unsigned int buttonMask, int x, int y, in
#endif
// 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)) {
joy_button0 = (buttonMask & 0x01) ? 0x80 : 0x0;
if (!(run_args.joy_button0 & 0x7f)) {
run_args.joy_button0 = (buttonMask & 0x01) ? 0x80 : 0x0;
}
if (!(joy_button1 & 0x7f)) {
joy_button1 = (buttonMask & 0x02) ? 0x80 : 0x0;
if (!(run_args.joy_button1 & 0x7f)) {
run_args.joy_button1 = (buttonMask & 0x02) ? 0x80 : 0x0;
}
// normalize GLUT range

View File

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

View File

@ -17,13 +17,12 @@
#endif
#include "cpu.h"
#include "glue-offsets.h"
#define X_Reg %bl /* 6502 X register in %bl */
#define Y_Reg %bh /* 6502 Y register in %bh */
#define A_Reg %cl /* 6502 A register in %cl */
#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_L %sil /* 6502 PC low */
#define PC_Reg_H %sih /* 6502 PC high */
@ -34,28 +33,20 @@
#define X86_CF_Bit 0x0 /* x86 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__
# define SZ_PTR 8
# define ROR_BIT 63
// 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 _XDI %rdi
# define _XSI %rsi
# define _XAX %rax /* scratch */
# define _XBX %rbx /* scratch2 */
# define _X8 %r8
// full-length Apple ][ registers
# define XY_Reg_X %rbx /* 6502 X&Y 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 EffectiveAddr_X %rdi /* Effective address */
// full-length assembly instructions
@ -83,18 +74,16 @@
# define SZ_PTR 4
# define ROR_BIT 31
// x86 registers
# define _XBP %ebp /* x86 base pointer */
# define _PICREG %ebp /* used for accessing GOT */
# define _XBP %ebp /* x86 base ptr / scratch */
# define _XSP %esp /* x86 stack pointer */
# define _XDI %edi
# define _XSI %esi
# define _XAX %eax /* scratch */
# define _XBX %ebx /* scratch2 */
# define _X8 %eax // WRONG!!! FIXMENOW
// full-length Apple ][ registers
# define XY_Reg_X %ebx /* 6502 X&Y 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 EffectiveAddr_X %edi /* Effective address */
// full-length assembly instructions
@ -122,92 +111,24 @@
/* Symbol naming issues */
#if NO_UNDERSCORES
# define _UNDER(x) x
# define ENTRY(x) .globl x; .balign 16; x##:
# define CALL(x) x
#else
# define _UNDER(x) _##x
# define ENTRY(x) .globl _##x##; .balign 16; _##x##:
# define CALL(x) _##x
#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 CALL_FN(op,fn,stk) op _UNDER(fn)
# 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
#define JUMP_IND(BASE,OFF) \
movLQ BASE(reg_args), _XBP; \
jmp *(_XBP,OFF,SZ_PTR);
#endif // whole file

View File

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