mirror of
https://github.com/ksherlock/x65.git
synced 2024-06-25 20:29:31 +00:00
x65macro.i added
- Adding standard macros with for loops, memory copy, add, subtract, move and set - macros can be named with dots - double negatives won't cause errors in expressions - vice output will convert labels named "debugbreak" to vice breakpoints rather than vice labels - fixed issues with mixing conditional operators with math operators in expressions
This commit is contained in:
parent
260f48e126
commit
6cbf7f8754
26
README.md
26
README.md
|
@ -50,11 +50,6 @@ Noteworthy features:
|
||||||
|
|
||||||
x65.cpp requires struse.h which is a single file text parsing library that can be retrieved from https://github.com/Sakrac/struse.
|
x65.cpp requires struse.h which is a single file text parsing library that can be retrieved from https://github.com/Sakrac/struse.
|
||||||
|
|
||||||
## Additional x65 Tools
|
|
||||||
|
|
||||||
* **dump_x65**: Inspect the contents of .x65 object files generated by x65 to track down linking issues
|
|
||||||
* **x65dsasm**: Disassemble assembled binary code for review
|
|
||||||
|
|
||||||
### References
|
### References
|
||||||
|
|
||||||
* [6502 opcodes](http://www.6502.org/tutorials/6502opcodes.html)
|
* [6502 opcodes](http://www.6502.org/tutorials/6502opcodes.html)
|
||||||
|
@ -68,6 +63,22 @@ x65.cpp requires struse.h which is a single file text parsing library that can b
|
||||||
* [Windows x64 binaries](../..//raw/master/bin/x65_x64.zip)
|
* [Windows x64 binaries](../..//raw/master/bin/x65_x64.zip)
|
||||||
* [Windows x86 binaries](../..//raw/master/bin/x65_win32.zip)
|
* [Windows x86 binaries](../..//raw/master/bin/x65_win32.zip)
|
||||||
|
|
||||||
|
### x65
|
||||||
|
|
||||||
|
x65 is the assembler
|
||||||
|
|
||||||
|
### x65macro.i
|
||||||
|
|
||||||
|
x65macro.i is a 6502 include file that defines a number of standard macros that can assign values, move values, copy values and loop constructs, see x65.txt for details.
|
||||||
|
|
||||||
|
### dump_x65
|
||||||
|
|
||||||
|
dump_x65 is a tool to inspect the contents of .x65 object files generated by x65 to track down linking issues
|
||||||
|
|
||||||
|
### x65dsasm
|
||||||
|
|
||||||
|
x65dsasm is a tool to disassemble assembled binary code for review, it will perform a basic analysis and assign labels where appropriate and treats unreferenced bytes as data rather than code. It can also export assemblable code from a binary.
|
||||||
|
|
||||||
### Acknowledgments
|
### Acknowledgments
|
||||||
|
|
||||||
This project would not be completed without the direct or indirect support of great people, some which I can currently remember:
|
This project would not be completed without the direct or indirect support of great people, some which I can currently remember:
|
||||||
|
@ -89,6 +100,11 @@ Primarily tested with personal archive of sources written for Kick assmebler, DA
|
||||||
* irp (indefinite repeat)
|
* irp (indefinite repeat)
|
||||||
|
|
||||||
**FIXED**
|
**FIXED**
|
||||||
|
* Adding x65macro.i
|
||||||
|
* Vice symbols will generate breakpoints whenever label 'debugbreak' is encountered
|
||||||
|
* Evaluating '==' was broken
|
||||||
|
* Macros can have dots in their names
|
||||||
|
* Handling double negative in expressions (--35 == 35)
|
||||||
* Macros works within conditionals (if/else/endif, etc)
|
* Macros works within conditionals (if/else/endif, etc)
|
||||||
* String symbols broke late evaluation resulting in garbage references, this has been fixed
|
* String symbols broke late evaluation resulting in garbage references, this has been fixed
|
||||||
* Added string symbols
|
* Added string symbols
|
||||||
|
|
516
macros/x65macro.i
Normal file
516
macros/x65macro.i
Normal file
|
@ -0,0 +1,516 @@
|
||||||
|
;x65macros.i
|
||||||
|
|
||||||
|
;
|
||||||
|
; set.b / .w / .t / .l Trg, Value
|
||||||
|
; - set the contents of an 1-4 byte location to a value
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; move.b / .w / .t / .l / .n Src,Trg
|
||||||
|
; - copy 1-4 (or n) bytes from Src location to Trg location
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; add.n Address1, Address2, Target, Bytes
|
||||||
|
; - add contents of two memory locations into a target lcoation
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; sub.n Address1, Address2, Target, Bytes
|
||||||
|
; - Target = Address1 - Address2
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; add.ni Address, Value, Target, Bytes
|
||||||
|
; - add a fixed value to a memory location into a target
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; sub.ni Address, Value, Target, Bytes
|
||||||
|
; - Target = Address - Value
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; addw.i Address, Value, Target
|
||||||
|
; - Subtract 16 bit Value from contents of Address and store at Target
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; subw.i Address1, Address2, Target
|
||||||
|
; - add contents of two 16 bit addresses into a target 16 bit location
|
||||||
|
; - uses accumulator
|
||||||
|
;
|
||||||
|
; mnop Count
|
||||||
|
; - add Count nops
|
||||||
|
;
|
||||||
|
; copy.x Source, Target, Size
|
||||||
|
; - copy up to 256 bytes using the x register as a counter
|
||||||
|
; - uses accumulator and x register
|
||||||
|
;
|
||||||
|
; copy.y Source, Target, Size
|
||||||
|
; - copy up to 256 bytes using the y register as a counter
|
||||||
|
; - uses accumulator and y register
|
||||||
|
;
|
||||||
|
; copy.p Src,Trg,Size,PoolZP
|
||||||
|
; - copy more than 256 bytes using zero page label pool addresses
|
||||||
|
; - uses accumulator, x and y register
|
||||||
|
;
|
||||||
|
; copy.a Src,Trg,Size
|
||||||
|
; - copy more than 256 bytes using absolute indexed in a loop
|
||||||
|
; - uses accumulator, x and y register
|
||||||
|
;
|
||||||
|
; copy.zp Src,Trg,Size,zpTmp1,zpTmp2
|
||||||
|
; - copy more than 256 bytes using two pairs of zero page values
|
||||||
|
; - uses accumulator, x and y register
|
||||||
|
;
|
||||||
|
; for.x Start, End
|
||||||
|
; - iterate using the x register from Start to End, End is not inclusive
|
||||||
|
; so to iterate from 31 to 0 use for.x 31, -1
|
||||||
|
; - uses x register
|
||||||
|
; - end for loop with forend macro
|
||||||
|
;
|
||||||
|
; for.y Start, End
|
||||||
|
; - same as for.x but with the y register
|
||||||
|
; - uses y register
|
||||||
|
; - end for loop with forend macro
|
||||||
|
;
|
||||||
|
; for.w Start, End, Counter
|
||||||
|
; - for loop for 16 bit counter
|
||||||
|
; - uses accumulator
|
||||||
|
; - end for loop with forend macro
|
||||||
|
;
|
||||||
|
; for.ws Start, End, Counter, Step
|
||||||
|
; - for loop for 16 bit counter with a step value
|
||||||
|
; - uses accumulator
|
||||||
|
; - end for loop with forend macro
|
||||||
|
;
|
||||||
|
; forend
|
||||||
|
; - terminates for loops
|
||||||
|
;
|
||||||
|
|
||||||
|
macro set.b Value,Trg
|
||||||
|
{
|
||||||
|
lda #Value
|
||||||
|
sta Trg
|
||||||
|
}
|
||||||
|
|
||||||
|
; Set two bytes to a 16 bit value
|
||||||
|
macro set.w Value,Trg
|
||||||
|
{
|
||||||
|
lda #<Value
|
||||||
|
sta Trg
|
||||||
|
lda #>Value
|
||||||
|
sta Trg+1
|
||||||
|
}
|
||||||
|
|
||||||
|
; Set three bytes to a 24 bit value
|
||||||
|
macro set.t Value,Trg
|
||||||
|
{
|
||||||
|
rept 3 {
|
||||||
|
lda #Value>>(rept*8)
|
||||||
|
sta Trg+rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; Set three bytes to a 24 bit value
|
||||||
|
macro set.l Value,Trg
|
||||||
|
{
|
||||||
|
rept 4 {
|
||||||
|
lda #Value>>(rept*8)
|
||||||
|
sta Trg+rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro move.b Src,Trg
|
||||||
|
{
|
||||||
|
lda Src
|
||||||
|
sta Trg
|
||||||
|
}
|
||||||
|
|
||||||
|
macro move.w Src,Trg
|
||||||
|
{
|
||||||
|
rept 2 {
|
||||||
|
lda Src + rept
|
||||||
|
sta Trg + rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro move.t Src,Trg
|
||||||
|
{
|
||||||
|
rept 3 {
|
||||||
|
lda Src + rept
|
||||||
|
sta Trg + rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro move.l Src,Trg
|
||||||
|
{
|
||||||
|
rept 4 {
|
||||||
|
lda Src + rept
|
||||||
|
sta Trg + rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro move.n Src,Trg,Size
|
||||||
|
{
|
||||||
|
rept Size {
|
||||||
|
lda Src + rept
|
||||||
|
sta Trg + rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; add two numbers together (A and B and Trg are addresses)
|
||||||
|
macro add.n A,B,Trg,NumSize
|
||||||
|
{
|
||||||
|
clc
|
||||||
|
rept NumSize {
|
||||||
|
lda A+rept
|
||||||
|
adc B+rept
|
||||||
|
sta Trg+rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; add two numbers together (A and B and Trg are addresses)
|
||||||
|
macro sub.n A,B,Trg,NumSize
|
||||||
|
{
|
||||||
|
sec
|
||||||
|
rept NumSize {
|
||||||
|
lda A+rept
|
||||||
|
sbc B+rept
|
||||||
|
sta Trg+rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; add a fixed value to an N byte number and store at Trg
|
||||||
|
macro add.ni Src,Value,Trg,NumSize
|
||||||
|
{
|
||||||
|
clc
|
||||||
|
rept NumSize {
|
||||||
|
lda Src+rept
|
||||||
|
adc #Value>>(8*rept)
|
||||||
|
sta Trg+rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; add a fixed value to an N byte number and store at Trg
|
||||||
|
macro sub.ni Src,Value,Trg,NumSize
|
||||||
|
{
|
||||||
|
sec
|
||||||
|
rept NumSize {
|
||||||
|
lda Src+rept
|
||||||
|
sbc #Value>>(8*rept)
|
||||||
|
sta Trg+rept
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; add a fixed value to a two byte number and store at Trg
|
||||||
|
macro addw.i Src,Value,Trg
|
||||||
|
{
|
||||||
|
clc
|
||||||
|
lda #<Value
|
||||||
|
adc Src
|
||||||
|
sta Trg
|
||||||
|
lda #>Value
|
||||||
|
adc Src+1
|
||||||
|
sta Trg+1
|
||||||
|
}
|
||||||
|
|
||||||
|
; add a fixed value to a two byte number and store at Trg
|
||||||
|
macro subw.i Src,Value,Trg
|
||||||
|
{
|
||||||
|
sec
|
||||||
|
lda Src
|
||||||
|
sbc #<Value
|
||||||
|
sta Trg
|
||||||
|
lda Src+1
|
||||||
|
sbc #>Value
|
||||||
|
sta Trg+1
|
||||||
|
}
|
||||||
|
|
||||||
|
; insert multiple nops
|
||||||
|
macro mnop Count {
|
||||||
|
rept Count {
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
; copy a fixed length buffer from one place to another
|
||||||
|
; size is up to a page, changing X and A
|
||||||
|
macro copy.x Src,Trg,Size
|
||||||
|
{
|
||||||
|
if Size==0
|
||||||
|
elif Size==1
|
||||||
|
lda Src
|
||||||
|
sta Trg
|
||||||
|
elif Size<129
|
||||||
|
ldx #Size-1
|
||||||
|
{
|
||||||
|
lda Src,x
|
||||||
|
sta Trg,x
|
||||||
|
dex
|
||||||
|
bpl !
|
||||||
|
}
|
||||||
|
elif Size<256
|
||||||
|
ldx #0
|
||||||
|
{
|
||||||
|
lda Src,x
|
||||||
|
sta Trg,x
|
||||||
|
inx
|
||||||
|
cpx #size
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error copy.x can only copy up to 256 bytes, use copy.p to copy Size bytes
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
; copy a fixed length buffer from one place to another
|
||||||
|
; size is up to a page, changing Y and A
|
||||||
|
macro copy.y Src,Trg,Size
|
||||||
|
{
|
||||||
|
if Size==0
|
||||||
|
elif Size==1
|
||||||
|
lda Src
|
||||||
|
sta Trg
|
||||||
|
elif Size<129
|
||||||
|
ldy #Size-1
|
||||||
|
{
|
||||||
|
lda Src,y
|
||||||
|
sta Trg,y
|
||||||
|
dey
|
||||||
|
bpl !
|
||||||
|
}
|
||||||
|
elif Size<256
|
||||||
|
ldy #0
|
||||||
|
{
|
||||||
|
lda Src,y
|
||||||
|
sta Trg,y
|
||||||
|
iny
|
||||||
|
cpy #size
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error copy.x can only copy up to 256 bytes, use copy.p to copy Size bytes
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
; copy a fixed length buffer using relative zp y indexing
|
||||||
|
; size is up to a page, changing Y and A
|
||||||
|
macro copy.ry zpSrcPtr,zpTrgPtr,Size
|
||||||
|
{
|
||||||
|
if (Size) > 256
|
||||||
|
error copy.ry can only copy up to 256 bytes
|
||||||
|
elif (Size) > 0
|
||||||
|
ldy #Size-1
|
||||||
|
{
|
||||||
|
lda (zpSrcPtr),y
|
||||||
|
sta (zpTrgPtr),y
|
||||||
|
dey
|
||||||
|
if (Size) > 128
|
||||||
|
cpy #$ff
|
||||||
|
bne !
|
||||||
|
else
|
||||||
|
bpl !
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
; copy pages using temp zero page registers
|
||||||
|
; falls back on CopyF if less than or equal to a page
|
||||||
|
; changes x, y and A
|
||||||
|
macro copy.p Src,Trg,Size,PoolZP
|
||||||
|
{
|
||||||
|
if (Size<256)
|
||||||
|
copy.x Src,Trg,Size
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PoolZP zpSrc.w
|
||||||
|
PoolZP zpTrg.w
|
||||||
|
set.w zpSrc,Src
|
||||||
|
set.w zpTrg,Trg
|
||||||
|
ldx #>Size
|
||||||
|
ldy #0
|
||||||
|
{
|
||||||
|
{
|
||||||
|
lda (zpSrc),y
|
||||||
|
sta (zpTrg),y
|
||||||
|
iny
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
inc zpSrc+1
|
||||||
|
inc zpTrg+1
|
||||||
|
dex
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
if Size & $ff
|
||||||
|
ldy #Size-1
|
||||||
|
{
|
||||||
|
lda (zpSrc),y
|
||||||
|
sta (zpTrg),y
|
||||||
|
dey
|
||||||
|
if (Size & $ff)<129
|
||||||
|
bpl !
|
||||||
|
else
|
||||||
|
cpy #$ff
|
||||||
|
bne !
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
macro copy.zp Src,Trg,Size,zpTmp1,zpTmp2
|
||||||
|
{
|
||||||
|
if (Size<256)
|
||||||
|
copy.x Src,Trg,Size
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set.w zpTmp1,Src
|
||||||
|
set.w zpTmp2,Trg
|
||||||
|
ldx #>Size
|
||||||
|
ldy #0
|
||||||
|
{
|
||||||
|
{
|
||||||
|
lda (zpTmp1),y
|
||||||
|
sta (zpTmp2),y
|
||||||
|
iny
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
inc zpTmp1+1
|
||||||
|
inc zpTmp2+1
|
||||||
|
dex
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
if Size & $ff
|
||||||
|
ldy #Size-1
|
||||||
|
{
|
||||||
|
lda (zpTmp1),y
|
||||||
|
sta (zpTmp2),y
|
||||||
|
dey
|
||||||
|
if (Size & $ff)<129
|
||||||
|
bpl !
|
||||||
|
else
|
||||||
|
cpy #$ff
|
||||||
|
bne !
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
macro copy.a Src,Trg,Size
|
||||||
|
{
|
||||||
|
if (Size<256)
|
||||||
|
copy.x Src,Trg,Size
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set.b >Src, ._addr+2
|
||||||
|
set.b >Trg, ._addr+5
|
||||||
|
ldy #>Size
|
||||||
|
ldx #0
|
||||||
|
._addr
|
||||||
|
{
|
||||||
|
{
|
||||||
|
lda Src,x
|
||||||
|
sta Trg,x
|
||||||
|
inx
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
inc ._addr+2
|
||||||
|
inc ._addr+5
|
||||||
|
dey
|
||||||
|
bne !
|
||||||
|
}
|
||||||
|
if Size & $ff
|
||||||
|
ldx #(Size&$ff)-1
|
||||||
|
{
|
||||||
|
lda Src+(Size & $ff00),x
|
||||||
|
sta Trg+(Size & $ff00),x
|
||||||
|
dex
|
||||||
|
if (Size & $ff)<129
|
||||||
|
bpl !
|
||||||
|
else
|
||||||
|
cpx #$ff
|
||||||
|
bne !
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
; for (x=start; x<end; x++)
|
||||||
|
macro for.x Start, End {
|
||||||
|
ldx #Start
|
||||||
|
if Start < End
|
||||||
|
string _ForEnd = "inx\ncpx #End\nbne _ForLoop"
|
||||||
|
elif Start > End
|
||||||
|
{
|
||||||
|
if (-1 == End) & (Start<129)
|
||||||
|
string _ForEnd = "dex\nbpl _ForLoop"
|
||||||
|
else
|
||||||
|
string _ForEnd = "dex\ncpx #End\nbne _ForLoop"
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
string _ForEnd = ""
|
||||||
|
endif
|
||||||
|
_ForLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
; for (y=start; y<end; y++)
|
||||||
|
macro for.y Start, End {
|
||||||
|
ldx #Start
|
||||||
|
if Start < End
|
||||||
|
string _ForEnd = "iny\ncpx #End\nbne _ForLoop"
|
||||||
|
elif Start > End
|
||||||
|
{
|
||||||
|
if (-1 == End) & (Start<129)
|
||||||
|
string _ForEnd = "dey\nbpl _ForLoop"
|
||||||
|
else
|
||||||
|
string _ForEnd = "dey\ncpy #End\nbne _ForLoop"
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
string _ForEnd = ""
|
||||||
|
endif
|
||||||
|
_ForLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
; for (Counter=start; Counter<end; Counter++)
|
||||||
|
macro for.w Start, End, Counter {
|
||||||
|
set.w Start, Counter
|
||||||
|
if (Start) < (End)
|
||||||
|
string _ForEnd = "{\ninc Counter\nbne %\ninc Counter+1\n}\nlda Counter+1\ncmp #>End\nbne _ForLoop\nlda Counter\ncmp #<End\nbne _ForLoop"
|
||||||
|
elif (Start) > (End)
|
||||||
|
string _ForEnd = "{\ndec Counter\nbne %\ndec Counter+1\n}\nlda Counter+1\ncmp #>End\nbne _ForLoop\nlda Counter\ncmp #<End\nbne _ForLoop"
|
||||||
|
else
|
||||||
|
string _ForEnd = ""
|
||||||
|
endif
|
||||||
|
_ForLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
macro forend {
|
||||||
|
_ForEnd
|
||||||
|
undef _ForEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
; for (Counter=start; Counter<end; Counter += Step)
|
||||||
|
macro for.ws Start, End, Counter, Step {
|
||||||
|
set.w Start, Counter
|
||||||
|
if Start < End
|
||||||
|
if ((Step)<1)
|
||||||
|
error Step is not a valid iterator for range Start to End
|
||||||
|
endif
|
||||||
|
string _ForEnd = "clc\nlda #<Step\nadc Counter\nsta Counter\nlda #>Step\n adc Counter+1\nsta Counter+1\ncmp #>End\nbcc _ForLoop\nlda Counter\ncmp #<End\nbcc _ForLoop"
|
||||||
|
elif Start > End
|
||||||
|
if ((Step)>-1)
|
||||||
|
error Step is not a valid iterator for range Start to End
|
||||||
|
endif
|
||||||
|
string _ForEnd = "sec\nlda Counter\n sbc #<(-Step)\nsta Counter\nlda Counter+1\nsbc #>(-Step)\nsta Counter+1\ncmp #(>End)+1\nbcs _ForLoop\nlda Counter\ncmp #(<End)+1\n\nbcs _ForLoop"
|
||||||
|
else
|
||||||
|
string _ForEnd = ""
|
||||||
|
endif
|
||||||
|
_ForLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
macro forend {
|
||||||
|
_ForEnd
|
||||||
|
undef _ForEnd
|
||||||
|
}
|
79
x65.cpp
79
x65.cpp
|
@ -305,11 +305,12 @@ enum EvalOperator {
|
||||||
EVOP_EOR, // r, ^
|
EVOP_EOR, // r, ^
|
||||||
EVOP_SHL, // s, <<
|
EVOP_SHL, // s, <<
|
||||||
EVOP_SHR, // t, >>
|
EVOP_SHR, // t, >>
|
||||||
EVOP_STP, // u, Unexpected input, should stop and evaluate what we have
|
EVOP_NEG, // u, negate value
|
||||||
EVOP_NRY, // v, Not ready yet
|
EVOP_STP, // v, Unexpected input, should stop and evaluate what we have
|
||||||
EVOP_XRF, // w, value from XREF label
|
EVOP_NRY, // w, Not ready yet
|
||||||
EVOP_EXP, // x, sub expression
|
EVOP_XRF, // x, value from XREF label
|
||||||
EVOP_ERR, // y, Error
|
EVOP_EXP, // y, sub expression
|
||||||
|
EVOP_ERR, // z, Error
|
||||||
};
|
};
|
||||||
|
|
||||||
// Opcode encoding
|
// Opcode encoding
|
||||||
|
@ -2757,7 +2758,8 @@ StatusCode Asm::AddMacro(strref macro, strref source_name, strref source_file, s
|
||||||
} else
|
} else
|
||||||
return ERROR_BAD_MACRO_FORMAT;
|
return ERROR_BAD_MACRO_FORMAT;
|
||||||
} else {
|
} else {
|
||||||
name = macro.split_label();
|
name = macro.split_range(label_end_char_range);
|
||||||
|
macro.skip_whitespace();
|
||||||
strref left_line = macro.get_line();
|
strref left_line = macro.get_line();
|
||||||
left_line.skip_whitespace();
|
left_line.skip_whitespace();
|
||||||
left_line = left_line.before_or_full(';').before_or_full(c_comment);
|
left_line = left_line.before_or_full(';').before_or_full(c_comment);
|
||||||
|
@ -3360,14 +3362,25 @@ StatusCode Asm::EvalExpression(strref expression, const struct EvalContext &etx,
|
||||||
} else if (op == EVOP_STP) {
|
} else if (op == EVOP_STP) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
while (sp) {
|
bool skip = false;
|
||||||
EvalOperator p = (EvalOperator)op_stack[sp-1];
|
if ((prev_op >= EVOP_EQU && prev_op <= EVOP_GTE) || (prev_op==EVOP_HIB || prev_op==EVOP_LOB)) {
|
||||||
if (p==EVOP_LPR || op>p)
|
if (op==EVOP_SUB)
|
||||||
break;
|
op = EVOP_NEG;
|
||||||
ops[numOps++] = p;
|
else if (op == EVOP_ADD)
|
||||||
sp--;
|
skip = true;
|
||||||
|
}
|
||||||
|
if (op == EVOP_SUB && sp && op_stack[sp-1]== EVOP_SUB)
|
||||||
|
sp--;
|
||||||
|
else {
|
||||||
|
while (sp && !skip) {
|
||||||
|
EvalOperator p = (EvalOperator)op_stack[sp-1];
|
||||||
|
if (p==EVOP_LPR || op>p)
|
||||||
|
break;
|
||||||
|
ops[numOps++] = p;
|
||||||
|
sp--;
|
||||||
|
}
|
||||||
|
op_stack[sp++] = op;
|
||||||
}
|
}
|
||||||
op_stack[sp++] = op;
|
|
||||||
}
|
}
|
||||||
// check for out of bounds or unexpected input
|
// check for out of bounds or unexpected input
|
||||||
if (numValues==MAX_EVAL_VALUES)
|
if (numValues==MAX_EVAL_VALUES)
|
||||||
|
@ -3442,6 +3455,10 @@ StatusCode Asm::EvalExpression(strref expression, const struct EvalContext &etx,
|
||||||
section_counts[i][ri-1] -= section_counts[i][ri];
|
section_counts[i][ri-1] -= section_counts[i][ri];
|
||||||
values[ri-1] -= values[ri];
|
values[ri-1] -= values[ri];
|
||||||
} break;
|
} break;
|
||||||
|
case EVOP_NEG:
|
||||||
|
if (ri>=1)
|
||||||
|
values[ri-1] = -values[ri-1];
|
||||||
|
break;
|
||||||
case EVOP_MUL: // *
|
case EVOP_MUL: // *
|
||||||
ri--;
|
ri--;
|
||||||
for (int i = 0; i<num_sections; i++)
|
for (int i = 0; i<num_sections; i++)
|
||||||
|
@ -4363,30 +4380,13 @@ StatusCode Asm::EvalStatement(strref line, bool &result)
|
||||||
int equ = line.find('=');
|
int equ = line.find('=');
|
||||||
struct EvalContext etx;
|
struct EvalContext etx;
|
||||||
SetEvalCtxDefaults(etx);
|
SetEvalCtxDefaults(etx);
|
||||||
if (equ >= 0) {
|
bool invert = line.get_first()=='!';
|
||||||
// (EXP) == (EXP)
|
if (invert)
|
||||||
strref left = line.get_clipped(equ);
|
++line;
|
||||||
bool equal = left.get_last()!='!';
|
int value;
|
||||||
left.trim_whitespace();
|
if (STATUS_OK != EvalExpression(line, etx, value))
|
||||||
strref right = line + equ + 1;
|
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
||||||
if (right.get_first()=='=')
|
result = (value!=0 && !invert) || (value==0 && invert);
|
||||||
++right;
|
|
||||||
right.trim_whitespace();
|
|
||||||
int value_left, value_right;
|
|
||||||
if (STATUS_OK != EvalExpression(left, etx, value_left))
|
|
||||||
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
|
||||||
if (STATUS_OK != EvalExpression(right, etx, value_right))
|
|
||||||
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
|
||||||
result = (value_left==value_right && equal) || (value_left!=value_right && !equal);
|
|
||||||
} else {
|
|
||||||
bool invert = line.get_first()=='!';
|
|
||||||
if (invert)
|
|
||||||
++line;
|
|
||||||
int value;
|
|
||||||
if (STATUS_OK != EvalExpression(line, etx, value))
|
|
||||||
return ERROR_CONDITION_COULD_NOT_BE_RESOLVED;
|
|
||||||
result = (value!=0 && !invert) || (value==0 && invert);
|
|
||||||
}
|
|
||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7163,7 +7163,10 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(f, "al $%04x %s" STRREF_FMT "\n", value, i->name[0]=='.' ? "" : ".",
|
if (i->name.same_str("debugbreak"))
|
||||||
|
fprintf(f, "break $%04x\n", value);
|
||||||
|
else
|
||||||
|
fprintf(f, "al $%04x %s" STRREF_FMT "\n", value, i->name[0]=='.' ? "" : ".",
|
||||||
STRREF_ARG(i->name));
|
STRREF_ARG(i->name));
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
112
x65.txt
112
x65.txt
|
@ -1155,3 +1155,115 @@ All Directives
|
||||||
|
|
||||||
|
|
||||||
-0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0-
|
-0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0--0-
|
||||||
|
|
||||||
|
|
||||||
|
x65macro.i
|
||||||
|
----------
|
||||||
|
|
||||||
|
A collection of macros to simplify common tasks such as assigning values
|
||||||
|
to addresses, moving values, addition and subtraction, memory copy
|
||||||
|
options and a variety of C-like for loops.
|
||||||
|
|
||||||
|
This is an example of how macros can be used:
|
||||||
|
|
||||||
|
jmp CodeEnd
|
||||||
|
CopyCode:
|
||||||
|
{
|
||||||
|
inx
|
||||||
|
beq !
|
||||||
|
txa
|
||||||
|
bne %
|
||||||
|
tay
|
||||||
|
dey
|
||||||
|
nop
|
||||||
|
}
|
||||||
|
CodeEnd:
|
||||||
|
sei
|
||||||
|
|
||||||
|
set.w CopyCode, $fc
|
||||||
|
|
||||||
|
for.ws $2000, $4000, $fe, CodeEnd-CopyCode
|
||||||
|
copy.ry $fc, $fe, CodeEnd - CopyCode
|
||||||
|
forend
|
||||||
|
cli
|
||||||
|
|
||||||
|
Included macros:
|
||||||
|
|
||||||
|
set.b / .w / .t / .l Trg, Value
|
||||||
|
- set the contents of an 1-4 byte location to a value
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
move.b / .w / .t / .l / .n Src,Trg
|
||||||
|
- copy 1-4 (or n) bytes from Src location to Trg location
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
add.n Address1, Address2, Target, Bytes
|
||||||
|
- add contents of two memory locations into a target lcoation
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
sub.n Address1, Address2, Target, Bytes
|
||||||
|
- Target = Address1 - Address2
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
add.ni Address, Value, Target, Bytes
|
||||||
|
- add a fixed value to a memory location into a target
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
sub.ni Address, Value, Target, Bytes
|
||||||
|
- Target = Address - Value
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
addw.i Address, Value, Target
|
||||||
|
- Subtract 16 bit Value from contents of Address and store at Target
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
subw.i Address1, Address2, Target
|
||||||
|
- add contents of two 16 bit addresses into a target 16 bit location
|
||||||
|
- uses accumulator
|
||||||
|
|
||||||
|
mnop Count
|
||||||
|
- add Count nops
|
||||||
|
|
||||||
|
copy.x Source, Target, Size
|
||||||
|
- copy up to 256 bytes using the x register as a counter
|
||||||
|
- uses accumulator and x register
|
||||||
|
|
||||||
|
copy.y Source, Target, Size
|
||||||
|
- copy up to 256 bytes using the y register as a counter
|
||||||
|
- uses accumulator and y register
|
||||||
|
|
||||||
|
copy.p Src,Trg,Size,PoolZP
|
||||||
|
- copy more than 256 bytes using zero page label pool addresses
|
||||||
|
- uses accumulator, x and y register
|
||||||
|
|
||||||
|
copy.a Src,Trg,Size
|
||||||
|
- copy more than 256 bytes using absolute indexed in a loop
|
||||||
|
- uses accumulator, x and y register
|
||||||
|
|
||||||
|
copy.zp Src,Trg,Size,zpTmp1,zpTmp2
|
||||||
|
- copy more than 256 bytes using two pairs of zero page values
|
||||||
|
- uses accumulator, x and y register
|
||||||
|
|
||||||
|
for.x Start, End
|
||||||
|
- iterate using the x register from Start to End, End is not inclusive
|
||||||
|
so to iterate from 31 to 0 use for.x 31, -1
|
||||||
|
- uses x register
|
||||||
|
- end for loop with forend macro
|
||||||
|
|
||||||
|
for.y Start, End
|
||||||
|
- same as for.x but with the y register
|
||||||
|
- uses y register
|
||||||
|
- end for loop with forend macro
|
||||||
|
|
||||||
|
for.w Start, End, Counter
|
||||||
|
- for loop for 16 bit counter
|
||||||
|
- uses accumulator
|
||||||
|
- end for loop with forend macro
|
||||||
|
|
||||||
|
for.ws Start, End, Counter, Step
|
||||||
|
- for loop for 16 bit counter with a step value
|
||||||
|
- uses accumulator
|
||||||
|
- end for loop with forend macro
|
||||||
|
|
||||||
|
forend
|
||||||
|
- terminates for-loops
|
Loading…
Reference in New Issue
Block a user