From e115fe8ed1576eb94e2409944feac979e9eb9eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl-Henrik=20Sk=C3=A5rstedt?= Date: Fri, 11 Mar 2016 17:43:16 -0800 Subject: [PATCH] Removing the disassembler and putting it into its own repo - The disassembler was taking on some girth and weighing the assembler code down. --- README.md | 3 + disassembler/README.MD | 157 --- disassembler/a78.lbl | 100 -- disassembler/c64.lbl | 75 - disassembler/c64kernal.lbl | 158 --- disassembler/x65dsasm.cpp | 2716 ------------------------------------ 6 files changed, 3 insertions(+), 3206 deletions(-) delete mode 100644 disassembler/README.MD delete mode 100644 disassembler/a78.lbl delete mode 100644 disassembler/c64.lbl delete mode 100644 disassembler/c64kernal.lbl delete mode 100644 disassembler/x65dsasm.cpp diff --git a/README.md b/README.md index 245d28c..4e95db0 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,9 @@ Primarily tested with personal archive of sources written for Kick assmebler, DA * irp (indefinite repeat) **FIXED** +* Removed the disassembler and put it into its own project [x65dsasm](http://github.com/sakrac/x65dsasm) +* LUP/REPT directives clean up local symbols each iteration to avoid crossing over an iteration with branches to local labels. +* Fixed Merlin MAC directive which is a little different from normal assembler macros * Labels can start with numbers and values will only be interpreted as decimal numbers if terminated by a character that is not an alphabetic character or underscore * INCSYM failed with local labels, this is now properly handled. (fixed again..) * INCBIN and IMPORT BINARY always failed (force 0 bytes length) diff --git a/disassembler/README.MD b/disassembler/README.MD deleted file mode 100644 index e3b724b..0000000 --- a/disassembler/README.MD +++ /dev/null @@ -1,157 +0,0 @@ -#x65 Disassembler - -Simple disassembler for 6502, 65C02 and 65816 (default). - -## Command Line Options - -Typical command line ([*] = optional): - -**Usage** - -``` -x65dsasm binary disasm.txt [$skip[-$end]] [addr=$xxxx] [cpu=6502/65C02/65816] - [mx=0-3] [src] [prg] [data=$xx] [labels=labels.lbl] -``` - -* binary: file which contains some 65xx series instructions -* disasm.txt: output file (default is stdout) -* $skip-$end: first byte offset to disassemble to last byte offset to disassemble -* addr: disassemble as if loaded at addr (addr) -* data: this number of initial bytes in file is data and not code -* prg: file is a c64 program file starting with the load address -* cpu: set which cpu to disassemble for (default is 6502) -* src: export near assemblable source with guesstimated data blocks -* mx: set the mx flags which control accumulator and index register size -* labels: import labels from a file (each line: label=$xxxx [code]/[data] comment) -* graph: prefix the file with a calling graph -* graph+bra: include branches in the calling graph (increases size significantly) - -### Updates - -* graph option exports a calling graph before the disassembly -* re-evaluation of separating segments after final cleanup -* c64kernal.lbl file defining c64 hw + kernal functions in the range of $e000-$fffa -* a78.lbl file defining Atari 7800 hardware addresses -* Switched the instruction info around to more easily determine read-only instructions -* Various improvements distinguishing between code and data -* c64.lbl file defining all c64 hardware addresses -* Tracking label references outside of the code including zero page -* Data / Code distinction improvements -* **Local labels** to improve code readability -* Improvements to code vs data determination -* Instrument labels through labels text file -* **src** option attempts to generate valid assembler source - -### Labels file format - -Labels is a text file with one label declaration per line followed by the address to assign and the -type of block to represent (code or data or pointers) followed by an optional comment. The labels -file makes the most sense together with the *src* command line argument. - -Addresses can define a range using a '-' after the address followed by an ending address. -No automatic labels will be inserted within this range. - -A special data format is pointers indicating a function pointer table, the label should be -defined with a range to limit the size. Each pointer within the pointer table will be -assigned a code label. - -If the keyword "pointers" is followed by the word "data" the pointers will be interpreted as -data pointers instead of code pointers. - -A label can be redefined with a different name for read-only instructions by using the keyword -read after the address. The label must first be defined as a data label to be assigned a -read-only name. Read only instructions include ora, and, bit, eor, adc, sbc, lda, ldx, ldy, cmp, cpy and cpx. - - -Example labels file: - -``` -TIA_VSYNC = $00 data -TIA_CXM0P = $00 read -Init = $1000 code Entry point into code -SinTable = $1400 data 256 byte sinus table -Interrupt = $10f3 code Interrupt code -Callbacks = $1123-$112b pointers Array of function pointers -MapRefs = $1200-$1240 pointers data Array of data pointers -VIC_Sprite0_x = $d000 set sprite 0 x position -VIC_Sprite0_y = $d001 set sprite 0 y position -VIC_Sprite1_x = $d002 set sprite 1 x position -VIC_Sprite1_y = $d003 set sprite 1 y position -``` - -The simple way to work with a labels file is to copy an existing hardware file and add labels to it. - -Sample output: - -``` -; -; FUNCTION CALLING GRAPH -; -; Code_140 ($d4af) [-] -; Code_21 ($c5a3) [jmp] -; Code_143 ($d56e) [jsr] -; Code_109 ($cec3) [jsr] -; -; DISASSEMBLY -; -; Referenced from ResetVector + $0 (subroutine, $fffc) -; Referenced from IntVector + $0 (subroutine, $fffe) -Reset: ; $c000 - cld - sei -; Referenced from Reset / .l_1 + $3 (branch, $c002) -.l_1: ; $c002 - -; -------------------------------- ; - -; Referenced from Label_14 + $7 (subroutine) -; Referenced from Label_14 + $c (subroutine) -Label_11: - lda $03,x - bpl Label_13 -; Referenced from Label_14 + $18 (subroutine) -Label_12: - sec - lda #$00 - sbc $00,x - sta $00,x - lda #$00 - sbc $01,x - sta $01,x - lda #$00 - sbc $02,x - sta $02,x - lda #$00 - sbc $03,x - sta $03,x -; Referenced from Label_11 + $2 (branch) -Label_13: - rts - -; -------------------------------- ; - -; Referenced from Label_1 + $1e (subroutine) -; Referenced from Label_16 + $1 (subroutine) -; Referenced from Label_24 + $b (subroutine) -; Referenced from Label_28 + $b (subroutine) -Label_14: - lda $f7 - eor $f3 -``` - - -``` - lda #$e4 - jsr Label_16 - bne Label_27 - beq Label_27 -; Referenced from Label_28 + $29 (branch) -Label_29: - rts - -; -------------------------------- ; - -; Referenced from Label_24 + $0 (data) -Label_30: - dc.b $55, $55, $d5, $ff, $22, $22, $02, $00, $ff, $f2, $ff, $ff, $2e, $00, $00, $00 -``` \ No newline at end of file diff --git a/disassembler/a78.lbl b/disassembler/a78.lbl deleted file mode 100644 index b1ff9b1..0000000 --- a/disassembler/a78.lbl +++ /dev/null @@ -1,100 +0,0 @@ -TIA_VSYNC = $00 data -TIA_VBLANK = $01 data -TIA_WSYNC = $02 data -TIA_RSYNC = $03 data -TIA_NUSIZ0 = $04 data -TIA_NUSIZ1 = $05 data -TIA_COLUP0 = $06 data -TIA_COLUP1 = $07 data -TIA_COLUPF = $08 data -TIA_COLUBK = $09 data -TIA_CTRLPF = $0A data -TIA_REFP0 = $0B data -TIA_REFP1 = $0C data -TIA_PF0 = $0D data -TIA_PF1 = $0E data -TIA_PF2 = $0F data -TIA_RESP0 = $10 data -TIA_RESP1 = $11 data -TIA_RESM0 = $12 data -TIA_RESM1 = $13 data -TIA_RESBL = $14 data -TIA_AUDC0 = $15 data -TIA_AUDC1 = $16 data -TIA_AUDF0 = $17 data -TIA_AUDF1 = $18 data -TIA_AUDV0 = $19 data -TIA_AUDV1 = $1A data -TIA_GRP0 = $1B data -TIA_GRP1 = $1C data -TIA_ENAM0 = $1D data -TIA_ENAM1 = $1E data -TIA_ENABL = $1F data -TIA_HMP0 = $20 data -TIA_HMP1 = $21 data -TIA_HMM0 = $22 data -TIA_HMM1 = $23 data -TIA_HMBL = $24 data -TIA_VDELP0 = $25 data -TIA_VDELP1 = $26 data -TIA_VDELBL = $27 data -TIA_RESMP0 = $28 data -TIA_RESMP1 = $29 data -TIA_HMOVE = $2A data -TIA_HMCLR = $2B data -TIA_CXCLR = $2C data - -TIA_CXM0P = $00 read -TIA_CXM1P = $01 read -TIA_CXP0FB = $02 read -TIA_CXP1FB = $03 read -TIA_CXM0FB = $04 read -TIA_CXM1FB = $05 read -TIA_CXBLPF = $06 read -TIA_CXPPMM = $07 read -TIA_INPT0 = $08 read -TIA_INPT1 = $09 read -TIA_INPT2 = $0A read -TIA_INPT3 = $0B read -TIA_INPT4 = $0C read -TIA_INPT5 = $0D read - -MARIA_Bkg_col = $0020 data -MARIA_pal_0_col_1 = $0021 data -MARIA_pal_0_col_2 = $0022 data -MARIA_pal_0_col_3 = $0023 data -MARIA_Wait_Sync = $0024 data -MARIA_pal_1_col_1 = $0025 data -MARIA_pal_1_col_2 = $0026 data -MARIA_pal_1_col_3 = $0027 data -MARIA_Status = $0028 data -MARIA_pal_2_col_1 = $0029 data -MARIA_pal_2_col_2 = $002A data -MARIA_pal_2_col_3 = $002B data -MARIA_Disp_List_Hi = $002C data -MARIA_pal_3_col_1 = $002D data -MARIA_pal_3_col_2 = $002E data -MARIA_pal_3_col_3 = $002F data -MARIA_Disp_List_Lo = $0030 data -MARIA_pal_4_col_1 = $0031 data -MARIA_pal_4_col_2 = $0032 data -MARIA_pal_4_col_3 = $0033 data -MARIA_Charbase = $0034 data -MARIA_pal_5_col_1 = $0035 data -MARIA_pal_5_col_2 = $0036 data -MARIA_pal_5_col_3 = $0037 data -MARIA_pal_6_col_1 = $0039 data -MARIA_pal_6_col_2 = $003A data -MARIA_pal_6_col_3 = $003B data -MARIA_CTRL = $003C data -MARIA_pal_7_col_1 = $003D data -MARIA_pal_7_col_2 = $003E data -MARIA_pal_7_col_3 = $003F data - -RIOT_IO = $0280 data -RIOT_IO_END = $0300 data -RIOT_RAM = $0480 data -RIOT_RAM_END = $0500 data -RAM = $1800 data -RAM_END = $2800 data - \ No newline at end of file diff --git a/disassembler/c64.lbl b/disassembler/c64.lbl deleted file mode 100644 index f49fa67..0000000 --- a/disassembler/c64.lbl +++ /dev/null @@ -1,75 +0,0 @@ -6510_Port_Data_Direction = 0 data -6510_Port_Data = 1 data -C64_System_Interrupt = $314-$316 data -C64_System_NMI = $318-$31a data -Vic_Sprite_Pos = $d000-$d011 data -Vic_Screen_Ctrl = $d011 data -Vic_Raster_Line = $d012 data -Vic_Light_Pen = $d013-$d015 data -Vic_Sprite_Enable = $d015 data -Vic_Sprite_Ctrl = $d016 data -Vic_Sprite_Height_Dbl = $d017 data -Vic_Memory_Setup = $d018 data -Vic_Int_Status = $d019-$d01b data -Vic_Sprite_Pri = $d01b data -Vic_Sprite_MultiCol = $d01C data -Vic_Sprite_Width_Dbl = $d01d data -Vic_Sprite_Sprite_Coll = $d01e data -Vic_Sprite_Background_Coll = $d01f data -Vic_Border_Color = $d020 data -Vic_Back_Color = $d021-$d025 data -Vic_Sprite_Color_Extra = $d025-$d027 data -Vic_Sprite_Color = $d027-$d02f data -Vic = $d02f-$d400 data -SID_Voice1_Freq = $d400-$d402 data -SID_Voice1_Pulse = $d402-$d404 data -SID_Voice1_Ctrl = $d404 data -SID_Voice1_AttackDecay = $d405 data -SID_Voice1_SustainRelease = $d406 data -SID_Voice2_Freq = $d407-$d409 data -SID_Voice2_Pulse = $d409-$d40b data -SID_Voice2_Ctrl = $d40b data -SID_Voice2_AttackDecay = $d40c data -SID_Voice2_SustainRelease = $d40d data -SID_Voice3_Freq = $d40e-$d410 data -SID_Voice3_Pulse = $d410-$d412 data -SID_Voice3_Ctrl = $d412 data -SID_Voice3_AttackDecay = $d413 data -SID_Voice3_SustainRelease = $d414 data -SID_Filter_Cutoff = $d415-$d417 data -SID_Filter_Ctrl = $d417 data -SID_Volume_Filter_Mode = $d418 data -SID_Paddles = $d419-$d41b data -SID_Voice3_Wave_Out = $d41b data -SID_Voice3_ADSR_Out = $d41c data -SID = $D41d-$D800 data -ColorRam = $D800-$DC00 data -CIA1_PortA_KBD_Joy2 = $dc00 data -CIA1_PortB_KBD_Joy1 = $dc01 data -CIA1_PortA_Data_Dir = $dc02 data -CIA1_PortB_Data_Dir = $dc03 data -CIA1_TimerA = $dc04-$dc06 data -CIA1_TimerB = $dc06-$dc08 data -CIA1_TimeOfDay = $dc08-$dc0c data -CIA1_Serial_Shift = $dc0c data -CIA1_Interrupt_Ctrl_Status = $dc0d data -CIA1_TimerA_Ctrl = $dc0e data -CIA1_TimerB_Ctrl = $dc0f data -CIA1 = $DC10-$DD00 data -CIA2_PortA_Serial = $dd00 data -CIA2_PortB_RS232 = $dd01 data -CIA2_PortA_Data_Dir = $dd02 data -CIA2_PortB_Data_Dir = $dd03 data -CIA2_TimerA = $dd04-$dd06 data -CIA2_TimerB = $dd06-$dd08 data -CIA2_TimeOfDay = $dd08-$dd0c data -CIA2_Serial_Shift = $dd0c data -CIA2_Interrupt_Ctrl_Status = $dd0d data -CIA2_TimerA_Ctrl = $dd0e data -CIA2_TimerB_Ctrl = $dd0f data -CIA2 = $dd10-$de00 data -IO_Area1 = $de00-$df00 data -IO_Area2 = $df00-$e000 data -NMIVector = $fffa-$fffc pointers vector to NMI interrupt -ResetVector = $fffc-$fffe pointers vector to reset address -IntVector = $fffe-$10000 pointers vector to interrupt address diff --git a/disassembler/c64kernal.lbl b/disassembler/c64kernal.lbl deleted file mode 100644 index f2d783e..0000000 --- a/disassembler/c64kernal.lbl +++ /dev/null @@ -1,158 +0,0 @@ -6510_Port_Data_Direction = 0 data -6510_Port_Data = 1 data -C64_System_Interrupt = $314-$316 data -C64_System_NMI = $318-$31a data -Vic_Sprite_Pos = $d000-$d011 data -Vic_Screen_Ctrl = $d011 data -Vic_Raster_Line = $d012 data -Vic_Light_Pen = $d013-$d015 data -Vic_Sprite_Enable = $d015 data -Vic_Sprite_Ctrl = $d016 data -Vic_Sprite_Height_Dbl = $d017 data -Vic_Memory_Setup = $d018 data -Vic_Int_Status = $d019-$d01b data -Vic_Sprite_Pri = $d01b data -Vic_Sprite_MultiCol = $d01C data -Vic_Sprite_Width_Dbl = $d01d data -Vic_Sprite_Sprite_Coll = $d01e data -Vic_Sprite_Background_Coll = $d01f data -Vic_Border_Color = $d020 data -Vic_Back_Color = $d021-$d025 data -Vic_Sprite_Color_Extra = $d025-$d027 data -Vic_Sprite_Color = $d027-$d02f data -Vic = $d02f-$d400 data -SID_Voice1_Freq = $d400-$d402 data -SID_Voice1_Pulse = $d402-$d404 data -SID_Voice1_Ctrl = $d404 data -SID_Voice1_AttackDecay = $d405 data -SID_Voice1_SustainRelease = $d406 data -SID_Voice2_Freq = $d407-$d409 data -SID_Voice2_Pulse = $d409-$d40b data -SID_Voice2_Ctrl = $d40b data -SID_Voice2_AttackDecay = $d40c data -SID_Voice2_SustainRelease = $d40d data -SID_Voice3_Freq = $d40e-$d410 data -SID_Voice3_Pulse = $d410-$d412 data -SID_Voice3_Ctrl = $d412 data -SID_Voice3_AttackDecay = $d413 data -SID_Voice3_SustainRelease = $d414 data -SID_Filter_Cutoff = $d415-$d417 data -SID_Filter_Ctrl = $d417 data -SID_Volume_Filter_Mode = $d418 data -SID_Paddles = $d419-$d41b data -SID_Voice3_Wave_Out = $d41b data -SID_Voice3_ADSR_Out = $d41c data -SID = $D41d-$D800 data -ColorRam = $D800-$DC00 data -CIA1_PortA_KBD_Joy2 = $dc00 data -CIA1_PortB_KBD_Joy1 = $dc01 data -CIA1_PortA_Data_Dir = $dc02 data -CIA1_PortB_Data_Dir = $dc03 data -CIA1_TimerA = $dc04-$dc06 data -CIA1_TimerB = $dc06-$dc08 data -CIA1_TimeOfDay = $dc08-$dc0c data -CIA1_Serial_Shift = $dc0c data -CIA1_Interrupt_Ctrl_Status = $dc0d data -CIA1_TimerA_Ctrl = $dc0e data -CIA1_TimerB_Ctrl = $dc0f data -CIA1 = $DC10-$DD00 data -CIA2_PortA_Serial = $dd00 data -CIA2_PortB_RS232 = $dd01 data -CIA2_PortA_Data_Dir = $dd02 data -CIA2_PortB_Data_Dir = $dd03 data -CIA2_TimerA = $dd04-$dd06 data -CIA2_TimerB = $dd06-$dd08 data -CIA2_TimeOfDay = $dd08-$dd0c data -CIA2_Serial_Shift = $dd0c data -CIA2_Interrupt_Ctrl_Status = $dd0d data -CIA2_TimerA_Ctrl = $dd0e data -CIA2_TimerB_Ctrl = $dd0f data -CIA2 = $dd10-$de00 data -IO_Area1 = $de00-$df00 data -IO_Area2 = $df00-$e000 data - -; from sta.c64.org - -KRN_SCINIT_JMP = $FF81 code Initialize VIC; restore default input/output to keyboard/screen; clear screen; set PAL/NTSC switch and interrupt timer. -KRN_SCINIT = $FF5B code Initialize VIC; restore default input/output to keyboard/screen; clear screen; set PAL/NTSC switch and interrupt timer. -KRN_IOINIT_JMP = $FF84 code Initialize CIA's, SID volume; setup memory configuration; set and start interrupt timer. -KRN_IOINIT= $FDA3 code Initialize CIA's, SID volume; setup memory configuration; set and start interrupt timer. -KRN_RAMTAS_JMP = $FF87 code Clear memory addresses $0002-$0101 and $0200-$03FF; run memory test and set start and end address of BASIC work area accordingly; set screen memory to $0400 and datasette buffer to $033C. -KRN_RAMTAS = FD50 code Clear memory addresses $0002-$0101 and $0200-$03FF; run memory test and set start and end address of BASIC work area accordingly; set screen memory to $0400 and datasette buffer to $033C. -KRN_RESTOR_JMP = $FF8A code Fill vector table at memory addresses $0314-$0333 with default values. -KRN_RESTOR = $FD15 code Fill vector table at memory addresses $0314-$0333 with default values. -KRN_VECTOR_JMP = $FF8D code Copy vector table at memory addresses $0314-$0333 from or into user table. -KRN_VECTOR = $FD1A code Copy vector table at memory addresses $0314-$0333 from or into user table. -KRN_SETMSG_JMP = $FF90 code Set system error display switch at memory address $009D. -KRN_SETMSG = $FE18 code Set system error display switch at memory address $009D. -KRN_LSTNSA_JMP = $FF93 code Send LISTEN secondary address to serial bus. (Must call LISTEN beforehands.) -KRN_LSTNSA = $EDB9. code Send LISTEN secondary address to serial bus. (Must call LISTEN beforehands.) -KRN_TALKSA_JMP = $FF96 code Send TALK secondary address to serial bus. (Must call TALK beforehands.) -KRN_TALKSA = $EDC7 code Send TALK secondary address to serial bus. (Must call TALK beforehands.) -KRN_MEMBOT_JMP = $FF99 code Save or restore start address of BASIC work area. -KRN_MEMBOT = $FE25 code Save or restore start address of BASIC work area. -KRN_MEMTOP_JMP = $FF9C code Save or restore end address of BASIC work area. -KRN_MEMTOP = $FE34 code Save or restore end address of BASIC work area. -KRN_SCNKEY_JMP = $FF9F code Query keyboard; put current matrix code into memory address $00CB, current status of shift keys into memory address $028D and PETSCII code into keyboard buffer. -KRN_SCNKEY = $EA87 code Query keyboard; put current matrix code into memory address $00CB, current status of shift keys into memory address $028D and PETSCII code into keyboard buffer. -KRN_SETTMO_JMP = $FFA2 code Unknown. (Set serial bus timeout.) -KRN_SETTMO = $FE21 code Unknown. (Set serial bus timeout.) -KRN_IECIN_JMP = $FFA5 code Read byte from serial bus. (Must call TALK and TALKSA beforehands.) -KRN_IECIN = $EE13 code Read byte from serial bus. (Must call TALK and TALKSA beforehands.) -KRN_IECOUT_JMP = $FFA8 code Write byte to serial bus. (Must call LISTEN and LSTNSA beforehands.) -KRN_IECOUT = $EDDD code Write byte to serial bus. (Must call LISTEN and LSTNSA beforehands.) -KRN_UNTALK_JMP = $FFAB code Send UNTALK command to serial bus. -KRN_UNTALK = $EDEF code Send UNTALK command to serial bus. -KRN_UNLSTN_JMP = $FFAE code Send UNLISTEN command to serial bus. -KRN_UNLSTN = $EDFE code Send UNLISTEN command to serial bus. -KRN_LISTEN_JMP = $FFB1 code Send LISTEN command to serial bus. -KRN_LISTEN = $ED0C code Send LISTEN command to serial bus. -KRN_TALK_JMP = $FFB4 code Send TALK command to serial bus. -KRN_TALK = $ED09 code Send TALK command to serial bus. -KRN_READST_JMP = $FFB7 code Fetch status of current input/output device, value of ST variable. (For RS232, status is cleared.) -KRN_READST = $FE07 code Fetch status of current input/output device, value of ST variable. (For RS232, status is cleared.) -KRN_SETLFS_JMP = $FFBA code Set file parameters. -KRN_SETLFS = $FE00 code Set file parameters. -KRN_SETNAM_JMP = $FFBD code Set file name parameters. -KRN_SETNAM = $FDF9 code Set file name parameters. -KRN_OPEN_JMP = $FFC0 code Open file. (Must call SETLFS and SETNAM beforehands.) -KRN_OPEN = $F34A code Open file. (Must call SETLFS and SETNAM beforehands.) -KRN_CLOSE_JMP = $FFC3 code Close file. -KRN_CLOSE = $F291 code Close file. -KRN_CHKIN_JMP = $FFC6 code Define file as default input. (Must call OPEN beforehands.) -KRN_CHKIN = $F20E code Define file as default input. (Must call OPEN beforehands.) -KRN_CHKOUT_JMP = $FFC9 code Define file as default output. (Must call OPEN beforehands.) -KRN_CHKOUT = $F250 code Define file as default output. (Must call OPEN beforehands.) -KRN_CLRCHN_JMP = $FFCC code Close default input/output files (for serial bus, send UNTALK and/or UNLISTEN); restore default input/output to keyboard/screen. -KRN_CLRCHN = $F333 code Close default input/output files (for serial bus, send UNTALK and/or UNLISTEN); restore default input/output to keyboard/screen. -KRN_CHRIN_JMP = $FFCF code Read byte from default input (for keyboard, read a line from the screen). (If not keyboard, must call OPEN and CHKIN beforehands.) -KRN_CHRIN = $F157 code Read byte from default input (for keyboard, read a line from the screen). (If not keyboard, must call OPEN and CHKIN beforehands.) -KRN_CHROUT_JMP = $FFD2 code Write byte to default output. (If not screen, must call OPEN and CHKOUT beforehands.) -KRN_CHROUT = $F1CA code Write byte to default output. (If not screen, must call OPEN and CHKOUT beforehands.) -KRN_LOAD_JMP = $FFD5 code Load or verify file. (Must call SETLFS and SETNAM beforehands.) -KRN_LOAD = $F49E code Load or verify file. (Must call SETLFS and SETNAM beforehands.) -KRN_SAVE_JMP = $FFD8 code Save file. (Must call SETLFS and SETNAM beforehands.) -KRN_SAVE = $F5DD code Save file. (Must call SETLFS and SETNAM beforehands.) -KRN_SETTIM_JMP = $FFDB code Set Time of Day, at memory address $00A0-$00A2. -KRN_SETTIM = $F6E4 code Set Time of Day, at memory address $00A0-$00A2. -KRN_RDTIM_JMP = $FFDE code read Time of Day, at memory address $00A0-$00A2. -KRN_RDTIM = $F6DD code read Time of Day, at memory address $00A0-$00A2. -KRN_STOP_JMP = $FFE1 code Query Stop key indicator, at memory address $0091; if pressed, call CLRCHN and clear keyboard buffer. -KRN_STOP = $F6ED code Query Stop key indicator, at memory address $0091; if pressed, call CLRCHN and clear keyboard buffer. -KRN_GETIN_JMP = $FFE4 code Read byte from default input. (If not keyboard, must call OPEN and CHKIN beforehands.) -KRN_GETIN = $F13E code Read byte from default input. (If not keyboard, must call OPEN and CHKIN beforehands.) -KRN_CLALL_JMP = $FFE7 code Clear file table; call CLRCHN. -KRN_CLALL = $F32F code Clear file table; call CLRCHN. -KRN_UDTIM_JMP = $FFEA code Update Time of Day, at memory address $00A0-$00A2, and Stop key indicator, at memory address $0091. -KRN_UDTIM = $F69B code Update Time of Day, at memory address $00A0-$00A2, and Stop key indicator, at memory address $0091. -KRN_SCREEN_JMP = $FFED code Fetch number of screen rows and columns. -KRN_SCREEN = $E505 code Fetch number of screen rows and columns. -KRN_PLOT_JMP = $FFF0 code Save or restore cursor position. -KRN_PLOT = $E50A code Save or restore cursor position. -KRN_IOBASE_JMP = $FFF3 code Fetch CIA #1 base address. -KRN_IOBASE = $E500 code Fetch CIA #1 base address. - -NMIVector = $fffa-$fffc pointers vector to NMI interrupt -ResetVector = $fffc-$fffe pointers vector to reset address -IntVector = $fffe-$10000 pointers vector to interrupt address - diff --git a/disassembler/x65dsasm.cpp b/disassembler/x65dsasm.cpp deleted file mode 100644 index 72c1150..0000000 --- a/disassembler/x65dsasm.cpp +++ /dev/null @@ -1,2716 +0,0 @@ -// -// x65dsasm.cpp -// -// -// Created by Carl-Henrik Skårstedt on 9/23/15. -// -// -// x65 companion disassembler -// -// -// The MIT License (MIT) -// -// Copyright (c) 2015 Carl-Henrik Skårstedt -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software -// and associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -// Details, source and documentation at https://github.com/Sakrac/x65. -// -// "struse.h" can be found at https://github.com/Sakrac/struse, only the header file is required. -// - -#define _CRT_SECURE_NO_WARNINGS // Windows shenanigans -#define STRUSE_IMPLEMENTATION // include implementation of struse in this file -#include "struse.h" // https://github.com/Sakrac/struse/blob/master/struse.h -#include -#include -#include - -static const char* aAddrModeFmt[] = { - "%s ($%02x,x)", // 00 - "%s $%02x", // 01 - "%s #$%02x", // 02 - "%s $%04x", // 03 - "%s ($%02x),y", // 04 - "%s $%02x,x", // 05 - "%s $%04x,y", // 06 - "%s $%04x,x", // 07 - "%s ($%04x)", // 08 - "%s A", // 09 - "%s ", // 0a - "%s ($%02x)", // 0b - "%s ($%04x,x)", // 0c - "%s $%02x, $%04x", // 0d - "%s [$%02x]", // 0e - "%s [$%02x],y", // 0f - "%s $%06x", // 10 - "%s $%06x,x", // 11 - "%s $%02x,s", // 12 - "%s ($%02x,s),y", // 13 - "%s [$%04x]", // 14 - "%s $%02x,$%02x", // 15 - - "%s $%02x,y", // 16 - "%s ($%02x,y)", // 17 - - "%s #$%02x", // 18 - "%s #$%02x", // 19 - - "%s $%04x", // 1a - "%s $%04x", // 1b -}; - -static const char* aAddrModeFmtSrc[] = { - "%s (%s,x)", // 00 - "%s %s", // 01 - "%s #%s", // 02 - "%s %s", // 03 - "%s (%s),y", // 04 - "%s %s,x", // 05 - "%s %s,y", // 06 - "%s %s,x", // 07 - "%s (%s)", // 08 - "%s A", // 09 - "%s ", // 0a - "%s (%s)", // 0b - "%s (%s,x)", // 0c - "%s $%02x, %s", // 0d - "%s [%s]", // 0e - "%s [%s],y", // 0f - "%s %s", // 10 - "%s %s,x", // 11 - "%s %s,s", // 12 - "%s (%s,s),y", // 13 - "%s [%s]", // 14 - "%s $%02x,%s", // 15 - - "%s %s,y", // 16 - "%s (%s,y)", // 17 - - "%s #%s", // 18 - "%s #%s", // 19 - - "%s %s", // 1a - "%s %s", // 1b -}; - -const char *AddressModeNames[] { - // address mode bit index - - // 6502 - - "AM_ZP_REL_X", // 0 ($12",x) - "AM_ZP", // 1 $12 - "AM_IMM", // 2 #$12 - "AM_ABS", // 3 $1234 - "AM_ZP_Y_REL", // 4 ($12)",y - "AM_ZP_X", // 5 $12",x - "AM_ABS_Y", // 6 $1234",y - "AM_ABS_X", // 7 $1234",x - "AM_REL", // 8 ($1234) - "AM_ACC", // 9 A - "AM_NON", // a - - // 65C02 - - "AM_ZP_REL", // b ($12) - "AM_REL_X", // c ($1234",x) - "AM_ZP_ABS", // d $12", *+$12 - - // 65816 - - "AM_ZP_REL_L", // e [$02] - "AM_ZP_REL_Y_L", // f [$00]",y - "AM_ABS_L", // 10 $bahilo - "AM_ABS_L_X", // 11 $123456",x - "AM_STK", // 12 $12",s - "AM_STK_REL_Y", // 13 ($12",s)",y - "AM_REL_L", // 14 [$1234] - "AM_BLK_MOV", // 15 $12",$34 - - "AM_ZP_Y", // 16 stx/ldx - "AM_ZP_REL_Y", // 17 sax/lax/ahx - - "AM_IMM_DBL_A", // 18 #$12/#$1234 - "AM_IMM_DBL_I", // 19 #$12/#$1234 - - "AM_BRANCH", // 1a beq $1234 - "AM_BRANCH_L", // 1b brl $1234 -}; - -enum AddressModes { - // address mode bit index - - // 6502 - - AM_ZP_REL_X, // 0 ($12,x) - AM_ZP, // 1 $12 - AM_IMM, // 2 #$12 - AM_ABS, // 3 $1234 - AM_ZP_Y_REL, // 4 ($12),y - AM_ZP_X, // 5 $12,x - AM_ABS_Y, // 6 $1234,y - AM_ABS_X, // 7 $1234,x - AM_REL, // 8 ($1234) - AM_ACC, // 9 A - AM_NON, // a - - // 65C02 - - AM_ZP_REL, // b ($12) - AM_REL_X, // c ($1234,x) - AM_ZP_ABS, // d $12, *+$12 - - // 65816 - - AM_ZP_REL_L, // e [$02] - AM_ZP_REL_Y_L, // f [$00],y - AM_ABS_L, // 10 $bahilo - AM_ABS_L_X, // 11 $123456,x - AM_STK, // 12 $12,s - AM_STK_REL_Y, // 13 ($12,s),y - AM_REL_L, // 14 [$1234] - AM_BLK_MOV, // 15 $12,$34 - - AM_ZP_Y, // 16 stx/ldx - AM_ZP_REL_Y, // 17 sax/lax/ahx - - AM_IMM_DBL_A, // 18 #$12/#$1234 - AM_IMM_DBL_I, // 19 #$12/#$1234 - - AM_BRANCH, // 1a beq $1234 - AM_BRANCH_L, // 1b brl $1234 - - AM_COUNT, -}; - -enum MNM_Base { - mnm_brk, - mnm_ora, - mnm_cop, - mnm_tsb, - mnm_asl, - mnm_php, - mnm_phd, - mnm_bpl, - mnm_trb, - mnm_clc, - mnm_inc, - mnm_tcs, - mnm_jsr, - mnm_and, - mnm_bit, - mnm_rol, - mnm_plp, - mnm_pld, - mnm_bmi, - mnm_sec, - mnm_dec, - mnm_tsc, - mnm_rti, - mnm_eor, - mnm_wdm, - mnm_mvp, - mnm_lsr, - mnm_pha, - mnm_phk, - mnm_jmp, - mnm_bvc, - mnm_mvn, - mnm_cli, - mnm_phy, - mnm_tcd, - mnm_rts, - mnm_adc, - mnm_per, - mnm_stz, - mnm_ror, - mnm_rtl, - mnm_bvs, - mnm_sei, - mnm_ply, - mnm_tdc, - mnm_bra, - mnm_sta, - mnm_brl, - mnm_sty, - mnm_stx, - mnm_dey, - mnm_txa, - mnm_phb, - mnm_bcc, - mnm_tya, - mnm_txs, - mnm_txy, - mnm_ldy, - mnm_lda, - mnm_ldx, - mnm_tay, - mnm_tax, - mnm_plb, - mnm_bcs, - mnm_clv, - mnm_tsx, - mnm_tyx, - mnm_cpy, - mnm_cmp, - mnm_rep, - mnm_iny, - mnm_dex, - mnm_wai, - mnm_bne, - mnm_pei, - mnm_cld, - mnm_phx, - mnm_stp, - mnm_cpx, - mnm_sbc, - mnm_sep, - mnm_inx, - mnm_nop, - mnm_xba, - mnm_beq, - mnm_pea, - mnm_sed, - mnm_plx, - mnm_xce, - mnm_inv, - mnm_pla, - - mnm_wdc_and_illegal_instructions, - - mnm_bbs0 = mnm_wdc_and_illegal_instructions, - mnm_bbs1, - mnm_bbs2, - mnm_bbs3, - mnm_bbs4, - mnm_bbs5, - mnm_bbs6, - mnm_bbs7, - mnm_bbr0, - mnm_bbr1, - mnm_bbr2, - mnm_bbr3, - mnm_bbr4, - mnm_bbr5, - mnm_bbr6, - mnm_bbr7, - - mnm_ahx, - mnm_anc, - mnm_aac, - mnm_alr, - mnm_axs, - mnm_dcp, - mnm_isc, - mnm_lax, - mnm_lax2, - mnm_rla, - mnm_rra, - mnm_sre, - mnm_sax, - mnm_slo, - mnm_xaa, - mnm_arr, - mnm_tas, - mnm_shy, - mnm_shx, - mnm_las, - mnm_sbi, - - mnm_count -}; - -const char *zsMNM[mnm_count] { - "brk", - "ora", - "cop", - "tsb", - "asl", - "php", - "phd", - "bpl", - "trb", - "clc", - "inc", - "tcs", - "jsr", - "and", - "bit", - "rol", - "plp", - "pld", - "bmi", - "sec", - "dec", - "tsc", - "rti", - "eor", - "wdm", - "mvp", - "lsr", - "pha", - "phk", - "jmp", - "bvc", - "mvn", - "cli", - "phy", - "tcd", - "rts", - "adc", - "per", - "stz", - "ror", - "rtl", - "bvs", - "sei", - "ply", - "tdc", - "bra", - "sta", - "brl", - "sty", - "stx", - "dey", - "txa", - "phb", - "bcc", - "tya", - "txs", - "txy", - "ldy", - "lda", - "ldx", - "tay", - "tax", - "plb", - "bcs", - "clv", - "tsx", - "tyx", - "cpy", - "cmp", - "rep", - "iny", - "dex", - "wai", - "bne", - "pei", - "cld", - "phx", - "stp", - "cpx", - "sbc", - "sep", - "inx", - "nop", - "xba", - "beq", - "pea", - "sed", - "plx", - "xce", - "???", - "pla", - "bbs0", - "bbs1", - "bbs2", - "bbs3", - "bbs4", - "bbs5", - "bbs6", - "bbs7", - "bbr0", - "bbr1", - "bbr2", - "bbr3", - "bbr4", - "bbr5", - "bbr6", - "bbr7", - "ahx", - "anc", - "aac", - "alr", - "axs", - "dcp", - "isc", - "lax", - "lax2", - "rla", - "rra", - "sre", - "sax", - "slo", - "xaa", - "arr", - "tas", - "shy", - "shx", - "las", - "sbi", -}; - -struct dismnm { - MNM_Base mnemonic; - unsigned char addrMode; - unsigned char arg_size; -}; - -struct dismnm a6502_ops[256] = { - { mnm_brk, AM_NON, 0}, - { mnm_ora, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_slo, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ora, AM_ZP, 1 }, - { mnm_asl, AM_ZP, 1 }, - { mnm_slo, AM_ZP, 1 }, - { mnm_php, AM_NON, 0 }, - { mnm_ora, AM_IMM, 1 }, - { mnm_asl, AM_NON, 0 }, - { mnm_anc, AM_IMM, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ora, AM_ABS, 2 }, - { mnm_asl, AM_ABS, 2 }, - { mnm_slo, AM_ABS, 2 }, - { mnm_bpl, AM_BRANCH, 1 }, - { mnm_ora, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_slo, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ora, AM_ZP_X, 1 }, - { mnm_asl, AM_ZP_X, 1 }, - { mnm_slo, AM_ZP_X, 1 }, - { mnm_clc, AM_NON, 0 }, - { mnm_ora, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_slo, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ora, AM_ABS_X, 2 }, - { mnm_asl, AM_ABS_X, 2 }, - { mnm_slo, AM_ABS_X, 2 }, - { mnm_jsr, AM_ABS, 2 }, - { mnm_and, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_rla, AM_ZP_REL_X, 1 }, - { mnm_bit, AM_ZP, 1 }, - { mnm_and, AM_ZP, 1 }, - { mnm_rol, AM_ZP, 1 }, - { mnm_rla, AM_ZP, 1 }, - { mnm_plp, AM_NON, 0 }, - { mnm_and, AM_IMM, 1 }, - { mnm_rol, AM_NON, 0 }, - { mnm_aac, AM_IMM, 1 }, - { mnm_bit, AM_ABS, 2 }, - { mnm_and, AM_ABS, 2 }, - { mnm_rol, AM_ABS, 2 }, - { mnm_rla, AM_ABS, 2 }, - { mnm_bmi, AM_BRANCH, 1 }, - { mnm_and, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_rla, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_and, AM_ZP_X, 1 }, - { mnm_rol, AM_ZP_X, 1 }, - { mnm_rla, AM_ZP_X, 1 }, - { mnm_sec, AM_NON, 0 }, - { mnm_and, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_rla, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_and, AM_ABS_X, 2 }, - { mnm_rol, AM_ABS_X, 2 }, - { mnm_rla, AM_ABS_X, 2 }, - { mnm_rti, AM_NON, 0 }, - { mnm_eor, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sre, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_eor, AM_ZP, 1 }, - { mnm_lsr, AM_ZP, 1 }, - { mnm_sre, AM_ZP, 1 }, - { mnm_pha, AM_NON, 0 }, - { mnm_eor, AM_IMM, 1 }, - { mnm_lsr, AM_NON, 0 }, - { mnm_alr, AM_IMM, 1 }, - { mnm_jmp, AM_ABS, 2 }, - { mnm_eor, AM_ABS, 2 }, - { mnm_lsr, AM_ABS, 2 }, - { mnm_sre, AM_ABS, 2 }, - { mnm_bvc, AM_BRANCH, 1 }, - { mnm_eor, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sre, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_eor, AM_ZP_X, 1 }, - { mnm_lsr, AM_ZP_X, 1 }, - { mnm_sre, AM_ZP_X, 1 }, - { mnm_cli, AM_NON, 0 }, - { mnm_eor, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sre, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_eor, AM_ABS_X, 2 }, - { mnm_lsr, AM_ABS_X, 2 }, - { mnm_sre, AM_ABS_X, 2 }, - { mnm_rts, AM_NON, 0 }, - { mnm_adc, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_rra, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_adc, AM_ZP, 1 }, - { mnm_ror, AM_ZP, 1 }, - { mnm_rra, AM_ZP, 1 }, - { mnm_pla, AM_NON, 0 }, - { mnm_adc, AM_IMM, 1 }, - { mnm_ror, AM_NON, 0 }, - { mnm_arr, AM_IMM, 1 }, - { mnm_jmp, AM_REL, 2 }, - { mnm_adc, AM_ABS, 2 }, - { mnm_ror, AM_ABS, 2 }, - { mnm_rra, AM_ABS, 2 }, - { mnm_bvs, AM_BRANCH, 1 }, - { mnm_adc, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_rra, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_adc, AM_ZP_X, 1 }, - { mnm_ror, AM_ZP_X, 1 }, - { mnm_rra, AM_ZP_X, 1 }, - { mnm_sei, AM_NON, 0 }, - { mnm_adc, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_rra, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_adc, AM_ABS_X, 2 }, - { mnm_ror, AM_ABS_X, 2 }, - { mnm_rra, AM_ABS_X, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sta, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sax, AM_ZP_REL_Y, 1 }, - { mnm_sty, AM_ZP, 1 }, - { mnm_sta, AM_ZP, 1 }, - { mnm_stx, AM_ZP, 1 }, - { mnm_sax, AM_ZP, 1 }, - { mnm_dey, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_txa, AM_NON, 0 }, - { mnm_xaa, AM_IMM, 1 }, - { mnm_sty, AM_ABS, 2 }, - { mnm_sta, AM_ABS, 2 }, - { mnm_stx, AM_ABS, 2 }, - { mnm_sax, AM_ABS, 2 }, - { mnm_bcc, AM_BRANCH, 1 }, - { mnm_sta, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ahx, AM_ZP_REL_Y, 1 }, - { mnm_sty, AM_ZP_X, 1 }, - { mnm_sta, AM_ZP_X, 1 }, - { mnm_stx, AM_ZP_Y, 1 }, - { mnm_sax, AM_ZP_Y, 1 }, - { mnm_tya, AM_NON, 0 }, - { mnm_sta, AM_ABS_Y, 2 }, - { mnm_txs, AM_NON, 0 }, - { mnm_tas, AM_ABS_Y, 2 }, - { mnm_shy, AM_ABS_X, 2 }, - { mnm_sta, AM_ABS_X, 2 }, - { mnm_shx, AM_ABS_Y, 2 }, - { mnm_ahx, AM_ABS_Y, 2 }, - { mnm_ldy, AM_IMM, 1 }, - { mnm_lda, AM_ZP_REL_X, 1 }, - { mnm_ldx, AM_IMM, 1 }, - { mnm_lax, AM_ZP_REL_Y, 1 }, - { mnm_ldy, AM_ZP, 1 }, - { mnm_lda, AM_ZP, 1 }, - { mnm_ldx, AM_ZP, 1 }, - { mnm_lax, AM_ZP, 1 }, - { mnm_tay, AM_NON, 0 }, - { mnm_lda, AM_IMM, 1 }, - { mnm_tax, AM_NON, 0 }, - { mnm_lax2, AM_IMM, 1 }, - { mnm_ldy, AM_ABS, 2 }, - { mnm_lda, AM_ABS, 2 }, - { mnm_ldx, AM_ABS, 2 }, - { mnm_lax, AM_ABS, 2 }, - { mnm_bcs, AM_BRANCH, 1 }, - { mnm_lda, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ldy, AM_ZP_X, 1 }, - { mnm_lda, AM_ZP_X, 1 }, - { mnm_ldx, AM_ZP_Y, 1 }, - { mnm_lax, AM_ZP_Y, 1 }, - { mnm_clv, AM_NON, 0 }, - { mnm_lda, AM_ABS_Y, 2 }, - { mnm_tsx, AM_NON, 0 }, - { mnm_las, AM_ABS_Y, 2 }, - { mnm_ldy, AM_ABS_X, 2 }, - { mnm_lda, AM_ABS_X, 2 }, - { mnm_ldx, AM_ABS_Y, 2 }, - { mnm_lax, AM_ABS_Y, 2 }, - { mnm_cpy, AM_IMM, 1 }, - { mnm_cmp, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_dcp, AM_ZP_REL_X, 1 }, - { mnm_cpy, AM_ZP, 1 }, - { mnm_cmp, AM_ZP, 1 }, - { mnm_dec, AM_ZP, 1 }, - { mnm_dcp, AM_ZP, 1 }, - { mnm_iny, AM_NON, 0 }, - { mnm_cmp, AM_IMM, 1 }, - { mnm_dex, AM_NON, 0 }, - { mnm_axs, AM_IMM, 1 }, - { mnm_cpy, AM_ABS, 2 }, - { mnm_cmp, AM_ABS, 2 }, - { mnm_dec, AM_ABS, 2 }, - { mnm_dcp, AM_ABS, 2 }, - { mnm_bne, AM_BRANCH, 1 }, - { mnm_cmp, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_dcp, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cmp, AM_ZP_X, 1 }, - { mnm_dec, AM_ZP_X, 1 }, - { mnm_dcp, AM_ZP_X, 1 }, - { mnm_cld, AM_NON, 0 }, - { mnm_cmp, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_dcp, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cmp, AM_ABS_X, 2 }, - { mnm_dec, AM_ABS_X, 2 }, - { mnm_dcp, AM_ABS_X, 2 }, - { mnm_cpx, AM_IMM, 1 }, - { mnm_sbc, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_isc, AM_ZP_REL_X, 1 }, - { mnm_cpx, AM_ZP, 1 }, - { mnm_sbc, AM_ZP, 1 }, - { mnm_inc, AM_ZP, 1 }, - { mnm_isc, AM_ZP, 1 }, - { mnm_inx, AM_NON, 0 }, - { mnm_sbc, AM_IMM, 1 }, - { mnm_nop, AM_NON, 0 }, - { mnm_sbi, AM_IMM, 1 }, - { mnm_cpx, AM_ABS, 2 }, - { mnm_sbc, AM_ABS, 2 }, - { mnm_inc, AM_ABS, 2 }, - { mnm_isc, AM_ABS, 2 }, - { mnm_beq, AM_BRANCH, 1 }, - { mnm_sbc, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_isc, AM_ZP_Y_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sbc, AM_ZP_X, 1 }, - { mnm_inc, AM_ZP_X, 1 }, - { mnm_isc, AM_ZP_X, 1 }, - { mnm_sed, AM_NON, 0 }, - { mnm_sbc, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_isc, AM_ABS_Y, 2 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sbc, AM_ABS_X, 2 }, - { mnm_inc, AM_ABS_X, 2 }, - { mnm_isc, AM_ABS_X, 2 }, -}; - -struct dismnm a65C02_ops[256] = { - { mnm_brk, AM_NON, 0}, - { mnm_ora, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_tsb, AM_ZP, 1 }, - { mnm_ora, AM_ZP, 1 }, - { mnm_asl, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_php, AM_NON, 0 }, - { mnm_ora, AM_IMM, 1 }, - { mnm_asl, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_tsb, AM_ABS, 2 }, - { mnm_ora, AM_ABS, 2 }, - { mnm_asl, AM_ABS, 2 }, - { mnm_bbr0, AM_ZP_ABS, 2 }, - { mnm_bpl, AM_BRANCH, 1 }, - { mnm_ora, AM_ZP_Y_REL, 1 }, - { mnm_ora, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_trb, AM_ZP, 1 }, - { mnm_ora, AM_ZP_X, 1 }, - { mnm_asl, AM_ZP_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_clc, AM_NON, 0 }, - { mnm_ora, AM_ABS_Y, 2 }, - { mnm_inc, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_trb, AM_ABS, 2 }, - { mnm_ora, AM_ABS_X, 2 }, - { mnm_asl, AM_ABS_X, 2 }, - { mnm_bbr1, AM_ZP_ABS, 2 }, - { mnm_jsr, AM_ABS, 2 }, - { mnm_and, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_bit, AM_ZP, 1 }, - { mnm_and, AM_ZP, 1 }, - { mnm_rol, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_plp, AM_NON, 0 }, - { mnm_and, AM_IMM, 1 }, - { mnm_rol, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_bit, AM_ABS, 2 }, - { mnm_and, AM_ABS, 2 }, - { mnm_rol, AM_ABS, 2 }, - { mnm_bbr2, AM_ZP_ABS, 2 }, - { mnm_bmi, AM_BRANCH, 1 }, - { mnm_and, AM_ZP_Y_REL, 1 }, - { mnm_and, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_bit, AM_ZP_X, 1 }, - { mnm_and, AM_ZP_X, 1 }, - { mnm_rol, AM_ZP_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sec, AM_NON, 0 }, - { mnm_and, AM_ABS_Y, 2 }, - { mnm_dec, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_bit, AM_ABS_X, 2 }, - { mnm_and, AM_ABS_X, 2 }, - { mnm_rol, AM_ABS_X, 2 }, - { mnm_bbr3, AM_ZP_ABS, 2 }, - { mnm_rti, AM_NON, 0 }, - { mnm_eor, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_eor, AM_ZP, 1 }, - { mnm_lsr, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_pha, AM_NON, 0 }, - { mnm_eor, AM_IMM, 1 }, - { mnm_lsr, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_jmp, AM_ABS, 2 }, - { mnm_eor, AM_ABS, 2 }, - { mnm_lsr, AM_ABS, 2 }, - { mnm_bbr4, AM_ZP_ABS, 2 }, - { mnm_bvc, AM_BRANCH, 1 }, - { mnm_eor, AM_ZP_Y_REL, 1 }, - { mnm_eor, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_eor, AM_ZP_X, 1 }, - { mnm_lsr, AM_ZP_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cli, AM_NON, 0 }, - { mnm_eor, AM_ABS_Y, 2 }, - { mnm_phy, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_eor, AM_ABS_X, 2 }, - { mnm_lsr, AM_ABS_X, 2 }, - { mnm_bbr5, AM_ZP_ABS, 2 }, - { mnm_rts, AM_NON, 0 }, - { mnm_adc, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_stz, AM_ZP, 1 }, - { mnm_adc, AM_ZP, 1 }, - { mnm_ror, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_pla, AM_NON, 0 }, - { mnm_adc, AM_IMM, 1 }, - { mnm_ror, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_jmp, AM_REL, 2 }, - { mnm_adc, AM_ABS, 2 }, - { mnm_ror, AM_ABS, 2 }, - { mnm_bbr6, AM_ZP_ABS, 2 }, - { mnm_bvs, AM_BRANCH, 1 }, - { mnm_adc, AM_ZP_Y_REL, 1 }, - { mnm_adc, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_stz, AM_ZP_X, 1 }, - { mnm_adc, AM_ZP_X, 1 }, - { mnm_ror, AM_ZP_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sei, AM_NON, 0 }, - { mnm_adc, AM_ABS_Y, 2 }, - { mnm_ply, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_jmp, AM_REL_X, 2 }, - { mnm_adc, AM_ABS_X, 2 }, - { mnm_ror, AM_ABS_X, 2 }, - { mnm_bbr7, AM_ZP_ABS, 2 }, - { mnm_bra, AM_BRANCH, 1 }, - { mnm_sta, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sty, AM_ZP, 1 }, - { mnm_sta, AM_ZP, 1 }, - { mnm_stx, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_dey, AM_NON, 0 }, - { mnm_bit, AM_IMM, 1 }, - { mnm_txa, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sty, AM_ABS, 2 }, - { mnm_sta, AM_ABS, 2 }, - { mnm_stx, AM_ABS, 2 }, - { mnm_bbs0, AM_ZP_ABS, 2 }, - { mnm_bcc, AM_BRANCH, 1 }, - { mnm_sta, AM_ZP_Y_REL, 1 }, - { mnm_sta, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sty, AM_ZP_X, 1 }, - { mnm_sta, AM_ZP_X, 1 }, - { mnm_stx, AM_ZP_Y, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_tya, AM_NON, 0 }, - { mnm_sta, AM_ABS_Y, 2 }, - { mnm_txs, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_stz, AM_ABS, 2 }, - { mnm_sta, AM_ABS_X, 2 }, - { mnm_stz, AM_ABS_X, 2 }, - { mnm_bbs1, AM_ZP_ABS, 2 }, - { mnm_ldy, AM_IMM, 1 }, - { mnm_lda, AM_ZP_REL_X, 1 }, - { mnm_ldx, AM_IMM, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ldy, AM_ZP, 1 }, - { mnm_lda, AM_ZP, 1 }, - { mnm_ldx, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_tay, AM_NON, 0 }, - { mnm_lda, AM_IMM, 1 }, - { mnm_tax, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ldy, AM_ABS, 2 }, - { mnm_lda, AM_ABS, 2 }, - { mnm_ldx, AM_ABS, 2 }, - { mnm_bbs2, AM_ZP_ABS, 2 }, - { mnm_bcs, AM_BRANCH, 1 }, - { mnm_lda, AM_ZP_Y_REL, 1 }, - { mnm_lda, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ldy, AM_ZP_X, 1 }, - { mnm_lda, AM_ZP_X, 1 }, - { mnm_ldx, AM_ZP_Y, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_clv, AM_NON, 0 }, - { mnm_lda, AM_ABS_Y, 2 }, - { mnm_tsx, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_ldy, AM_ABS_X, 2 }, - { mnm_lda, AM_ABS_X, 2 }, - { mnm_ldx, AM_ABS_Y, 2 }, - { mnm_bbs3, AM_ZP_ABS, 2 }, - { mnm_cpy, AM_IMM, 1 }, - { mnm_cmp, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cpy, AM_ZP, 1 }, - { mnm_cmp, AM_ZP, 1 }, - { mnm_dec, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_iny, AM_NON, 0 }, - { mnm_cmp, AM_IMM, 1 }, - { mnm_dex, AM_NON, 0 }, - { mnm_wai, AM_NON, 0 }, - { mnm_cpy, AM_ABS, 2 }, - { mnm_cmp, AM_ABS, 2 }, - { mnm_dec, AM_ABS, 2 }, - { mnm_bbs4, AM_ZP_ABS, 2 }, - { mnm_bne, AM_BRANCH, 1 }, - { mnm_cmp, AM_ZP_Y_REL, 1 }, - { mnm_cmp, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cmp, AM_ZP_X, 1 }, - { mnm_dec, AM_ZP_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cld, AM_NON, 0 }, - { mnm_cmp, AM_ABS_Y, 2 }, - { mnm_phx, AM_NON, 0 }, - { mnm_stp, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cmp, AM_ABS_X, 2 }, - { mnm_dec, AM_ABS_X, 2 }, - { mnm_bbs5, AM_ZP_ABS, 2 }, - { mnm_cpx, AM_IMM, 1 }, - { mnm_sbc, AM_ZP_REL_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cpx, AM_ZP, 1 }, - { mnm_sbc, AM_ZP, 1 }, - { mnm_inc, AM_ZP, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inx, AM_NON, 0 }, - { mnm_sbc, AM_IMM, 1 }, - { mnm_nop, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_cpx, AM_ABS, 2 }, - { mnm_sbc, AM_ABS, 2 }, - { mnm_inc, AM_ABS, 2 }, - { mnm_bbs6, AM_ZP_ABS, 2 }, - { mnm_beq, AM_BRANCH, 1 }, - { mnm_sbc, AM_ZP_Y_REL, 1 }, - { mnm_sbc, AM_ZP_REL, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sbc, AM_ZP_X, 1 }, - { mnm_inc, AM_ZP_X, 1 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sed, AM_NON, 0 }, - { mnm_sbc, AM_ABS_Y, 2 }, - { mnm_plx, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_inv, AM_NON, 0 }, - { mnm_sbc, AM_ABS_X, 2 }, - { mnm_inc, AM_ABS_X, 2 }, - { mnm_bbs7, AM_ZP_ABS, 2 }, -}; - -struct dismnm a65816_ops[256] = { - { mnm_brk, AM_NON, 0}, - { mnm_ora, AM_ZP_REL_X, 1 }, - { mnm_cop, AM_NON, 0 }, - { mnm_ora, AM_STK, 1 }, - { mnm_tsb, AM_ZP, 1 }, - { mnm_ora, AM_ZP, 1 }, - { mnm_asl, AM_ZP, 1 }, - { mnm_ora, AM_ZP_REL_L, 1 }, - { mnm_php, AM_NON, 0 }, - { mnm_ora, AM_IMM_DBL_A, 1 }, - { mnm_asl, AM_NON, 0 }, - { mnm_phd, AM_NON, 0 }, - { mnm_tsb, AM_ABS, 2 }, - { mnm_ora, AM_ABS, 2 }, - { mnm_asl, AM_ABS, 2 }, - { mnm_ora, AM_ABS_L, 3 }, - { mnm_bpl, AM_BRANCH, 1 }, - { mnm_ora, AM_ZP_Y_REL, 1 }, - { mnm_ora, AM_ZP_REL, 1 }, - { mnm_ora, AM_STK_REL_Y, 1 }, - { mnm_trb, AM_ZP, 1 }, - { mnm_ora, AM_ZP_X, 1 }, - { mnm_asl, AM_ZP_X, 1 }, - { mnm_ora, AM_ZP_REL_Y_L, 1 }, - { mnm_clc, AM_NON, 0 }, - { mnm_ora, AM_ABS_Y, 2 }, - { mnm_inc, AM_NON, 0 }, - { mnm_tcs, AM_NON, 0 }, - { mnm_trb, AM_ABS, 2 }, - { mnm_ora, AM_ABS_X, 2 }, - { mnm_asl, AM_ABS_X, 2 }, - { mnm_ora, AM_ABS_L_X, 3 }, - { mnm_jsr, AM_ABS, 2 }, - { mnm_and, AM_ZP_REL_X, 1 }, - { mnm_jsr, AM_ABS_L, 3 }, - { mnm_and, AM_STK, 1 }, - { mnm_bit, AM_ZP, 1 }, - { mnm_and, AM_ZP, 1 }, - { mnm_rol, AM_ZP, 1 }, - { mnm_and, AM_ZP_REL_L, 1 }, - { mnm_plp, AM_NON, 0 }, - { mnm_and, AM_IMM_DBL_A, 1 }, - { mnm_rol, AM_NON, 0 }, - { mnm_pld, AM_NON, 0 }, - { mnm_bit, AM_ABS, 2 }, - { mnm_and, AM_ABS, 2 }, - { mnm_rol, AM_ABS, 2 }, - { mnm_and, AM_ABS_L, 3 }, - { mnm_bmi, AM_BRANCH, 1 }, - { mnm_and, AM_ZP_Y_REL, 1 }, - { mnm_and, AM_ZP_REL, 1 }, - { mnm_and, AM_STK_REL_Y, 1 }, - { mnm_bit, AM_ZP_X, 1 }, - { mnm_and, AM_ZP_X, 1 }, - { mnm_rol, AM_ZP_X, 1 }, - { mnm_and, AM_ZP_REL_Y_L, 1 }, - { mnm_sec, AM_NON, 0 }, - { mnm_and, AM_ABS_Y, 2 }, - { mnm_dec, AM_NON, 0 }, - { mnm_tsc, AM_NON, 0 }, - { mnm_bit, AM_ABS_X, 2 }, - { mnm_and, AM_ABS_X, 2 }, - { mnm_rol, AM_ABS_X, 2 }, - { mnm_and, AM_ABS_L_X, 3 }, - { mnm_rti, AM_NON, 0 }, - { mnm_eor, AM_ZP_REL_X, 1 }, - { mnm_wdm, AM_NON, 0 }, - { mnm_eor, AM_STK, 1 }, - { mnm_mvp, AM_BLK_MOV, 2 }, - { mnm_eor, AM_ZP, 1 }, - { mnm_lsr, AM_ZP, 1 }, - { mnm_eor, AM_ZP_REL_L, 1 }, - { mnm_pha, AM_NON, 0 }, - { mnm_eor, AM_IMM_DBL_A, 1 }, - { mnm_lsr, AM_NON, 0 }, - { mnm_phk, AM_NON, 0 }, - { mnm_jmp, AM_ABS, 2 }, - { mnm_eor, AM_ABS, 2 }, - { mnm_lsr, AM_ABS, 2 }, - { mnm_eor, AM_ABS_L, 3 }, - { mnm_bvc, AM_BRANCH, 1 }, - { mnm_eor, AM_ZP_Y_REL, 1 }, - { mnm_eor, AM_ZP_REL, 1 }, - { mnm_eor, AM_STK_REL_Y, 1 }, - { mnm_mvn, AM_BLK_MOV, 2 }, - { mnm_eor, AM_ZP_X, 1 }, - { mnm_lsr, AM_ZP_X, 1 }, - { mnm_eor, AM_ZP_REL_Y_L, 1 }, - { mnm_cli, AM_NON, 0 }, - { mnm_eor, AM_ABS_Y, 2 }, - { mnm_phy, AM_NON, 0 }, - { mnm_tcd, AM_NON, 0 }, - { mnm_jmp, AM_ABS_L, 3 }, - { mnm_eor, AM_ABS_X, 2 }, - { mnm_lsr, AM_ABS_X, 2 }, - { mnm_eor, AM_ABS_L_X, 3 }, - { mnm_rts, AM_NON, 0 }, - { mnm_adc, AM_ZP_REL_X, 1 }, - { mnm_per, AM_BRANCH_L, 2 }, - { mnm_adc, AM_STK, 1 }, - { mnm_stz, AM_ZP, 1 }, - { mnm_adc, AM_ZP, 1 }, - { mnm_ror, AM_ZP, 1 }, - { mnm_adc, AM_ZP_REL_L, 1 }, - { mnm_pla, AM_NON, 0 }, - { mnm_adc, AM_IMM_DBL_A, 1 }, - { mnm_ror, AM_NON, 0 }, - { mnm_rtl, AM_NON, 0 }, - { mnm_jmp, AM_REL, 2 }, - { mnm_adc, AM_ABS, 2 }, - { mnm_ror, AM_ABS, 2 }, - { mnm_adc, AM_ABS_L, 3 }, - { mnm_bvs, AM_BRANCH, 1 }, - { mnm_adc, AM_ZP_Y_REL, 1 }, - { mnm_adc, AM_ZP_REL, 1 }, - { mnm_adc, AM_STK_REL_Y, 1 }, - { mnm_stz, AM_ZP_X, 1 }, - { mnm_adc, AM_ZP_X, 1 }, - { mnm_ror, AM_ZP_X, 1 }, - { mnm_adc, AM_ZP_REL_Y_L, 1 }, - { mnm_sei, AM_NON, 0 }, - { mnm_adc, AM_ABS_Y, 2 }, - { mnm_ply, AM_NON, 0 }, - { mnm_tdc, AM_NON, 0 }, - { mnm_jmp, AM_REL_X, 2 }, - { mnm_adc, AM_ABS_X, 2 }, - { mnm_ror, AM_ABS_X, 2 }, - { mnm_adc, AM_ABS_L_X, 3 }, - { mnm_bra, AM_BRANCH, 1 }, - { mnm_sta, AM_ZP_REL_X, 1 }, - { mnm_brl, AM_BRANCH_L, 2 }, - { mnm_sta, AM_STK, 1 }, - { mnm_sty, AM_ZP, 1 }, - { mnm_sta, AM_ZP, 1 }, - { mnm_stx, AM_ZP, 1 }, - { mnm_sta, AM_ZP_REL_L, 1 }, - { mnm_dey, AM_NON, 0 }, - { mnm_bit, AM_IMM_DBL_A, 1 }, - { mnm_txa, AM_NON, 0 }, - { mnm_phb, AM_NON, 0 }, - { mnm_sty, AM_ABS, 2 }, - { mnm_sta, AM_ABS, 2 }, - { mnm_stx, AM_ABS, 2 }, - { mnm_sta, AM_ABS_L, 3 }, - { mnm_bcc, AM_BRANCH, 1 }, - { mnm_sta, AM_ZP_Y_REL, 1 }, - { mnm_sta, AM_ZP_REL, 1 }, - { mnm_sta, AM_STK_REL_Y, 1 }, - { mnm_sty, AM_ZP_X, 1 }, - { mnm_sta, AM_ZP_X, 1 }, - { mnm_stx, AM_ZP_Y, 1 }, - { mnm_sta, AM_ZP_REL_Y_L, 1 }, - { mnm_tya, AM_NON, 0 }, - { mnm_sta, AM_ABS_Y, 2 }, - { mnm_txs, AM_NON, 0 }, - { mnm_txy, AM_NON, 0 }, - { mnm_stz, AM_ABS, 2 }, - { mnm_sta, AM_ABS_X, 2 }, - { mnm_stz, AM_ABS_X, 2 }, - { mnm_sta, AM_ABS_L_X, 3 }, - { mnm_ldy, AM_IMM_DBL_I, 1 }, - { mnm_lda, AM_ZP_REL_X, 1 }, - { mnm_ldx, AM_IMM_DBL_I, 1 }, - { mnm_lda, AM_STK, 1 }, - { mnm_ldy, AM_ZP, 1 }, - { mnm_lda, AM_ZP, 1 }, - { mnm_ldx, AM_ZP, 1 }, - { mnm_lda, AM_ZP_REL_L, 1 }, - { mnm_tay, AM_NON, 0 }, - { mnm_lda, AM_IMM_DBL_A, 1 }, - { mnm_tax, AM_NON, 0 }, - { mnm_plb, AM_NON, 0 }, - { mnm_ldy, AM_ABS, 2 }, - { mnm_lda, AM_ABS, 2 }, - { mnm_ldx, AM_ABS, 2 }, - { mnm_lda, AM_ABS_L, 3 }, - { mnm_bcs, AM_BRANCH, 1 }, - { mnm_lda, AM_ZP_Y_REL, 1 }, - { mnm_lda, AM_ZP_REL, 1 }, - { mnm_lda, AM_STK_REL_Y, 1 }, - { mnm_ldy, AM_ZP_X, 1 }, - { mnm_lda, AM_ZP_X, 1 }, - { mnm_ldx, AM_ZP_Y, 1 }, - { mnm_lda, AM_ZP_REL_Y_L, 1 }, - { mnm_clv, AM_NON, 0 }, - { mnm_lda, AM_ABS_Y, 2 }, - { mnm_tsx, AM_NON, 0 }, - { mnm_tyx, AM_NON, 0 }, - { mnm_ldy, AM_ABS_X, 2 }, - { mnm_lda, AM_ABS_X, 2 }, - { mnm_ldx, AM_ABS_Y, 2 }, - { mnm_lda, AM_ABS_L_X, 3 }, - { mnm_cpy, AM_IMM_DBL_I, 1 }, - { mnm_cmp, AM_ZP_REL_X, 1 }, - { mnm_rep, AM_IMM, 1 }, - { mnm_cmp, AM_STK, 1 }, - { mnm_cpy, AM_ZP, 1 }, - { mnm_cmp, AM_ZP, 1 }, - { mnm_dec, AM_ZP, 1 }, - { mnm_cmp, AM_ZP_REL_L, 1 }, - { mnm_iny, AM_NON, 0 }, - { mnm_cmp, AM_IMM_DBL_A, 1 }, - { mnm_dex, AM_NON, 0 }, - { mnm_wai, AM_NON, 0 }, - { mnm_cpy, AM_ABS, 2 }, - { mnm_cmp, AM_ABS, 2 }, - { mnm_dec, AM_ABS, 2 }, - { mnm_cmp, AM_ABS_L, 3 }, - { mnm_bne, AM_BRANCH, 1 }, - { mnm_cmp, AM_ZP_Y_REL, 1 }, - { mnm_cmp, AM_ZP_REL, 1 }, - { mnm_cmp, AM_STK_REL_Y, 1 }, - { mnm_pei, AM_ZP_REL, 1 }, - { mnm_cmp, AM_ZP_X, 1 }, - { mnm_dec, AM_ZP_X, 1 }, - { mnm_cmp, AM_ZP_REL_Y_L, 1 }, - { mnm_cld, AM_NON, 0 }, - { mnm_cmp, AM_ABS_Y, 2 }, - { mnm_phx, AM_NON, 0 }, - { mnm_stp, AM_NON, 0 }, - { mnm_jmp, AM_REL_L, 2 }, - { mnm_cmp, AM_ABS_X, 2 }, - { mnm_dec, AM_ABS_X, 2 }, - { mnm_cmp, AM_ABS_L_X, 3 }, - { mnm_cpx, AM_IMM_DBL_I, 1 }, - { mnm_sbc, AM_ZP_REL_X, 1 }, - { mnm_sep, AM_IMM, 1 }, - { mnm_sbc, AM_STK, 1 }, - { mnm_cpx, AM_ZP, 1 }, - { mnm_sbc, AM_ZP, 1 }, - { mnm_inc, AM_ZP, 1 }, - { mnm_sbc, AM_ZP_REL_L, 1 }, - { mnm_inx, AM_NON, 0 }, - { mnm_sbc, AM_IMM_DBL_A, 1 }, - { mnm_nop, AM_NON, 0 }, - { mnm_xba, AM_NON, 0 }, - { mnm_cpx, AM_ABS, 2 }, - { mnm_sbc, AM_ABS, 2 }, - { mnm_inc, AM_ABS, 2 }, - { mnm_sbc, AM_ABS_L, 3 }, - { mnm_beq, AM_BRANCH, 1 }, - { mnm_sbc, AM_ZP_Y_REL, 1 }, - { mnm_sbc, AM_ZP_REL, 1 }, - { mnm_sbc, AM_STK_REL_Y, 1 }, - { mnm_pea, AM_ABS, 2 }, - { mnm_sbc, AM_ZP_X, 1 }, - { mnm_inc, AM_ZP_X, 1 }, - { mnm_sbc, AM_ZP_REL_Y_L, 1 }, - { mnm_sed, AM_NON, 0 }, - { mnm_sbc, AM_ABS_Y, 2 }, - { mnm_plx, AM_NON, 0 }, - { mnm_xce, AM_NON, 0 }, - { mnm_jsr, AM_REL_X, 2 }, - { mnm_sbc, AM_ABS_X, 2 }, - { mnm_inc, AM_ABS_X, 2 }, - { mnm_sbc, AM_ABS_L_X, 3 }, -}; - -enum RefType { - RT_NONE, - RT_BRANCH, // bne, etc. - RT_BRA_L, // brl - RT_JUMP, // jmp - RT_JSR, // jsr - RT_DATA, // lda $... - RT_ZP, // using a zero page / direct page instruction - RT_FALLTHROUGH, // function is entered from prior function - RT_COUNT -}; - -enum DataType { - DT_CODE, - DT_DATA, - DT_PTRS, - DT_PTRS_DATA -}; - -const char *aRefNames[RT_COUNT] = { "???", "branch", "long branch", "jump", "subroutine", "data", "zp", "fallthrough" }; - -struct RefLink { - int instr_addr; - RefType type; -}; - -struct RefAddr { - int address:29; // address - int data:3; // 0 if code, 1 if data, 2 if pointers - int size:16; // user specified size - int local:1; // nonzero if local label - int separator:1; // nonzero if following a separator - int number:15; // label count - strref label; // user defined label - strref comment; - strref read_only_label; // for labels that have a different meaning between reading and writing - std::vector *pRefs; // what is referencing this address - - RefAddr() : address(-1), data(0), size(0), local(0), separator(0), number(-1), pRefs(nullptr) {} - RefAddr(int addr) : address(addr), data(0), size(0), local(0), separator(0), number(-1), pRefs(nullptr) {} -}; - -std::vector refs; - -static int _sortRefs(const void *A, const void *B) -{ - return ((const RefAddr*)A)->address - ((const RefAddr*)B)->address; -} - -static const strref kw_data("data"); -static const strref kw_code("code"); -static const strref kw_read("read"); -static const strref kw_pointers("pointers"); - -int GetLabelIndex(int addr) { - for (int i = 0; i<(int)refs.size(); i++) { - if (addr == refs[i].address) - return i; - } - return -1; -} - - -void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, int addr, bool ill_wdc, const dismnm *opcodes, int init_data, strref labels) -{ - int start_addr = addr; - int end_addr = addr + (int)bytes; - - while (strref lab_line = labels.line()) { - if (lab_line.get_first()==';') - continue; - strref name = lab_line.split_token_trim('='); - if (lab_line.get_first()=='$') - ++lab_line; - unsigned int address = lab_line.ahextoui_skip(); - int size = 0; - lab_line.skip_whitespace(); - if (lab_line.get_first()=='-') { - ++lab_line; - if (lab_line.get_first()=='$') - ++lab_line; - size = lab_line.ahextoui_skip() - address; - if (size<0) - size = 0; - } - if (lab_line.get_first()==',') - ++lab_line; - lab_line.skip_whitespace(); - - if (kw_read.is_prefix_word(lab_line)) { - int label_index = GetLabelIndex(address); - if (label_index>=0) - refs[label_index].read_only_label = name; - } else { - refs.push_back(RefAddr(address)); - RefAddr &r = refs[refs.size()-1]; - r.pRefs = new std::vector(); - r.size = size; - if (kw_data.is_prefix_word(lab_line)) { - r.data = DT_DATA; - lab_line += kw_data.get_len(); - } else if (kw_code.is_prefix_word(lab_line)) { - r.data = DT_CODE; - lab_line += kw_code.get_len(); - } else if (kw_pointers.is_prefix_word(lab_line)) { - lab_line += kw_pointers.get_len(); - lab_line.skip_whitespace(); - if (kw_data.is_prefix_word(lab_line)) - r.data = DT_PTRS_DATA; - else - r.data = DT_PTRS; - } - lab_line.trim_whitespace(); - r.label = name; - r.comment = lab_line; - } - } - - if (GetLabelIndex(start_addr)<0) { - refs.push_back(RefAddr(start_addr)); - refs[refs.size()-1].pRefs = new std::vector(); - refs[refs.size()-1].data = DT_DATA; - } if (init_data && GetLabelIndex(start_addr + init_data)<0) { - refs.push_back(RefAddr(start_addr+init_data)); - refs[refs.size()-1].pRefs = new std::vector(); - } - - if (refs.size()) - qsort(&refs[0], refs.size(), sizeof(RefAddr), _sortRefs); - - int last_user = (int)refs.size(); - for (int i = 0; i=addr && (refs[i].address+refs[i].size)<=(addr+(int)bytes)) { - unsigned char *p = mem + refs[i].address - addr; - for (int l = 0; l(); - refs[nr].data = refs[i].data==DT_PTRS_DATA ? DT_DATA : DT_CODE; - refs[nr].pRefs->push_back(ref); - } else - refs[n].pRefs->push_back(ref); - p += 2; - } - } - } - } - - unsigned char *mem_orig = mem; - size_t bytes_orig = bytes; - int addr_orig = addr; - - if (size_t(init_data)>bytes) - return; - - if (refs.size()) - qsort(&refs[0], refs.size(), sizeof(RefAddr), _sortRefs); - - bool curr_data = !!init_data; - int curr_label = 0; - int start_labels = (int)refs.size(); - while (curr_labelrefs[curr_label].address) { - curr_data = refs[curr_label].data == DT_CODE; - ++curr_label; - } - - while (bytes) { - if (curr_label=refs[curr_label].address) { - while (curr_label=refs[curr_label].address) { - curr_data = refs[curr_label].data != DT_CODE; - if (addr>=(refs[curr_label].address+refs[curr_label].size)) - ++curr_label; - else - break; - } - } else if (curr_label && addr>(refs[curr_label-1].address + refs[curr_label-1].size)) - curr_data = false; - } else - curr_data = false; - - unsigned char op = *mem++; - int curr = addr; - bytes--; - addr++; - int reference = -1; - RefType type = RT_NONE; - int arg_size = 0; - int mode = 0; - - if (!curr_data) { - if (opcodes == a65816_ops) { - if (op == 0xe2) { // sep - if ((*mem)&0x20) acc_16 = false; - if ((*mem)&0x10) ind_16 = false; - } else if (op == 0xc2) { // rep - if ((*mem)&0x20) acc_16 = true; - if ((*mem)&0x10) ind_16 = true; - } - } - - bool not_valid = opcodes[op].mnemonic==mnm_inv || (!ill_wdc && opcodes[op].mnemonic>=mnm_wdc_and_illegal_instructions); - - arg_size = not_valid ? 0 : opcodes[op].arg_size;; - mode = not_valid ? AM_NON : opcodes[op].addrMode; - switch (mode) { - case AM_IMM_DBL_A: - arg_size = acc_16 ? 2 : 1; - break; - case AM_IMM_DBL_I: - arg_size = ind_16 ? 2 : 1; - break; - } - - if (mode == AM_BRANCH) { - reference = curr + 2 + (char)*mem; - type = RT_BRANCH; - } else if (mode == AM_BRANCH_L) { - reference = curr + 2 + (short)(unsigned short)mem[0] + ((unsigned short)mem[1]<<8); - type = RT_BRA_L; - } else if (mode == AM_ABS || mode == AM_ABS_Y || mode == AM_ABS_X || mode == AM_REL || mode == AM_REL_X || mode == AM_REL_L) { - reference = (unsigned short)mem[0] + ((unsigned short)mem[1]<<8); - if (op == 0x20 || op == 0xfc || op == 0x22) // jsr opcodes - type = RT_JSR; - else if (op == 0x4c || op == 0x7c || op == 0x5c || op == 0xdc) // jmp opcodes - type = RT_JUMP; - else - type = RT_DATA; - } else if (mode == AM_ZP || mode == AM_ZP_REL || mode == AM_ZP_REL_L || mode == AM_ZP_REL_X || mode == AM_ZP_Y_REL || - mode == AM_ZP_REL_Y || mode == AM_ZP_X || mode == AM_ZP_Y || mode == AM_ZP_REL_Y_L) { - reference = mem[0]; - type = RT_ZP; - } - } - - if (reference>=0 && type != RT_NONE) { - bool found = false; - for (std::vector::iterator i = refs.begin(); i != refs.end(); ++i) { - if (i->address == reference || (reference>i->address && (reference-i->size)address)) { - struct RefLink ref = { curr, type }; - i->pRefs->push_back(ref); - found = true; - break; - } - } - if (!found) { - refs.push_back(RefAddr(reference)); - struct RefAddr &last = refs[refs.size()-1]; - struct RefLink ref = { curr, type }; - last.pRefs = new std::vector(); - last.pRefs->push_back(ref); - } - } - - addr += arg_size; - mem += arg_size; - if (arg_size > (int)bytes) - break; - bytes -= arg_size; - } - - // sort the order of the labels by address - if (refs.size()) - qsort(&refs[0], refs.size(), sizeof(RefAddr), _sortRefs); - - // validate the label addresses - mem = mem_orig; - bytes = bytes_orig; - addr = addr_orig; - curr_label = 0; - int prev_addr = -1; - bool was_data = init_data>0; - bool separator = false; - int prev_op = 0xff; - addr += init_data; - bytes -= init_data; - mem += init_data; - bool cutoff = false; - - while (curr_label<(int)refs.size() && refs[curr_label].address=mnm_wdc_and_illegal_instructions); - - int arg_size = not_valid ? 0 : opcodes[op].arg_size;; - int mode = not_valid ? AM_NON : opcodes[op].addrMode; - switch (mode) { - case AM_IMM_DBL_A: - arg_size = acc_16 ? 2 : 1; - break; - case AM_IMM_DBL_I: - arg_size = ind_16 ? 2 : 1; - break; - } - if (arg_size > (int)bytes) - break; // ended on partial instruction - addr += arg_size; - bytes -= arg_size; - mem += arg_size; - } - if (separator && curr_label>0 && refs[curr_label-1].data!=DT_PTRS && refs[curr_label-1].data!=DT_PTRS_DATA && - curr!=refs[curr_label].address && !cutoff) { - int end_addr = curr_label<(int)refs.size() ? refs[curr_label].address : (int)(addr_orig + bytes_orig); - for (std::vector::iterator k = refs.begin(); k!= refs.end(); ++k) { - std::vector &l = *k->pRefs; - std::vector::iterator r = l.begin(); - while (r!=l.end()) { - if (r->instr_addr>=curr && r->instr_addr refs[curr_label].address && prev_addr>=0)) { - if (curr != refs[curr_label].address && !refs[curr_label].label) { - int curr_look_ahead = curr_label; - while ((curr_look_ahead+1)<(int)refs.size() && curr>refs[curr_look_ahead].address && curr>=refs[curr_look_ahead+1].address) - curr_look_ahead++; - if (curr_look_ahead>curr_label) - curr_label = curr_look_ahead; - if (curr>refs[curr_label].address) - refs[curr_label].address = prev_addr; - } - std::vector &pRefs = *refs[curr_label].pRefs; - if (curr_label < (int)refs.size()) { - if (refs[curr_label].label) { - refs[curr_label].separator = 1; // user labels are always global - was_data = refs[curr_label].data!=DT_CODE; - } else { - bool prev_data = was_data && !cutoff; - was_data = (separator || cutoff) && !(!was_data && op==0x4c && prev_op==0x4c); - if (!prev_data) { - for (size_t j = 0; jcurr && type == RT_BRANCH) && type != RT_DATA) { - was_data = false; - prev_data = false; - break; - } - } - } - - if (!was_data && prev_data) { - bool only_data_ref = pRefs.size() ? true : false; - if (!curr_label || refs[curr_label-1].data == DT_CODE) { - for (size_t j = 0; j &pRefs = *refs[k].pRefs; - std::vector::iterator r = pRefs.begin(); - while (r != pRefs.end()) { - if (r->instr_addr>=start && r->instr_addrsize()==0 && !refs[curr_label].label) { - int lbl = curr_label; - while (lbl && refs[lbl].pRefs->size()==0) - lbl--; - was_data = refs[lbl].data != DT_CODE; - } - } - cutoff = false; - curr_label++; - } - separator = false; - - // after a separator if there is no jmp, jsr, brl begin data block - if (!was_data) { - if (op == 0x00 || op == 0x60 || op == 0x40 || op == 0x6b || - ((op == 0x4c || op == 0x6c) && (prev_op!=0x4c && prev_op!=0x6c)) || - op == 0x6c || op == 0x7c || op == 0x5c || op == 0xdc) { // rts, rti, rtl or jmp - bool exit_instr = false; - int lbl = GetLabelIndex(addr); - if (lbl>=0) { - std::vector &links = *refs[lbl].pRefs; - for (std::vector::iterator lnk = links.begin(); lnk!=links.end(); ++lnk) { - if (lnk->type == RT_BRANCH && lnk->instr_addr1 && refs[last-1].data!=DT_CODE) { - int start_addr = refs[last].address; - for (int k = 0; k<(int)refs.size(); ++k) { - std::vector &pRefs = *refs[k].pRefs; - std::vector::iterator r = pRefs.begin(); - while (r != pRefs.end()) { - if (r->instr_addr>=start_addr && r->instr_addr::iterator k = refs.begin(); - while (k!=refs.end()) { - if (k->pRefs && k->pRefs->size()==0 && !k->label && !k->separator && k->address!=addr_orig) { - delete k->pRefs; - k = refs.erase(k); - } else - ++k; - } - - // remove duplicate labels - k = refs.begin(); - while (k!=refs.end()) { - std::vector::iterator n = k; - ++n; - if (n != refs.end() && k->address == n->address) { - std::vector &pRefs = *k->pRefs; - std::vector &pRefs2 = *n->pRefs; - std::vector::iterator r = pRefs2.begin(); - while (r != pRefs2.end()) { - pRefs.push_back(*r); - r = pRefs2.erase(r); - } - if (n->separator) - k->separator = 1; - delete &pRefs2; - refs.erase(n); - } - ++k; - } - - bytes = bytes_orig; - addr = addr_orig; - mem = mem_orig; - curr_label = 0; - was_data = true; - - // disassemble code sections again with all the labels filtered out to - // re-evaluate separators - bool was_separator = true; - while (bytes && curr_label<(int)refs.size()) { - while (curr_label<(int)refs.size() && addr>=refs[curr_label].address) { - if (!was_data && !was_separator && refs[curr_label].separator) - refs[curr_label].separator = 0; - was_data = refs[curr_label].data != DT_CODE; - was_separator = !!refs[curr_label].separator || was_data; - curr_label++; - } - if (curr_label==refs.size()) - break; - if (was_data || was_separator) { - int skip = refs[curr_label].address-addr; - if (skip>(int)bytes) - break; - bytes -= skip; - addr += skip; - mem += skip; - } else { - unsigned char op = *mem++; - int curr = addr; - bytes--; - addr++; - if (opcodes == a65816_ops) { - if (op == 0xe2) { // sep - if ((*mem)&0x20) acc_16 = false; - if ((*mem)&0x10) ind_16 = false; - } else if (op == 0xc2) { // rep - if ((*mem)&0x20) acc_16 = true; - if ((*mem)&0x10) ind_16 = true; - } - } - - bool not_valid = opcodes[op].mnemonic==mnm_inv || (!ill_wdc && opcodes[op].mnemonic>=mnm_wdc_and_illegal_instructions); - int arg_size = not_valid ? 0 : opcodes[op].arg_size;; - int mode = not_valid ? AM_NON : opcodes[op].addrMode; - switch (mode) { - case AM_IMM_DBL_A: - arg_size = acc_16 ? 2 : 1; - break; - case AM_IMM_DBL_I: - arg_size = ind_16 ? 2 : 1; - break; - } - - addr += arg_size; - mem += arg_size; - if (arg_size > (int)bytes) - break; - bytes -= arg_size; - - if (op == 0x00 || op == 0x60 || op == 0x40 || op == 0x6b || - ((op == 0x4c || op == 0x6c) && (prev_op!=0x4c && prev_op!=0x6c)) || - op == 0x6c || op == 0x7c || op == 0x5c || op == 0xdc) { // rts, rti, rtl or jmp - refs[curr_label].separator = true; - was_separator = true; - int skip = refs[curr_label+1].address-addr; - if (skip>(int)bytes) - break; - bytes -= skip; - addr += skip; - mem += skip; - } - } - } - - // figure out which labels can be local - - k = refs.begin(); // make all labels that are not assigned something local - bool was_sep = false; - while (k!=refs.end()) { - if (k->label || k->address<0x200 || k->separator) - k->local = false; - else - k->local = true; - was_sep = !!k->separator; - ++k; - } - - // check over and over for global labels breaking local boundaries - bool check_locals_completed = false; - while (!check_locals_completed) { - check_locals_completed = true; - k = refs.begin(); // make all labels that are not assigned something local - while (k!=refs.end()) { - if (k->local) { - std::vector &links = *k->pRefs; - for (std::vector::iterator l = links.begin(); k->local && l!=links.end(); ++l) { - int trg_addr = l->instr_addr; - bool skip_global = false; - std::vector::iterator j = k; - if (trg_addraddress) { // backward check - for (;;) { - if (!j->local) - skip_global = true; - if (j!=refs.begin()) - --j; - if (trg_addr>=j->address || j == refs.begin()) - break; - } - } else { // forward check - while (j!=refs.end()) { - ++j; - if (j==refs.end() || trg_addraddress) - break; - if (j!=refs.end() && !j->local) - skip_global = true; - } - } - if (skip_global) { - if (j!=refs.end()) { - k->local = false; - check_locals_completed = false; - } - } - } - } - ++k; - } - } - - // now simply assign label numbers according to locality - k = refs.begin(); - int label_count_code_global = 1; - int label_count_data_global = 1; - int label_count_local = 1; - while (k!=refs.end()) { - if (k->local) { - k->number = label_count_local++; - } else if (k->data==DT_CODE) { - label_count_local = 1; - k->number = label_count_data_global++; - } else { - label_count_local = 1; - k->number = label_count_code_global++; - } - ++k; - } - - - - // re-check for code references to code being mislabeled - bool adjusted_code_ref = true; - while (adjusted_code_ref) { - adjusted_code_ref = false; - k = refs.begin(); - while (k!=refs.end()) { - if (k->data != DT_CODE && !k->label) { - std::vector &links = *k->pRefs; - for (std::vector::iterator l = links.begin(); l!=links.end(); ++l) { - RefType t = l->type; - if (t==RT_BRANCH || t==RT_BRA_L || t==RT_JUMP || t==RT_JSR) { - int trg_addr = l->instr_addr; - std::vector::iterator j = k; - if (trg_addraddress) { - while (j!=refs.begin() && trg_addraddress) - --j; - } else { - std::vector::iterator n = j; - while (n!=refs.end() && trg_addr>n->address) { - j = n; - ++n; - } - } - if (j->data == DT_CODE) { - k->data = DT_CODE; - adjusted_code_ref = true; - } - break; - } - } - } - ++k; - } - } - k = refs.begin(); - bool was_code = false; - while (k!=refs.end()) { - if (k->data == DT_CODE && !k->label && (!was_code || k->separator)) { - std::vector &links = *k->pRefs; - bool definitely_code = false; - for (std::vector::iterator l = links.begin(); l!=links.end(); ++l) { - RefType t = l->type; - if (t==RT_BRANCH || t==RT_BRA_L || t==RT_JUMP || t==RT_JSR) { - definitely_code = true; - break; - } - } - if (!definitely_code) - k->data = DT_DATA; - } - was_code = k->data == DT_CODE; - ++k; - } -} - -// returns true if the instruction accessing memory can ONLY read that memory, not write back or jump to it -// used to distinguish read-only labels when there is a different definition between reading and writing to the -// same physical address -bool IsReadOnlyInstruction(MNM_Base op_base) -{ - switch (op_base) { - case mnm_ora: - case mnm_and: - case mnm_bit: - case mnm_eor: - case mnm_adc: - case mnm_sbc: - case mnm_lda: - case mnm_ldx: - case mnm_ldy: - case mnm_cmp: - case mnm_cpy: - case mnm_cpx: - return true; - } - return false; -} - -struct call_ref { - int address; - int target; - int seg_addr; - int seg_trg; - bool recursed; - RefType type; -}; - -struct seg_call { - int first_call_in_seg; - int num_calls_in_seg; - int address; -}; - - -typedef std::vector call_vector; -typedef std::vector seg_lookup; - -static int _sortCalls(const void *A, const void *B) -{ - return ((const struct call_ref*)A)->address - ((const struct call_ref*)B)->address; -} - -static int _sortInclusiveCalls(const void *A, const void *B) -{ - return ((const int*)B)[1] - ((const int*)A)[1]; -} - -static int countCalls(const int curr_ref, const call_ref *pCalls, const int num_calls, const seg_call *pLookup, const int num_lookup, char *visited) -{ - visited[curr_ref>>3] |= 1<<(curr_ref&7); - int ret = 1; - for (int j = 0; j>3] & 1<<(next_ref&7))==0) - ret += countCalls(next_ref, pCalls, num_calls, pLookup, num_lookup, visited); - } - return ret; -} - -static strown<256> _lblName; - -static const char *aRefStr[] = { - "-", //RT_NONE, - "branch", //RT_BRANCH, // bne, etc. - "long branch", //RT_BRA_L, // brl - "jmp", //RT_JUMP, // jmp - "jsr", //RT_JSR, // jsr - "data", //RT_DATA, // lda $... - "zp", //RT_ZP, // using a zero page / direct page instruction - "fallthrough" -}; - -static void printCalls(const int curr_ref, const call_ref *pCalls, const int num_calls, const seg_call *pLookup, const int num_lookup, char *visited, char *included, char *prefix, RefType rtype, FILE *f) -{ - if (rtype != RT_FALLTHROUGH) { - RefAddr &ra = refs[curr_ref]; - if (ra.label) - _lblName.copy(ra.label); - else - _lblName.sprintf("%s_%d", ra.local ? ".l" : (ra.data==DT_CODE ? "Code" : - (ra.address>=0 && ra.address<0x100 ? "zp" : "Data")), ra.number); - - fprintf(f, "%s" STRREF_FMT " ($%x) [%s]%s\n", prefix, STRREF_ARG(_lblName), pLookup[curr_ref].address, aRefStr[rtype], (visited[curr_ref>>3] & 1<<(curr_ref&7)) ? " ...":""); - if (visited[curr_ref>>3] & 1<<(curr_ref&7)) - return; - strcpy(prefix+strlen(prefix), " "); - } - visited[curr_ref>>3] |= 1<<(curr_ref&7); - included[curr_ref>>3] |= 1<<(curr_ref&7); - - for (int j = 0; j>3] & 1<<(next_ref&7)) == 0) { - RefType next_type = pCalls[pLookup[curr_ref].first_call_in_seg + j].type; - printCalls(next_ref, pCalls, num_calls, pLookup, num_lookup, visited, included, prefix, next_type, f); - } - } - if (rtype != RT_FALLTHROUGH) - prefix[strlen(prefix)-2] = 0; -} - - - -void CallGraph(int start, int end, bool branches, FILE *f) -{ - call_vector calls; - calls.reserve(refs.size() * 5); - std::vector call_counts; - call_counts.reserve(refs.size()); - seg_lookup lookup; - lookup.reserve(refs.size()); - - - int g = 0; - int pg = 0; - DataType prevType = DT_DATA; - bool separator = true; - for (int i = 0; i<(int)refs.size(); ++i) { - if (refs[i].data == DT_CODE) { - if (!refs[i].local || prevType != DT_CODE) { - pg = g; - g = i; - } - int addr0 = refs[g].address; - int addr1 = (i+1)<(int)refs.size() ? refs[i+1].address : end; - - if (prevType == DT_CODE && !refs[i].separator && g==i) { - struct call_ref c; - c.address = refs[i-1].address; - c.target = refs[i].address; - c.seg_trg = g; - c.seg_addr = pg; - c.type = RT_FALLTHROUGH; - calls.push_back(c); - } - - if (std::vector *pLinks = refs[i].pRefs) { - for (std::vector::iterator l = pLinks->begin(); l!=pLinks->end(); ++l) { - if (l->instr_addr>=addr0 && l->instr_addrtype == RT_JSR || l->type==RT_JUMP || (branches && (l->type == RT_BRANCH || l->type==RT_BRA_L))) && - l->instr_addr>=start && l->instr_addrinstr_addr; - c.target = refs[i].address; - c.seg_trg = g; - c.seg_addr = -1; - c.type = l->type; - int jg = 0; - for (int j = 0; j<(int)refs.size(); ++j) { - if (!j || !refs[j].local) - jg = j; - if (c.address>=refs[j].address && ((j+1)==refs.size() || c.address=0) - call_counts[calls[i].seg_addr]++; - if (seg>3]&(1<<(n&7))) == 0 && refs[n].data==DT_CODE && !refs[n].local) { - memset(visited, 0, call8s); - printCalls(n, &calls[0], (int)calls.size(), &lookup[0], (int)lookup.size(), visited, included, prefix, RT_NONE, f); - } - } - } - fprintf(f, ";\n; DISASSEMBLY\n;\n"); - free(subcalls); - free(visited); - free(included); - } -} - -static const char spacing[] = " "; -void Disassemble(strref filename, unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, int addr, bool ill_wdc, bool graph, bool graph_branches, const dismnm *opcodes, bool src, int init_data, strref labels) -{ - const char *spc = src ? "" : spacing; - - strref prev_src; - int start_addr = addr; - int end_addr = addr + (int)bytes; - - refs.clear(); - GetReferences(mem, bytes, acc_16, ind_16, addr, ill_wdc, opcodes, init_data, labels); - - int curr_label_index = 0; - bool separator = false; - bool is_data = refs.size() ? (refs[0].data==DT_DATA || refs[0].data==DT_PTRS || refs[0].data==DT_PTRS_DATA) : false; - bool is_ptrs = is_data && (refs[0].data==DT_PTRS || refs[0].data==DT_PTRS_DATA); - strown<256> out; - - FILE *f = stdout; - bool opened = false; - if (filename) { - f = fopen(strown<512>(filename).c_str(), "w"); - if (!f) - return; - opened = true; - } - - int reseperate = -1; - - if (graph) - CallGraph(addr, addr+(int)bytes, graph_branches, f); - - while (bytes) { - // Determine if current address is referenced from somewhere - while (curr_label_index<(int)refs.size() && addr >= refs[curr_label_index].address) { - struct RefAddr &ref = refs[curr_label_index]; - if (ref.pRefs) { - for (size_t j = 0; jsize(); ++j) { - if (src) { - struct RefLink &lnk = (*ref.pRefs)[j]; - int lbl = -1; - int prv_addr = 0; - int ref_addr = lnk.instr_addr; - for (size_t k = 0; kref_addr) - break; - lbl = (int)k; - prv_addr = refs[k].address; - } - if (refs[lbl].label) - out.sprintf("%s; Referenced from " STRREF_FMT " + $%x (%s, $%02x)\n", spc, - STRREF_ARG(refs[lbl].label), ref_addr - prv_addr, - aRefNames[(*ref.pRefs)[j].type], ref_addr); - else { - out.sprintf("%s; Referenced from", spc); - if (refs[lbl].local) { - int lbl_glb = lbl; - while (lbl_glb>0 && refs[lbl_glb].local) - lbl_glb--; - if (refs[lbl_glb].label) { - out.append(' '); - out.append(refs[lbl_glb].label); - out.append(" /"); - } else { - RefAddr &ra = refs[lbl_glb]; - out.sprintf_append(" %s_%d /", ra.local ? ".l" : (ra.data==DT_CODE ? "Code" : (ra.address>=0 && ra.address<0x100 ? "zp" : "Data")), ra.number); - } - } - RefAddr &ra = refs[lbl]; - out.sprintf_append(" %s_%d + $%x (%s, $%02x)\n", ra.local ? ".l" : (ra.data==DT_CODE ? "Code" : (ra.address>=0 && ra.address<0x100 ? "zp" : "Data")), - ra.number, ref_addr - prv_addr, aRefNames[(*ref.pRefs)[j].type], ra.address); - } - } else - out.sprintf("%s; Referenced from $%04x (%s)\n", spc, (*ref.pRefs)[j].instr_addr, - aRefNames[(*ref.pRefs)[j].type]); - fputs(out.c_str(), f); - } - } - if (addr>refs[curr_label_index].address) { - if (ref.label) - out.sprintf(STRREF_FMT " = $%02x\n", STRREF_ARG(ref.label), ref.address); - else - out.sprintf("%s_%d = $%02x\n", ref.local ? ".l" : (ref.data==DT_CODE ? "Code" : (ref.address>=0 && ref.address<0x100 ? "zp" : "Data")), - ref.number, ref.address); - } else { - out.clear(); - if (ref.comment) - out.sprintf_append("%s; " STRREF_FMT"\n", spc, STRREF_ARG(ref.comment)); - if (ref.label) - out.sprintf_append("%s" STRREF_FMT ": ; $%04x\n", spc, - STRREF_ARG(ref.label), ref.address); - else - out.sprintf_append("%s%s_%d: ; $%04x\n", spc, - ref.local ? ".l" : (ref.data==DT_CODE ? "Code" : (ref.address>=0 && ref.address<0x100 ? "zp" : "Data")), - ref.number, ref.address); - } - fputs(out.c_str(), f); - is_data = !!ref.data; - is_ptrs = is_data && (ref.data==DT_PTRS || ref.data==DT_PTRS_DATA); - separator = false; - reseperate = -1; - curr_label_index++; - } - if (src && (is_data || separator)) { - out.clear(); - int left = end_addr - addr; - if (curr_label_index<(int)refs.size() && refs[curr_label_index].addressreseperate && !is_data) - left = reseperate - addr; - else - is_data = true; - reseperate = -1; - separator = false; - if (is_ptrs) { - int blk = refs[curr_label_index-1].size ? refs[curr_label_index-1].size : left; - while (left>=2 && bytes>=2 && blk) { - out.clear(); - out.copy(" dc.w "); - int a = mem[0] + (((unsigned short)mem[1])<<8); - int lbl = GetLabelIndex(a); - if (lbl>=0) { - if (refs[lbl].label) { - out.append(refs[lbl].label); - out.sprintf_append(" ; $%04x " STRREF_FMT "\n", a, STRREF_ARG(refs[lbl].comment)); - } else { - RefAddr &ra = refs[lbl]; - out.sprintf_append("%s%s_%d ; $%04x" STRREF_FMT "\n", spc, - ra.local ? ".l" : (ra.data==DT_CODE ? "Code" : (ra.address>=0 && ra.address<0x100 ? "zp" : "Data")), - ra.number, a, STRREF_ARG(ra.comment)); - } - } else - out.sprintf_append("$%04x\n", a); - fputs(out.c_str(), f); - mem += 2; - addr += 2; - bytes -= 2; - left -= 2; - blk -= 2; - } - } - int addr_line = addr; - out.copy(" dc.b "); - for (int i = 0; i=16) { - out.sprintf_append(" ; $%04x-$%04x\n", addr_line, addr); - addr_line = addr; - fputs(out.c_str(), f); - out.copy(" dc.b "); - } - out.sprintf_append("$%02x", *mem++); - if ((i&0xf)!=0xf && i<(left-1)) - out.append(", "); - addr++; - bytes--; - } - if (addr!=addr_line) { - out.sprintf_append(" ; $%04x-$%04x\n", addr_line, addr); - fputs(out.c_str(), f); - } - separator = false; - } else { - int curr_addr = addr; - unsigned char op = *mem++; - bytes--; - out.clear(); - if (!src) - out.sprintf("$%04x ", addr); - addr++; - - if (opcodes == a65816_ops) { - if (op == 0xe2) { // sep - if ((*mem)&0x20) acc_16 = false; - if ((*mem)&0x10) ind_16 = false; - } else if (op == 0xc2) { // rep - if ((*mem)&0x20) acc_16 = true; - if ((*mem)&0x10) ind_16 = true; - } - } - - bool not_valid = opcodes[op].mnemonic==mnm_inv || (!ill_wdc && opcodes[op].mnemonic>=mnm_wdc_and_illegal_instructions); - - int arg_size = not_valid ? 0 : opcodes[op].arg_size;; - int mode = not_valid ? AM_NON : opcodes[op].addrMode; - switch (mode) { - case AM_IMM_DBL_A: - arg_size = acc_16 ? 2 : 1; - break; - case AM_IMM_DBL_I: - arg_size = ind_16 ? 2 : 1; - break; - } - addr += arg_size; - - if (arg_size > (int)bytes) - return; - bytes -= arg_size; - - if (!src) { - out.sprintf_append("%02x ", op); - for (int n = 0; n < arg_size; n++) - out.sprintf_append("%02x ", mem[n]); - } - - out.append_to(' ', src ? 2 : 18); - - int reference = -1; - separator = false; - if (op == 0x00 || op == 0x60 || op == 0x40 || op == 0x6b || - ((op == 0x4c || op == 0x6c) && mem[arg_size] != 0x4c && mem[arg_size] != 0x6c) || - op == 0x6c || op == 0x7c || op == 0x5c || op == 0xdc) { // rts, rti, rtl or jmp - separator = true; - for (size_t i = 0; i &pRefs = *refs[i].pRefs; - if (refs[i].address<=curr_addr) { - for (size_t j = 0; jcurr_addr) { - if (refs[i].address==addr) - separator = false; - else if (reseperate<0 || pRefs[j].instr_addr lblname; - strref lblcmt; - for (size_t i = 0; i=refs[i].address && reference<(refs[i].address+refs[i].size)) || - (reference>=start_addr && reference<=end_addr && reference>=refs[i].address)) { - if (i==(refs.size()-1) || reference=0 && ra.address<0x100 ? "zp" : "Data")), ra.number); - lblcmt = ra.comment; - if (reference > ra.address) - lblname.sprintf_append(" + $%x", reference - ra.address); - break; - } - } - } - - if (not_valid) - out.sprintf_append("dc.b $%02x ; $%04x ", op, curr_addr); - - const char *fmt = (src && lblname) ? aAddrModeFmtSrc[mode] : aAddrModeFmt[mode]; - const char *mnemonic = zsMNM[opcodes[op].mnemonic]; - switch (mode) { - case AM_ABS: // 3 $1234 - case AM_ABS_Y: // 6 $1234,y - case AM_ABS_X: // 7 $1234,x - case AM_REL: // 8 ($1234) - case AM_REL_X: // c ($1234,x) - case AM_REL_L: // 14 [$1234] - reference = (int)mem[0] | ((int)mem[1])<<8; - if (src && lblname) - out.sprintf_append(fmt, mnemonic, lblname.c_str()); - else - out.sprintf_append(fmt, mnemonic, (int)mem[0] | ((int)mem[1])<<8); - break; - - case AM_ABS_L: // 10 $bahilo - case AM_ABS_L_X: // 11 $123456,x - reference = (int)mem[0] | ((int)mem[1])<<8 | ((int)mem[2])<<16; - if (src && lblname) - out.sprintf_append(fmt, mnemonic, lblname); - else - out.sprintf_append(fmt, mnemonic, (int)mem[0] | ((int)mem[1])<<8 | ((int)mem[2])<<16); - break; - - case AM_IMM_DBL_A: // 18 #$12/#$1234 - case AM_IMM_DBL_I: // 19 #$12/#$1234 - if (arg_size==2) { - if (src && lblname) - out.sprintf_append("%s #%s", mnemonic, lblname.c_str()); - else - out.sprintf_append("%s #$%04x", mnemonic, (int)mem[0] | ((int)mem[1])<<8); - } else { - if (src && lblname) - out.sprintf_append(fmt, mnemonic, lblname.c_str()); - else - out.sprintf_append(fmt, mnemonic, mem[0]); - } - break; - - case AM_BRANCH: // beq $1234 - if (src && lblname) - out.sprintf_append(fmt, mnemonic, lblname.c_str()); - else - out.sprintf_append(fmt, mnemonic, addr + (char)mem[0]); - break; - - case AM_BRANCH_L: // brl $1234 - if (src && lblname) - out.sprintf_append(fmt, mnemonic, lblname.c_str()); - else - out.sprintf_append(fmt, mnemonic, addr + ((short)(char)mem[0] + (((short)(char)mem[1])<<8))); - break; - - case AM_ZP_ABS: // d $12, *+$12 - if (src && lblname) - out.sprintf_append(fmt, mnemonic, lblname.c_str()); - else - out.sprintf_append(fmt, mnemonic, mem[0], addr + (char)mem[1]); - break; - - case AM_ZP: - case AM_ZP_REL: - case AM_ZP_REL_L: - case AM_ZP_REL_X: - case AM_ZP_REL_Y: - case AM_ZP_X: - case AM_ZP_Y: - case AM_ZP_REL_Y_L: - case AM_ZP_Y_REL: - if (src && lblname) - out.sprintf_append(fmt, mnemonic, lblname.c_str()); - else - out.sprintf_append(fmt, mnemonic, mem[0], mem[1]); - break; - - default: - out.sprintf_append(fmt, mnemonic, mem[0], mem[1]); - break; - } - if (!src && lblname) - out.sprintf_append(" ; %s " STRREF_FMT, lblname.c_str(), STRREF_ARG(lblcmt)); - else if (src && lblname) - out.sprintf_append(" ; $%04x " STRREF_FMT, reference, STRREF_ARG(lblcmt)); - - mem += arg_size; - out.append('\n'); - fputs(out.c_str(), f); - } - if (separator || (curr_label_index<(int)refs.size() && - refs[curr_label_index].address==addr && is_data && - !refs[curr_label_index].data)) { - fputs("\n", f); - fputs(spc, f); - fprintf(f, "; ------------- $%04x ------------- ;\n\n", addr); - } - } - if (opened) - fclose(f); - - for (int i = (int)refs.size()-1; i>=0; --i) { - if (refs[i].pRefs) - delete refs[i].pRefs; - refs.erase(refs.begin() + i); - } - -} - -strref read_text(const char *filename) -{ - if (filename) { - if (FILE *f = fopen(strown<512>(filename).c_str(), "rb")) { - fseek(f, 0, SEEK_END); - size_t size = ftell(f); - fseek(f, 0, SEEK_SET); - if (char *buf = (char*)malloc(size)) { - fread(buf, size, 1, f); - fclose(f); - return strref(buf, (strl_t)size); - } - } - } - return strref(); -} - - -int main(int argc, char **argv) -{ - - - - const char *bin = nullptr; - const char *out = nullptr; - int skip = 0; - int end = 0; - int addr = 0x1000; - int data = 0; - bool acc_16 = true; - bool ind_16 = true; - bool src = false; - bool prg = false; - bool ill_wdc = false; - bool graph = false; - bool graph_branches = false; - - const dismnm *opcodes = a6502_ops; - strref labels; - - for (int i = 1; i < argc; i++) { - strref arg(argv[i]); - if (arg[0] == '$') { - ++arg; - skip = arg.ahextoui_skip(); - if (arg.get_first() == '-') { - ++arg; - if (arg.get_first() == '$') { - ++arg; - end = arg.ahextoui(); - } - } - } else { - strref var = arg.split_token('='); - if (var.same_str("src")) - src = true; - else if (var.same_str("prg")) - prg = true; - else if (var.same_str("graph")) - graph = true; - else if (var.same_str("graph+bra")) { - graph = true; - graph_branches = true; - } else if (!arg) { - if (!bin) - bin = argv[i]; - else if (!out) - out = argv[i]; - } else { - if (var.same_str("mx")) { - int mx = arg.atoi(); - ind_16 = !!(mx & 1); - acc_16 = !!(mx & 2); - } else if (var.same_str("labels")) { - labels = read_text(arg.get()); - } else if (var.same_str("addr")) { - if (arg.get_first() == '$') - ++arg; - addr = arg.ahextoui(); - } else if (var.same_str("data")) { - if (arg.get_first() == '$') { - ++arg; - data = arg.ahextoui(); - } else - data = arg.atoi(); - } else if (var.same_str("cpu")) { - if (arg.same_str("65816")) - opcodes = a65816_ops; - else if (arg.same_str("65C02")) - opcodes = a65C02_ops; - else if (arg.same_str("6502")) - opcodes = a6502_ops; - else if (arg.same_str("65C02WDC")) { - opcodes = a65C02_ops; - ill_wdc = true; - } else if (arg.same_str("6502ILL")) { - opcodes = a6502_ops; - ill_wdc = true; - } - } - } - } - } - - if (bin) { - FILE *f = fopen(bin, "rb"); - if (!f) - return -1; - fseek(f, 0, SEEK_END); - size_t size = ftell(f); - fseek(f, 0, SEEK_SET); - if (unsigned char *mem = (unsigned char*)malloc(size)) { - fread(mem, size, 1, f); - fclose(f); - if (prg) { - addr = mem[0] + ((int)mem[1]<<8); - skip += 2; - if (end) - end += 2; - } - if (size > (size_t)skip && (end == 0 || end > skip)) { - size_t bytes = size - skip; - if (end && bytes > size_t(end - skip)) - bytes = size_t(end - skip); - Disassemble(out, mem + skip, bytes, acc_16, ind_16, addr, ill_wdc, graph, graph_branches, opcodes, src, data, labels); - } - free(mem); - } - } else { - puts("Usage:\n" - "x65dsasm binary disasm.txt [$skip[-$end]] [addr=$xxxx] [cpu=6502/65C02/65816]\n" - " [mx=0-3] [src] [labels=(labels.txt)]\n" - " * binary: file which contains some 65xx series instructions\n" - " * disasm.txt: output file (default is stdout)\n" - " * $skip-$end: first byte offset to disassemble to last byte offset to disassemble\n" - " * addr: disassemble as if loaded at addr\n" - " * prg: file is a c64 program file starting with the load address\n" - " * cpu: set which cpu to disassemble for (default is 6502)\n" - " * src: export near assemblable source with guesstimated data blocks\n" - " * mx: set the mx flags which control accumulator and index register size\n" - " * labels: define some labels with address and type (lbl=$addr,[code]/[data])\n"); - } - if (labels) - free(const_cast(labels.get())); - return 0; -} \ No newline at end of file