mirror of
https://github.com/ksherlock/x65.git
synced 2024-12-26 22:30:50 +00:00
Starting WDC syntax support, adding unit test to repo.
This commit is contained in:
parent
23aedcf686
commit
482470b410
@ -239,7 +239,7 @@ macro asrm.n Trg,Size
|
||||
lda Trg+Size-1
|
||||
asl
|
||||
rept Size {
|
||||
ror (Trg - 1 + Size - rept)
|
||||
ror 0 + (Trg - 1 + Size - rept)
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,7 +249,7 @@ macro asrm.nx Trg,Size
|
||||
lda Trg+Size-1,x
|
||||
asl
|
||||
rept Size {
|
||||
ror (Trg + Size - 1 - rept), x
|
||||
ror 0 + (Trg + Size - 1 - rept), x
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,7 +493,7 @@ macro copy.o Src,Trg,Size,PoolZP
|
||||
{
|
||||
if (Size<256)
|
||||
copy.x Src,Trg,Size
|
||||
else
|
||||
else
|
||||
{
|
||||
PoolZP zpSrc.w
|
||||
PoolZP zpTrg.w
|
||||
@ -535,7 +535,7 @@ macro copy.zp Src,Trg,Size,zpTmp1,zpTmp2
|
||||
{
|
||||
if (Size<256)
|
||||
copy.x Src,Trg,Size
|
||||
else
|
||||
else
|
||||
{
|
||||
set.w zpTmp1,Src
|
||||
set.w zpTmp2,Trg
|
||||
@ -575,7 +575,7 @@ macro copy.a Src,Trg,Size
|
||||
{
|
||||
if (Size<256)
|
||||
copy.x Src,Trg,Size
|
||||
else
|
||||
else
|
||||
{
|
||||
set.b >Src, ._addr+2
|
||||
set.b >Trg, ._addr+5
|
||||
|
@ -72,22 +72,22 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
|
@ -72,23 +72,23 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
293
test/8BitDiff_6502.s
Normal file
293
test/8BitDiff_6502.s
Normal file
@ -0,0 +1,293 @@
|
||||
// EXAMPLE KICK ASSEMBLER FILE
|
||||
|
||||
//
|
||||
// 6502 Decoder for 8BitDiff
|
||||
//
|
||||
// Copyright 2015 Carl-Henrik Skårstedt. All rights reserved.
|
||||
// https://github.com/sakrac/8BitDiff/
|
||||
//
|
||||
// 8BDIFF FORMAT
|
||||
// -------------
|
||||
// 4 bits: size of offset bit sizes
|
||||
// 4 bits: size of length bit sizes
|
||||
// 1 byte length bit sizes
|
||||
// 1 byte offset bit sizes
|
||||
// 2 bytes size of injected bytes (8 bit specific)
|
||||
// injected bytes
|
||||
// loop until end of inject buffer:
|
||||
// bit: 0=inject, 1=source or target
|
||||
// length bit cnt+length bits
|
||||
// if source or target:
|
||||
// buffer offset bit cnt + buffer offset bits
|
||||
// sign of offset (not instead of negate)
|
||||
// bit: 0=source, 1=target
|
||||
// repeat loop
|
||||
//
|
||||
// target/source/inject source pointers start
|
||||
// at the start of each buffer.
|
||||
// any pointer is set to the end of the run after
|
||||
// copy and the offset increments/decrements for source
|
||||
// for a negative offset, invert the number, don't negate.
|
||||
//
|
||||
// USAGE
|
||||
// -----
|
||||
// Use the 8BDIFF tool (https://github.com/sakrac/8BitDiff)
|
||||
// to generate a patch between two files. Load the
|
||||
// original file and the patch file and assign them as parameters:
|
||||
// z8BDiff = Address of patch
|
||||
// z8BSrc = Address of original data
|
||||
// z8BDst = Address to decode updated data
|
||||
// jsr Patch_8BDiff
|
||||
//
|
||||
|
||||
.label zParam8B = $f0 // 6 bytes
|
||||
.label zWork8B = $f6 // 10 bytes
|
||||
|
||||
// input (will be changed)
|
||||
.label z8BDiff = zParam8B // start of diff
|
||||
.label z8BSrc = z8BDiff+2 // start of source
|
||||
.label z8BDst = z8BSrc+2 // start of destination
|
||||
|
||||
// work (will be changed)
|
||||
.label z8BOff = zWork8B // 2 bytes current instruction offset
|
||||
.label z8BTemp = z8BOff // 1 byte temporary address
|
||||
.label z8BLen = z8BOff+2 // 2 bytes current instruction length
|
||||
.label z8BOffsSize = z8BLen+2 // 1 byte hot many bits to read for offset
|
||||
.label z8BLenSize = z8BOffsSize+1 // 1 byte how many bits to read for length
|
||||
.label z8BInj = z8BLenSize+1 // 2 bytes current injection address
|
||||
.label z8BTrg = z8BInj+2 // start of target 2 bytes
|
||||
|
||||
.label z8BInjSize = z8BTrg // 2 bytes size of injection buffer
|
||||
.label z8BInjEnd = z8BDiff // 2 bytes keeps track of end condition
|
||||
|
||||
// macro for reading one bit
|
||||
.macro GetBit() {
|
||||
asl
|
||||
bne !BitOk+
|
||||
jsr GetByte
|
||||
!BitOk:
|
||||
}
|
||||
|
||||
Patch_8BDiff:
|
||||
ldy #0 // clear Y
|
||||
lda (z8BDiff),y // first byte is prefix length bits | offset bits<<4
|
||||
tax
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
sta z8BOffsSize
|
||||
txa
|
||||
and #$0f
|
||||
sta z8BLenSize
|
||||
inc z8BDiff
|
||||
bne NotLastByte
|
||||
inc z8BDiff+1
|
||||
NotLastByte:
|
||||
lda z8BDiff // store off address to length bit sizes
|
||||
sta GetLenBits+1
|
||||
lda z8BDiff+1
|
||||
sta GetLenBits+2
|
||||
ldx z8BLenSize // prefix bits for length
|
||||
jsr BitX // A = 1<<X, does not change Y
|
||||
ldx #z8BDiff // add A to z8BDiff
|
||||
jsr ApplyOffsetA // does not change Y
|
||||
lda z8BDiff // store off address to offset bit sizes
|
||||
sta GetOffsBits+1
|
||||
lda z8BDiff+1
|
||||
sta GetOffsBits+2
|
||||
ldx z8BOffsSize // prefix bits for offset
|
||||
jsr BitX // A = 1<<X, does not change Y
|
||||
ldx #z8BDiff // add A to z8BDiff
|
||||
jsr ApplyOffsetA // does not change Y
|
||||
|
||||
// read out injected bytes size (only up to $7fff supported)
|
||||
lda (z8BDiff),y
|
||||
pha
|
||||
iny
|
||||
lda (z8BDiff),y
|
||||
pha
|
||||
iny
|
||||
ldx #z8BDiff // skip inject size bytes (2)
|
||||
jsr ApplyOffsetY
|
||||
clc
|
||||
lda z8BDiff // store off inject buffer address high
|
||||
sta z8BInj
|
||||
pla
|
||||
adc z8BDiff
|
||||
sta DiffPtr+1 // store off instruction start low
|
||||
sta z8BInjEnd // store off inject buffer end low
|
||||
lda z8BDiff+1
|
||||
sta z8BInj+1 // store off inject buffer address high
|
||||
pla
|
||||
adc z8BDiff+1
|
||||
sta DiffPtr+2 // store off instruction start high
|
||||
sta z8BInjEnd+1 // store off inject buffer end high
|
||||
|
||||
lda z8BDst // store off target buffer
|
||||
sta z8BTrg
|
||||
lda z8BDst+1
|
||||
sta z8BTrg+1
|
||||
|
||||
// read instructions!
|
||||
lda #0 // clear bit shift byte => force fetch
|
||||
NextInstruction:
|
||||
:GetBit() // bit is 0 => inject, otherwise source or target buffer
|
||||
bcs SrcTrg
|
||||
ldx z8BInj // check if complete
|
||||
cpx z8BInjEnd
|
||||
bcc NotEnd
|
||||
ldx z8BInj+1
|
||||
cpx z8BInjEnd+1
|
||||
bcc NotEnd
|
||||
rts // patching is complete, return to caller
|
||||
NotEnd:
|
||||
jsr GetLen // number of bytes to inject y = 0 here
|
||||
pha // save bit shift byte
|
||||
ldx #z8BInj // use inject buffer
|
||||
bne MoveToDest // always branch!
|
||||
// PC will not cross this line
|
||||
SrcTrg:
|
||||
jsr GetLen // number of bytes to copy
|
||||
jsr GetOffs // offset in buffer, y = 0 here
|
||||
:GetBit() // check sign bit
|
||||
bcc PositiveOffs
|
||||
pha
|
||||
lda #$ff // apply negativity to offset
|
||||
eor z8BOff
|
||||
sta z8BOff
|
||||
lda #$ff
|
||||
eor z8BOff+1
|
||||
sta z8BOff+1
|
||||
pla
|
||||
PositiveOffs:
|
||||
:GetBit()
|
||||
ldx #z8BSrc // use source buffer
|
||||
bcc Src
|
||||
ldx #z8BTrg // use target buffer
|
||||
Src:
|
||||
pha // save bit shift byte
|
||||
clc
|
||||
lda z8BOff // apply offset to current buffer
|
||||
adc $00,x
|
||||
sta $00,x
|
||||
lda z8BOff+1
|
||||
adc $01,x
|
||||
sta $01,x
|
||||
|
||||
MoveToDest:
|
||||
stx BufferCopyTrg+1 // x = zero page source buffer to copy from
|
||||
|
||||
PageCopy: // copy pages (256 bytes) at a time
|
||||
dec z8BLen+1
|
||||
bmi PageCopyDone
|
||||
jsr BufferCopy // y is 0 here so copy 256 bytes
|
||||
inc $01,x
|
||||
inc z8BDst+1
|
||||
bne PageCopy
|
||||
// PC will not cross this line
|
||||
PageCopyDone:
|
||||
ldy z8BLen // get remaining number of bytes in y
|
||||
beq NoLowLength
|
||||
jsr BufferCopy
|
||||
lda z8BLen // apply remainder of bytes to buffer
|
||||
jsr ApplyOffsetA
|
||||
lda z8BLen
|
||||
ldx #z8BDst // apply remainder of bytes to destination
|
||||
jsr ApplyOffsetA
|
||||
NoLowLength:
|
||||
pla // retrieve bit shift byte to parse next bit
|
||||
bne NextInstruction
|
||||
// PC will not cross this line
|
||||
|
||||
// BufferCopy copies bytes forward from 0 to y (256 if y is 0)
|
||||
BufferCopy:
|
||||
sty BufferCopyLength+1
|
||||
ldy #0
|
||||
BufferCopyTrg:
|
||||
lda (z8BInj),y
|
||||
sta (z8BDst),y
|
||||
iny
|
||||
BufferCopyLength:
|
||||
cpy #0
|
||||
bne BufferCopyTrg // Y returns unchanged
|
||||
rts
|
||||
|
||||
// Gets Y number of bits and return the value in Y
|
||||
GetLenOffBits:
|
||||
:GetBit()
|
||||
rol z8BTemp
|
||||
dey
|
||||
bne GetLenOffBits
|
||||
ldy z8BTemp
|
||||
rts
|
||||
|
||||
// Gets the next length
|
||||
GetLen:
|
||||
ldy #0
|
||||
sty z8BTemp
|
||||
ldy z8BLenSize
|
||||
jsr GetLenOffBits
|
||||
pha // save bit shift byte
|
||||
GetLenBits:
|
||||
lda $1234,y
|
||||
ldx #z8BLen // X is the zero page address to store in
|
||||
GetLenOffValue:
|
||||
tay
|
||||
lda #0 // clear target indirect address
|
||||
sta $00,x
|
||||
sta $01,x
|
||||
pla // retrieve bit shift byte
|
||||
GetLenOffLoop:
|
||||
:GetBit()
|
||||
rol $00,x
|
||||
rol $01,x
|
||||
dey
|
||||
bne GetLenOffLoop // y returns 0
|
||||
rts
|
||||
|
||||
// Gets the next buffer offset
|
||||
GetOffs:
|
||||
ldy #0
|
||||
sty z8BTemp
|
||||
ldy z8BOffsSize
|
||||
jsr GetLenOffBits
|
||||
pha // save bit shift byte
|
||||
GetOffsBits:
|
||||
lda $1234,y
|
||||
ldx #z8BOff // X is the zero page address to store in
|
||||
bne GetLenOffValue
|
||||
|
||||
// Gets one byte of bits and returns top bit in C
|
||||
GetByte:
|
||||
sec
|
||||
DiffPtr:
|
||||
lda $1234
|
||||
rol
|
||||
inc DiffPtr+1
|
||||
bne DiffPage
|
||||
inc DiffPtr+2
|
||||
DiffPage:
|
||||
rts
|
||||
|
||||
// Returns 1<<X
|
||||
BitX: // does not change Y
|
||||
lda #0
|
||||
sec
|
||||
BitXShift:
|
||||
rol
|
||||
dex
|
||||
bpl BitXShift
|
||||
rts
|
||||
|
||||
// Apply an offset to a zero page indirect address in X
|
||||
ApplyOffsetY:
|
||||
tya
|
||||
ApplyOffsetA:
|
||||
clc
|
||||
adc $00,x
|
||||
sta $00,x
|
||||
bcc ApplyLow
|
||||
inc $01,x
|
||||
ApplyLow:
|
||||
rts
|
42
test/AddrMode_65816.s
Normal file
42
test/AddrMode_65816.s
Normal file
@ -0,0 +1,42 @@
|
||||
cpu 65816
|
||||
Test65816_ForceAddrMode:
|
||||
{
|
||||
jmp >$123456
|
||||
lda >$123456,x
|
||||
lda (<$1234,s),y
|
||||
ora ($21,x)
|
||||
jsr ($2120,x)
|
||||
|
||||
lda [<$1234],y
|
||||
lda (<$1234,x)
|
||||
|
||||
lda <$101030
|
||||
}
|
||||
|
||||
{
|
||||
lda.z $101030 // .z zero page
|
||||
if !((*-!) == 2)
|
||||
err Expected zero page instruction
|
||||
endif
|
||||
}
|
||||
|
||||
{
|
||||
lda.a $101030 // .a force absolute
|
||||
if !((*-!) == 3)
|
||||
err Expected zero page instruction
|
||||
endif
|
||||
}
|
||||
{
|
||||
lda.l $30 // .l force long
|
||||
if !((*-!) == 4)
|
||||
err Expected zero page instruction
|
||||
endif
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
jmp [$1010]
|
||||
}
|
||||
|
||||
rts
|
||||
|
301
test/Test65816_OpCodes.s
Normal file
301
test/Test65816_OpCodes.s
Normal file
@ -0,0 +1,301 @@
|
||||
cpu 65816
|
||||
|
||||
TestOpcodes:
|
||||
|
||||
brk
|
||||
jsr $2120
|
||||
jsr ($2120,x)
|
||||
jsr.l $222120
|
||||
jsl $222120
|
||||
rti
|
||||
rts
|
||||
rtl
|
||||
ora ($21,x)
|
||||
ora $21
|
||||
ora.b #$21
|
||||
ora.w #$2322
|
||||
ora $2120
|
||||
ora ($21),y
|
||||
ora $21,x
|
||||
ora $2120,y
|
||||
ora $2120,x
|
||||
ora ($21)
|
||||
ora [$21]
|
||||
ora [$21],y
|
||||
ora.l $222120
|
||||
ora.l $222120,x
|
||||
ora $21,s
|
||||
ora ($21,s),y
|
||||
and ($21,x)
|
||||
and $21
|
||||
and.b #$21
|
||||
and.w #$2322
|
||||
and $2120
|
||||
and ($21),y
|
||||
and $21,x
|
||||
and $2120,y
|
||||
and $2120,x
|
||||
and ($21)
|
||||
and [$21]
|
||||
and [$21],y
|
||||
and.l $222120
|
||||
and.l $222120,x
|
||||
and $21,s
|
||||
and ($21,s),y
|
||||
eor ($21,x)
|
||||
eor $21
|
||||
eor.b #$21
|
||||
eor.w #$2322
|
||||
eor $2120
|
||||
eor ($21),y
|
||||
eor $21,x
|
||||
eor $2120,y
|
||||
eor $2120,x
|
||||
eor ($21)
|
||||
eor [$21]
|
||||
eor [$21],y
|
||||
eor.l $222120
|
||||
eor.l $222120,x
|
||||
eor $21,s
|
||||
eor ($21,s),y
|
||||
adc ($21,x)
|
||||
adc $21
|
||||
adc.b #$21
|
||||
adc.w #$2322
|
||||
adc $2120
|
||||
adc ($21),y
|
||||
adc $21,x
|
||||
adc $2120,y
|
||||
adc $2120,x
|
||||
adc ($21)
|
||||
adc [$21]
|
||||
adc [$21],y
|
||||
adc.l $222120
|
||||
adc.l $222120,x
|
||||
adc $21,s
|
||||
adc ($21,s),y
|
||||
sta ($21,x)
|
||||
sta $21
|
||||
sta $2120
|
||||
sta ($21),y
|
||||
sta $21,x
|
||||
sta $2120,y
|
||||
sta $2120,x
|
||||
sta ($21)
|
||||
sta [$21]
|
||||
sta [$21],y
|
||||
sta.l $222120
|
||||
sta.l $222120,x
|
||||
sta $21,s
|
||||
sta ($21,s),y
|
||||
lda ($21,x)
|
||||
lda $21
|
||||
lda.b #$21
|
||||
lda.w #$2322
|
||||
lda $2120
|
||||
lda ($21),y
|
||||
lda $21,x
|
||||
lda $2120,y
|
||||
lda $2120,x
|
||||
lda ($21)
|
||||
lda [$21]
|
||||
lda [$21],y
|
||||
lda.l $222120
|
||||
lda.l $222120,x
|
||||
lda $21,s
|
||||
lda ($21,s),y
|
||||
cmp ($21,x)
|
||||
cmp $21
|
||||
cmp.b #$21
|
||||
cmp.w #$2322
|
||||
cmp $2120
|
||||
cmp ($21),y
|
||||
cmp $21,x
|
||||
cmp $2120,y
|
||||
cmp $2120,x
|
||||
cmp ($21)
|
||||
cmp [$21]
|
||||
cmp [$21],y
|
||||
cmp.l $222120
|
||||
cmp.l $222120,x
|
||||
cmp $21,s
|
||||
cmp ($21,s),y
|
||||
sbc ($21,x)
|
||||
sbc $21
|
||||
sbc.b #$21
|
||||
sbc.w #$2322
|
||||
sbc $2120
|
||||
sbc ($21),y
|
||||
sbc $21,x
|
||||
sbc $2120,y
|
||||
sbc $2120,x
|
||||
sbc ($21)
|
||||
sbc [$21]
|
||||
sbc [$21],y
|
||||
sbc.l $222120
|
||||
sbc.l $222120,x
|
||||
sbc $21,s
|
||||
sbc ($21,s),y
|
||||
oral $222120
|
||||
oral $222120,x
|
||||
andl $222120
|
||||
andl $222120,x
|
||||
eorl $222120
|
||||
eorl $222120,x
|
||||
adcl $222120
|
||||
adcl $222120,x
|
||||
stal $222120
|
||||
stal $222120,x
|
||||
ldal $222120
|
||||
ldal $222120,x
|
||||
cmpl $222120
|
||||
cmpl $222120,x
|
||||
sbcl $222120
|
||||
sbcl $222120,x
|
||||
asl $21
|
||||
asl $2120
|
||||
asl $21,x
|
||||
asl $2120,x
|
||||
asl A
|
||||
asl
|
||||
rol $21
|
||||
rol $2120
|
||||
rol $21,x
|
||||
rol $2120,x
|
||||
rol A
|
||||
rol
|
||||
lsr $21
|
||||
lsr $2120
|
||||
lsr $21,x
|
||||
lsr $2120,x
|
||||
lsr A
|
||||
lsr
|
||||
ror $21
|
||||
ror $2120
|
||||
ror $21,x
|
||||
ror $2120,x
|
||||
ror A
|
||||
ror
|
||||
stx $21
|
||||
stx $2120
|
||||
stx $21,y
|
||||
ldx $21
|
||||
ldx.b #$21
|
||||
ldx.w #$2322
|
||||
ldx $2120
|
||||
ldx $21,y
|
||||
ldx $2120,y
|
||||
dec $21
|
||||
dec $2120
|
||||
dec $21,x
|
||||
dec $2120,x
|
||||
dec A
|
||||
dec
|
||||
inc $21
|
||||
inc $2120
|
||||
inc $21,x
|
||||
inc $2120,x
|
||||
inc A
|
||||
inc
|
||||
dea
|
||||
ina
|
||||
php
|
||||
plp
|
||||
pha
|
||||
pla
|
||||
phy
|
||||
ply
|
||||
phx
|
||||
plx
|
||||
dey
|
||||
tay
|
||||
iny
|
||||
inx
|
||||
bpl *+5
|
||||
bmi *+5
|
||||
bvc *+5
|
||||
bvs *+5
|
||||
bra *+5
|
||||
brl $2120
|
||||
bcc *+5
|
||||
bcs *+5
|
||||
bne *+5
|
||||
beq *+5
|
||||
clc
|
||||
sec
|
||||
cli
|
||||
sei
|
||||
tya
|
||||
clv
|
||||
cld
|
||||
sed
|
||||
bit $21
|
||||
bit.b #$21
|
||||
bit.w #$2322
|
||||
bit $2120
|
||||
bit $21,x
|
||||
bit $2120,x
|
||||
stz $21
|
||||
stz $2120
|
||||
stz $21,x
|
||||
stz $2120,x
|
||||
trb $21
|
||||
trb $2120
|
||||
tsb $21
|
||||
tsb $2120
|
||||
jmp $2120
|
||||
jmp ($2120)
|
||||
jmp ($2120,x)
|
||||
jmp.l $222120
|
||||
jmp [$2120]
|
||||
jml.l $222120
|
||||
jml [$2120]
|
||||
sty $21
|
||||
sty $2120
|
||||
sty $21,x
|
||||
ldy $21
|
||||
ldy.b #$21
|
||||
ldy.w #$2322
|
||||
ldy $2120
|
||||
ldy $21,x
|
||||
ldy $2120,x
|
||||
cpy $21
|
||||
cpy.b #$21
|
||||
cpy.w #$2322
|
||||
cpy $2120
|
||||
cpx $21
|
||||
cpx.b #$21
|
||||
cpx.w #$2322
|
||||
cpx $2120
|
||||
txa
|
||||
txs
|
||||
tax
|
||||
tsx
|
||||
dex
|
||||
nop
|
||||
cop
|
||||
wdm
|
||||
mvp $21,$20
|
||||
mvn $21,$20
|
||||
pea $2120
|
||||
pei ($21)
|
||||
per $2120
|
||||
rep $21
|
||||
rep #$21
|
||||
sep $21
|
||||
sep #$21
|
||||
phd
|
||||
tcs
|
||||
pld
|
||||
tsc
|
||||
phk
|
||||
tcd
|
||||
tdc
|
||||
phb
|
||||
txy
|
||||
plb
|
||||
tyx
|
||||
wai
|
||||
stp
|
||||
xba
|
||||
xce
|
4
test/alias_test.s
Normal file
4
test/alias_test.s
Normal file
@ -0,0 +1,4 @@
|
||||
Again
|
||||
rol
|
||||
bge Again
|
||||
blt Again
|
BIN
test/compare/8BitDiff_6502_cmp.prg
Normal file
BIN
test/compare/8BitDiff_6502_cmp.prg
Normal file
Binary file not shown.
BIN
test/compare/alias_test_cmp.prg
Normal file
BIN
test/compare/alias_test_cmp.prg
Normal file
Binary file not shown.
BIN
test/compare/huffman_cmp.prg
Normal file
BIN
test/compare/huffman_cmp.prg
Normal file
Binary file not shown.
1
test/compare/merlin_lup_cmp.bin
Normal file
1
test/compare/merlin_lup_cmp.bin
Normal file
@ -0,0 +1 @@
|
||||
¡O‘îOÐîPÈ¡O‘îOÐîPÈ¡O‘îOÐîPÈ¡O‘îOÐîPÈ¡O‘îOÐîPÈ¡O‘îOÐîPÈ`
|
BIN
test/compare/merlin_macro_cmp.bin
Normal file
BIN
test/compare/merlin_macro_cmp.bin
Normal file
Binary file not shown.
BIN
test/compare/x65macro_test_cmp.prg
Normal file
BIN
test/compare/x65macro_test_cmp.prg
Normal file
Binary file not shown.
13
test/merlin_lup.s
Normal file
13
test/merlin_lup.s
Normal file
@ -0,0 +1,13 @@
|
||||
; merlin_lup.s
|
||||
|
||||
lup 6
|
||||
lda (sprt,x)
|
||||
sta ($06),y
|
||||
inc sprt
|
||||
bne :c0
|
||||
inc sprt+1
|
||||
:c0 iny
|
||||
--^
|
||||
rts
|
||||
|
||||
sprt
|
60
test/merlin_macro.s
Normal file
60
test/merlin_macro.s
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
RAGDAG MAC
|
||||
lda #]1
|
||||
sta ]2
|
||||
bcc :CONT_B
|
||||
jmp ]3
|
||||
:CONT_B
|
||||
EOM
|
||||
|
||||
BEQ_FAR MAC ]1
|
||||
nop
|
||||
{
|
||||
BNE %
|
||||
JMP ]1
|
||||
}
|
||||
nop
|
||||
EOM
|
||||
|
||||
MOCMAC MAC
|
||||
{
|
||||
bvc %
|
||||
jmp ]1
|
||||
}
|
||||
EOM
|
||||
|
||||
|
||||
JUST_NOPNOP MAC
|
||||
nop
|
||||
nop
|
||||
EOM
|
||||
|
||||
RAGDAG 63; $d800; START
|
||||
|
||||
START
|
||||
MOCMAC :NEXT
|
||||
|
||||
JSR INIT
|
||||
|
||||
JUST_NOPNOP
|
||||
|
||||
:CONT LDA #00
|
||||
BEQ_FAR :NEXT
|
||||
|
||||
LDA #00
|
||||
BEQ_FAR :NEXT
|
||||
|
||||
STA TEMP
|
||||
:NEXT
|
||||
JSR REDUCESTARSPEED
|
||||
|
||||
rts
|
||||
|
||||
INIT
|
||||
rts
|
||||
TEMP
|
||||
dc.b 0
|
||||
REDUCESTARSPEED:
|
||||
rts
|
||||
|
||||
|
83
test/unittest.bat
Normal file
83
test/unittest.bat
Normal file
@ -0,0 +1,83 @@
|
||||
@echo off
|
||||
|
||||
echo Unit tests for x65 assembler >unittest.txt
|
||||
echo >>unittest.txt
|
||||
|
||||
echo 65816 OpCodes Test >>unittest.txt
|
||||
..\bin\x64\x65 Test65816_OpCodes.s -cpu=65816 -lst >> unittest.txt
|
||||
if %errorlevel% EQU 0 goto opcodes_65816_pass
|
||||
:opcodes_65816_fail
|
||||
echo 65816 OpCodes failed
|
||||
goto exit
|
||||
:opcodes_65816_pass
|
||||
|
||||
|
||||
echo 65816 Force Addressing Mode Test >>unittest.txt
|
||||
..\bin\x64\x65 AddrMode_65816.s -cpu=65816 -lst >> unittest.txt
|
||||
if %errorlevel% EQU 0 goto addrmode_pass
|
||||
:addrmode_fail
|
||||
echo Force Addressing Mode failed
|
||||
goto exit
|
||||
:addrmode_pass
|
||||
|
||||
echo Merlin Macro Test >>unittest.txt
|
||||
echo ----------------- >>unittest.txt
|
||||
..\bin\x64\x65 merlin_macro.s merlin_macro.bin -bin -org=$1000 -merlin -lst >>unittest.txt
|
||||
if %errorlevel% GTR 0 goto mermac_fail
|
||||
fc /B compare\merlin_macro_cmp.bin merlin_macro.bin >>unittest.txt
|
||||
if %errorlevel% EQU 0 goto mermac_pass
|
||||
:mermac_fail
|
||||
echo Merlin macro test failed
|
||||
goto exit
|
||||
:mermac_pass
|
||||
|
||||
echo 8BitDiff Test >>unittest.txt
|
||||
echo ------------- >>unittest.txt
|
||||
..\bin\x64\x65 8BitDiff_6502.s 8BitDiff_6502.prg -kickasm -sym 8BitDiff_6502.sym -lst >>unittest.txt
|
||||
if %errorlevel% GTR 0 goto 8BitDiff_6502_fail
|
||||
fc /B compare\8BitDiff_6502_cmp.prg 8BitDiff_6502.prg >>unittest.txt
|
||||
if %errorlevel% EQU 0 goto 8BitDiff_6502_pass
|
||||
:8BitDiff_6502_fail
|
||||
echo 8BitDiff_6502 test failed
|
||||
goto exit
|
||||
:8BitDiff_6502_pass
|
||||
|
||||
echo Alias Test >>unittest.txt
|
||||
echo ---------- >>unittest.txt
|
||||
..\bin\x64\x65 alias_test.s alias_test.prg -sym alias_test.sym -lst >>unittest.txt
|
||||
if %errorlevel% GTR 0 goto alias_test_fail
|
||||
fc /B compare\alias_test_cmp.prg alias_test.prg >>unittest.txt
|
||||
if %errorlevel% EQU 0 goto alias_test_pass
|
||||
:alias_test_fail
|
||||
echo Alias test failed
|
||||
goto exit
|
||||
:alias_test_pass
|
||||
|
||||
echo x65macro.i Test >>unittest.txt
|
||||
echo --------------- >>unittest.txt
|
||||
..\bin\x64\x65 x65macro_test.s x65macro_test.prg -org=$1000 -sym x65macro_test.sym -lst >>unittest.txt
|
||||
if %errorlevel% GTR 0 goto x65macro_test_fail
|
||||
fc /B compare\x65macro_test_cmp.prg x65macro_test.prg >>unittest.txt
|
||||
if %errorlevel% EQU 0 goto x65macro_test_pass
|
||||
:x65macro_test_fail
|
||||
echo x65macro.i test failed
|
||||
goto exit
|
||||
:x65macro_test_pass
|
||||
|
||||
echo Merlin LUP Test >>unittest.txt
|
||||
echo --------------- >>unittest.txt
|
||||
..\bin\x64\x65 merlin_lup.s merlin_lup.bin -bin -org=$1000 -merlin -lst >>unittest.txt
|
||||
if %errorlevel% GTR 0 goto merlup_fail
|
||||
fc /B compare\merlin_lup_cmp.bin merlin_lup.bin >>unittest.txt
|
||||
if %errorlevel% EQU 0 goto merlup_pass
|
||||
:merlup_fail
|
||||
echo Merlin LUP test failed
|
||||
goto exit
|
||||
:merlup_pass
|
||||
|
||||
|
||||
echo All Tests Passed
|
||||
goto exit
|
||||
|
||||
|
||||
:exit
|
53
test/x65macro_test.s
Normal file
53
test/x65macro_test.s
Normal file
@ -0,0 +1,53 @@
|
||||
include "../macros/x65macro.i"
|
||||
|
||||
sec
|
||||
bcs Begin
|
||||
|
||||
CopyCode
|
||||
inx
|
||||
dey
|
||||
nop
|
||||
CodeEnd
|
||||
|
||||
CodeSegLen = CodeEnd-CopyCode
|
||||
; $fc = CopyCode
|
||||
; for ($fe=$2000; $fe<$4000; $fe += (CodeEnd-CopyCode)) {
|
||||
; memcpy($fe, $fc, CodeEnd-CopyCode)
|
||||
; }
|
||||
Begin:
|
||||
set.w CopyCode, $fc
|
||||
for.wsp $2000, $4000, $fe, CodeSegLen
|
||||
copy.ry128 $fc, $fe, CodeSegLen
|
||||
forend
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
; int $fc
|
||||
; $fc >>= 1
|
||||
asrm.n $fc,4
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldx #$0c
|
||||
aslm.nx $f0,4
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
; int $fc
|
||||
; $fc = -$fc
|
||||
|
||||
neg.n $fc,4
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
; int $fc = abs($fc)
|
||||
abs.n $fc, 4
|
||||
|
153
x65.cpp
153
x65.cpp
@ -74,6 +74,7 @@
|
||||
// ruleset can be specified on the command line.
|
||||
enum AsmSyntax {
|
||||
SYNTAX_SANE,
|
||||
SYNTAX_KICKASM,
|
||||
SYNTAX_MERLIN
|
||||
};
|
||||
|
||||
@ -114,6 +115,7 @@ enum StatusCode {
|
||||
ERROR_DS_MUST_EVALUATE_IMMEDIATELY,
|
||||
ERROR_NOT_AN_X65_OBJECT_FILE,
|
||||
ERROR_COULD_NOT_INCLUDE_FILE,
|
||||
ERROR_USER,
|
||||
|
||||
ERROR_STOP_PROCESSING_ON_HIGHER, // errors greater than this will stop execution
|
||||
|
||||
@ -185,6 +187,7 @@ const char *aStatusStrings[STATUSCODE_COUNT] = {
|
||||
"DS directive failed to evaluate immediately",
|
||||
"File is not a valid x65 object file",
|
||||
"Failed to read include file",
|
||||
"User invoked error",
|
||||
|
||||
"Errors after this point will stop execution",
|
||||
|
||||
@ -276,6 +279,7 @@ enum AssemblerDirective {
|
||||
AD_ENT, // ENT: MERLIN extern this address label
|
||||
AD_EXT, // EXT: MERLIN reference this address label from a different file
|
||||
AD_CYC, // CYC: MERLIN start / stop cycle timer
|
||||
AD_ERROR,
|
||||
};
|
||||
|
||||
// Operators are either instructions or directives
|
||||
@ -864,7 +868,7 @@ static const int nCPUs = sizeof(aCPUs) / sizeof(aCPUs[0]);
|
||||
// hardtexted strings
|
||||
static const strref c_comment("//");
|
||||
static const strref word_char_range("!0-9a-zA-Z_@$!#");
|
||||
static const strref label_end_char_range("!0-9a-zA-Z_@$!.");
|
||||
static const strref label_end_char_range("!0-9a-zA-Z_@$!.!:");
|
||||
static const strref label_end_char_range_merlin("!0-9a-zA-Z_@$]:?");
|
||||
static const strref filename_end_char_range("!0-9a-zA-Z_!@#$%&()/\\-.");
|
||||
static const strref keyword_equ("equ");
|
||||
@ -908,7 +912,7 @@ static const char *str_section_type[] = {
|
||||
"CODE", // default type
|
||||
"DATA", // data section (matters for GS/OS OMF)
|
||||
"BSS", // uninitialized data section
|
||||
"ZEROPAGE" // ununitialized data section in zero page / direct page
|
||||
"ZEROPAGE" // uninitialized data section in zero page / direct page
|
||||
};
|
||||
static const int num_section_type_str = sizeof(str_section_type) / sizeof(str_section_type[0]);
|
||||
|
||||
@ -1686,6 +1690,7 @@ public:
|
||||
|
||||
// Syntax
|
||||
bool Merlin() const { return syntax == SYNTAX_MERLIN; }
|
||||
bool KickAsm() const { return syntax == SYNTAX_KICKASM; }
|
||||
|
||||
// constructor
|
||||
Asm() : opcode_table(opcodes_6502), opcode_count(num_opcodes_6502), num_instructions(0),
|
||||
@ -5261,37 +5266,134 @@ StatusCode Asm::GetAddressMode(strref line, bool flipXY, uint32_t &validModes, A
|
||||
bool force_24 = false;
|
||||
bool force_abs = false;
|
||||
bool need_more = true;
|
||||
bool first = true;
|
||||
strref arg, deco;
|
||||
|
||||
len = 0;
|
||||
while (need_more) {
|
||||
need_more = false;
|
||||
line.skip_whitespace();
|
||||
uint8_t c = line.get_first();
|
||||
if (!c)
|
||||
addrMode = AMB_NON;
|
||||
else if (!force_abs && (c == '[' || (c == '(' &&
|
||||
(validModes&(AMM_REL | AMM_REL_X | AMM_ZP_REL | AMM_ZP_REL_X | AMM_ZP_Y_REL))))) {
|
||||
deco = line.scoped_block_skip();
|
||||
line.skip_whitespace();
|
||||
expression = deco.split_token_trim(',');
|
||||
addrMode = c == '[' ? (force_zp ? AMB_ZP_REL_L : AMB_REL_L) : (force_zp ? AMB_ZP_REL : AMB_REL);
|
||||
if (strref::tolower(deco[0]) == 'x')
|
||||
addrMode = c == '[' ? AMB_ILL : AMB_ZP_REL_X;
|
||||
else if (line[0] == ',') {
|
||||
++line;
|
||||
line.skip_whitespace();
|
||||
if (strref::tolower(line[0]) == 'y') {
|
||||
if (strref::tolower(deco[0]) == 's')
|
||||
addrMode = AMB_STK_REL_Y;
|
||||
else
|
||||
addrMode = c == '[' ? AMB_ZP_REL_Y_L : AMB_ZP_Y_REL;
|
||||
++line;
|
||||
if (!c) { addrMode = AMB_NON; }
|
||||
if( c == '[' || c == '(' ) {
|
||||
strref block_suffix( line.get(), line.scoped_block_comment_len() );
|
||||
strref suffix = line.get_skipped( block_suffix.get_len() );
|
||||
suffix.trim_whitespace();
|
||||
if( suffix.get_first() == ',' ) { ++suffix; suffix.skip_whitespace(); }
|
||||
else { suffix.clear(); }
|
||||
++block_suffix; block_suffix.clip(1); block_suffix.trim_whitespace();
|
||||
++line; line.skip_whitespace();
|
||||
strref block = block_suffix.split_token_trim( ',' );
|
||||
validModes &= AMM_ZP_REL_X | AMM_ZP_Y_REL | AMM_REL | AMM_ZP_REL | AMM_REL_X | AMM_ZP_REL_L | AMM_ZP_REL_Y_L | AMM_STK_REL_Y | AMM_REL_L;
|
||||
if( line.get_first() == '>' ) { // [>$aaaa]
|
||||
if( c == '[' ) { addrMode = AMB_REL_L; validModes &= AMM_REL_L; expression = block+1; }
|
||||
} else if( line.get_first() == '|' || line.get_first() == '!' && c == '(' ) { // (|$aaaa) or (|$aaaa,x)
|
||||
strref arg = block.after( ',' ); arg.skip_whitespace();
|
||||
if( arg && ( arg.get_first() == 'x' || arg.get_first() == 'X' ) ) {
|
||||
addrMode = AMB_REL_X; validModes &= AMM_REL_X; expression = block.before( ',' ); }
|
||||
else { addrMode = AMB_REL; validModes &= AMM_REL; expression = block; }
|
||||
} else if( line.get_first() == '<' ) { // (<$aa) (<$aa),y (<$aa,x) (<$aa,s),y [<$aa] [<$aa],y
|
||||
if( suffix ) {
|
||||
if( suffix.get_first() == 'y' || suffix.get_first() == 'Y' ) {
|
||||
if( c == '(' ) { // (<$aa),y or (<$aa,s),y
|
||||
if( block_suffix && ( block_suffix.get_first() == 's' || block_suffix.get_first() == 'S' ) ) {
|
||||
expression = block+1;
|
||||
addrMode = AMB_STK_REL_Y; validModes &= AMM_STK_REL_Y;
|
||||
} else {
|
||||
expression = block+1;
|
||||
addrMode = AMB_ZP_Y_REL; validModes &= AMM_ZP_Y_REL;
|
||||
}
|
||||
} else { // [<$aa],y
|
||||
expression = block+1;
|
||||
addrMode = AMB_ZP_REL_Y_L; validModes &= AMM_ZP_REL_Y_L;
|
||||
}
|
||||
} else { return ERROR_BAD_ADDRESSING_MODE; }
|
||||
} else { // (<$aa) (<$aa,x) [<$aa]
|
||||
if( c == '[' ) {
|
||||
if( block.find( ',' ) >= 0 || suffix.get_first() == ',' ) { return ERROR_BAD_ADDRESSING_MODE; }
|
||||
expression = block+1;
|
||||
addrMode = AMB_ZP_REL_L; validModes &= AMM_ZP_REL_L;
|
||||
} else {
|
||||
if( block_suffix ) {
|
||||
if( block_suffix.get_first() != 'x' && block_suffix.get_first() != 'X' ) { return ERROR_BAD_ADDRESSING_MODE; }
|
||||
expression = block+1;
|
||||
addrMode = AMB_ZP_REL_X; validModes &= AMM_ZP_REL_X;
|
||||
} else {
|
||||
expression = block+1;
|
||||
addrMode = AMB_ZP_REL; validModes &= AMM_ZP_REL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // no <, |, ! or > decorator inside (...) or [...]
|
||||
if( c == '[' && ( block_suffix.get_first() == 's' || block_suffix.get_first() == 'S' ) ) {
|
||||
if( suffix.get_first() == 'y' || suffix.get_first() == 'Y' ) {
|
||||
expression = block;
|
||||
addrMode = AMB_STK_REL_Y; validModes &= AMM_STK_REL_Y;
|
||||
} else { return ERROR_BAD_ADDRESSING_MODE; }
|
||||
} else if( block_suffix.get_first() == 'x' || block_suffix.get_first() == 'X' ) { // ($aa,x) ($aaaa,x)
|
||||
if( c == '[' ) { return ERROR_BAD_ADDRESSING_MODE; }
|
||||
expression = block;
|
||||
switch( validModes & ( AMM_ZP_REL_X | AMM_REL_X ) ) {
|
||||
case AMM_ZP_REL_X: addrMode = AMB_ZP_REL_X; validModes = AMM_ZP_REL_X; break;
|
||||
case AMM_REL_X: addrMode = AMB_REL_X; validModes = AMM_REL_X; break;
|
||||
default: addrMode = force_zp ? AMB_ZP_REL_X : AMB_REL_X; validModes &= force_zp ? AMM_ZP_REL_X : ( force_abs ? AMM_ZP_REL_X : ( AMM_ZP_REL_X | AMM_REL_X ) );
|
||||
break;
|
||||
}
|
||||
} else if( suffix && ( suffix.get_first() == 'y' || suffix.get_first() == 'Y' ) ) {
|
||||
if( c == '[' ) {
|
||||
expression = block;
|
||||
addrMode = AMB_ZP_REL_Y_L; validModes &= AMM_ZP_REL_Y_L;
|
||||
} else { // ($aa),y
|
||||
expression = block;
|
||||
addrMode = AMB_ZP_Y_REL; validModes &= AMM_ZP_Y_REL;
|
||||
}
|
||||
} else { // ($aa), ($aaaa), [$aa], [$aaaa]
|
||||
if( c == '[' ) { // [$aa], [$aaaa]
|
||||
expression = block;
|
||||
addrMode = force_zp ? AMB_ZP_REL_L : AMB_REL_L; validModes &= force_zp ? AMM_ZP_REL_L : ( force_abs ? AMM_REL_L : ( AMM_ZP_REL_L | AMM_REL_L ) );
|
||||
}
|
||||
else { // ($aa), ($aaaa)
|
||||
expression = block;
|
||||
addrMode = force_zp ? AMB_ZP_REL : AMB_REL; validModes &= force_zp ? AMM_ZP_REL : ( force_abs ? AMM_REL : ( AMM_ZP_REL | AMM_REL ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
expression.trim_whitespace();
|
||||
} else if (c == '<' ) { // force zero page not indirect
|
||||
++line; line.trim_whitespace();
|
||||
strref suffix = line.after(','); suffix.skip_whitespace();
|
||||
expression = line.before_or_full(','); expression.trim_whitespace();
|
||||
if( suffix ) {
|
||||
if( suffix.get_first() == 's' || suffix.get_first() == 'S' ) {
|
||||
addrMode = AMB_STK; validModes &= AMM_STK; // not correct usage of < but I'll allow it.
|
||||
} else if( suffix.get_first() == 'x' || suffix.get_first() == 'X' ) {
|
||||
addrMode = AMB_ZP_X; validModes &= AMM_ZP_X;
|
||||
} else { return ERROR_BAD_ADDRESSING_MODE; }
|
||||
} else {
|
||||
addrMode = AMB_ZP; validModes &= AMM_ZP;
|
||||
}
|
||||
} else if( c == '>' ) {
|
||||
++line; line.trim_whitespace();
|
||||
strref suffix = line.after( ',' ); suffix.skip_whitespace();
|
||||
expression = line.before_or_full( ',' ); expression.trim_whitespace();
|
||||
if( suffix ) {
|
||||
if( suffix.get_first() == 'x' || suffix.get_first() == 'X' ) {
|
||||
addrMode = AMB_ABS_L_X; validModes &= AMM_ABS_L_X;
|
||||
}
|
||||
else { return ERROR_BAD_ADDRESSING_MODE; }
|
||||
}
|
||||
else {
|
||||
addrMode = AMB_ABS_L; validModes &= AMM_ABS_L;
|
||||
}
|
||||
|
||||
} else if (c == '#') {
|
||||
++line;
|
||||
addrMode = AMB_IMM;
|
||||
validModes &= AMM_IMM;
|
||||
expression = line;
|
||||
} else if (c == '<') {
|
||||
validModes &= AMM_ZP | AMM_ZP_X | AMM_ZP_REL_X | AMM_ZP_Y_REL |
|
||||
AMM_ZP_REL | AMM_ZP_ABS | AMM_ZP_REL_L | AMM_ZP_REL_Y_L | AMM_FLIPXY;
|
||||
} else if (line) {
|
||||
if (line[0]=='.' && strref::is_ws(line[2])) {
|
||||
switch (strref::tolower(line[1])) {
|
||||
@ -5309,6 +5411,8 @@ StatusCode Asm::GetAddressMode(strref line, bool flipXY, uint32_t &validModes, A
|
||||
addrMode = force_24 ? AMB_ABS_L : (force_zp ? AMB_ZP : AMB_ABS);
|
||||
expression = line.split_token_trim(',');
|
||||
if( force_abs ) { validModes &= AMM_ABS | AMM_ABS_X | AMM_ABS_Y | AMM_REL | AMM_REL_X; }
|
||||
if( force_zp ) { validModes &= AMM_ZP | AMM_ZP_X | AMM_ZP_REL_X | AMM_ZP_Y_REL |
|
||||
AMM_ZP_REL | AMM_ZP_ABS | AMM_ZP_REL_L | AMM_ZP_REL_Y_L | AMM_FLIPXY; }
|
||||
if( line && (line[ 0 ] == 's' || line[ 0 ] == 'S') ) { addrMode = AMB_STK; }
|
||||
else {
|
||||
bool relX = line && (line[0]=='x' || line[0]=='X');
|
||||
@ -5323,6 +5427,7 @@ StatusCode Asm::GetAddressMode(strref line, bool flipXY, uint32_t &validModes, A
|
||||
}
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
@ -5629,16 +5734,17 @@ StatusCode Asm::BuildLine(strref line) {
|
||||
line = line.before_or_full(';'); // clip any line comments
|
||||
line = line.before_or_full(c_comment);
|
||||
line.clip_trailing_whitespace();
|
||||
if (line[0]==':'&&!Merlin()) { ++line; } // Kick Assembler macro prefix (incompatible with merlin)
|
||||
if (KickAsm()&&line.get_first()==':') { ++line; } // Kick Assembler macro prefix (incompatible with merlin and sane syntax)
|
||||
strref line_nocom = line;
|
||||
strref operation = line.split_range(Merlin() ? label_end_char_range_merlin : label_end_char_range);
|
||||
if( operation.get_last() == ':' ) { operation.clip( 1 ); }
|
||||
char char1 = operation[0]; // first char of first word
|
||||
char charE = operation.get_last(); // end char of first word
|
||||
line.trim_whitespace();
|
||||
bool force_label = charE==':' || charE=='$';
|
||||
if (!force_label && Merlin()&&(line||operation)) { // MERLIN fixes and PoP does some naughty stuff like 'and = 0'
|
||||
force_label = (!strref::is_ws(char0)&&char0!='{' && char0!='}')||char1==']'||charE=='?';
|
||||
} else if (!Merlin()&&line[0]==':') { force_label = true; }
|
||||
} /*else if (!Merlin()&&line[0]==':') { force_label = true; }*/
|
||||
if (!operation && !force_label) {
|
||||
if (ConditionalAsm()) {
|
||||
// scope open / close
|
||||
@ -7023,6 +7129,7 @@ int main(int argc, char **argv) {
|
||||
if (argv[a][0]=='-') {
|
||||
strref arg(argv[a]+1);
|
||||
if (arg.get_first()=='i') { assembler.AddIncludeFolder(arg+1); }
|
||||
else if (arg.same_str("kickasm") ) { assembler.syntax = SYNTAX_KICKASM; }
|
||||
else if (arg.same_str("merlin")) { assembler.syntax = SYNTAX_MERLIN; }
|
||||
else if (arg.get_first()=='D'||arg.get_first()=='d') {
|
||||
++arg;
|
||||
|
Loading…
Reference in New Issue
Block a user