From af32b6c2f0ed2f1a4582c3e8d7ac704b9c61fa4c Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 14 Apr 2007 12:38:17 +0000 Subject: [PATCH] first debug version of ncpu git-svn-id: file:///home/notaz/opt/svn/fceu@102 be3aeb3a-fb24-0410-a615-afba39da0efa --- Makefile.base | 5 +- Makefile.gp2x | 20 +- fce.c | 2 + ncpu.S | 3135 +++++++++++++++++++++++++++++++++++++++++++++++++ ncpu.h | 124 ++ ncpu_debug.c | 156 +++ x6502.c | 30 +- x6502.h | 84 +- 8 files changed, 3531 insertions(+), 25 deletions(-) create mode 100644 ncpu.S create mode 100644 ncpu.h create mode 100644 ncpu_debug.c diff --git a/Makefile.base b/Makefile.base index cedc5a6..734b1b1 100644 --- a/Makefile.base +++ b/Makefile.base @@ -1,5 +1,6 @@ CFLAGS = -Wall ${TFLAGS} -OBJECTS = fce.o x6502.o video.o general.o endian.o svga.o sound.o nsf.o fds.o netplay.o ines.o state.o unif.o input.o file.o cart.o crc32.o memory.o cheat.o debug.o +OBJECTS = fce.o video.o general.o endian.o svga.o sound.o nsf.o fds.o netplay.o ines.o state.o unif.o input.o file.o cart.o crc32.o memory.o cheat.o debug.o +# x6502.o fceu: fceu2 include mappers/Makefile @@ -17,7 +18,7 @@ clean: ${RM} fceu fceu.exe ${OBJECTS} ${INPOBJS} ${MOBJS} ${MUOBJS} ${MUSOBJS} ${OBJDRIVER} nsf.o: nsf.c nsf.h fce.h x6502.h svga.h video.h sound.h nsfbgnew.h general.h file.h -x6502.o: x6502.c x6502.h ops.h fce.h sound.h +#x6502.o: x6502.c x6502.h ops.h fce.h sound.h video.o: video.c types.h video.h svga.h version.h general.h sound.o: sound.c sound.h types.h fce.h svga.h x6502.h svga.o: svga.c svga.h types.h palette.h state.h netplay.h fds.h fce.h nsf.h video.h sound.h palettes/*.h driver.h drawing.h diff --git a/Makefile.gp2x b/Makefile.gp2x index ac85a1f..bca522a 100644 --- a/Makefile.gp2x +++ b/Makefile.gp2x @@ -15,6 +15,9 @@ TFLAGS += -O3 # -pg LDRIVER += -O3 # -pg endif +asm_6502=1 +debug_asm_6502=1 + all: fceu gpfce: fceu @@ -25,7 +28,22 @@ include zlib/Makefile OBJDRIVER = ${B}minimal.o ${B}squidgehack.o ${B}asmutils.o ${B}gp2x.o ${B}main.o ${B}throttle.o \ ${B}unix-netplay.o ${B}gp2x-sound.o ${B}gp2x-video.o ${B}lnx-joystick.o \ drivers/common/cheat.o drivers/common/config.o drivers/common/args.o drivers/common/vidblit.o ${UNZIPOBJS} ppu.o -LDRIVER += -L /mnt/sd/lib -L/mnt/sd/gp2x/usr/lib -lm -lz -static +LDRIVER += -L /mnt/sd/lib -L/mnt/sd/gp2x/usr/lib -lm -lz -static -Wl,-Map=fceu.map + +ifeq ($(asm_6502),1) +TFLAGS += -DASM_6502 +OBJDRIVER += ncpu.o +ifeq ($(debug_asm_6502),1) +TFLAGS += -DDEBUG_ASM_6502 +OBJDRIVER += x6502.o ncpu_debug.o +endif +else +OBJDRIVER += x6502.o +endif + +x6502.o: x6502.c x6502.h ops.h fce.h sound.h +ncpu.o: ncpu.S ncpu.h + $(CC) -c $< -o $@ include Makefile.base diff --git a/fce.c b/fce.c index 4c7ffc6..3e4dde5 100644 --- a/fce.c +++ b/fce.c @@ -208,7 +208,9 @@ static uint32 scanlines_per_frame; uint8 GameMemBlock[131072] __attribute__ ((aligned (4))); uint8 NTARAM[0x800] __attribute__ ((aligned (4))); uint8 PALRAM[0x20] __attribute__ ((aligned (4))); +#ifndef ASM_6502 uint8 RAM[0x800] __attribute__ ((aligned (4))); +#endif uint8 PPU[4]; uint8 PPUSPL; diff --git a/ncpu.S b/ncpu.S new file mode 100644 index 0000000..381437f --- /dev/null +++ b/ncpu.S @@ -0,0 +1,3135 @@ +/************************************* + Little John GP32 + File : ncpu.S + Authors : FCA author + modified and adapted by Yoyo. + adapted for fceu by notaz, 2007. +**************************************/ + +#include "ncpu.h" + +@@@ +@@@ Offets from REG_OP_TABLE +@@@ +#define OTOFFS_NES_RAM (nes_internal_ram - cpu_exec_table) +#define OTOFFS_NES_STACK (nes_stack - cpu_exec_table) +#define OTOFFS_NES_REGS (nes_registers - cpu_exec_table) +#define OTOFFS_PC_BASE (pc_base - cpu_exec_table) + +@ fceu +#define FCEU_IQNMI 0x08 +#define FCEU_IQTEMP 0x80 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@ + + +@ SECTION_FAST + SECTION_TEXT + ALIGN + + + +@@@ +@@@ r0 = Address (unbased) +@@@ uses REG_OP_TABLE; sets REG_PC; trashes r1,r2; keeps r0 +@@@ +.macro REBASE_PC + @ FIXME: do something with mem not in Page[]. + cmp r0, #0x2000 + ldrge r1, =Page + movge r2, r0, lsr #11 + ldrge r2, [r1, r2, lsl #2] + andlt r2, r0, #0xf800 + addlt r1, REG_OP_TABLE, #OTOFFS_NES_RAM + sublt r2, r1, r2 + str r2, [REG_OP_TABLE, #OTOFFS_PC_BASE] + add REG_PC, r2, r0 +.endm + + +.macro RETURN_FROM_CPU_EXEC + b cpu_exec_end +.endm + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ CYCLE_NEXT +@@@ +@@@ »Ä¤ê¥µ¥¤¥¯¥ë¤ò¥Á¥§¥Ã¥¯¤·¤Æ»Ä¤Ã¤Æ¤¤¤ì¤Ð¼¡¤ÎÌ¿Îá¤ò¼Â¹Ô +@@@ ¤¿¤À¤·³ä¤ê¹þ¤ß¤ò¥Á¥§¥Ã¥¯¤·¤Ê¤¤ +@@@ +@@@ ¤Ê¤ó¤«Ì¾Á°¤¬ÊѤÀ¤Ê(¤É¡¼¤Ç¤â¤¤¡¼¤±¤É¡¼ +@@@ +.macro CYCLE_NEXT n + @@DEBUG_INFO + + subs REG_CYCLE, REG_CYCLE, #\n*48 + ble cpu_exec_end + ldrb r0, [REG_PC], #1 + tst REG_P_REST, #0xff<<8 + ldreq pc, [REG_OP_TABLE, r0, lsl #2] + + @ do some messing to find out which IRQ is pending.. + tst REG_P_REST, #FCEU_IQNMI<<8 + bne do_int + tst REG_P_REST, #P_REST_I_FLAG + @@ if I_FLAG=1, continue execution, don't trigger IRQ + bicne REG_P_REST, REG_P_REST, #FCEU_IQTEMP<<8 + ldrne pc, [REG_OP_TABLE, r0, lsl #2] + @@ I_FLAG=0 and REST is checked, we have a IRQ + b do_int +.endm + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ CYCLE_NEXT_INT +@@@ +@@@ »Ä¤ê¥µ¥¤¥¯¥ë¤ò¥Á¥§¥Ã¥¯¤·¤Æ»Ä¤Ã¤Æ¤¤¤ì¤Ð¼¡¤ÎÌ¿Îá¤ò¼Â¹Ô +@@@ CLI¡¦PHP¤Ê¤É¥Õ¥é¥°¤òÊѹ¹¤·¤¿¾ì¹ç¤Ï¤³¤ì +@@@ +.macro CYCLE_NEXT_INT n +@ @@DEBUG_INFO +@ +@ subs REG_CYCLE, REG_CYCLE, #\n*48 +@ bgt cpu_exec_check_int +@ RETURN_FROM_CPU_EXEC + CYCLE_NEXT \n +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ¥¼¥í¥Ú¡¼¥¸¤«¤éÆɤà +@@@ +.macro ZP_READ + add REG_ADDR, REG_ADDR, #OTOFFS_NES_RAM + ldrb r0, [REG_ADDR, REG_OP_TABLE]! +.endm + +@@@ +@@@ Æɤó¤À¸å¡¤½ñ¤¯¾ì¹ç¤Ï¤³¤ì¤ò»È¤¦(¥·¥Õ¥È¤Ê¤É)¡£¤Ç¤â¡¤¾å¤ÈƱ¤¸ +@@@ +.macro ZP_READ_W + ZP_READ +.endm + +@@@ +@@@ ¥¢¥É¥ì¥¹¤òÆɤà +@@@ +.macro ZP_READ_ADDR + ZP_READ + ldrb REG_ADDR, [REG_ADDR, #1] + orr REG_ADDR, r0, REG_ADDR, lsl #8 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ¥¼¥í¥Ú¡¼¥¸¤Ë½ñ¤¯ +@@@ +.macro ZP_WRITE reg=r0 + add REG_ADDR, REG_ADDR, #OTOFFS_NES_RAM + strb \reg, [REG_ADDR, REG_OP_TABLE] +.endm + +@@@ +@@@ ZP_READ_W ¤ÇÆɤó¤À¸å¡¤Æ±¤¸¥¢¥É¥ì¥¹¤Ë½ñ¤¯ +@@@ +.macro ZP_WRITE_W + strb r0, [REG_ADDR] +.endm + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ 16¥Ó¥Ã¥È¥¢¥É¥ì¥¹¤ÎÆɤ߽ñ¤­ +@@@ +@@@ REG_ADDR => 16¥Ó¥Ã¥È¥¢¥É¥ì¥¹ +@@@ r0 => ½ñ¤¯¥Ð¥¤¥È(write) +@@@ r0 <= Æɤó¤À¥Ð¥¤¥È(read)¡¦½ñ¤¤¤¿¥Ð¥¤¥È(write) +@@@ + +@@@ +@@@ 3¼ïÎà¤ÎÌ¿Î᤬¤¢¤ë +@@@ +@@@ °ìÈÖ¿¤¤¤Î¤¬ +@@@ 16¥Ó¥Ã¥È¥¢¥É¥ì¥¹¤«¤é8¥Ó¥Ã¥È¥í¡¼¥É¤¹¤ë¤À¤±¤ÎÌ¿Îá +@@@ ¼¡¤Ë¿¤¤¤Î¤¬ +@@@ ¥í¡¼¥É¡¤·×»»¡¤¥¹¥È¥¢¤ò¤¹¤ëÌ¿Îá +@@@ »Ä¤ê¤Ï +@@@ ¥¹¥È¥¢¤¹¤ë¤À¤±¤ÎÌ¿Îá + +@@@ +@@@ 16¥Ó¥Ã¥È¥¢¥É¥ì¥¹¤«¤é¥í¡¼¥É¤Î¤ß +@@@ +@@@ RAM¤«¤é¤Î¥í¡¼¥É¤¬°ìÈÖ¿¤¤¤Î¤ÇÍ¥À褹¤ë +@@@ +@@@ READ_1 +@@@ OP +@@@ READ_2 +@@@ OP +@@@ +@@@ ¤Î¤è¤¦¤Ë»È¤¦ + +.macro READ_1 + movs r1, REG_ADDR, lsr #13 + adr lr, 9999f + @@ 0¤Ç¤Ê¤¤»þ¤Ï¥¸¥ã¥ó¥×¤¹¤ë¡£ + @@ ¤Á¤ç¤Ã¤È¹©Éפ·¤Æ1¥¯¥í¥Ã¥¯¸º¤é¤¹ + ldrne pc, [lr, -r1, lsl #2] + @@ RAM¤«¤é¥í¡¼¥É + bic r0, REG_ADDR, #0x1800 + add r0, r0, #OTOFFS_NES_RAM + ldrb r0, [r0, REG_OP_TABLE] +.endm + +.macro READ_2 + .long read_rom_byte + .long read_rom_byte + .long read_rom_byte + .long read_rom_byte + .long read_save_ram + .long read_high_reg + .long read_ppu_reg +9999: +.endm + +.macro READ + mov r1, REG_ADDR, lsr #13 + adr lr, 1f + ldr pc, [pc, r1, lsl #2] + nop + .long 2f @ fast path + .long read_ppu_reg + .long read_high_reg + .long read_save_ram + .long read_rom_byte + .long read_rom_byte + .long read_rom_byte + .long read_rom_byte +2: + bic r0, REG_ADDR, #0x1800 + add r0, r0, #OTOFFS_NES_RAM + ldrb r0, [r0, REG_OP_TABLE] + @@ ¤È¤¤¤¦¤ï¤±¤Ç¥¸¥ã¥ó¥×¤¹¤ëɬÍפϤʤ¤ +1: +.endm + +@@@ +@@@ Æɤó¤À¤¢¤È½ñ¤¯¾ì¹ç +@@@ +@@@ READ_WRITE_1 +@@@ OP +@@@ READ_WRITE_2 +@@@ +@@@ READ_WRITE_3 +@@@ OP +@@@ READ_WRITE_4 +@@@ ¤Î¤è¤¦¤Ë»È¤¦ +@@@ OP¤Ç¤Ïr3¤òÊݸ¤·¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤ + +.macro READ_WRITE_1 + movs r3, REG_ADDR, lsr #13 + adr lr, 9999f + @@ 0¤Ç¤Ê¤¤»þ¤Ï¥¸¥ã¥ó¥×¤¹¤ë¡£ + @@ ¤Á¤ç¤Ã¤È¹©Éפ·¤Æ1¥¯¥í¥Ã¥¯¸º¤é¤¹ + ldrne pc, [lr, -r3, lsl #2] + @@ RAM¤«¤é¥í¡¼¥É + bic REG_ADDR, REG_ADDR, #0x1800 + add REG_ADDR, REG_ADDR, #OTOFFS_NES_RAM + ldrb r0, [REG_ADDR, REG_OP_TABLE]! +.endm + +.macro READ_WRITE_2 + strb r0, [REG_ADDR] +.endm + +.macro READ_WRITE_3 + .long read_rom_byte + .long read_rom_byte + .long read_rom_byte + .long read_rom_byte + .long read_save_ram + .long read_high_reg + .long read_ppu_reg +9999: +.endm + +.macro READ_WRITE_4 + adr lr, 1f + ldr pc, [pc, r3, lsl #2] + nop + nop + .long write_ppu_reg + .long write_high_reg + .long write_save_ram + .long write_rom_byte + .long write_rom_byte + .long write_rom_byte + .long write_rom_byte +1: +.endm + +@@@ +@@@ ½ñ¤­¹þ¤ß¤À¤±¤Î¾ì¹ç +@@@ +@@@ WRITE_1 +@@@ TAIL +@@@ WRITE_2 +@@@ TAIL +@@@ ¤È¤¹¤ë + +.macro WRITE_1 + @@DEBUG_INFO + + movs r1, REG_ADDR, lsr #13 + adr lr, 9999f + ldrne pc, [lr, -r1, lsl #2] + bic REG_ADDR, REG_ADDR, #0x1800 + add REG_ADDR, REG_ADDR, #OTOFFS_NES_RAM + + strb r0, [REG_ADDR, REG_OP_TABLE] +.endm + +.macro WRITE_2 + .long write_rom_byte + .long write_rom_byte + .long write_rom_byte + .long write_rom_byte + .long write_save_ram + .long write_high_reg + .long write_ppu_reg +9999: +.endm + +@@@ +@@@ ¤½¤·¤Æ¡¤¤³¤ì¤òɬÍפȤ¹¤ë¤Î¤Ï¥¸¥ã¥ó¥×Ì¿Îᡦ³ä¤ê¹þ¤ß¡¦¥ê¥»¥Ã¥È¤Î¤ß¤Ç¤¢¤ë +@@@ ¤¢¤Þ¤ê½ÅÍפǤʤ¤¤Î¤ÇŬÅö¤Ç¤è¤¤¡£ +@@@ ¥Æ¥ó¥Ý¥é¥ê¤Ë»È¤¨¤ë¥ì¥¸¥¹¥¿¤¬Â­¤ê¤Ê¤¤¤Î¤Ç REG_PC ¤ò»È¤¦¤¬µ¤¤Ë¤¹¤ë¤Ê +@@@ ¤¹¤°¸å¤Ç¾å½ñ¤­¤µ¤ì¤ë¡£ +@@@ REG_ADDR¤òÊѹ¹¤¹¤ë¤¬µ¤¤Ë¤¹¤ë¤Ê +@@@ +.macro READ_WORD + READ + mov REG_PC, r0 + add REG_ADDR, REG_ADDR, #1 + READ + orr r0, REG_PC, r0, lsl #8 +.endm + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ¥¹¥¿¥Ã¥¯¤Î¥×¥Ã¥·¥å¡¦¥Ý¥Ã¥× +@@@ +@@@ + +@@ Push byte <- r0 +.macro PUSH_BYTE + add r1, REG_OP_TABLE, #OTOFFS_NES_STACK + strb r0, [r1, REG_S, lsr #24] + sub REG_S, REG_S, #1 << 24 +.endm + +@@ Push word <- r0 +.macro PUSH_WORD + add r1, REG_OP_TABLE, #OTOFFS_NES_STACK + mov r2, r0, lsr #8 + strb r2, [r1, REG_S, lsr #24] + @@ ¤¤¤Á¤ª¤¦ REG_S ¤Î¥ª¡¼¥Ð¡¼¥Õ¥í¡¼¤òµ¤¤Ë¤·¤Æ¤ß¤ë + sub REG_S, REG_S, #1 << 24 + strb r0, [r1, REG_S, lsr #24] + sub REG_S, REG_S, #1 << 24 +.endm + +@@ Pop byte -> r0 +.macro POP_BYTE + add r0, REG_OP_TABLE, #OTOFFS_NES_STACK + add REG_S, REG_S, #1 << 24 + ldrb r0, [r0, REG_S, lsr #24] +.endm + +@@ Pop word -> r0 +.macro POP_WORD + add r0, REG_OP_TABLE, #OTOFFS_NES_STACK + add REG_S, REG_S, #1 << 24 + ldrb r1, [r0, REG_S, lsr #24] + add REG_S, REG_S, #1 << 24 + ldrb r0, [r0, REG_S, lsr #24] + orr r0, r1, r0, lsl #8 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ¥¢¥É¥ì¥Ã¥·¥ó¥°¥â¡¼¥É +@@@ + +.macro IMPLIED + @@ ¤Ê¤Ë¤âɬÍפʤ¤ +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ¥ª¥Ú¥é¥ó¥É¤¬1¥Ð¥¤¥È¤Î¾ì¹ç +@@@ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ #$nn +.macro IMM_VALUE + ldrb r0, [REG_PC], #1 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ $nn +.macro ZERO_ADDR + ldrb REG_ADDR, [REG_PC], #1 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ $nn, X +.macro ZEROX_ADDR + ZERO_ADDR + add REG_ADDR, REG_ADDR, REG_X + and REG_ADDR, REG_ADDR, #0xFF +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ $nn, Y +.macro ZEROY_ADDR + ZERO_ADDR + add REG_ADDR, REG_ADDR, REG_Y + and REG_ADDR, REG_ADDR, #0xFF +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ ($nn, X) +.macro INDX_ADDR + ZEROX_ADDR + ZP_READ_ADDR +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ ($nn), Y +.macro INDY_ADDR + ZERO_ADDR + ZP_READ_ADDR + add REG_ADDR, REG_ADDR, REG_Y + bic REG_ADDR, REG_ADDR, #0x10000 + and r0,REG_ADDR,#0xff + cmp REG_Y,r0 + subgt REG_CYCLE,REG_CYCLE,#1*48 +.endm + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ¥ª¥Ú¥é¥ó¥É¤¬2¥Ð¥¤¥È¤Î¾ì¹ç +@@@ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ $nnnn + +.macro ABS_ADDR + tst REG_PC, #1 + ldrneb REG_ADDR, [REG_PC], #1 + ldrneb r0, [REG_PC], #1 + ldreqh REG_ADDR, [REG_PC], #2 + orrne REG_ADDR, REG_ADDR, r0, lsl #8 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ $nnnn, X +.macro ABSX_ADDR + ABS_ADDR + add REG_ADDR, REG_ADDR, REG_X + bic REG_ADDR, REG_ADDR, #0x10000 + and r0,REG_ADDR,#0xff + cmp REG_X,r0 + subgt REG_CYCLE,REG_CYCLE,#1*48 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ $nnnn, Y +.macro ABSY_ADDR + ABS_ADDR + add REG_ADDR, REG_ADDR, REG_Y + bic REG_ADDR, REG_ADDR, #0x10000 + and r0,REG_ADDR,#0xff + cmp REG_Y,r0 + subgt REG_CYCLE,REG_CYCLE,#1*48 +.endm + +@@@ P ¤òÉü¸µ¤¹¤ë +@@@ r0 => 6502 ¤Î P ¥ì¥¸¥¹¥¿ +@@@ REG_NZ <= Éü¸µ¤µ¤ì¤¿ REG_NZ +@@@ REG_P_REST <= Éü¸µ¤µ¤ì¤¿ REG_P_REST +.macro LOAD_P + mov REG_NZ, #0 + tst r0, #P_Z_FLAG + moveq REG_NZ, #0x01 + tst r0, #P_N_FLAG + orrne REG_NZ, REG_NZ, #0x80 << 24 + + bic REG_P_REST, REG_P_REST, #P_REST_FLAGS + and r0, r0, #P_REST_FLAGS + orr REG_P_REST, REG_P_REST, r0 +.endm + +@@@ P ¤òÊݸ¤¹¤ë +@@@ +@@@ REG_NZ => ¸µ¤Ë¤¹¤ë REG_NZ +@@@ REG_P_REST => ¸µ¤Ë¤¹¤ë REG_P_REST +@@@ r0 <= 6502 ¤Î P +.macro SAVE_P + and r0, REG_P_REST, #P_REST_FLAGS + tst REG_NZ, #0x80 << 24 + orrne r0, r0, #P_N_FLAG + tst REG_NZ, #0xFF + orreq r0, r0, #P_Z_FLAG + orr r0, r0, #P_R_FLAG +.endm + +@ SECTION_FAST + SECTION_TEXT + ALIGN +@@@ +@@@ Op-codes +@@@ + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ NOP +@@@ +@@@ ¤Ê¤Ë¤â¤·¤Ê¤¤ +opEA: @ NOP + IMPLIED + CYCLE_NEXT 2 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ CLC/SEC/CLD/SED/CLI/SEI/CLV +@@@ +@@@ ¥Õ¥é¥°ÁàºîÌ¿Îá +@@@ ¤¹¤Ù¤Æ1¥Ð¥¤¥È +@@@ +@@@ ¤³¤ì¤ÇÊѹ¹¤Ç¤­¤ë¥Õ¥é¥°¤ÏÁ´¤ÆREG_P_REST¤Ë¤¢¤ë +@@@ I¤òÊѹ¹¤¹¤ë¾ì¹ç¤Ï³ä¤ê¹þ¤ß¤ò¥Á¥§¥Ã¥¯¤·¤Ê¤ì¤Ð¤Ê¤é¤Ê¤¤ +@@@ +op18: @ CLC + IMPLIED + bic REG_P_REST, REG_P_REST, #P_REST_C_FLAG + CYCLE_NEXT 2 + +op38: @ SEC + IMPLIED + orr REG_P_REST, REG_P_REST, #P_REST_C_FLAG + CYCLE_NEXT 2 + +opD8: @ CLD + IMPLIED + @@bic REG_P_REST, REG_P_REST, #P_REST_D_FLAG + CYCLE_NEXT 2 + +opF8: @ SED + IMPLIED + @@orr REG_P_REST, REG_P_REST, #P_REST_D_FLAG + CYCLE_NEXT 2 + +op58: @ CLI + IMPLIED + bic REG_P_REST, REG_P_REST, #P_REST_I_FLAG + CYCLE_NEXT_INT 2 + +op78: @ SEI + IMPLIED + orr REG_P_REST, REG_P_REST, #P_REST_I_FLAG + CYCLE_NEXT 2 + +opB8: @ CLV + IMPLIED + bic REG_P_REST, REG_P_REST, #P_REST_V_FLAG + CYCLE_NEXT 2 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ TAX/TXA/TAY/TYA/TSX/TXS +@@@ +@@@ ¥ì¥¸¥¹¥¿´ÖžÁ÷Ì¿Îá +@@@ ¤¹¤Ù¤Æ1¥Ð¥¤¥È +@@@ +@@@ TXS°Ê³°¤ÏNZ¤òÊѹ¹¤¹¤ë +@@@ +opAA: @ TAX + IMPLIED + mov REG_X, REG_A, lsr #24 + mov REG_NZ, REG_A, asr #24 + CYCLE_NEXT 2 + +op8A: @ TXA + IMPLIED + mov REG_A, REG_X, lsl #24 + mov REG_NZ, REG_A, asr #24 + CYCLE_NEXT 2 + +opA8: @ TAY + IMPLIED + mov REG_Y, REG_A, lsr #24 + mov REG_NZ, REG_A, asr #24 + CYCLE_NEXT 2 + +op98: @ TYA + IMPLIED + mov REG_A, REG_Y, lsl #24 + mov REG_NZ, REG_A, asr #24 + CYCLE_NEXT 2 + +opBA: @ TSX + IMPLIED + mov REG_X, REG_S, lsr #24 + orr REG_NZ, REG_X, REG_X, lsl #24 + CYCLE_NEXT 2 + +op9A: @ TXS + IMPLIED + bic REG_S, REG_S, #0xFF << 24 + orr REG_S, REG_S, REG_X, lsl #24 + CYCLE_NEXT 2 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ PHA/PHP/PLA/PLP +@@@ +@@@ ¥¹¥¿¥Ã¥¯ÁàºîÌ¿Îá +@@@ PLA¤ÏNZ¤òPLP¤ÏÁ´¤Æ¤Î¥Õ¥é¥°¤òÊѹ¹¤¹¤ë +@@@ +op48: @ PHA + IMPLIED + mov r0, REG_A, lsr #24 + PUSH_BYTE + CYCLE_NEXT 3 + +op08: @ PHP + IMPLIED + SAVE_P + orr r0, r0, #P_B_FLAG + PUSH_BYTE + CYCLE_NEXT 3 + +op68: @ PLA + IMPLIED + POP_BYTE + mov REG_A, r0, lsl #24 + mov REG_NZ, REG_A, asr #24 + CYCLE_NEXT 4 + +op28: @ PLP + IMPLIED + POP_BYTE + LOAD_P + CYCLE_NEXT 4 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ LDA/LDX/LDY +@@@ +@@@ ¥ì¥¸¥¹¥¿¤Ë¥í¡¼¥É +@@@ +@@@ NZVC +@@@ ---- +@@@ **-- +.macro OP_LDA + mov REG_A, r0, lsl #24 + mov REG_NZ, REG_A, asr #24 +.endm + +.macro OP_LDXY reg + mov \reg, r0 + orr REG_NZ, r0, r0, lsl #24 +.endm + +.macro OP_LDX + OP_LDXY REG_X +.endm +.macro OP_LDY + OP_LDXY REG_Y +.endm + +opA9: @ LDA #$nn + IMM_VALUE + OP_LDA + CYCLE_NEXT 2 + +opA5: @ LDA $nn + ZERO_ADDR + ZP_READ + OP_LDA + CYCLE_NEXT 3 + +opB5: @ LDA $nn, X + ZEROX_ADDR + ZP_READ + OP_LDA + CYCLE_NEXT 4 + +opAD: @ LDA $nnnn + ABS_ADDR + READ_1 + OP_LDA + CYCLE_NEXT 4 + READ_2 + OP_LDA + CYCLE_NEXT 4 + +opBD: @ LDA $nnnn, X + ABSX_ADDR + READ_1 + OP_LDA + CYCLE_NEXT 4 + READ_2 + OP_LDA + CYCLE_NEXT 4 + +opB9: @ LDA $nnnn, Y + ABSY_ADDR + READ_1 + OP_LDA + CYCLE_NEXT 4 + READ_2 + OP_LDA + CYCLE_NEXT 4 + +opA1: @ LDA ($nn, X) + INDX_ADDR + READ_1 + OP_LDA + CYCLE_NEXT 6 + READ_2 + OP_LDA + CYCLE_NEXT 6 + +opB1: @ LDA ($nn), Y + INDY_ADDR + READ_1 + OP_LDA + CYCLE_NEXT 5 + READ_2 + OP_LDA + CYCLE_NEXT 5 + + +opA2: @ LDX #$nn + IMM_VALUE + OP_LDX + CYCLE_NEXT 2 + +opA6: @ LDX $nn + ZERO_ADDR + ZP_READ + OP_LDX + CYCLE_NEXT 3 + +opB6: @ LDX $nn, Y + ZEROY_ADDR + ZP_READ + OP_LDX + CYCLE_NEXT 4 + +opAE: @ LDX $nnnn + ABS_ADDR + READ_1 + OP_LDX + CYCLE_NEXT 4 + READ_2 + OP_LDX + CYCLE_NEXT 4 + +opBE: @ LDX $nnnn, Y + ABSY_ADDR + READ_1 + OP_LDX + CYCLE_NEXT 4 + READ_2 + OP_LDX + CYCLE_NEXT 4 + + + +opA0: @ LDY #$nn + IMM_VALUE + OP_LDY + CYCLE_NEXT 2 + +opA4: @ LDY $nn + ZERO_ADDR + ZP_READ + OP_LDY + CYCLE_NEXT 3 + +opB4: @ LDY $nn, X + ZEROX_ADDR + ZP_READ + OP_LDY + CYCLE_NEXT 4 + + + +opAC: @ LDY $nnnn + ABS_ADDR + READ_1 + OP_LDY + CYCLE_NEXT 4 + READ_2 + OP_LDY + CYCLE_NEXT 4 + +opBC: @ LDY $nnnn, X + ABSX_ADDR + READ_1 + OP_LDY + CYCLE_NEXT 4 + READ_2 + OP_LDY + CYCLE_NEXT 4 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ STA/STX/STY +@@@ +@@@ ¥ì¥¸¥¹¥¿¤Î¥¹¥È¥¢ +@@@ +@@@ NZVC +@@@ ---- +@@@ ---- +.macro OP_STA + mov r0, REG_A, lsr #24 +.endm + +op85: @ STA $nn + ZERO_ADDR + OP_STA + ZP_WRITE + CYCLE_NEXT 3 + +op95: @ STA $nn, X + ZEROX_ADDR + OP_STA + ZP_WRITE + CYCLE_NEXT 4 + +op8D: @ STA $nnnn + ABS_ADDR + OP_STA + WRITE_1 + CYCLE_NEXT 4 + WRITE_2 + CYCLE_NEXT 4 + +op9D: @ STA $nnnn, X + ABSX_ADDR + OP_STA + WRITE_1 + CYCLE_NEXT 5 + WRITE_2 + CYCLE_NEXT 5 + +op99: @ STA $nnnn, Y + ABSY_ADDR + OP_STA + WRITE_1 + CYCLE_NEXT 5 + WRITE_2 + CYCLE_NEXT 5 + +op81: @ STA ($nn, X) + INDX_ADDR + OP_STA + WRITE_1 + CYCLE_NEXT 6 + WRITE_2 + CYCLE_NEXT 6 + +op91: @ STA ($nn), Y + INDY_ADDR + OP_STA + WRITE_1 + CYCLE_NEXT 6 + WRITE_2 + CYCLE_NEXT 6 + + +op86: @ STX $nn + ZERO_ADDR + ZP_WRITE REG_X + CYCLE_NEXT 3 + +op96: @ STX $nn, Y + ZEROY_ADDR + ZP_WRITE REG_X + CYCLE_NEXT 4 + +op8E: @ STX $nnnn + ABS_ADDR + mov r0, REG_X + WRITE_1 + CYCLE_NEXT 4 + WRITE_2 + CYCLE_NEXT 4 + + +op84: @ STY $nn + ZERO_ADDR + ZP_WRITE REG_Y + CYCLE_NEXT 3 + +op94: @ STY $nn, X + ZEROX_ADDR + ZP_WRITE REG_Y + CYCLE_NEXT 4 + +op8C: @ STY $nnnn + ABS_ADDR + mov r0, REG_Y + WRITE_1 + CYCLE_NEXT 4 + WRITE_2 + CYCLE_NEXT 4 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ INC/INX/INY/DEC/DEX/DEY +@@@ ¥¤¥ó¥¯¥ê¥á¥ó¥È¡¤¥Ç¥¯¥ê¥á¥ó¥È +@@@ ¤¹¤Ù¤ÆNZ¤òÊѹ¹¤¹¤ë¡£C¤ÏÊѹ¹¤·¤Ê¤¤ +@@@ +@@@ NZVC +@@@ ---- +@@@ **-- + +.macro OP_INC + add r0, r0, #1 + and r0, r0, #0xFF + orr REG_NZ, r0, r0, lsl #24 +.endm + +.macro OP_INXY reg + add \reg, \reg, #1 + and \reg, \reg, #0xFF + orr REG_NZ, \reg, \reg, lsl #24 +.endm + +.macro OP_DEC + sub r0, r0, #1 + and r0, r0, #0xFF + orr REG_NZ, r0, r0, lsl #24 +.endm + +.macro OP_DEXY reg + sub \reg, \reg, #1 + and \reg, \reg, #0xFF + orr REG_NZ, \reg, \reg, lsl #24 +.endm + +opE6: @ INC $nn + ZERO_ADDR + ZP_READ_W + OP_INC + ZP_WRITE_W + CYCLE_NEXT 5 + +opF6: @ INC $nn, X + ZEROX_ADDR + ZP_READ_W + OP_INC + ZP_WRITE_W + CYCLE_NEXT 6 + +opEE: @ INC $nnnn + ABS_ADDR + READ_WRITE_1 + OP_INC + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_INC + READ_WRITE_4 + CYCLE_NEXT 6 + +opFE: @ INC $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_INC + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_INC + READ_WRITE_4 + CYCLE_NEXT 7 + +opE8: @ INX + IMPLIED + OP_INXY REG_X + CYCLE_NEXT 2 + +opC8: @ INY + IMPLIED + OP_INXY REG_Y + CYCLE_NEXT 2 + +opC6: @ DEC $nn + ZERO_ADDR + ZP_READ_W + OP_DEC + ZP_WRITE_W + CYCLE_NEXT 5 + +opD6: @ DEC $nn, X + ZEROX_ADDR + ZP_READ_W + OP_DEC + ZP_WRITE_W + CYCLE_NEXT 6 + +opCE: @ DEC $nnnn + ABS_ADDR + READ_WRITE_1 + OP_DEC + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_DEC + READ_WRITE_4 + CYCLE_NEXT 6 + +opDE: @ DEC $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_DEC + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_DEC + READ_WRITE_4 + CYCLE_NEXT 7 + +opCA: @ DEX + IMPLIED + OP_DEXY REG_X + CYCLE_NEXT 2 + +op88: @ DEY + IMPLIED + OP_DEXY REG_Y + CYCLE_NEXT 2 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ADC/SBC +@@@ +@@@ ¥­¥ã¥ê¡¼/¥Ü¥í¡¼¤Ä¤­¤Î²Ã»»/¸º»» + +.macro OP_ADC + @@ ¥­¥ã¥ê¡¼¤ò¥»¥Ã¥È¤·¤Æ + movs r1, REG_P_REST, lsr #1 + @@ ¾å24¥Ó¥Ã¥È¤òÁ´¤Æ1¤Ë + subcs r0, r0, #0x100 + @@ ¥­¥ã¥ê¡¼¤Ä¤­¤Î²Ã»» + adcs REG_A, REG_A, r0, ror #8 + mov REG_NZ, REG_A, asr #24 + adc REG_P_REST, r1, r1 + orrvs REG_P_REST, REG_P_REST, #P_REST_V_FLAG + bicvc REG_P_REST, REG_P_REST, #P_REST_V_FLAG +.endm + +.macro OP_SBC + @@ ¥­¥ã¥ê¡¼¤ò¥»¥Ã¥È¤·¤Æ + movs r1, REG_P_REST, lsr #1 + @@ ¥­¥ã¥ê¡¼¤Ä¤­¤Î¸º»» + sbcs REG_A, REG_A, r0, lsl #24 + and REG_A, REG_A, #0xFF << 24 + mov REG_NZ, REG_A, asr #24 + adc REG_P_REST, r1, r1 + orrvs REG_P_REST, REG_P_REST, #P_REST_V_FLAG + bicvc REG_P_REST, REG_P_REST, #P_REST_V_FLAG +.endm + +op69: @ ADC #$nn + IMM_VALUE + OP_ADC + CYCLE_NEXT 2 + +op65: @ ADC $nn + ZERO_ADDR + ZP_READ + OP_ADC + CYCLE_NEXT 3 + +op75: @ ADC $nn, X + ZEROX_ADDR + ZP_READ + OP_ADC + CYCLE_NEXT 4 + +op6D: @ ADC $nnnn + ABS_ADDR + READ_1 + OP_ADC + CYCLE_NEXT 4 + READ_2 + OP_ADC + CYCLE_NEXT 4 + +op7D: @ ADC $nnnn, X + ABSX_ADDR + READ_1 + OP_ADC + CYCLE_NEXT 4 + READ_2 + OP_ADC + CYCLE_NEXT 4 + +op79: @ ADC $nnnn, Y + ABSY_ADDR + READ_1 + OP_ADC + CYCLE_NEXT 4 + READ_2 + OP_ADC + CYCLE_NEXT 4 + +op61: @ ADC ($nn, X) + INDX_ADDR + READ_1 + OP_ADC + CYCLE_NEXT 6 + READ_2 + OP_ADC + CYCLE_NEXT 6 + +op71: @ ADC ($nn), Y + INDY_ADDR + READ_1 + OP_ADC + CYCLE_NEXT 5 + READ_2 + OP_ADC + CYCLE_NEXT 5 + +opEB: @ USBC #$nn +opE9: @ SBC #$nn + IMM_VALUE + OP_SBC + CYCLE_NEXT 2 + +opE5: @ SBC $nn + ZERO_ADDR + ZP_READ + OP_SBC + CYCLE_NEXT 3 + +opF5: @ SBC $nn, X + ZEROX_ADDR + ZP_READ + OP_SBC + CYCLE_NEXT 4 + +opED: @ SBC $nnnn + ABS_ADDR + READ_1 + OP_SBC + CYCLE_NEXT 4 + READ_2 + OP_SBC + CYCLE_NEXT 4 + +opFD: @ SBC $nnnn, X + ABSX_ADDR + READ_1 + OP_SBC + CYCLE_NEXT 4 + READ_2 + OP_SBC + CYCLE_NEXT 4 + +opF9: @ SBC $nnnn, Y + ABSY_ADDR + READ_1 + OP_SBC + CYCLE_NEXT 4 + READ_2 + OP_SBC + CYCLE_NEXT 4 + +opE1: @ SBC ($nn, X) + INDX_ADDR + READ_1 + OP_SBC + CYCLE_NEXT 6 + READ_2 + OP_SBC + CYCLE_NEXT 6 + +opF1: @ SBC ($nn), Y + INDY_ADDR + READ_1 + OP_SBC + CYCLE_NEXT 5 + READ_2 + OP_SBC + CYCLE_NEXT 5 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ AND/EOR/ORA +@@@ +@@@ ¥Ó¥Ã¥È±é»»¡£¤¹¤Ù¤ÆNZ¤òÊѹ¹¤¹¤ë +@@@ +@@@ NZVC +@@@ ---- +@@@ **-- +.macro OP_AND + and REG_A, REG_A, r0, lsl #24 + mov REG_NZ, REG_A, asr #24 +.endm + +.macro OP_EOR + eor REG_A, REG_A, r0, lsl #24 + mov REG_NZ, REG_A, asr #24 +.endm + +.macro OP_ORA + orr REG_A, REG_A, r0, lsl #24 + mov REG_NZ, REG_A, asr #24 +.endm + +op29: @ AND #$nn + IMM_VALUE + OP_AND + CYCLE_NEXT 2 + +op25: @ AND $nn + ZERO_ADDR + ZP_READ + OP_AND + CYCLE_NEXT 3 + +op35: @ AND $nn, X + ZEROX_ADDR + ZP_READ + OP_AND + CYCLE_NEXT 4 + +op2D: @ AND $nnnn + ABS_ADDR + READ_1 + OP_AND + CYCLE_NEXT 4 + READ_2 + OP_AND + CYCLE_NEXT 4 + +op3D: @ AND $nnnn, X + ABSX_ADDR + READ_1 + OP_AND + CYCLE_NEXT 4 + READ_2 + OP_AND + CYCLE_NEXT 4 + +op39: @ AND $nnnn, Y + ABSY_ADDR + READ_1 + OP_AND + CYCLE_NEXT 4 + READ_2 + OP_AND + CYCLE_NEXT 4 + +op21: @ AND ($nn, X) + INDX_ADDR + READ_1 + OP_AND + CYCLE_NEXT 6 + READ_2 + OP_AND + CYCLE_NEXT 6 + +op31: @ AND ($nn), Y + INDY_ADDR + READ_1 + OP_AND + CYCLE_NEXT 5 + READ_2 + OP_AND + CYCLE_NEXT 5 + + +op49: @ EOR #$nn + IMM_VALUE + OP_EOR + CYCLE_NEXT 2 + +op45: @ EOR $nn + ZERO_ADDR + ZP_READ + OP_EOR + CYCLE_NEXT 3 + +op55: @ EOR $nn, X + ZEROX_ADDR + ZP_READ + OP_EOR + CYCLE_NEXT 4 + +op4D: @ EOR $nnnn + ABS_ADDR + READ_1 + OP_EOR + CYCLE_NEXT 4 + READ_2 + OP_EOR + CYCLE_NEXT 4 + +op5D: @ EOR $nnnn, X + ABSX_ADDR + READ_1 + OP_EOR + CYCLE_NEXT 4 + READ_2 + OP_EOR + CYCLE_NEXT 4 + +op59: @ EOR $nnnn, Y + ABSY_ADDR + READ_1 + OP_EOR + CYCLE_NEXT 4 + READ_2 + OP_EOR + CYCLE_NEXT 4 + +op41: @ EOR ($nn, X) + INDX_ADDR + READ_1 + OP_EOR + CYCLE_NEXT 6 + READ_2 + OP_EOR + CYCLE_NEXT 6 + +op51: @ EOR ($nn), Y + INDY_ADDR + READ_1 + OP_EOR + CYCLE_NEXT 5 + READ_2 + OP_EOR + CYCLE_NEXT 5 + + +op09: @ ORA #$nn + IMM_VALUE + OP_ORA + CYCLE_NEXT 2 + +op05: @ ORA $nn + ZERO_ADDR + ZP_READ + OP_ORA + CYCLE_NEXT 3 + +op15: @ ORA $nn, X + ZEROX_ADDR + ZP_READ + OP_ORA + CYCLE_NEXT 4 + +op0D: @ ORA $nnnn + ABS_ADDR + READ_1 + OP_ORA + CYCLE_NEXT 4 + READ_2 + OP_ORA + CYCLE_NEXT 4 + +op1D: @ ORA $nnnn, X + ABSX_ADDR + READ_1 + OP_ORA + CYCLE_NEXT 4 + READ_2 + OP_ORA + CYCLE_NEXT 4 + +op19: @ ORA $nnnn, Y + ABSY_ADDR + READ_1 + OP_ORA + CYCLE_NEXT 4 + READ_2 + OP_ORA + CYCLE_NEXT 4 + +op01: @ ORA ($nn, X) + INDX_ADDR + READ_1 + OP_ORA + CYCLE_NEXT 6 + READ_2 + OP_ORA + CYCLE_NEXT 6 + +op11: @ ORA ($nn), Y + INDY_ADDR + READ_1 + OP_ORA + CYCLE_NEXT 5 + READ_2 + OP_ORA + CYCLE_NEXT 5 + + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ CMP/CPX/CPY +@@@ +@@@ Èæ³Ó¡£¤¹¤Ù¤ÆNZC¤òÊѹ¹¤¹¤ë +@@@ +@@@ NZVC +@@@ ---- +@@@ **-* +.macro OP_CMP + subs REG_NZ, REG_A, r0, lsl #24 + mov REG_NZ, REG_NZ, asr #24 + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG +.endm + +.macro OP_CPXY reg + mov r1, \reg, lsl #24 + subs REG_NZ, r1, r0, lsl #24 + mov REG_NZ, REG_NZ, asr #24 + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG +.endm + +.macro OP_CPX + OP_CPXY REG_X +.endm + +.macro OP_CPY + OP_CPXY REG_Y +.endm + +opC9: @ CMP #$nn + IMM_VALUE + OP_CMP + CYCLE_NEXT 2 + +opC5: @ CMP $nn + ZERO_ADDR + ZP_READ + OP_CMP + CYCLE_NEXT 3 + +opD5: @ CMP $nn, X + ZEROX_ADDR + ZP_READ + OP_CMP + CYCLE_NEXT 4 + +opCD: @ CMP $nnnn + ABS_ADDR + READ_1 + OP_CMP + CYCLE_NEXT 4 + READ_2 + OP_CMP + CYCLE_NEXT 4 + +opDD: @ CMP $nnnn, X + ABSX_ADDR + READ_1 + OP_CMP + CYCLE_NEXT 4 + READ_2 + OP_CMP + CYCLE_NEXT 4 + +opD9: @ CMP $nnnn, Y + ABSY_ADDR + READ_1 + OP_CMP + CYCLE_NEXT 4 + READ_2 + OP_CMP + CYCLE_NEXT 4 + +opC1: @ CMP ($nn, X) + INDX_ADDR + READ_1 + OP_CMP + CYCLE_NEXT 6 + READ_2 + OP_CMP + CYCLE_NEXT 6 + +opD1: @ CMP ($nn), Y + INDY_ADDR + READ_1 + OP_CMP + CYCLE_NEXT 5 + READ_2 + OP_CMP + CYCLE_NEXT 5 + + +opE0: @ CPX #$nn + IMM_VALUE + OP_CPX + CYCLE_NEXT 2 + +opE4: @ CPX $nn + ZERO_ADDR + ZP_READ + OP_CPX + CYCLE_NEXT 3 + +opEC: @ CPX $nnnn + ABS_ADDR + READ_1 + OP_CPX + CYCLE_NEXT 4 + READ_2 + OP_CPX + CYCLE_NEXT 4 + + +opC0: @ CPY #$nn + IMM_VALUE + OP_CPY + CYCLE_NEXT 2 + +opC4: @ CPY $nn + ZERO_ADDR + ZP_READ + OP_CPY + CYCLE_NEXT 3 + +opCC: @ CPY $nnnn + ABS_ADDR + READ_1 + OP_CPY + CYCLE_NEXT 4 + READ_2 + OP_CPY + CYCLE_NEXT 4 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ BIT +@@@ +@@@ Z <= A ¢Ê M == 0 +@@@ N <= M[7] +@@@ V <= M[6] +@@@ +@@@ NZVC +@@@ ---- +@@@ ***- +.macro OP_BIT + and REG_NZ, r0, REG_A, lsr #24 + @@ R0[7] => C, R0[6] => N + movs r0, r0, lsl #25 + orrcs REG_NZ, REG_NZ, #0x80 << 24 + orrmi REG_P_REST, REG_P_REST, #P_REST_V_FLAG + bicpl REG_P_REST, REG_P_REST, #P_REST_V_FLAG +.endm + +op24: @ BIT $nn + ZERO_ADDR + ZP_READ + OP_BIT + CYCLE_NEXT 3 + +op2C: @ BIT $nnnn + ABS_ADDR + READ_1 + OP_BIT + CYCLE_NEXT 4 + READ_2 + OP_BIT + CYCLE_NEXT 4 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ASL/LSR +@@@ +@@@ ±¦¥·¥Õ¥È¡¦º¸¥·¥Õ¥È +@@@ +@@@ NZC¤òÊѹ¹¤¹¤ë +@@@ +.macro OP_ASL + movs REG_NZ, r0, lsl #25 + mov r0, REG_NZ, lsr #24 + mov REG_NZ, REG_NZ, asr #24 + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG +.endm + +.macro OP_ASL_A + movs REG_A, REG_A, lsl #1 + mov REG_NZ, REG_A, asr #24 + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG +.endm + +.macro OP_LSR + movs r0, r0, lsr #1 + @@ N¤ÏΩ¤¿¤Ê¤¤ + mov REG_NZ, r0 + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG +.endm + +.macro OP_LSR_A + @@ N¤ÏΩ¤¿¤Ê¤¤ + movs REG_NZ, REG_A, lsr #25 + mov REG_A, REG_NZ, lsl #24 + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG +.endm + +op0A: @ ASL A + IMPLIED + OP_ASL_A + CYCLE_NEXT 2 + +op06: @ ASL $nn + ZERO_ADDR + ZP_READ_W + OP_ASL + ZP_WRITE_W + CYCLE_NEXT 5 + +op16: @ ASL $nn, X + ZEROX_ADDR + ZP_READ_W + OP_ASL + ZP_WRITE_W + CYCLE_NEXT 6 + +op0E: @ ASL $nnnn + ABS_ADDR + READ_WRITE_1 + OP_ASL + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_ASL + READ_WRITE_4 + CYCLE_NEXT 6 + +op1E: @ ASL $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_ASL + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_ASL + READ_WRITE_4 + CYCLE_NEXT 7 + + +op4A: @ LSR A + IMPLIED + OP_LSR_A + CYCLE_NEXT 2 + +op46: @ LSR $nn + ZERO_ADDR + ZP_READ_W + OP_LSR + ZP_WRITE_W + CYCLE_NEXT 5 + +op56: @ LSR $nn, X + ZEROX_ADDR + ZP_READ_W + OP_LSR + ZP_WRITE_W + CYCLE_NEXT 6 + +op4E: @ LSR $nnnn + ABS_ADDR + READ_WRITE_1 + OP_LSR + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_LSR + READ_WRITE_4 + CYCLE_NEXT 6 + +op5E: @ LSR $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_LSR + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_LSR + READ_WRITE_4 + CYCLE_NEXT 7 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ ROL/ROR +@@@ +@@@ º¸²óž/±¦²óž +@@@ +@@@ NZC¤òÊѹ¹¤¹¤ë +@@@ +.macro OP_ROL + @@ ¥­¥ã¥ê¡¼¤ò¥»¥Ã¥È + movs r1, REG_P_REST, lsr #1 + @@ ¥·¥Õ¥È + adc r0, r0, r0 + @@ NZ¤È¥­¥ã¥ê¡¼¤ò¥»¥Ã¥È + orrs REG_NZ, r0, r0, lsl #24 + @@ ¥­¥ã¥ê¡¼¤òÊݸ + adc REG_P_REST, r1, r1 +.endm + +.macro OP_ROL_A + @@ ¥­¥ã¥ê¡¼¤ò¥»¥Ã¥È + movs r1, REG_P_REST, lsr #1 + orrcs REG_A, REG_A, #0x80 << 16 + movs REG_A, REG_A, lsl #1 + mov REG_NZ, REG_A, asr #24 + adc REG_P_REST, r1, r1 +.endm + +.macro OP_ROR + movs r1, REG_P_REST, lsr #1 + orrcs r0, r0, #0x100 + movs r0, r0, lsr #1 + orr REG_NZ, r0, r0, lsl #24 + adc REG_P_REST, r1, r1 +.endm + +.macro OP_ROR_A + movs r1, REG_P_REST, lsr #1 + mov REG_NZ, REG_A, rrx + movs REG_NZ, REG_NZ, asr #24 + mov REG_A, REG_NZ, lsl #24 + adc REG_P_REST, r1, r1 +.endm + +op2A: @ ROL A + IMPLIED + OP_ROL_A + CYCLE_NEXT 2 + +op26: @ ROL $nn + ZERO_ADDR + ZP_READ_W + OP_ROL + ZP_WRITE_W + CYCLE_NEXT 5 + +op36: @ ROL $nn, X + ZEROX_ADDR + ZP_READ_W + OP_ROL + ZP_WRITE_W + CYCLE_NEXT 6 + +op2E: @ ROL $nnnn + ABS_ADDR + READ_WRITE_1 + OP_ROL + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_ROL + READ_WRITE_4 + CYCLE_NEXT 6 + + +op3E: @ ROL $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_ROL + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_ROL + READ_WRITE_4 + CYCLE_NEXT 7 + + +op6A: @ ROR A + IMPLIED + OP_ROR_A + CYCLE_NEXT 2 + +op66: @ ROR $nn + ZERO_ADDR + ZP_READ_W + OP_ROR + ZP_WRITE_W + CYCLE_NEXT 5 + +op76: @ ROR $nn, X + ZEROX_ADDR + ZP_READ_W + OP_ROR + ZP_WRITE_W + CYCLE_NEXT 6 + +op6E: @ ROR $nnnn + ABS_ADDR + READ_WRITE_1 + OP_ROR + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_ROR + READ_WRITE_4 + CYCLE_NEXT 6 + +op7E: @ ROR $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_ROR + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_ROR + READ_WRITE_4 + CYCLE_NEXT 7 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ BCC/BCS/BNE/BEQ/BPL/BMI/BVC/BVS +@@@ +@@@ ʬ´ô +@@@ + +.macro HAD_BRANCH + @@ R0 <- PC + ldr r0, [REG_OP_TABLE, #OTOFFS_PC_BASE] + sub r0, REG_PC, r0 + mov r3, r1 @ preserve immediate + REBASE_PC + + sub r1,r0,r3 + @@ R1 <- (PC&0xFF)+ReadValue + and r1,r1,#0xff + add r1,r3,r1 + tst r1,#0x100 + subne REG_CYCLE,REG_CYCLE, #1*48 +.endm + +.macro BRANCH_EQ + ldreqsb r1, [REG_PC], #1 + movne r1, #1 + add REG_PC, REG_PC, r1 + subeq REG_CYCLE, REG_CYCLE, #1*48 + bne 1f + HAD_BRANCH +1: +.endm + +.macro BRANCH_NE + ldrnesb r1, [REG_PC], #1 + moveq r1, #1 + add REG_PC, REG_PC, r1 + subne REG_CYCLE, REG_CYCLE, #1*48 + beq 1f + HAD_BRANCH +1: +.endm + +op90: @ BCC $nn + tst REG_P_REST, #P_REST_C_FLAG + @@ Z ¤¬Î©¤Æ¤Ð + BRANCH_EQ + CYCLE_NEXT 2 + .pool + +opB0: @ BCS $nn + tst REG_P_REST, #P_REST_C_FLAG + @@ Z ¤¬²¼¤ê¤Æ¤ì¤Ð + BRANCH_NE + CYCLE_NEXT 2 + +opD0: @ BNE $nn + tst REG_NZ, #0xFF + BRANCH_NE + CYCLE_NEXT 2 + +opF0: @ BEQ $nn + tst REG_NZ, #0xFF + BRANCH_EQ + CYCLE_NEXT 2 + +op30: @ BMI $nn + tst REG_NZ, #0x80 << 24 + @@ ·ë²Ì¤¬0¤Ç¤Ê¤¤¤Ê¤é + BRANCH_NE + CYCLE_NEXT 2 + +op10: @ BPL $nn + tst REG_NZ, #0x80 << 24 + @@ ·ë²Ì¤¬0¤Ê¤é + BRANCH_EQ + CYCLE_NEXT 2 + +op50: @ BVC $nn + tst REG_P_REST, #P_REST_V_FLAG + @@ ·ë²Ì¤¬0¤Ê¤é + BRANCH_EQ + CYCLE_NEXT 2 + + +op70: @ BVS $nn + tst REG_P_REST, #P_REST_V_FLAG + @@ ·ë²Ì0¤Ç¤Ê¤¤¤Ê¤é + BRANCH_NE + CYCLE_NEXT 2 + .pool + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@ UNDOC +@@ LAX +@@ +.macro OP_LAX + mov REG_A, r0, lsl #24 + mov REG_X, r0 + mov REG_NZ, REG_A, asr #24 +.endm + +.macro OP_SLO + movs r0, r0, lsl #25 + @@set C flag + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG + + orr REG_A,REG_A,r0 + @@set NZ flag + mov REG_NZ, REG_A, asr #24 + @@restore value to write + mov r0, r0, lsr #24 +.endm + +.macro OP_ISB + add r0, r0, #1 + and r0, r0, #0xFF +.endm + +.macro OP_SHY + mov r0,REG_ADDR, lsr #8 + add r0,r0,#1 + and r0,r0,REG_Y +.endm + +.macro OP_SRE + movs r0, r0, lsr #1 + @@set C flag + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG + + eor REG_A,REG_A,r0, lsl #24 + @@set NZ flag + mov REG_NZ, REG_A, asr #24 +.endm + +.macro OP_SBX + and r1,REG_X,REG_A, lsr #24 + subs r0,r1,r0 + orrcs REG_P_REST, REG_P_REST, #P_REST_C_FLAG + biccc REG_P_REST, REG_P_REST, #P_REST_C_FLAG + and REG_X,r0,#0xFF + orr REG_NZ, REG_X, REG_X, lsl #24 +.endm + +.macro OP_DCP + sub r0,r0,#1 + and r0,r0,#0xFF +.endm + +.macro OP_RLA + @@ ¥­¥ã¥ê¡¼¤ò¥»¥Ã¥È + movs r1, REG_P_REST, lsr #1 + @@ ¥·¥Õ¥È + adc r0, r0, r0 + @@ NZ¤È¥­¥ã¥ê¡¼¤ò¥»¥Ã¥È + orrs REG_NZ, r0, r0, lsl #24 + @@ ¥­¥ã¥ê¡¼¤òÊݸ + adc REG_P_REST, r1, r1 + and REG_A,REG_A,r0,lsl #24 +.endm + +.macro OP_RRA + movs r1, REG_P_REST, lsr #1 + orrcs r0, r0, #0x100 + movs r0, r0, lsr #1 +.endm + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@ +@@ UNDOCUMENTED +@@ + +op47: @ SRE $nn + ZERO_ADDR + ZP_READ_W + OP_SRE + ZP_WRITE_W + CYCLE_NEXT 5 + +op57: @ SRE $nn, X + ZEROX_ADDR + ZP_READ_W + OP_SRE + ZP_WRITE_W + CYCLE_NEXT 6 + +op4F: @ SRE $nnnn + ABS_ADDR + READ_WRITE_1 + OP_SRE + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_SRE + READ_WRITE_4 + CYCLE_NEXT 6 + +op5F: @ SRE $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_SRE + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_SRE + READ_WRITE_4 + CYCLE_NEXT 7 + +op5B: @ SRE $nnnn, Y + ABSY_ADDR + READ_WRITE_1 + OP_SRE + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_SRE + READ_WRITE_4 + CYCLE_NEXT 7 + +op43: @ SRE ($nn, X) + INDX_ADDR + READ_WRITE_1 + OP_SRE + READ_WRITE_2 + CYCLE_NEXT 8 + READ_WRITE_3 + OP_SRE + READ_WRITE_4 + CYCLE_NEXT 8 + +op53: @ SRE ($nn), Y + INDY_ADDR + READ_WRITE_1 + OP_SRE + READ_WRITE_2 + CYCLE_NEXT 8 + READ_WRITE_3 + OP_SRE + READ_WRITE_4 + CYCLE_NEXT 8 + + +op9C: @ SHY $nnnn, X + ABSX_ADDR + OP_SHY + WRITE_1 + CYCLE_NEXT 5 + WRITE_2 + CYCLE_NEXT 5 + +opE7: @ ISB $nn + ZERO_ADDR + ZP_READ_W + OP_ISB + ZP_WRITE_W + OP_SBC + CYCLE_NEXT 5 + +opF7: @ ISB $nn, X + ZEROX_ADDR + ZP_READ_W + OP_ISB + ZP_WRITE_W + OP_SBC + CYCLE_NEXT 6 + +opEF: @ ISB $nnnn + ABS_ADDR + READ_WRITE_1 + OP_ISB + READ_WRITE_2 + OP_SBC + CYCLE_NEXT 6 + READ_WRITE_3 + OP_ISB + READ_WRITE_4 + OP_SBC + CYCLE_NEXT 6 + + +opFF: @ ISB $nnnn,X + ABSX_ADDR + READ_WRITE_1 + OP_ISB + READ_WRITE_2 + OP_SBC + CYCLE_NEXT 7 + READ_WRITE_3 + OP_ISB + READ_WRITE_4 + OP_SBC + CYCLE_NEXT 7 + +opFB: @ ISB $nnnn, Y + ABSY_ADDR + READ_WRITE_1 + OP_ISB + READ_WRITE_2 + OP_SBC + CYCLE_NEXT 7 + READ_WRITE_3 + OP_ISB + READ_WRITE_4 + OP_SBC + CYCLE_NEXT 7 + +opE3: @ ISB ($nn, X) + INDX_ADDR + READ_WRITE_1 + OP_ISB + READ_WRITE_2 + OP_SBC + CYCLE_NEXT 7 + READ_WRITE_3 + OP_ISB + READ_WRITE_4 + OP_SBC + CYCLE_NEXT 7 + +opF3: @ ISB ($nn), Y + INDY_ADDR + READ_WRITE_1 + OP_ISB + READ_WRITE_2 + OP_SBC + CYCLE_NEXT 7 + READ_WRITE_3 + OP_ISB + READ_WRITE_4 + OP_SBC + CYCLE_NEXT 7 + +opA7: @ LAX $nn + ZERO_ADDR + ZP_READ + OP_LAX + CYCLE_NEXT 3 + +opB7: @ LAX $nn, Y + ZEROY_ADDR + ZP_READ + OP_LAX + CYCLE_NEXT 4 + +opAF: @ LAX $nnnn + ABS_ADDR + READ_1 + OP_LAX + CYCLE_NEXT 4 + READ_2 + OP_LAX + CYCLE_NEXT 4 + +opBF: @ LAX $nnnn, Y + ABSY_ADDR + READ_1 + OP_LAX + CYCLE_NEXT 4 + READ_2 + OP_LAX + CYCLE_NEXT 4 + +opA3: @ LAX ($nn, X) + INDX_ADDR + READ_1 + OP_LAX + CYCLE_NEXT 6 + READ_2 + OP_LAX + CYCLE_NEXT 6 + +opB3: @ LAX ($nn), Y + INDY_ADDR + READ_1 + OP_LAX + CYCLE_NEXT 5 + READ_2 + OP_LAX + CYCLE_NEXT 5 + +op07: @ SLO $nn + ZERO_ADDR + ZP_READ_W + OP_SLO + ZP_WRITE_W + CYCLE_NEXT 5 + +op17: @ SLO $nn, X + ZEROX_ADDR + ZP_READ_W + OP_SLO + ZP_WRITE_W + CYCLE_NEXT 6 + +op0F: @ SLO $nnnn + ABS_ADDR + READ_WRITE_1 + OP_SLO + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_SLO + READ_WRITE_4 + CYCLE_NEXT 6 + +op1F: @ SLO $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_SLO + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_SLO + READ_WRITE_4 + CYCLE_NEXT 7 + +op1B: @ SLO $nnnn, Y + ABSY_ADDR + READ_WRITE_1 + OP_SLO + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_SLO + READ_WRITE_4 + CYCLE_NEXT 7 + +op03: @ SLO ($nn, X) + INDX_ADDR + READ_WRITE_1 + OP_SLO + READ_WRITE_2 + CYCLE_NEXT 8 + READ_WRITE_3 + OP_SLO + READ_WRITE_4 + CYCLE_NEXT 8 + +op13: @ SLO ($nn), Y + INDY_ADDR + READ_WRITE_1 + OP_SLO + READ_WRITE_2 + CYCLE_NEXT 8 + READ_WRITE_3 + OP_SLO + READ_WRITE_4 + CYCLE_NEXT 8 + +opCB: @ SBX #$nn + IMM_VALUE + OP_SBX + CYCLE_NEXT 2 + +opC7: @ DCP $nn + ZERO_ADDR + ZP_READ_W + OP_DCP + ZP_WRITE_W + OP_CMP + CYCLE_NEXT 5 + +opD7: @ DCP $nn, X + ZEROX_ADDR + ZP_READ_W + OP_DCP + ZP_WRITE_W + OP_CMP + CYCLE_NEXT 6 + +opCF: @ DCP $nnnn + ABS_ADDR + READ_WRITE_1 + OP_DCP + READ_WRITE_2 + OP_CMP + CYCLE_NEXT 6 + READ_WRITE_3 + OP_DCP + READ_WRITE_4 + OP_CMP + CYCLE_NEXT 6 + +opDF: @ DCP $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_DCP + READ_WRITE_2 + OP_CMP + CYCLE_NEXT 7 + READ_WRITE_3 + OP_DCP + READ_WRITE_4 + OP_CMP + CYCLE_NEXT 7 + +opDB: @ DCP $nnnn, Y + ABSY_ADDR + READ_WRITE_1 + OP_DCP + READ_WRITE_2 + OP_CMP + CYCLE_NEXT 7 + READ_WRITE_3 + OP_DCP + READ_WRITE_4 + OP_CMP + CYCLE_NEXT 7 + + +opC3: @ DCP ($nn, X) + INDX_ADDR + READ_WRITE_1 + OP_DCP + READ_WRITE_2 + OP_CMP + CYCLE_NEXT 8 + READ_WRITE_3 + OP_DCP + READ_WRITE_4 + OP_CMP + CYCLE_NEXT 8 + +opD3: @ DCP ($nn), Y + INDY_ADDR + READ_WRITE_1 + OP_DCP + READ_WRITE_2 + OP_CMP + CYCLE_NEXT 8 + READ_WRITE_3 + OP_DCP + READ_WRITE_4 + OP_CMP + CYCLE_NEXT 8 + +op27: @ RLA $nn + ZERO_ADDR + ZP_READ_W + OP_RLA + ZP_WRITE_W + CYCLE_NEXT 5 + +op37: @ RLA $nn, X + ZEROX_ADDR + ZP_READ_W + OP_RLA + ZP_WRITE_W + CYCLE_NEXT 6 + +op2F: @ RLA $nnnn + ABS_ADDR + READ_WRITE_1 + OP_RLA + READ_WRITE_2 + CYCLE_NEXT 6 + READ_WRITE_3 + OP_RLA + READ_WRITE_4 + CYCLE_NEXT 6 + +op3F: @ RLA $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_RLA + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_RLA + READ_WRITE_4 + CYCLE_NEXT 7 + +op3B: @ RLA $nnnn, Y + ABSY_ADDR + READ_WRITE_1 + OP_RLA + READ_WRITE_2 + CYCLE_NEXT 7 + READ_WRITE_3 + OP_RLA + READ_WRITE_4 + CYCLE_NEXT 7 + +op23: @ RLA ($nn, X) + INDX_ADDR + READ_WRITE_1 + OP_RLA + READ_WRITE_2 + CYCLE_NEXT 8 + READ_WRITE_3 + OP_RLA + READ_WRITE_4 + CYCLE_NEXT 8 + +op33: @ RLA ($nn), Y + INDY_ADDR + READ_WRITE_1 + OP_RLA + READ_WRITE_2 + CYCLE_NEXT 8 + READ_WRITE_3 + OP_RLA + READ_WRITE_4 + CYCLE_NEXT 8 + +op67: @ RRA $nn + ZERO_ADDR + ZP_READ_W + OP_RRA + ZP_WRITE_W + OP_ADC + CYCLE_NEXT 5 + +op77: @ RRA $nn, X + ZEROX_ADDR + ZP_READ_W + OP_RRA + ZP_WRITE_W + OP_ADC + CYCLE_NEXT 6 + +op6F: @ RRA $nnnn + ABS_ADDR + READ_WRITE_1 + OP_RRA + READ_WRITE_2 + OP_ADC + CYCLE_NEXT 6 + READ_WRITE_3 + OP_RRA + READ_WRITE_4 + OP_ADC + CYCLE_NEXT 6 + +op7F: @ RRA $nnnn, X + ABSX_ADDR + READ_WRITE_1 + OP_RRA + READ_WRITE_2 + OP_ADC + CYCLE_NEXT 7 + READ_WRITE_3 + OP_RRA + READ_WRITE_4 + OP_ADC + CYCLE_NEXT 7 + +op7B: @ RRA $nnnn, Y + ABSY_ADDR + READ_WRITE_1 + OP_RRA + READ_WRITE_2 + OP_ADC + CYCLE_NEXT 7 + READ_WRITE_3 + OP_RRA + READ_WRITE_4 + OP_ADC + CYCLE_NEXT 7 + +op63: @ RRA ($nn, X) + INDX_ADDR + READ_WRITE_1 + OP_RRA + READ_WRITE_2 + OP_ADC + CYCLE_NEXT 8 + READ_WRITE_3 + OP_RRA + READ_WRITE_4 + OP_ADC + CYCLE_NEXT 8 + +op73: @ RRA ($nn), Y + INDY_ADDR + READ_WRITE_1 + OP_RRA + READ_WRITE_2 + OP_ADC + CYCLE_NEXT 8 + READ_WRITE_3 + OP_RRA + READ_WRITE_4 + OP_ADC + CYCLE_NEXT 8 + + +op04: @ NOP $nn +op44: +op64: + add REG_PC,REG_PC,#1 + CYCLE_NEXT 3 + +op0C: @ NOP $nnnn + add REG_PC,REG_PC,#2 + CYCLE_NEXT 4 + +op14: @ NOP $nn, X +op34: +op54: +op74: +opD4: +opF4: + add REG_PC,REG_PC,#1 + CYCLE_NEXT 4 + +op1A: @ NOP +op3A: +op5A: +op7A: +opDA: +opFA: + CYCLE_NEXT 2 + +op1C: @ NOP $nnnn, X +op3C: +op5C: +op7C: +opDC: +opFC: + add REG_PC,REG_PC,#2 + CYCLE_NEXT 4 + +op80: @ NOP #$nn +op82: +op89: +opC2: +opE2: + add REG_PC,REG_PC,#1 + CYCLE_NEXT 2 + + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ JMP_INDIRECT +@@@ +@@@ NZVC +@@@ ---- +@@@ ---- +@ JMP ($nnnn) +op6C: + ABS_ADDR + and r0, REG_ADDR, #0xFF + teq r0, #0xFF + beq jmp_indirect_bug + READ_WORD + REBASE_PC + CYCLE_NEXT 5 +jmp_indirect_bug: +@@ +@@ BUG is : to not read word at REG_ADDR, because it loops +@@ but read low part at REG_ADDR and high part at REG_ADDR&0xFF00 instead of REG_ADDR+1 +@@ + READ + mov REG_PC, r0 + and REG_ADDR, REG_ADDR, #0xff00 + READ + orr r0, REG_PC, r0, lsl #8 + REBASE_PC + + CYCLE_NEXT 5 + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ JMP_ABSOLUTE +@@@ +@@@ NZVC +@@@ ---- +@@@ ---- +@ JMP $nnnn +op4C: + ABS_ADDR + mov r0, REG_ADDR + @sub r3, REG_PC, #3 + REBASE_PC + CYCLE_NEXT 3 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ JSR +@@@ +@@@ NZVC +@@@ ---- +@@@ ---- +@ JSR $nnnn +op20: + ABS_ADDR + ldr r0, [REG_OP_TABLE, #OTOFFS_PC_BASE] + sub r0, REG_PC, r0 + sub r0, r0, #1 + PUSH_WORD + mov r0, REG_ADDR + REBASE_PC + CYCLE_NEXT 6 + + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ BRK +@@@ +@@@ NZVC BI +@@@ ---- -- +@@@ ---- 11 +op00: @ BRK + IMPLIED + add REG_PC, REG_PC, #1 + ldr r0, [REG_OP_TABLE, #OTOFFS_PC_BASE] + sub r0, REG_PC, r0 + PUSH_WORD + orr REG_P_REST, REG_P_REST, #P_REST_B_FLAG + SAVE_P + PUSH_BYTE + orr REG_P_REST, REG_P_REST, #P_REST_I_FLAG + mov REG_ADDR, #0x10000 + sub REG_ADDR, REG_ADDR, #IRQ_VECTOR + READ_WORD + REBASE_PC + CYCLE_NEXT 7 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ RTI +@@@ +@@@ NZVC +@@@ ---- +@@@ ---- +@ RTI +op40: + IMPLIED + POP_BYTE + LOAD_P + POP_WORD + REBASE_PC + CYCLE_NEXT_INT 6 + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ RTS +@@@ +@@@ NZVC +@@@ ---- +@@@ ---- +@ RTS +op60: + IMPLIED + POP_WORD + add r0, r0, #1 + REBASE_PC + CYCLE_NEXT 6 + +@@@ +@@@ ³ä¤ê¹þ¤ß¤Î½èÍý +@@@ +do_int: + ldr r0, [REG_OP_TABLE, #OTOFFS_PC_BASE] + sub r0, REG_PC, r0 + PUSH_WORD + bic REG_P_REST, REG_P_REST, #P_REST_B_FLAG + SAVE_P + PUSH_BYTE + tst REG_P_REST, #FCEU_IQNMI<<8 + orreq REG_P_REST, REG_P_REST, #P_REST_I_FLAG + bic REG_P_REST, REG_P_REST, #((FCEU_IQNMI|FCEU_IQTEMP)<<8) + mov REG_ADDR, #0x10000 + subeq REG_ADDR, REG_ADDR, #IRQ_VECTOR + subne REG_ADDR, REG_ADDR, #NMI_VECTOR + READ_WORD + REBASE_PC + CYCLE_NEXT 7 + +@@@ +@@@ ¥ê¥»¥Ã¥È¤Î½èÍý +@@@ + .globl reset_cpu + +reset_cpu: + stmfd r13!,{r4-r11,lr} + + ldr r0, =nes_registers + ldmia r0, {r4-r12} + + @@ Set Z, clear N + mov REG_NZ, #0 + @@REG_P_REST = 0, don't touch REG_S + bic REG_P_REST, REG_P_REST, #0xff + + @@ R bit is always 1 + orr REG_NZ, REG_NZ, #P_R_FLAG + + @@ INTERRUPT + orr REG_P_REST, REG_P_REST, #P_REST_I_FLAG + + mov REG_ADDR, #0x10000 + sub REG_ADDR, REG_ADDR, #RESET_VECTOR + READ_WORD + REBASE_PC + + ldr r0, =nes_registers + stmia r0, {r4-r12} + + ldmfd r13!,{r4-r11,lr} + bx lr + +@@@ +@@@ low-level memhandlers +@@@ + +read_ppu_reg: +read_high_reg: +read_save_ram: +read_rom_byte: + @ must preserve r3 for the callers too + @ TODO: check if all of saves are needed, optimize read_rom_byte, _DB + str REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased + str REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq + str REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used + mov REG_PC, lr @ r7 + mov REG_P_REST, r3 @ r8 + + ldr r2, =ARead + bic r0, REG_ADDR, #0x00ff0000 + mov lr, pc + ldr pc, [r2, r0, lsl #2] + + ldr REG_OP_TABLE, =cpu_exec_table @ got trashed because was in r12 + mov lr, REG_PC + mov r3, REG_P_REST + ldr REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased + ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq + ldr REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used + bx lr + + +write_ppu_reg: +write_high_reg: +write_save_ram: +write_rom_byte: + @ must preserve r3 for the callers too + str REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased + str REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq + str REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used + mov REG_PC, lr @ r7 + mov REG_P_REST, r3 @ r8 + + ldr r2, =BWrite + mov r1, r0 + bic r0, REG_ADDR, #0x00ff0000 + mov lr, pc + ldr pc, [r2, r0, lsl #2] + + ldr REG_OP_TABLE, =cpu_exec_table @ got trashed because was in r12 + mov lr, REG_PC + mov r3, REG_P_REST + ldr REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x0c)] @ might get rebased + ldr REG_P_REST, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x10)] @ might set irq + ldr REG_CYCLE, [REG_OP_TABLE, #(OTOFFS_NES_REGS + 0x1c)] @ might get used + bx lr + + +.pool + + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ 6502 ¤ò¥¨¥ß¥å¥ì¡¼¥È¤¹¤ë +@@@ +@@@ REG_CYCLE => ¼Â¹Ô¤¹¤ë¥µ¥¤¥¯¥ë +@@@ REG_CYCLE <= »Ä¤Ã¤Æ¤¤¤ë¥µ¥¤¥¯¥ë(Îí¤Þ¤¿¤ÏÉé) + .globl cpu_exec +cpu_exec: + stmfd r13!,{r4-r11,lr} + + ldr r0, =nes_registers + ldmia r0, {r4-r12} + +@ ldr REG_OP_TABLE, = cpu_exec_table @ set on init + + CYCLE_NEXT 0 + +cpu_exec_end: + ldr r0, =nes_registers + stmia r0, {r4-r12} + + ldmfd r13!,{r4-r11,lr} + bx lr + +@@@ +@@@ ¤ß¤ì¤Ð¤ï¤«¤ë¤è¤¦¤Ë¥ª¥Ú¥³¡¼¥É¤ò¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ë¤·¤¿¥¸¥ã¥ó¥×¥Æ¡¼¥Ö¥ë +@@@ 0x400¥Ð¥¤¥È +@@@ + +@ the code does RAM accesses through cpu_exec_table pointer + offset, so +@ they must be in the same section + + SECTION_DATA + ALIGN + +cpu_exec_table: + .long op00, op01, op02, op03, op04, op05, op06, op07 + .long op08, op09, op0A, op0B, op0C, op0D, op0E, op0F + + .long op10, op11, op12, op13, op14, op15, op16, op17 + .long op18, op19, op1A, op1B, op1C, op1D, op1E, op1F + + .long op20, op21, op22, op23, op24, op25, op26, op27 + .long op28, op29, op2A, op2B, op2C, op2D, op2E, op2F + + .long op30, op31, op32, op33, op34, op35, op36, op37 + .long op38, op39, op3A, op3B, op3C, op3D, op3E, op3F + + .long op40, op41, op42, op43, op44, op45, op46, op47 + .long op48, op49, op4A, op4B, op4C, op4D, op4E, op4F + + .long op50, op51, op52, op53, op54, op55, op56, op57 + .long op58, op59, op5A, op5B, op5C, op5D, op5E, op5F + + .long op60, op61, op62, op63, op64, op65, op66, op67 + .long op68, op69, op6A, op6B, op6C, op6D, op6E, op6F + + .long op70, op71, op72, op73, op74, op75, op76, op77 + .long op78, op79, op7A, op7B, op7C, op7D, op7E, op7F + + .long op80, op81, op82, op83, op84, op85, op86, op87 + .long op88, op89, op8A, op8B, op8C, op8D, op8E, op8F + + .long op90, op91, op92, op93, op94, op95, op96, op97 + .long op98, op99, op9A, op9B, op9C, op9D, op9E, op9F + + .long opA0, opA1, opA2, opA3, opA4, opA5, opA6, opA7 + .long opA8, opA9, opAA, opAB, opAC, opAD, opAE, opAF + + .long opB0, opB1, opB2, opB3, opB4, opB5, opB6, opB7 + .long opB8, opB9, opBA, opBB, opBC, opBD, opBE, opBF + + .long opC0, opC1, opC2, opC3, opC4, opC5, opC6, opC7 + .long opC8, opC9, opCA, opCB, opCC, opCD, opCE, opCF + + .long opD0, opD1, opD2, opD3, opD4, opD5, opD6, opD7 + .long opD8, opD9, opDA, opDB, opDC, opDD, opDE, opDF + + .long opE0, opE1, opE2, opE3, opE4, opE5, opE6, opE7 + .long opE8, opE9, opEA, opEB, opEC, opED, opEE, opEF + + .long opF0, opF1, opF2, opF3, opF4, opF5, opF6, opF7 + .long opF8, opF9, opFA, opFB, opFC, opFD, opFE, opFF + +@@@ +@@@ ¥ª¥Ú¥³¡¼¥É¥Æ¡¼¥Ö¥ë¤Îľ¸å¤Ë¤³¤ì¤òÃÖ¤¯REG_OP_TABLEÁêÂÐ¤Ç +@@@ ÍøÍѤǤ­¤ë +@@@ +nes_registers: + .fill 0x40, 1, 0 +RAM: +nes_internal_ram: + .fill 0x100, 1, 0 +nes_stack: + .fill 0x700, 1, 0 +@ TODO: write code which keeps it up-to-date +pc_base: + .long 0 + +.pool + +@ SECTION_SLOW + SECTION_TEXT + ALIGN + + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@ +@@@ Undefined Opcodes +@@@ +op0B: @ ANC #$nn +op2B: @ ANC #$nn +op8B: @ ANE #$nn +op6B: @ ARR #$nn +op4B: @ ASR #$nn +@opC7: @ DCP $nn +@opD7: @ DCP $nn, X +@opCF: @ DCP $nnnn +@opDF: @ DCP $nnnn, X +@opDB: @ DCP $nnnn, Y +@opC3: @ DCP ($nn, X) +@opD3: @ DCP ($nn), Y + + + +@opE7: @ ISB $nn +@opF7: @ ISB $nn, X +@opEF: @ ISB $nnnn +@opFF: @ ISB $nnnn, X +@opFB: @ ISB $nnnn, Y +@opE3: @ ISB ($nn, X) +@opF3: @ ISB ($nn), Y + + +op02: @ JAM +op12: +op22: +op32: +op42: +op52: +op62: +op72: +op92: +opB2: +opD2: +opF2: + + +opBB: @ LAS $nnnn,Y +@opA3: @ LAX ($nn, X) +@opA7: @ LAX $nn +@opB7: @ LAX $nn, Y +@opAF: @ LAX $nnnn +@opBF: @ LAX $nnnn, Y + +@opB3: @ LAX ($nn), Y +opAB: @ LXA #$nn +@op27: @ RLA $nn +@op37: @ RLA $nn, X +@op2F: @ RLA $nnnn +@op3F: @ RLA $nnnn, X +@op3B: @ RLA $nnnn, Y +@op23: @ RLA ($nn, X) +@op33: @ RLA ($nn), Y +@op67: @ RRA $nn +@op77: @ RRA $nn, X +@op6F: @ RRA $nnnn +@op7F: @ RRA $nnnn, X +@op7B: @ RRA $nnnn, Y +@op63: @ RRA ($nn, X) +@op73: @ RRA ($nn), Y +op87: @ SAX $nn +op97: @ SAX $nn, Y +op8F: @ SAX $nnnn +op83: @ SAX ($nn, X) +@opCB: @ SBX #$nn +op9F: @ SHA $nnnn, Y +op93: @ SHA ($nn), Y +op9B: @ SHS $nnnn, Y +op9E: @ SHX $nnnn, Y +@op9C: @ SHY $nnnn, X +@op03: @ SLO ($nn, X) +@op07: @ SLO $nn +@op17: @ SLO $nn, X +@op0F: @ SLO $nnnn +@op1F: @ SLO $nnnn, X +@op1B: @ SLO $nnnn, Y +@op13: @ SLO ($nn), Y +@op47: @ SRE $nn +@op57: @ SRE $nn, X +@op4F: @ SRE $nnnn +@op5F: @ SRE $nnnn, X +@op5B: @ SRE $nnnn, Y +@op43: @ SRE ($nn, X) +@op53: @ SRE ($nn), Y + CYCLE_NEXT 1 +@ emu_panic? + + + +@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ fceu stuff... +@@@@@@@@@@@@@@@@@@@@@@@@@@ + +@ for reference +.extern Page +.extern ARead +.extern BWrite + + + SECTION_DATA + ALIGN +@ .globl X + .globl RAM + .globl nes_registers @ TODO: hide? + .globl pc_base +@ .globl timestamp +@ .globl MapIRQHook @ (int a) +@ TODO... .. conversion X <-> nes_registers for savestates +@timestamp: .long 0 +@MapIRQHook: .long 0 +@X: .fill 0x20, 1, 0 + .globl X6502_Reset_a @ (void); + .globl X6502_Power_a @ (void); + .globl X6502_Run_a @ (int32 cycles); + .globl TriggerIRQ_a @ (void); + .globl TriggerNMI_a @ (void); + .globl TriggerNMINSF_a @ (void); + .globl X6502_AddCycles_a @ (int x); + .globl X6502_IRQBegin_a @ (int w); + .globl X6502_IRQEnd_a @ (int w); + .globl X6502_rebase_a @ (void); + + SECTION_TEXT + ALIGN + +.equiv X6502_Reset_a, reset_cpu +.equiv X6502_Run_a, cpu_exec + + +X6502_Power_a: + ldr r1, =timestamp + mov r0, #0 + str r0, [r1] + ldr r1, =nes_registers + mov r2, #(0x40/4) +X6502_Power_loop1: + subs r2, r2, #1 + str r0, [r1], #4 + bne X6502_Power_loop1 + ldr r0, =cpu_exec_table + sub r1, r1, #0x40 + str r0, [r1, #0x20] + b X6502_Reset_a + + +TriggerIRQ_a: + mov r0, #FCEU_IQTEMP + +X6502_IRQBegin_a: + ldr r2, =nes_registers + and r0, r0, #0xff + ldr r1, [r2, #0x10] @ REG_P_REST + orr r1, r1, r0, lsl #8 + str r1, [r2, #0x10] + bx lr + + +X6502_IRQEnd_a: + ldr r2, =nes_registers + and r0, r0, #0xff + ldr r1, [r2, #0x10] + bic r1, r1, r0, lsl #8 + str r1, [r2, #0x10] + bx lr + + +TriggerNMI_a: + mov r0, #FCEU_IQTEMP + b X6502_IRQBegin_a + + +TriggerNMINSF_a: + @ not implemented + bx lr + + +X6502_AddCycles_a: + ldr r2, =nes_registers + ldr r1, [r2, #0x1c] + mvn r3, #49 + mla r0, r3, r0, r1 + str r0, [r2, #0x1c] + bx lr + + +@ rebase PC when not executing or in memhandlers +X6502_rebase_a: + stmfd sp!,{REG_PC,REG_OP_TABLE} + ldr REG_OP_TABLE, =cpu_exec_table + ldr r0, [REG_OP_TABLE, #(OTOFFS_NES_REGS+0x0c)] @ PC + ldr r1, [REG_OP_TABLE, #OTOFFS_PC_BASE] + sub r0, r0, r1 + REBASE_PC + str REG_PC, [REG_OP_TABLE, #(OTOFFS_NES_REGS+0x0c)] @ PC + ldmfd sp!,{REG_PC,REG_OP_TABLE} + bx lr +.pool + + +@ vim:filetype=armasm + diff --git a/ncpu.h b/ncpu.h new file mode 100644 index 0000000..015320a --- /dev/null +++ b/ncpu.h @@ -0,0 +1,124 @@ +#ifndef NES_H +#define NES_H + +//#define SECTION_FAST //.section emu.fast, "awx" +//#define SECTION_SLOW //.section emu.slow, "awx" +//#define SECTION_HEAD //.section emu.head, "awx" + +#define ALIGN .align 4 +#define SECTION_DATA .data +#define SECTION_TEXT .text + +/* + * 6502 ¤Î¥ì¥¸¥¹¥¿ + * + * A ¤Ï¾ï¤Ë 24 ¥Ó¥Ã¥È¥·¥Õ¥È¤·¤Æ¤ª¤¯ + * P ¤Ï2¤Ä¤Ëʬ¤±¤ë¡£ + * NZ¤Ï¤Û¤È¤ó¤É¤ÎÌ¿Î᤬Êѹ¹¤¹¤ë¤Î¤Ç¡¤NZ¤Î¸µ¤Ë¤Ê¤ëÃͤòÊݸ + * »Ä¤ê¤Ï¾¤Î¾ì½ê¤ËÃÖ¤¯ + * + * S ¤Ï24¥Ó¥Ã¥È¥·¥Õ¥È¤·¤Æ¤ª¤¯ + * ¤³¤ì¤Ç;¤Ã¤Æ²¼¤Î¥Ó¥Ã¥È¤Ë P ¤Î»Ä¤ê¤òÃÖ¤¯(VBDI) + * ¤µ¤é¤Ë;¤Ã¤Æ¤ë¤È¤³¤í¤Ë¤Ï³ä¤ê¹þ¤ß¤Ë´Ø¤¹¤ë¥Õ¥é¥°¤òÃÖ¤¯ + * + * PC ¤ÏROMÆâ¤Î¥¢¥É¥ì¥¹¤ËÊÑ´¹¤·¤Æ¤ª¤¯ + * ¤³¤Î¾ì¹ç¤Ï¶­³¦¥Á¥§¥Ã¥¯¤ò¤·¤¿¤Û¤¦¤¬¤¤¤¤¤Î¤À¤¬¡¤´Êñ¤Ç¤Ï¤Ê¤¤ + * ËÜÅö¤Î PC ¤òÆÀ¤ë¤¿¤á¤Ë¤Ï¸½ºß¤Î¥Ð¥ó¥¯¤ÎÀèƬ¥¢¥É¥ì¥¹¤ò°ú¤±¤Ð¤è¤¤ + * + * I just love the above comments :) + */ + +// // offs in nes_registers +#define REG_A r4 // 00 +#define REG_X r5 // 04 +#define REG_Y r6 // 08 +#define REG_PC r7 // 0c +#define REG_S r8 // 10 +#define REG_P_REST r8 +#define REG_NZ r9 // 14 +#define REG_ADDR r10 // 18 +#define REG_CYCLE r11 // 1c +#define REG_OP_TABLE r12 // 20 + + +/* + * REG_P_REST ¤Ë¤Ï³Æ¼ï¥Õ¥é¥°¤òÃÖ¤¯ + * + * 0 + * FEDCBA98 76543210 + * |||||||| |||||||+---C ¥­¥ã¥ê¡¼¤Þ¤¿¤Ï¥Ü¥í¡¼¤Ê¤· + * |||||||| ||||||+---NMI¤ÎȯÀ¸ + * |||||||| |||||+---I ³ä¤ê¹þ¤ßµö²Ä + * |||||||| ||||+---D ½½¿Ê¥â¡¼¥É + * |||||||| |||+---B + * |||||||| ||+---IRQ¤ÎȯÀ¸ + * |||||||| |+---V ¥ª¡¼¥Ð¡¼¥Õ¥í¡¼ + * |||||||| +---$2005/$2006 ¥È¥°¥ë¥Õ¥é¥° + * |||||||| + * |||||||+---$2000[2] 32¥¤¥ó¥¯¥ê¥á¥ó¥È + * ||||||+---$2000[3] ¥¹¥×¥é¥¤¥È¥¢¥É¥ì¥¹ÁªÂò + * |||||+---$2000[4] ¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¥¢¥É¥ì¥¹ÁªÂò + * ||||+---$2000[5] ¥¹¥×¥é¥¤¥È¥µ¥¤¥º + * |||+---̤»ÈÍÑ + * ||+---$2000[7] NMIµö²Ä + * |+---$2001[3] ¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤òÉÁ²è + * +---$2001[4] ¥¹¥×¥é¥¤¥È¤òÉÁ²è + * + * 1 + * FEDCBA9876543210 + * |||||||||||||||+---$2002[4] VRAM¤Ë½ñ¤­¹þ¤ß²Ä¡© + * ||||||||||||||+---$2002[5] ¥¹¥×¥é¥¤¥È¤¬Â¿¤¹¤® + * |||||||||||||+---$2002[6] ¥¹¥×¥é¥¤¥È¥Ò¥Ã¥È(¼ÂÁõ¤Ç¤­¤ë¤Î¤«¡©) + * ||||||||||||+---$2002[7] VBL + * |||||||||||+---DMC³ä¤ê¹þ¤ßȯÀ¸ + * ||||||||||+---VRAM¤ò»ý¤Ã¤Æ¤¤¤ë + * ||||||||++---̤»ÈÍÑ + * ++++++++---S ¥¹¥¿¥Ã¥¯¥Ý¥¤¥ó¥¿ + * + * note: fceu uses this differently + * [7:0] - interrupt flags (same as above) + * [15:8] - FCEU IRQ pending sources + * [23:16] - unused + * [31:24] - stack pointer + */ + + +/* + * REG_P_REST ¤Ç»È¤¦¥Õ¥é¥°¡£´ðËÜŪ¤ËP¤ÈƱ¤¸°ÌÃ֤ˤ¢¤ë + */ +#define P_REST_V_FLAG 0x40 +#define P_REST_B_FLAG 0x10 +#define P_REST_D_FLAG 0x08 +#define P_REST_I_FLAG 0x04 +#define P_REST_C_FLAG 0x01 +#define P_REST_FLAGS 0x5D + +/* + * ³ä¤ê¹þ¤ß¤¬È¯À¸¤¹¤ë¤È¥»¥Ã¥È¤µ¤ì¤ë + */ +// will be using FCE flags instead of this +// #define P_REST_INT_PENDING 0x20 +// #define P_REST_NMI_PENDING 0x02 + +// #define ASSERT_NMI orr REG_P_REST, REG_P_REST, #P_REST_NMI_PENDING +// #define ASSERT_INT orr REG_P_REST, REG_P_REST, #P_REST_INT_PENDING + + +/* + * 6502 ¤ÎËÜÅö¤Î¥Õ¥é¥° + */ +#define P_N_FLAG 0x80 +#define P_V_FLAG 0x40 +#define P_R_FLAG 0x20 +#define P_B_FLAG 0x10 +#define P_D_FLAG 0x08 +#define P_I_FLAG 0x04 +#define P_Z_FLAG 0x02 +#define P_C_FLAG 0x01 + +#define NMI_VECTOR 6 +#define RESET_VECTOR 4 +#define IRQ_VECTOR 2 + +#endif + diff --git a/ncpu_debug.c b/ncpu_debug.c new file mode 100644 index 0000000..864cae3 --- /dev/null +++ b/ncpu_debug.c @@ -0,0 +1,156 @@ +#include +#include + +#include "types.h" +#include "x6502.h" +#include "fce.h" + +// asm core state +extern uint32 nes_registers[0x10]; +extern uint32 pc_base; +uint32 PC_prev = 0; + + +static void leave(void) +{ + printf("A: %02x, X: %02x, Y: %02x, S: %02x\n", X.A, X.X, X.Y, X.S); + printf("PC = %04lx, OP=%02X\n", PC_prev, (PC_prev < 0x2000) ? RAM[PC_prev&0x7ff] : ARead[PC_prev](PC_prev)); + exit(1); +} + +static void compare_state(void) +{ + uint8 nes_flags; + + if ((nes_registers[0] >> 24) != X.A) { + printf("A: %02lx vs %02x\n", nes_registers[0] >> 24, X.A); + leave(); + } + + if ((nes_registers[1] & 0xff) != X.X) { + printf("X: %02lx vs %02x\n", nes_registers[1] & 0xff, X.X); + leave(); + } + + if ((nes_registers[2] & 0xff) != X.Y) { + printf("Y: %02lx vs %02x\n", nes_registers[2] & 0xff, X.Y); + leave(); + } + + if (nes_registers[3] - pc_base != X.PC) { + printf("PC: %04lx vs %04x\n", nes_registers[3] - pc_base, X.PC); + leave(); + } + + if ((nes_registers[4] >> 24) != X.S) { + printf("S: %02lx vs %02x\n", nes_registers[4] >> 24, X.S); + leave(); + } + + if (((nes_registers[4]>>8)&0xff) != X.IRQlow) { + printf("IRQlow: %02lx vs %02x\n", ((nes_registers[4]>>8)&0xff), X.IRQlow); + leave(); + } + + // NVUB DIZC + nes_flags = nes_registers[4] & 0x5d; + if ( nes_registers[5]&0x80000000) nes_flags |= 0x80; // N + if (!(nes_registers[5]&0x000000ff)) nes_flags |= 0x02; // Z + // nes_flags |= 0x20; // U, not set in C core (set only when pushing) + + if (nes_flags != X.P) { + printf("flags: %02x vs %02x\n", nes_flags, X.P); + leave(); + } + + if ((int32)nes_registers[7] != X.count) { + printf("cycles: %li vs %li\n", (int32)nes_registers[7], X.count); + leave(); + } +} + + +void TriggerIRQ_d(void) +{ + printf("-- irq\n"); + TriggerIRQ_c(); + TriggerIRQ_a(); + compare_state(); +} + +void TriggerNMI_d(void) +{ + printf("-- nmi\n"); + TriggerNMI_c(); + TriggerNMI_a(); + compare_state(); +} + +void TriggerNMINSF_d(void) +{ +} + +void X6502_Run_d(int32 c) +{ + int32 cycles = c << 4; /* *16 */ \ + if (PAL) cycles -= c; /* *15 */ \ + + printf("-- run(%i)\n", (int)c); + + while (cycles > 0) + { + PC_prev = X.PC; + nes_registers[7]=1; + X.count=1; + X6502_Run_c(); + X6502_Run_a(); + compare_state(); + cycles -= 1 - X.count; + } +} + +void X6502_Reset_d(void) +{ + printf("-- reset\n"); + + X6502_Reset_c(); + X6502_Reset_a(); + compare_state(); +} + +void X6502_Power_d(void) +{ + printf("-- power\n"); + + X6502_Power_c(); + X6502_Power_a(); + compare_state(); +} + +void X6502_AddCycles_d(int x) +{ + printf("-- AddCycles(%i)\n", x); + + X6502_AddCycles_c(x); + X6502_AddCycles_a(x); + //compare_state(); +} + +void X6502_IRQBegin_d(int w) +{ + printf("-- IRQBegin(%02x)\n", w); + + X6502_IRQBegin_c(w); + X6502_IRQBegin_a(w); +} + +void X6502_IRQEnd_d(int w) +{ + printf("-- IRQEnd(%02x)\n", w); + + X6502_IRQEnd_c(w); + X6502_IRQEnd_a(w); +} + + + diff --git a/x6502.c b/x6502.c index c1e55b3..87ba0f5 100644 --- a/x6502.c +++ b/x6502.c @@ -37,7 +37,7 @@ void FP_FASTAPASS(1) (*MapIRQHook)(int a); #define _S X.S #define _P X.P #define _PI X.mooPI -#define _PZ X.PZ +#define _PZ X.PZ // unused? #define _DB X.DB #define _count X.count #define _tcount X.tcount @@ -88,7 +88,7 @@ static INLINE void ADDCYC(int x) timestamp+=x; } -void FASTAPASS(1) X6502_AddCycles(int x) +void FASTAPASS(1) X6502_AddCycles_c(int x) { ADDCYC(x); } @@ -366,22 +366,22 @@ static uint8 CycTable[256] = /*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7, }; -void FASTAPASS(1) X6502_IRQBegin(int w) +void FASTAPASS(1) X6502_IRQBegin_c(int w) { _IRQlow|=w; } -void FASTAPASS(1) X6502_IRQEnd(int w) +void FASTAPASS(1) X6502_IRQEnd_c(int w) { _IRQlow&=~w; } -void TriggerIRQ(void) /* This function should probably be phased out. */ +void TriggerIRQ_c(void) /* This function should probably be phased out. */ { _IRQlow|=FCEU_IQTEMP; } -void TriggerNMINSF(void) +void TriggerNMINSF_c(void) { ADDCYC(7); PUSH(_PC>>8); @@ -390,7 +390,7 @@ void TriggerNMINSF(void) _PC=0x3800; } -void TriggerNMI(void) +void TriggerNMI_c(void) { _IRQlow|=FCEU_IQNMI; } @@ -422,7 +422,7 @@ void TriggerIRQReal(void) } } -void X6502_Reset(void) +void X6502_Reset_c(void) { _PC=RdMem(0xFFFC); _PC|=RdMem(0xFFFD)<<8; @@ -431,17 +431,17 @@ void X6502_Reset(void) _PI=_P=I_FLAG; } -void X6502_Power(void) +void X6502_Power_c(void) { memset((void *)&X,0,sizeof(X)); timestamp=0; - X6502_Reset(); + X6502_Reset_c(); } //int asdc = 0; -void X6502_Run_(void/*int32 cycles*/) +void X6502_Run_c(void/*int32 cycles*/) { /* if(PAL) @@ -475,6 +475,7 @@ void X6502_Run_(void/*int32 cycles*/) ADDCYC(temp); //temp=_tcount; //_tcount=0; +/* if(MapIRQHook) MapIRQHook(temp); temp*=48; @@ -497,10 +498,11 @@ void X6502_Run_(void/*int32 cycles*/) { extern uint8 SIRQStat; SIRQStat|=0x80; - X6502_IRQBegin(FCEU_IQDPCM); + X6502_IRQBegin_c(FCEU_IQDPCM); } } } +*/ //printf("$%04x:$%02x\n",_PC,b1); //_PC++; //printf("$%02x\n",b1); @@ -509,6 +511,10 @@ void X6502_Run_(void/*int32 cycles*/) { #include "ops.h" } + +#ifdef DEBUG_ASM_6502 + _PI=_P; +#endif } } diff --git a/x6502.h b/x6502.h index 86f4f06..48843fc 100644 --- a/x6502.h +++ b/x6502.h @@ -53,23 +53,87 @@ extern void FP_FASTAPASS(1) (*MapIRQHook)(int a); #define FCEU_IQFCOUNT 0x20 #define FCEU_IQTEMP 0x80 -void X6502_Reset(void); -void X6502_Power(void); +#if defined(DEBUG_ASM_6502) +#define TriggerIRQ TriggerIRQ_d +#define TriggerNMI TriggerNMI_d +#define TriggerNMINSF TriggerNMINSF_d +#define X6502_Run X6502_Run_d +#define X6502_Reset X6502_Reset_d +#define X6502_Power X6502_Power_d +#define X6502_AddCycles X6502_AddCycles_d +#define X6502_IRQBegin X6502_IRQBegin_d +#define X6502_IRQEnd X6502_IRQEnd_d +#define X6502_C +#define X6502_A +#define X6502_D + +#elif defined(ASM_6502) +#define TriggerIRQ TriggerIRQ_a +#define TriggerNMI TriggerNMI_a +#define TriggerNMINSF TriggerNMINSF_a +#define X6502_Reset X6502_Reset_a +#define X6502_Power X6502_Power_a +#define X6502_AddCycles X6502_AddCycles_a +#define X6502_IRQBegin X6502_IRQBegin_a +#define X6502_IRQEnd X6502_IRQEnd_a +#define X6502_A + +extern uint32 nes_registers[0x10]; +#define X6502_Run(c) \ +{ \ + int32 cycles = (c) << 4; /* *16 */ \ + if (PAL) cycles -= (c); /* *15 */ \ + nes_registers[7]+=cycles; \ + if (nes_registers[7] > 0) X6502_Run_a(); \ +} + +#else #define X6502_Run(c) \ { \ int32 cycles = (c) << 4; /* *16 */ \ if (PAL) cycles -= (c); /* *15 */ \ X.count+=cycles; \ - if (X.count > 0) X6502_Run_(); \ + if (X.count > 0) X6502_Run_c(); \ } -void X6502_Run_(void); +#define X6502_C +#endif +// c +#ifdef X6502_C +void TriggerIRQ_c(void); +void TriggerNMI_c(void); +void TriggerNMINSF_c(void); +void X6502_Run_c(void); +void X6502_Reset_c(void); +void X6502_Power_c(void); +void FASTAPASS(1) X6502_AddCycles_c(int x); +void FASTAPASS(1) X6502_IRQBegin_c(int w); +void FASTAPASS(1) X6502_IRQEnd_c(int w); +#endif -void TriggerIRQ(void); -void TriggerNMI(void); -void TriggerNMINSF(void); +// asm +#ifdef X6502_A +void TriggerIRQ_a(void); +void TriggerNMI_a(void); +void TriggerNMINSF_a(void); +void X6502_Run_a(void); +void X6502_Reset_a(void); +void X6502_Power_a(void); +void X6502_AddCycles_a(int x); +void X6502_IRQBegin_a(int w); +void X6502_IRQEnd_a(int w); +#endif -void FASTAPASS(1) X6502_AddCycles(int x); -void FASTAPASS(1) X6502_IRQBegin(int w); -void FASTAPASS(1) X6502_IRQEnd(int w); +// debug +#ifdef X6502_D +void TriggerIRQ_d(void); +void TriggerNMI_d(void); +void TriggerNMINSF_d(void); +void X6502_Run_d(int32 c); +void X6502_Reset_d(void); +void X6502_Power_d(void); +void X6502_AddCycles_d(int x); +void X6502_IRQBegin_d(int w); +void X6502_IRQEnd_d(int w); +#endif -- 2.39.2