Joined: Thu May 28, 2009 9:46 pm Posts: 8514 Location: Midwestern USA
|
ElEctric_EyE wrote: I'm looking to get into programming the 65816 and am looking for an easy to use program similar to M.Kowalski's 6502 assembler, that can at least create a .bin file from the assembly code, under a Windows environment... I've searched the threads here @6502.org and found: HXA by teamtempest and ACME by Marco Baye They don't appear to have a GUI like MK's assembler though... Thanks for your help! Other than the package sold by WDC for a lot of money, I don't have any suggestions for a windowing assembler. What I did was write macros for the Kowalski simulator that synthesize some of the '816 functions. Code for it follows.
Code: ;================================================================================ ; ;W65C816S INSTRUCTION MACROS ; ; ————————————————————————————————————————————————————————— ; These macros implement 65C02 & many W65C816S native mode ; instructions that are not recognized by the Kowalski ass- ; embler (e.g., STP & WAI). ; ————————————————————————————————————————————————————————— ; .if !.ref(brl) ; brl .macro .ad ;long relative branch... .if .ad ;won't work for forward... .isize =3 ;branches because of forward... .os =*+.isize ;address reference .os =.ad-.os .if .os > 32767 .error %1 + ": FORWARD BRANCH OUT OF RANGE" .endif .if .os < -32768 .error %1 + ": BACKWARD BRANCH OUT OF RANGE" .endif .byte $82 .word .os .else .error "INSTRUCTION REQUIRES TARGET ADDRESS" .endif .endm ; cop .macro .op ;co-processor .if .op > $ff .error "SIGNATURE MUST BE $00 - $FF" .endif .byte $02,.op .endm ; jml .macro .ad ;JMP $bbahal (long JMP) .byte $dc,<.ad, >.ad,.ad >> 16 .endm ; jsl .macro .bk,.ad ;JSL $bbahal (long JSR) .byte $22,<.ad, >.ad,.ad >> 16 .endm ; jsx .macro .ad ;JSR (<addr>,X) .byte $fc,<.ad, >.ad .endm ; mvn .macro .s,.d ;move next <sbnk>,<dbnk> .if .s > $ff .error "SOURCE BANK MUST BE $00 - $FF" .endif .if .d > $ff .error "DESTINATION BANK MUST BE $00 - $FF" .endif .byte $54,.d,.s .endm ; mvp .macro .s,.d ;move prev <sbnk>,<dbnk> .if .s > $ff .error "SOURCE BANK MUST BE $00 - $FF" .endif .if .d > $ff .error "DESTINATION BANK MUST BE $00 - $FF" .endif .byte $44,.d,.s .endm ; pea .macro .ad ;pea <addr> .byte $f4,<.ad, >.ad .endm ; pei .macro .ad ;pei (<addr>) .if .ad > $ff .error "INDIRECT ADDRESS MUST BE $00 - $FF" .endif .byte $d4,.ad .endm ; phb .macro ;push data bank register .byte $8b .endm ; phd .macro ;push direct page register .byte $0b .endm ; phk .macro ;push program bank register .byte $4b .endm ; plb .macro ;pull data bank register .byte $ab .endm ; pld .macro ;pull direct page register .byte $2b .endm ; rep .macro .op ;clear status register bits .if .op > $ff .error "OPERAND MUST BE $00 - $FF" .endif .byte $c2,.op .endm ; rtl .macro ;return long from subroutine .byte $6b .endm ; sep .macro .op ;set status register bits .if .op > $ff .error "OPERAND MUST BE $00 - $FF" .endif .byte $e2,.op .endm ; stp .macro ;halt MPU .byte $db .endm ; tcd .macro ;transfer .C to direct page register .byte $5b .endm ; tcs .macro ;transfer .C to stack pointer .byte $1b .endm ; tdc .macro ;transfer direct page register to .C .byte $7b .endm ; tsc .macro ;transfer stack pointer to .C .byte $3b .endm ; txy .macro ;transfer .X to .Y .byte $9b .endm ; tyx .macro ;transfer .Y to .X .byte $bb .endm ; wai .macro ;wait for interrupt .byte $cb .endm ; xba .macro ;swap B & A accumulators .byte $eb .endm ; xce .macro ;swap carry & emulation bits .byte $fb .endm ; ; ; synthesized stack-based accumulator instructions... ; ; ————————————————————————————————————————————————————————————————————— ; Stack-based accumulator instructions take the form ***S or ***SI, the ; latter for indexed indirect operations. *** represents the parent ; instruction. For example, LDAS 1 is equivalent to LDA 1,S & LDASI 1 ; is the equivalent of LDA (1,S),Y. The actual macro names are lower ; case. The macro comment indicates the official WDC assembly language ; syntax for the instruction being synthesized. ; ————————————————————————————————————————————————————————————————————— ; adcs .macro .of ;ADC <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $63,.of .endm ; adcsi .macro .of ;ADC (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $73,.of .endm ; ands .macro .of ;AND <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $23,.of .endm ; andsi .macro .of ;AND (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $33,.of .endm ; cmps .macro .of ;CMP <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $c3,.of .endm ; cmpsi .macro .of ;CMP (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $d3,.of .endm ; eors .macro .of ;EOR <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $43,.of .endm ; eorsi .macro .of ;EOR (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $53,.of .endm ; ldas .macro .of ;LDA <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $a3,.of .endm ; ldasi .macro .of ;LDA (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $b3,.of .endm ; oras .macro .of ;ORA <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $03,.of .endm ; orasi .macro .of ;ORA (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $13,.of .endm ; sbcs .macro .of ;SBC <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $e3,.of .endm ; sbcsi .macro .of ;SBC (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $f3,.of .endm ; stas .macro .of ;STA <offset>,S .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $83,.of .endm ; stasi .macro .of ;STA (<offset>,S),Y .if .of > $ff .error "OFFSET MUST BE $00 - $FF" .endif .byte $93,.of .endm ; ; ; 16 bit immediate mode instructions... ; ; ———————————————————————————————————————————————————————————————————— ; Immediate mode instructions that are able to accept 16 bit operands ; take the form ***W, where *** is the parent 8 bit instruction. For ; example, ADCW is the 16 bit form of ADC. The actual macro names are ; lower case. It is the responsibility of the programmer to assure ; that MPU register sizes have been correctly configured before using ; ***W instructions. For example: ; ; LONGA ;16 bit .A & memory ; LDAW $1234 ;assembles as LDA #$1234 ; SHORTA ;8 bit .A & memory ; LDAW $1234 ;won't work as expected!!! ; ; The macro comment indicates the official WDC assembly language syn- ; tax for the instruction being synthesized. ; ———————————————————————————————————————————————————————————————————— ; adcw .macro .op ;ADC #nnnn adc #<.op .byte >.op .endm ; andw .macro .op ;AND #nnnn and #<.op .byte >.op .endm ; bitw .macro .op ;BIT #nnnn bit #<.op .byte >.op .endm ; cmpw .macro .op ;CMP #nnnn cmp #<.op .byte >.op .endm ; cpxw .macro .op ;CPX #nnnn cpx #<.op .byte >.op .endm ; cpyw .macro .op ;CPY #nnnn cpy #<.op .byte >.op .endm ; eorw .macro .op ;EOR #nnnn eor #<.op .byte >.op .endm ; ldaw .macro .op ;LDA #nnnn lda #<.op .byte >.op .endm ; ldxw .macro .op ;LDX #nnnn ldx #<.op .byte >.op .endm ; ldyw .macro .op ;LDY #nnnn ldy #<.op .byte >.op .endm ; oraw .macro .op ;ORA #nnnn ora #<.op .byte >.op .endm ; sbcw .macro .op ;SBC #nnnn sbc #<.op .byte >.op .endm ; ; ; register size macros... ; ; ———————————————————————————————————————————————————————————————————— ; These macros are a convenient way to change the MPU's register sizes ; without having to remember the correct bit pattern for the REP & SEP ; instructions. The assembler itself has no awareness of whether 8 or ; 16 bit immediate mode operands are to be used. Therefore, it is up ; to the programmer to use the appropriate instructions. ; ———————————————————————————————————————————————————————————————————— ; longa .macro ;16 bit accumulator & memory rep $20 .endm ; longr .macro ;16 bit all registers rep $30 .endm ; longx .macro ;16 bit index registers rep $10 .endm ; shorta .macro ;8 bit accumulator & memory sep $20 .endm ; shortr .macro ;8 bit all registers sep $30 .endm ; shortx .macro ;8 bit index registers sep $10 .endm ; ; ; INT pseudoinstruction — assembles as BRK followed by operand... ; int .macro .op ;INT <intnum> .if .op > $ff .error "INTERRUPT NUMBER MUST BE $00 - $FF" .endif brk .byte .op .endm ; .endif .end
BRL forward branches won't work right due to unresolvable forward references. I may some day figure out a workaround.
The JML (JuMP long) and JSL (Jump to Subroutine Long) instructions process the operand as a 24 bit address, even if it is only 8 or 16 bits. For example:
Code: JML $123456 will jump to address $3456 in bank $12. Similarly:
Code: JSL $1234 will call a subroutine in bank 0 (which is implied) at address $1234.
Understand that the Kowalski assembler internally resolves all values to 32 bits and provides a number of logical operators that can extract the most significant 16 bits. This is how I was able to synthesize the JML and JSL instructions. The assembler will only display the lower 16 bits in the listing output.
If you call a subroutine using JSL be sure to use RTL at the end of the subroutine to return. Otherwise, be prepared to press the reset button.
EDIT: I updated this macro list with some new ones added since I originally posted this.
EDIT: Macro list revised on 2012/07/01. In the near future this will be posted on my POC website.
_________________ x86? We ain't got no x86. We don't NEED no stinking x86!
Last edited by BigDumbDinosaur on Sun Jul 01, 2012 6:22 pm, edited 2 times in total.
|
|