mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-01-10 23:29:43 +00:00
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:
parent
6e7af373d7
commit
e4e0c941d3
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 < $< > $@
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
207
src/arm/cpu.S
207
src/arm/cpu.S
@ -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
5
src/arm/glue-offsets.h
Normal 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
53
src/arm/glue-offsets32.h
Normal 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
|
@ -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)
|
||||
|
||||
|
182
src/cpu-supp.c
182
src/cpu-supp.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
23
src/cpu.h
23
src/cpu.h
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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
95
src/glue-offsets.c
Normal 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;
|
||||
}
|
||||
|
133
src/glue.h
133
src/glue.h
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
12
src/keys.c
12
src/keys.c
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
5862
src/test/testcpu.c
5862
src/test/testcpu.c
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.);
|
||||
|
1130
src/test/testvm.c
1130
src/test/testvm.c
File diff suppressed because it is too large
Load Diff
51
src/timing.c
51
src/timing.c
@ -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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
20
src/vm.h
20
src/vm.h
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
270
src/x86/cpu.S
270
src/x86/cpu.S
@ -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
5
src/x86/glue-offsets.h
Normal 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
53
src/x86/glue-offsets32.h
Normal 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
53
src/x86/glue-offsets64.h
Normal 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
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user