1
0
mirror of https://github.com/zellyn/go6502.git synced 2024-09-29 23:54:38 +00:00
go6502/asm/flavors/tests/simple_parse_test.go

304 lines
12 KiB
Go
Raw Normal View History

2014-03-05 01:42:51 +00:00
package flavors
import (
"encoding/hex"
"testing"
2014-05-08 00:44:03 +00:00
"github.com/zellyn/go6502/asm/flavors"
2014-03-05 01:42:51 +00:00
"github.com/zellyn/go6502/asm/flavors/as65"
"github.com/zellyn/go6502/asm/flavors/merlin"
2014-05-23 23:53:46 +00:00
"github.com/zellyn/go6502/asm/flavors/redbook"
2014-03-05 01:42:51 +00:00
"github.com/zellyn/go6502/asm/flavors/scma"
"github.com/zellyn/go6502/asm/lines"
)
func TestSimpleCommonFunctions(t *testing.T) {
ss := scma.New()
2014-06-04 15:35:31 +00:00
ra := redbook.NewRedbookA()
rb := redbook.NewRedbookB()
// aa := as65.New()
2014-06-13 00:39:48 +00:00
mm := merlin.New()
2014-03-05 01:42:51 +00:00
tests := []struct {
2014-05-08 00:44:03 +00:00
a flavors.F // assembler flavor
i string // input string
p string // printed instruction, expected
b string // bytes, expected
2014-03-05 01:42:51 +00:00
}{
2014-06-13 00:39:48 +00:00
// {aa, " beq $2343", "{BEQ/rel $2343}", "f0fc"},
// {aa, " beq $2345", "{BEQ/rel $2345}", "f0fe"},
// {aa, " beq $2347", "{BEQ/rel $2347}", "f000"},
// {aa, " dw $1234", "{data/wle $1234}", "3412"},
// {aa, " jmp $1234", "{JMP/abs $1234}", "4c3412"},
// {aa, " jmp ($1234)", "{JMP/ind $1234}", "6c3412"},
// {aa, " lda #$12", "{LDA/imm (lsb $0012)}", "a912"},
// {aa, " lda $12", "{LDA/zp $0012}", "a512"},
// {aa, " lda $12,x", "{LDA/zpX $0012}", "b512"},
// {aa, " lda $1234", "{LDA/abs $1234}", "ad3412"},
// {aa, " lda $1234,x", "{LDA/absX $1234}", "bd3412"},
// {aa, " lda ($12),y", "{LDA/indY $0012}", "b112"},
// {aa, " lda ($12,x)", "{LDA/indX $0012}", "a112"},
// {aa, " ldx $12,y", "{LDX/zpY $0012}", "b612"},
// {aa, " org $D000", "{org $d000}", ""},
// {aa, " rol $12", "{ROL/zp $0012}", "2612"},
// {aa, " rol $1234", "{ROL/abs $1234}", "2e3412"},
// {aa, " rol a", "{ROL/a}", "2a"},
// {aa, " sta $1234,y", "{STA/absY $1234}", "993412"},
2014-06-04 15:35:31 +00:00
// {aa, "; Comment", "{-}", ""},
// {aa, "Label", "{- 'Label'}", ""},
// {aa, ` include "FILE.NAME"`, "{inc 'FILE.NAME'}", ""},
// {aa, ` title "Title here"`, "{-}", ""},
2014-03-05 01:42:51 +00:00
// {ss, " .TA *-1234", "{target (- * $04d2)}", ""},
2014-06-13 00:39:48 +00:00
{mm, " >>> M1,$42 ;$43", `{call M1 {"$42"}}`, ""},
{mm, " >>> M1.$42", `{call M1 {"$42"}}`, ""},
{mm, " >>> M1/$42;$43", `{call M1 {"$42", "$43"}}`, ""},
{mm, " BEQ $2343", "{BEQ/rel $2343}", "f0fc"},
{mm, " BEQ $2345", "{BEQ/rel $2345}", "f0fe"},
{mm, " BEQ $2347", "{BEQ/rel $2347}", "f000"},
{mm, " DA $12,$34,$1234", "{data/wle $0012,$0034,$1234}", "120034003412"},
2014-06-19 04:57:17 +00:00
{mm, " DA $1234", "{data/wle $1234}", "3412"},
2014-06-13 00:39:48 +00:00
{mm, " DDB $12,$34,$1234", "{data/wbe $0012,$0034,$1234}", "001200341234"},
{mm, " DFB $12,$34,$1234", "{data/b $0012,$0034,$1234}", "123434"},
{mm, " DFB $34,100,$81A2-$77C4,%1011,>$81A2-$77C4", "{data/b $0034,$0064,(- $81a2 $77c4),$000b,(msb (- $81a2 $77c4))}", "3464de0b09"},
{mm, " DSK OUTFILE", "{-}", ""},
{mm, " HEX 00,01,FF,AB", "{data/b}", "0001ffab"},
{mm, " HEX 0001FFAB", "{data/b}", "0001ffab"},
2014-06-19 04:57:17 +00:00
{mm, " INCW $42;$43", `{call INCW {"$42", "$43"}}`, ""},
2014-06-13 00:39:48 +00:00
{mm, " JMP $1234", "{JMP/abs $1234}", "4c3412"},
{mm, " JMP ($1234)", "{JMP/ind $1234}", "6c3412"},
{mm, " LDA #$12", "{LDA/imm (lsb $0012)}", "a912"},
2014-06-19 04:57:17 +00:00
{mm, " LDA #$1234", "{LDA/imm (lsb $1234)}", "a934"},
{mm, " LDA #/$1234", "{LDA/imm (msb $1234)}", "a912"},
{mm, " LDA #<$1234", "{LDA/imm (lsb $1234)}", "a934"},
{mm, " LDA #>$1234", "{LDA/imm (msb $1234)}", "a912"},
{mm, " LDA $12", "{LDA/zp $0012}", "a512"},
2014-06-13 00:39:48 +00:00
{mm, " LDA $12", "{LDA/zp $0012}", "a512"},
{mm, " LDA $12,X", "{LDA/zpX $0012}", "b512"},
{mm, " LDA $1234", "{LDA/abs $1234}", "ad3412"},
2014-06-19 04:57:17 +00:00
{mm, " LDA $1234", "{LDA/abs $1234}", "ad3412"},
2014-06-13 00:39:48 +00:00
{mm, " LDA $1234,X", "{LDA/absX $1234}", "bd3412"},
{mm, " LDA ($12),Y", "{LDA/indY $0012}", "b112"},
{mm, " LDA ($12,X)", "{LDA/indX $0012}", "a112"},
2014-06-19 04:57:17 +00:00
{mm, " LDA: $12", "{LDA/zp $0012}", "ad1200"},
{mm, " LDA@ $12", "{LDA/zp $0012}", "ad1200"},
{mm, " LDAX $12", "{LDA/zp $0012}", "ad1200"},
2014-06-13 00:39:48 +00:00
{mm, " LDX $12,Y", "{LDX/zpY $0012}", "b612"},
{mm, " ORG $D000", "{org $d000}", ""},
{mm, " PMC M1($42", `{call M1 {"$42"}}`, ""},
{mm, " PMC M1-$42", `{call M1 {"$42"}}`, ""},
{mm, " PUT !FILE.NAME", "{inc 'FILE.NAME'}", ""},
{mm, " ROL $12", "{ROL/zp $0012}", "2612"},
{mm, " ROL $1234", "{ROL/abs $1234}", "2e3412"},
{mm, " ROL", "{ROL/a}", "2a"},
{mm, " SAV OUTFILE", "{-}", ""},
{mm, " STA $1234,Y", "{STA/absY $1234}", "993412"},
{mm, "* Comment", "{-}", ""},
{mm, "ABC = $800", "{= 'ABC' $0800}", ""},
2014-06-19 04:57:17 +00:00
{mm, "L1 = 'A.2", "{= 'L1' (| $0041 $0002)}", ""},
{mm, "L1 = *-2", "{= 'L1' (- * $0002)}", ""},
{mm, "L1 = 1234+%10111", "{= 'L1' (+ $04d2 $0017)}", ""},
{mm, "L1 = 2*L2+$231", "{= 'L1' (+ (* $0002 L2) $0231)}", ""},
{mm, "L1 = L2!'A'", "{= 'L1' (^ L2 $0041)}", ""},
{mm, "L1 = L2&$7F", "{= 'L1' (& L2 $007f)}", ""},
{mm, "L1 = L2-L3", "{= 'L1' (- L2 L3)}", ""},
{mm, "L1 = L2.%10000000", "{= 'L1' (| L2 $0080)}", ""},
2014-06-13 00:39:48 +00:00
{mm, "Label ;Comment", "{- 'Label'}", ""},
{mm, "Label", "{- 'Label'}", ""},
{mm, "Label", "{- 'Label'}", ""},
{mm, "Label;Comment", "{- 'Label'}", ""},
2014-06-19 04:57:17 +00:00
{mm, "MacroName MAC", `{macro "MacroName"}`, ""},
2014-06-13 00:39:48 +00:00
{mm, ` ASC !ABC!`, "{data/b}", "c1c2c3"},
{mm, ` ASC "ABC"`, "{data/b}", "c1c2c3"},
{mm, ` ASC #ABC#`, "{data/b}", "c1c2c3"},
{mm, ` ASC $ABC$`, "{data/b}", "c1c2c3"},
{mm, ` ASC %ABC%`, "{data/b}", "c1c2c3"},
{mm, ` ASC &ABC&`, "{data/b}", "c1c2c3"},
{mm, ` ASC 'ABC'`, "{data/b}", "414243"},
{mm, ` ASC (ABC(`, "{data/b}", "414243"},
{mm, ` ASC )ABC)`, "{data/b}", "414243"},
{mm, ` ASC +ABC+`, "{data/b}", "414243"},
{mm, ` ASC ?ABC?`, "{data/b}", "414243"},
{mm, ` DCI !ABC!`, "{data/b}", "c1c243"},
{mm, ` DCI "ABC"`, "{data/b}", "c1c243"},
{mm, ` DCI #ABC#`, "{data/b}", "c1c243"},
{mm, ` DCI $ABC$`, "{data/b}", "c1c243"},
{mm, ` DCI %ABC%`, "{data/b}", "c1c243"},
{mm, ` DCI &ABC&`, "{data/b}", "c1c243"},
{mm, ` DCI 'ABC'`, "{data/b}", "4142c3"},
{mm, ` DCI (ABC(`, "{data/b}", "4142c3"},
{mm, ` DCI )ABC)`, "{data/b}", "4142c3"},
{mm, ` DCI +ABC+`, "{data/b}", "4142c3"},
{mm, ` DCI ?ABC?`, "{data/b}", "4142c3"},
{mm, ` TTL "Title here"`, "{-}", ""},
{mm, `L1 = "A+3`, "{= 'L1' (+ $00c1 $0003)}", ""},
2014-06-19 04:57:17 +00:00
{mm, `L1 = L2!"A"`, "{= 'L1' (^ L2 $00c1)}", ""},
2014-06-13 00:39:48 +00:00
{ra, " ; Comment", "{-}", ""},
{ra, " DDB $12,$34,$1234", "{data/wbe $0012,$0034,$1234}", "001200341234"},
2014-06-04 15:35:31 +00:00
{ra, " DFB $12", "{data/b $0012}", "12"},
{ra, " DFB $12,$34,$1234", "{data/b $0012,$0034,$1234}", "123434"},
{ra, " DW $12,$34,$1234", "{data/wle $0012,$0034,$1234}", "120034003412"},
2014-06-13 00:39:48 +00:00
{ra, " LST OFF", "{set LST OFF}", ""},
{ra, " LST ON", "{set LST ON}", ""},
{ra, " MSB OFF", "{set MSB OFF}", ""},
{ra, " MSB ON", "{set MSB ON}", ""},
{ra, " ORG $D000", "{org $d000}", ""},
2014-06-04 15:35:31 +00:00
{ra, " ROL A", "{ROL/a}", "2a"}, // two spaces is no big deal
2014-06-13 00:39:48 +00:00
{ra, " ROL A", "{ROL/a}", "2a"},
{ra, "* Comment", "{-}", ""},
{ra, "Label", "{- 'Label'}", ""},
{ra, "Label:", "{- 'Label'}", ""},
{ra, ` ASC "ABC"`, "{data/b}", "c1c2c3"},
{ra, ` ASC $ABC$ ;comment`, "{data/b}", "c1c2c3"},
{ra, ` ASC $ABC`, "{data/b}", "c1c2c3"},
{ra, ` ASC -ABC-`, "{data/b}", "c1c2c3"},
{ra, ` DCI "ABC"`, "{data/b}", "4142c3"},
{ra, ` SBTL Title here`, "{-}", ""},
{ra, ` TITLE Title here`, "{-}", ""},
2014-06-04 15:35:31 +00:00
{rb, " ROL Comment after three spaces", "{ROL/a}", "2a"},
{rb, " ROL X", "{ROL/a}", "2a"}, // two spaces = comment
2014-06-13 00:39:48 +00:00
{rb, " ROL", "{ROL/a}", "2a"},
{ss, " far-out-comment", "{-}", ""},
{ss, " .BS $8", "{block $0008}", "xxxxxxxxxxxxxxxx"},
{ss, " .DA $1234", "{data $1234}", "3412"},
{ss, " .DA/$1234,#$1234,$1234", "{data (msb $1234),(lsb $1234),$1234}", "12343412"},
{ss, " .DO A<$3", "{if (< A $0003)}", ""},
{ss, " .ELSE", "{else}", ""},
{ss, " .EM", "{endm}", ""},
{ss, " .EN", "{end}", ""},
{ss, " .FIN", "{endif}", ""},
{ss, " .HS 0001FFAB", "{data/b}", "0001ffab"},
{ss, " .IN FILE.NAME", "{inc 'FILE.NAME'}", ""},
{ss, " .IN S.DEFS", "{inc 'S.DEFS'}", ""},
2014-06-16 15:24:42 +00:00
{ss, " .MA MacroName", `{macro "MacroName"}`, ""},
2014-06-13 00:39:48 +00:00
{ss, " .OR $D000", "{org $d000}", ""},
{ss, " .TF OUT.BIN", "{-}", ""},
{ss, " .TI 76,Title here", "{-}", ""},
{ss, " BEQ $2343", "{BEQ/rel $2343}", "f0fc"},
2014-03-05 01:42:51 +00:00
{ss, " BEQ $2345", "{BEQ/rel $2345}", "f0fe"},
{ss, " BEQ $2347", "{BEQ/rel $2347}", "f000"},
2014-06-13 00:39:48 +00:00
{ss, " CMP #';'+1", "{CMP/imm (lsb (+ $003b $0001))}", "c93c"},
{ss, " JMP $1234", "{JMP/abs $1234}", "4c3412"},
{ss, " JMP ($1234)", "{JMP/ind $1234}", "6c3412"},
{ss, " LDA #$12", "{LDA/imm (lsb $0012)}", "a912"},
2014-03-05 01:42:51 +00:00
{ss, " LDA $12", "{LDA/zp $0012}", "a512"},
{ss, " LDA $12,X", "{LDA/zpX $0012}", "b512"},
2014-06-13 00:39:48 +00:00
{ss, " LDA $1234", "{LDA/abs $1234}", "ad3412"},
{ss, " LDA $1234,X", "{LDA/absX $1234}", "bd3412"},
2014-03-05 01:42:51 +00:00
{ss, " LDA ($12),Y", "{LDA/indY $0012}", "b112"},
{ss, " LDA ($12,X)", "{LDA/indX $0012}", "a112"},
2014-06-13 00:39:48 +00:00
{ss, " LDX #']+$80", "{LDX/imm (lsb (+ $005d $0080))}", "a2dd"},
{ss, " LDX $12,Y", "{LDX/zpY $0012}", "b612"},
{ss, " ROL Comment after two spaces", "{ROL/a}", "2a"},
{ss, " ROL X", "{ROL/a}", "2a"}, // two spaces = comment
{ss, " ROL $12", "{ROL/zp $0012}", "2612"},
{ss, " ROL $1234", "{ROL/abs $1234}", "2e3412"},
{ss, " ROL", "{ROL/a}", "2a"},
{ss, " STA $1234,Y", "{STA/absY $1234}", "993412"},
{ss, "* Comment", "{-}", ""},
{ss, "A.B .EQ *-C.D", "{= 'A.B' (- * C.D)}", ""},
{ss, "Label", "{- 'Label'}", ""},
2014-05-31 19:55:36 +00:00
{ss, ` .AS "ABC"`, "{data/b}", "414243"},
{ss, ` .AS -"ABC"`, "{data/b}", "c1c2c3"},
2014-06-13 00:39:48 +00:00
{ss, ` .AS -DABCD`, "{data/b}", "c1c2c3"},
{ss, ` .AS /ABC/`, "{data/b}", "414243"},
{ss, ` .AT "ABC"`, "{data/b}", "4142c3"},
2014-05-31 19:55:36 +00:00
{ss, ` .AT -"ABC"`, "{data/b}", "c1c243"},
2014-06-13 00:39:48 +00:00
{ss, ` .AT -DABCD`, "{data/b}", "c1c243"},
{ss, ` .AT /ABC/`, "{data/b}", "4142c3"},
{ss, `>SAM AB,$12,"A B","A, B, "" C"`, `{call SAM {"AB", "$12", "A B", "A, B, \" C"}}`, ""},
2014-03-05 01:42:51 +00:00
}
// TODO(zellyn): Add tests for finalization of four SCMA directives:
// "Labels used in operand expressions after .OR, TA, .BS,
// and .EQ directives must be defined prior to use (to prevent an
// undefined or ambiguous location counter)."
for i, tt := range tests {
// TODO(zellyn): Test AS65 and Merlin too.
// Initialize to a known state for testing.
tt.a.Clear()
tt.a.SetAddr(0x2345)
tt.a.Set("A.B", 0x6789)
tt.a.Set("C.D", 0x789a)
2014-06-13 00:39:48 +00:00
tt.a.Set("L2", 0x6789)
tt.a.Set("L3", 0x789a)
2014-06-19 04:57:17 +00:00
tt.a.AddMacroName("INCW")
tt.a.AddMacroName("M1")
2014-03-05 01:42:51 +00:00
inst, err := tt.a.ParseInstr(lines.NewSimple(tt.i))
if err != nil {
t.Errorf(`%d. %T.ParseInstr("%s") => error: %s`, i, tt.a, tt.i, err)
continue
}
if inst.Line.Parse == nil {
t.Errorf("Got empty inst.Line.Parse on input '%s'", tt.i)
}
_, err = inst.Compute(tt.a, true, true)
if err != nil {
2014-06-13 00:39:48 +00:00
t.Errorf(`%d. %T.ParseInstr("%s"): %s.Compute(tt.a, true, true) => error: %s`, i, tt.a, tt.i, inst, err)
2014-03-05 01:42:51 +00:00
continue
}
if inst.String() != tt.p {
t.Errorf(`%d. %T.ParseInstr("%s") = %s; want %s`, i, tt.a, tt.i, inst.String(), tt.p)
continue
}
if tt.b != "?" {
hx := hex.EncodeToString(inst.Data)
2014-05-31 19:55:36 +00:00
// xxxxxx sets the width, but doesn't expect actual data
if hx != tt.b && (len(tt.b) == 0 || tt.b[0] != 'x') {
t.Errorf(`%d. %T.ParseInstr("%s").Data = [%s]; want [%s]`, i, tt.a, tt.i, hx, tt.b)
continue
}
// Check length
w := uint16(len(tt.b) / 2)
if !inst.WidthKnown {
t.Errorf(`%d. %s.WidthKnown is false`, i, inst)
continue
}
if inst.MinWidth != inst.MaxWidth {
t.Errorf(`%d. %s: MinWidth(%d) != MaxWidth(%d)`, i, inst, inst.MinWidth, inst.MaxWidth)
continue
}
if inst.MinWidth != w {
t.Errorf(`%d. %s.MinWidth=%d; want %d`, i, inst, inst.MinWidth, w)
continue
2014-03-05 01:42:51 +00:00
}
}
}
}
func TestSimpleErrors(t *testing.T) {
ss := scma.New()
aa := as65.New()
mm := merlin.New()
tests := []struct {
2014-05-08 00:44:03 +00:00
a flavors.F // assembler flavor
i string // input string
2014-03-05 01:42:51 +00:00
}{
{ss, " LDA"}, // missing arg
{aa, " lda"}, //
{mm, " LDA"}, //
{aa, " rol"}, // missing arg (for assemblers that need "A")
{ss, " .DA $1234,"}, // data: trailing comma
{ss, `>MACRO "ABC`}, // macro: unclosed quote on arg
{ss, `>MACRO "ABC"$12`}, // macro: stuff after closing quote
}
for i, tt := range tests {
// TODO(zellyn): Test AS65 and Merlin too.
if tt.a != ss {
continue
}
inst, err := tt.a.ParseInstr(lines.NewSimple(tt.i))
if err == nil {
t.Errorf(`%d. %T.ParseInstr("%s") want err; got %s`, i, tt.a, tt.i, inst)
continue
}
}
}