mirror of
https://github.com/ksherlock/x65.git
synced 2025-01-01 15:30:06 +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
|
lda Trg+Size-1
|
||||||
asl
|
asl
|
||||||
rept Size {
|
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
|
lda Trg+Size-1,x
|
||||||
asl
|
asl
|
||||||
rept Size {
|
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)
|
if (Size<256)
|
||||||
copy.x Src,Trg,Size
|
copy.x Src,Trg,Size
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PoolZP zpSrc.w
|
PoolZP zpSrc.w
|
||||||
PoolZP zpTrg.w
|
PoolZP zpTrg.w
|
||||||
@ -535,7 +535,7 @@ macro copy.zp Src,Trg,Size,zpTmp1,zpTmp2
|
|||||||
{
|
{
|
||||||
if (Size<256)
|
if (Size<256)
|
||||||
copy.x Src,Trg,Size
|
copy.x Src,Trg,Size
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set.w zpTmp1,Src
|
set.w zpTmp1,Src
|
||||||
set.w zpTmp2,Trg
|
set.w zpTmp2,Trg
|
||||||
@ -575,7 +575,7 @@ macro copy.a Src,Trg,Size
|
|||||||
{
|
{
|
||||||
if (Size<256)
|
if (Size<256)
|
||||||
copy.x Src,Trg,Size
|
copy.x Src,Trg,Size
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set.b >Src, ._addr+2
|
set.b >Src, ._addr+2
|
||||||
set.b >Trg, ._addr+5
|
set.b >Trg, ._addr+5
|
||||||
|
@ -72,22 +72,22 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
@ -72,23 +72,23 @@
|
|||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)$(Configuration)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
<OutDir>$(SolutionDir)..\bin\$(Platform)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)\</IntDir>
|
<IntDir>$(SolutionDir)..\obj\$(Platform)$(Configuration)$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<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.
|
// ruleset can be specified on the command line.
|
||||||
enum AsmSyntax {
|
enum AsmSyntax {
|
||||||
SYNTAX_SANE,
|
SYNTAX_SANE,
|
||||||
|
SYNTAX_KICKASM,
|
||||||
SYNTAX_MERLIN
|
SYNTAX_MERLIN
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,6 +115,7 @@ enum StatusCode {
|
|||||||
ERROR_DS_MUST_EVALUATE_IMMEDIATELY,
|
ERROR_DS_MUST_EVALUATE_IMMEDIATELY,
|
||||||
ERROR_NOT_AN_X65_OBJECT_FILE,
|
ERROR_NOT_AN_X65_OBJECT_FILE,
|
||||||
ERROR_COULD_NOT_INCLUDE_FILE,
|
ERROR_COULD_NOT_INCLUDE_FILE,
|
||||||
|
ERROR_USER,
|
||||||
|
|
||||||
ERROR_STOP_PROCESSING_ON_HIGHER, // errors greater than this will stop execution
|
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",
|
"DS directive failed to evaluate immediately",
|
||||||
"File is not a valid x65 object file",
|
"File is not a valid x65 object file",
|
||||||
"Failed to read include file",
|
"Failed to read include file",
|
||||||
|
"User invoked error",
|
||||||
|
|
||||||
"Errors after this point will stop execution",
|
"Errors after this point will stop execution",
|
||||||
|
|
||||||
@ -276,6 +279,7 @@ enum AssemblerDirective {
|
|||||||
AD_ENT, // ENT: MERLIN extern this address label
|
AD_ENT, // ENT: MERLIN extern this address label
|
||||||
AD_EXT, // EXT: MERLIN reference this address label from a different file
|
AD_EXT, // EXT: MERLIN reference this address label from a different file
|
||||||
AD_CYC, // CYC: MERLIN start / stop cycle timer
|
AD_CYC, // CYC: MERLIN start / stop cycle timer
|
||||||
|
AD_ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Operators are either instructions or directives
|
// Operators are either instructions or directives
|
||||||
@ -864,7 +868,7 @@ static const int nCPUs = sizeof(aCPUs) / sizeof(aCPUs[0]);
|
|||||||
// hardtexted strings
|
// hardtexted strings
|
||||||
static const strref c_comment("//");
|
static const strref c_comment("//");
|
||||||
static const strref word_char_range("!0-9a-zA-Z_@$!#");
|
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 label_end_char_range_merlin("!0-9a-zA-Z_@$]:?");
|
||||||
static const strref filename_end_char_range("!0-9a-zA-Z_!@#$%&()/\\-.");
|
static const strref filename_end_char_range("!0-9a-zA-Z_!@#$%&()/\\-.");
|
||||||
static const strref keyword_equ("equ");
|
static const strref keyword_equ("equ");
|
||||||
@ -908,7 +912,7 @@ static const char *str_section_type[] = {
|
|||||||
"CODE", // default type
|
"CODE", // default type
|
||||||
"DATA", // data section (matters for GS/OS OMF)
|
"DATA", // data section (matters for GS/OS OMF)
|
||||||
"BSS", // uninitialized data section
|
"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]);
|
static const int num_section_type_str = sizeof(str_section_type) / sizeof(str_section_type[0]);
|
||||||
|
|
||||||
@ -1686,6 +1690,7 @@ public:
|
|||||||
|
|
||||||
// Syntax
|
// Syntax
|
||||||
bool Merlin() const { return syntax == SYNTAX_MERLIN; }
|
bool Merlin() const { return syntax == SYNTAX_MERLIN; }
|
||||||
|
bool KickAsm() const { return syntax == SYNTAX_KICKASM; }
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
Asm() : opcode_table(opcodes_6502), opcode_count(num_opcodes_6502), num_instructions(0),
|
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_24 = false;
|
||||||
bool force_abs = false;
|
bool force_abs = false;
|
||||||
bool need_more = true;
|
bool need_more = true;
|
||||||
|
bool first = true;
|
||||||
strref arg, deco;
|
strref arg, deco;
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
while (need_more) {
|
while (need_more) {
|
||||||
need_more = false;
|
need_more = false;
|
||||||
|
line.skip_whitespace();
|
||||||
uint8_t c = line.get_first();
|
uint8_t c = line.get_first();
|
||||||
if (!c)
|
if (!c) { addrMode = AMB_NON; }
|
||||||
addrMode = AMB_NON;
|
if( c == '[' || c == '(' ) {
|
||||||
else if (!force_abs && (c == '[' || (c == '(' &&
|
strref block_suffix( line.get(), line.scoped_block_comment_len() );
|
||||||
(validModes&(AMM_REL | AMM_REL_X | AMM_ZP_REL | AMM_ZP_REL_X | AMM_ZP_Y_REL))))) {
|
strref suffix = line.get_skipped( block_suffix.get_len() );
|
||||||
deco = line.scoped_block_skip();
|
suffix.trim_whitespace();
|
||||||
line.skip_whitespace();
|
if( suffix.get_first() == ',' ) { ++suffix; suffix.skip_whitespace(); }
|
||||||
expression = deco.split_token_trim(',');
|
else { suffix.clear(); }
|
||||||
addrMode = c == '[' ? (force_zp ? AMB_ZP_REL_L : AMB_REL_L) : (force_zp ? AMB_ZP_REL : AMB_REL);
|
++block_suffix; block_suffix.clip(1); block_suffix.trim_whitespace();
|
||||||
if (strref::tolower(deco[0]) == 'x')
|
++line; line.skip_whitespace();
|
||||||
addrMode = c == '[' ? AMB_ILL : AMB_ZP_REL_X;
|
strref block = block_suffix.split_token_trim( ',' );
|
||||||
else if (line[0] == ',') {
|
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;
|
||||||
++line;
|
if( line.get_first() == '>' ) { // [>$aaaa]
|
||||||
line.skip_whitespace();
|
if( c == '[' ) { addrMode = AMB_REL_L; validModes &= AMM_REL_L; expression = block+1; }
|
||||||
if (strref::tolower(line[0]) == 'y') {
|
} else if( line.get_first() == '|' || line.get_first() == '!' && c == '(' ) { // (|$aaaa) or (|$aaaa,x)
|
||||||
if (strref::tolower(deco[0]) == 's')
|
strref arg = block.after( ',' ); arg.skip_whitespace();
|
||||||
addrMode = AMB_STK_REL_Y;
|
if( arg && ( arg.get_first() == 'x' || arg.get_first() == 'X' ) ) {
|
||||||
else
|
addrMode = AMB_REL_X; validModes &= AMM_REL_X; expression = block.before( ',' ); }
|
||||||
addrMode = c == '[' ? AMB_ZP_REL_Y_L : AMB_ZP_Y_REL;
|
else { addrMode = AMB_REL; validModes &= AMM_REL; expression = block; }
|
||||||
++line;
|
} 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 == '#') {
|
} else if (c == '#') {
|
||||||
++line;
|
++line;
|
||||||
addrMode = AMB_IMM;
|
addrMode = AMB_IMM;
|
||||||
|
validModes &= AMM_IMM;
|
||||||
expression = line;
|
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) {
|
} else if (line) {
|
||||||
if (line[0]=='.' && strref::is_ws(line[2])) {
|
if (line[0]=='.' && strref::is_ws(line[2])) {
|
||||||
switch (strref::tolower(line[1])) {
|
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);
|
addrMode = force_24 ? AMB_ABS_L : (force_zp ? AMB_ZP : AMB_ABS);
|
||||||
expression = line.split_token_trim(',');
|
expression = line.split_token_trim(',');
|
||||||
if( force_abs ) { validModes &= AMM_ABS | AMM_ABS_X | AMM_ABS_Y | AMM_REL | AMM_REL_X; }
|
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; }
|
if( line && (line[ 0 ] == 's' || line[ 0 ] == 'S') ) { addrMode = AMB_STK; }
|
||||||
else {
|
else {
|
||||||
bool relX = line && (line[0]=='x' || line[0]=='X');
|
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;
|
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(';'); // clip any line comments
|
||||||
line = line.before_or_full(c_comment);
|
line = line.before_or_full(c_comment);
|
||||||
line.clip_trailing_whitespace();
|
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 line_nocom = line;
|
||||||
strref operation = line.split_range(Merlin() ? label_end_char_range_merlin : label_end_char_range);
|
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 char1 = operation[0]; // first char of first word
|
||||||
char charE = operation.get_last(); // end char of first word
|
char charE = operation.get_last(); // end char of first word
|
||||||
line.trim_whitespace();
|
line.trim_whitespace();
|
||||||
bool force_label = charE==':' || charE=='$';
|
bool force_label = charE==':' || charE=='$';
|
||||||
if (!force_label && Merlin()&&(line||operation)) { // MERLIN fixes and PoP does some naughty stuff like 'and = 0'
|
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=='?';
|
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 (!operation && !force_label) {
|
||||||
if (ConditionalAsm()) {
|
if (ConditionalAsm()) {
|
||||||
// scope open / close
|
// scope open / close
|
||||||
@ -7023,6 +7129,7 @@ int main(int argc, char **argv) {
|
|||||||
if (argv[a][0]=='-') {
|
if (argv[a][0]=='-') {
|
||||||
strref arg(argv[a]+1);
|
strref arg(argv[a]+1);
|
||||||
if (arg.get_first()=='i') { assembler.AddIncludeFolder(arg+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.same_str("merlin")) { assembler.syntax = SYNTAX_MERLIN; }
|
||||||
else if (arg.get_first()=='D'||arg.get_first()=='d') {
|
else if (arg.get_first()=='D'||arg.get_first()=='d') {
|
||||||
++arg;
|
++arg;
|
||||||
|
Loading…
Reference in New Issue
Block a user