1
0
mirror of https://github.com/zellyn/go6502.git synced 2024-06-16 10:29:29 +00:00

Removed WidthKnown: ParseInstr sets width

This commit is contained in:
Zellyn Hunter 2014-09-08 20:59:14 -07:00
parent ddc6d85b46
commit 072a4521de
9 changed files with 96 additions and 107 deletions

View File

@ -71,10 +71,6 @@ func (a *Assembler) Load(filename string, prefix int) error {
return parseErr return parseErr
} }
if mode == flavors.ParseModeNormal && !in.WidthKnown {
return in.Errorf("Width unknown")
}
if _, err := a.passInst(&in, false); err != nil { if _, err := a.passInst(&in, false); err != nil {
return err return err
} }
@ -253,7 +249,11 @@ func (a *Assembler) RawBytes() ([]byte, error) {
if !in.Final { if !in.Final {
return []byte{}, in.Errorf("cannot finalize value: %s", in) return []byte{}, in.Errorf("cannot finalize value: %s", in)
} }
result = append(result, in.Data...) data := in.Data
for len(data) < int(in.Width) {
data = append(data, 0x00)
}
result = append(result, data...)
} }
return result, nil return result, nil
} }

View File

@ -139,3 +139,14 @@ It's a bit tricky:
4. Evaluate instructions. 4. Evaluate instructions.
** How it works now
asm.Load
for each line:
Flavor.ParseInstr(...)
passInst
Set address if ORG
in.Compute
Update addr
asm.Pass2
passInst

View File

@ -20,3 +20,17 @@ MD5_MONITOR=$(md5 -q monitor.rom)
[[ $MD5_MONITOR == 'bc0163ca04c463e06f99fb029ad21b1f' ]] || echo 'Wrong checksum for monitor.rom' [[ $MD5_MONITOR == 'bc0163ca04c463e06f99fb029ad21b1f' ]] || echo 'Wrong checksum for monitor.rom'
MD5_SWEET16=$(md5 -q sweet16.rom) MD5_SWEET16=$(md5 -q sweet16.rom)
[[ $MD5_SWEET16 == '93e148f5e30cdd574fd1bb3c26798787' ]] || echo 'Wrong checksum for sweet16.rom' [[ $MD5_SWEET16 == '93e148f5e30cdd574fd1bb3c26798787' ]] || echo 'Wrong checksum for sweet16.rom'
go run a2as.go --in ../../../../goapple2/source/progaid/hires.asm --out hires.rom --flavor redbooka
go run a2as.go --in ../../../../goapple2/source/progaid/verify.asm --out verify.rom --flavor redbooka
go run a2as.go --in ../../../../goapple2/source/progaid/ramtest.asm --out ramtest.rom --flavor redbooka
go run a2as.go --in ../../../../goapple2/source/progaid/music.asm --out music.rom --flavor redbooka
MD5_HIRES=$(md5 -q hires.rom)
[[ $MD5_HIRES == 'efe22f1a8c94458068fb12ae702b58c4' ]] || echo 'Wrong checksum for hires.rom'
MD5_MUSIC=$(md5 -q music.rom)
[[ $MD5_MUSIC == '0ffe796a73410e822fcae5e510374924' ]] || echo 'Wrong checksum for music.rom'
MD5_RAMTEST=$(md5 -q ramtest.rom)
[[ $MD5_RAMTEST == '0420635256a3b016323989e3a9fe4ce7' ]] || echo 'Wrong checksum for ramtest.rom'
MD5_VERIFY=$(md5 -q verify.rom)
[[ $MD5_VERIFY == '527f420462426e4851b942af46cc7f48' ]] || echo 'Wrong checksum for verify.rom'

View File

@ -29,7 +29,6 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
return in, in.Errorf("%s (addr,X) doesn't have a wide variant", in.Command) return in, in.Errorf("%s (addr,X) doesn't have a wide variant", in.Command)
} }
in.Op = op.Byte in.Op = op.Byte
in.WidthKnown = true
in.Width = 2 in.Width = 2
in.Mode = opcodes.MODE_INDIRECT_X in.Mode = opcodes.MODE_INDIRECT_X
in.Var = inst.VarOpByte in.Var = inst.VarOpByte
@ -46,7 +45,6 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
if forceWide { if forceWide {
return in, fmt.Errorf("%s (addr),Y doesn't have a wide variant", in.Command) return in, fmt.Errorf("%s (addr),Y doesn't have a wide variant", in.Command)
} }
in.WidthKnown = true
in.Width = 2 in.Width = 2
in.Mode = opcodes.MODE_INDIRECT_Y in.Mode = opcodes.MODE_INDIRECT_Y
in.Op = op.Byte in.Op = op.Byte
@ -62,7 +60,6 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
return in, in.Errorf("%s doesn't support indirect (addr) mode", in.Command) return in, in.Errorf("%s doesn't support indirect (addr) mode", in.Command)
} }
in.Op = op.Byte in.Op = op.Byte
in.WidthKnown = true
in.Width = 3 in.Width = 3
in.Mode = opcodes.MODE_INDIRECT in.Mode = opcodes.MODE_INDIRECT
in.Var = inst.VarOpWord in.Var = inst.VarOpWord
@ -85,7 +82,6 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
} }
in.Op = op.Byte in.Op = op.Byte
in.WidthKnown = true
in.Width = 2 in.Width = 2
in.Mode = opcodes.MODE_RELATIVE in.Mode = opcodes.MODE_RELATIVE
in.Var = inst.VarOpBranch in.Var = inst.VarOpBranch
@ -107,7 +103,6 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
panic(fmt.Sprintf("opcode error: %s has no MODE_IMMEDIATE opcode", in.Command)) panic(fmt.Sprintf("opcode error: %s has no MODE_IMMEDIATE opcode", in.Command))
} }
in.Op = op.Byte in.Op = op.Byte
in.WidthKnown = true
in.Width = 2 in.Width = 2
in.Mode = opcodes.MODE_IMMEDIATE in.Mode = opcodes.MODE_IMMEDIATE
in.Var = inst.VarOpByte in.Var = inst.VarOpByte
@ -139,50 +134,77 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect
return in, in.Errorf("%s opcode doesn't support %s or %s modes.", zpS, wideS) return in, in.Errorf("%s opcode doesn't support %s or %s modes.", zpS, wideS)
} }
if !summary.AnyModes(zp) { if !zpOk {
if !wideOk {
panic(fmt.Sprintf("opcode error: %s has no %s opcode", in.Command, wideS))
}
in.Op = opWide.Byte in.Op = opWide.Byte
in.WidthKnown = true
in.Width = 3 in.Width = 3
in.Mode = wide in.Mode = wide
in.Var = inst.VarOpWord
in.Mode = wide
if valKnown {
in.Data = []byte{in.Op, byte(val), byte(val >> 8)}
in.Final = true
}
return in, nil return in, nil
} }
if !summary.AnyModes(wide) { if !wideOk {
if !zpOk {
panic(fmt.Sprintf("opcode error: %s has no %s opcode", in.Command, zpS))
}
if forceWide { if forceWide {
return in, fmt.Errorf("%s doesn't have a wide variant", in.Command) return in, fmt.Errorf("%s doesn't have a wide variant", in.Command)
} }
in.Op = opZp.Byte in.Op = opZp.Byte
in.WidthKnown = true
in.Width = 2 in.Width = 2
in.Mode = zp in.Mode = zp
in.Var = inst.VarOpByte
in.Mode = zp
if valKnown {
in.Data = []byte{in.Op, byte(val)}
in.Final = true
}
return in, nil return in, nil
} }
if forceWide { if forceWide {
in.Op = opWide.Byte in.Op = opWide.Byte
in.WidthKnown = true
in.Width = 3 in.Width = 3
in.Mode = wide in.Mode = wide
in.Var = inst.VarOpWord
if valKnown {
in.Data = []byte{in.Op, byte(val), byte(val >> 8)}
in.Final = true
}
return in, nil return in, nil
} }
// Okay, we don't know whether it's wide or narrow: store enough info for either. if valKnown {
if !zpOk { if val < 0x100 {
panic(fmt.Sprintf("opcode error: %s has no %s opcode", in.Command, zpS)) in.Op = opZp.Byte
in.Data = []byte{in.Op, byte(val)}
in.Width = 2
in.Var = inst.VarOpByte
in.Mode = zp
in.Final = true
return in, nil
}
in.Op = opWide.Byte
in.Data = []byte{in.Op, byte(val), byte(val >> 8)}
in.Width = 3
in.Var = inst.VarOpWord
in.Mode = wide
in.Final = true
return in, nil
} }
if !wideOk {
panic(fmt.Sprintf("opcode error: %s has no %s opcode", in.Command, wideS)) if in.Exprs[0].Width() == 1 {
in.Op = opZp.Byte
in.Mode = zp
in.Width = 2
in.Var = inst.VarOpByte
return in, nil
} }
in.Op = opWide.Byte in.Op = opWide.Byte
in.ZeroOp = opZp.Byte
in.Mode = wide in.Mode = wide
in.ZeroMode = zp in.Width = 3
in.Width = 2 in.Var = inst.VarOpWord
return in, nil return in, nil
} }

View File

@ -200,7 +200,6 @@ func (m *Merlin) ParseInclude(ctx context.Context, in inst.I, lp *lines.Parse) (
return in, in.Errorf("%s expects filename", in.Command) return in, in.Errorf("%s expects filename", in.Command)
} }
in.TextArg = prefix + filename in.TextArg = prefix + filename
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil

View File

@ -102,7 +102,6 @@ func (a *Base) ParseInstr(ctx context.Context, line lines.Line, mode flavors.Par
if a.ExtraCommenty != nil && a.ExtraCommenty(lp.Rest()) { if a.ExtraCommenty != nil && a.ExtraCommenty(lp.Rest()) {
in.Type = inst.TypeNone in.Type = inst.TypeNone
in.Final = true in.Final = true
in.WidthKnown = true
in.Width = 0 in.Width = 0
return in, nil return in, nil
} }
@ -112,7 +111,6 @@ func (a *Base) ParseInstr(ctx context.Context, line lines.Line, mode flavors.Par
if trimmed == "" || trimmed[0] == '*' || rune(trimmed[0]) == a.CommentChar { if trimmed == "" || trimmed[0] == '*' || rune(trimmed[0]) == a.CommentChar {
in.Type = inst.TypeNone in.Type = inst.TypeNone
in.Final = true in.Final = true
in.WidthKnown = true
in.Width = 0 in.Width = 0
return in, nil return in, nil
} }
@ -143,7 +141,6 @@ func (a *Base) ParseInstr(ctx context.Context, line lines.Line, mode flavors.Par
} }
} }
in.Final = true in.Final = true
in.WidthKnown = true
in.Width = 0 in.Width = 0
return in, nil return in, nil
} }
@ -221,7 +218,6 @@ func (a *Base) parseCmd(ctx context.Context, in inst.I, lp *lines.Parse, mode fl
return in, err return in, err
} }
if isMacro { if isMacro {
i.WidthKnown = true
i.Width = 0 i.Width = 0
i.Final = true i.Final = true
return i, nil return i, nil
@ -232,7 +228,6 @@ func (a *Base) parseCmd(ctx context.Context, in inst.I, lp *lines.Parse, mode fl
in.Type = dir.Type in.Type = dir.Type
in.Var = dir.Var in.Var = dir.Var
if dir.Func == nil { if dir.Func == nil {
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil
@ -278,7 +273,6 @@ func (a *Base) parseSetting(ctx context.Context, in inst.I, lp *lines.Parse) (in
default: default:
return in, in.Errorf("expecting ON/OFF, found '%s'", in.TextArg) return in, in.Errorf("expecting ON/OFF, found '%s'", in.TextArg)
} }
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil
@ -330,7 +324,6 @@ func (a *Base) parseOpArgs(ctx context.Context, in inst.I, lp *lines.Parse, summ
if summary.Modes == opcodes.MODE_IMPLIED { if summary.Modes == opcodes.MODE_IMPLIED {
op := summary.Ops[0] op := summary.Ops[0]
in.Data = []byte{op.Byte} in.Data = []byte{op.Byte}
in.WidthKnown = true
in.Width = 1 in.Width = 1
in.Final = true in.Final = true
in.Mode = opcodes.MODE_IMPLIED in.Mode = opcodes.MODE_IMPLIED
@ -358,7 +351,6 @@ func (a *Base) parseOpArgs(ctx context.Context, in inst.I, lp *lines.Parse, summ
panic(fmt.Sprintf("%s doesn't support accumulator mode", in.Command)) panic(fmt.Sprintf("%s doesn't support accumulator mode", in.Command))
} }
in.Data = []byte{op.Byte} in.Data = []byte{op.Byte}
in.WidthKnown = true
in.Width = 1 in.Width = 1
in.Final = true in.Final = true
in.Mode = opcodes.MODE_A in.Mode = opcodes.MODE_A
@ -387,7 +379,6 @@ func (a *Base) parseOpArgs(ctx context.Context, in inst.I, lp *lines.Parse, summ
panic(fmt.Sprintf("%s doesn't support accumulator mode", in.Command)) panic(fmt.Sprintf("%s doesn't support accumulator mode", in.Command))
} }
in.Data = []byte{op.Byte} in.Data = []byte{op.Byte}
in.WidthKnown = true
in.Width = 1 in.Width = 1
in.Final = true in.Final = true
in.Mode = opcodes.MODE_A in.Mode = opcodes.MODE_A
@ -441,7 +432,6 @@ func (a *Base) ParseOrg(ctx context.Context, in inst.I, lp *lines.Parse) (inst.I
if err != nil { if err != nil {
return in, err return in, err
} }
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
in.Addr = val in.Addr = val
@ -483,7 +473,6 @@ func (a *Base) ParseAscii(ctx context.Context, in inst.I, lp *lines.Parse) (inst
} }
} }
in.Width = uint16(len(in.Data)) in.Width = uint16(len(in.Data))
in.WidthKnown = true
in.Final = true in.Final = true
return in, nil return in, nil
} }
@ -500,7 +489,6 @@ func (a *Base) ParseBlockStorage(ctx context.Context, in inst.I, lp *lines.Parse
return in, in.Errorf("Cannot evaluate size of block storage on first pass") return in, in.Errorf("Cannot evaluate size of block storage on first pass")
} }
in.WidthKnown = true
in.Final = true in.Final = true
in.Width = val in.Width = val
return in, nil return in, nil
@ -520,7 +508,6 @@ func (a *Base) ParseData(ctx context.Context, in inst.I, lp *lines.Parse) (inst.
} }
switch in.Var { switch in.Var {
case inst.VarBytes: case inst.VarBytes:
in.WidthKnown = true
in.Width = uint16(len(in.Exprs)) in.Width = uint16(len(in.Exprs))
in.Final = true in.Final = true
for _, expr := range in.Exprs { for _, expr := range in.Exprs {
@ -528,11 +515,11 @@ func (a *Base) ParseData(ctx context.Context, in inst.I, lp *lines.Parse) (inst.
if err != nil { if err != nil {
in.Final = false in.Final = false
in.Data = nil in.Data = nil
break
} }
in.Data = append(in.Data, byte(val)) in.Data = append(in.Data, byte(val))
} }
case inst.VarWordsLe, inst.VarWordsBe: case inst.VarWordsLe, inst.VarWordsBe:
in.WidthKnown = true
in.Width = 2 * uint16(len(in.Exprs)) in.Width = 2 * uint16(len(in.Exprs))
in.Final = true in.Final = true
for _, expr := range in.Exprs { for _, expr := range in.Exprs {
@ -540,6 +527,7 @@ func (a *Base) ParseData(ctx context.Context, in inst.I, lp *lines.Parse) (inst.
if err != nil { if err != nil {
in.Final = false in.Final = false
in.Data = nil in.Data = nil
break
} }
if in.Var == inst.VarWordsLe { if in.Var == inst.VarWordsLe {
in.Data = append(in.Data, byte(val), byte(val>>8)) in.Data = append(in.Data, byte(val), byte(val>>8))
@ -548,7 +536,6 @@ func (a *Base) ParseData(ctx context.Context, in inst.I, lp *lines.Parse) (inst.
} }
} }
case inst.VarMixed: case inst.VarMixed:
in.WidthKnown = true
in.Final = true in.Final = true
for _, expr := range in.Exprs { for _, expr := range in.Exprs {
in.Width += expr.Width() in.Width += expr.Width()
@ -582,7 +569,6 @@ func (a *Base) ParseDo(ctx context.Context, in inst.I, lp *lines.Parse) (inst.I,
return in, err return in, err
} }
in.Exprs = append(in.Exprs, expr) in.Exprs = append(in.Exprs, expr)
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil
@ -601,7 +587,6 @@ func (a *Base) ParseEquate(ctx context.Context, in inst.I, lp *lines.Parse) (ins
} }
_ = xyzzy _ = xyzzy
in.Exprs = append(in.Exprs, expr) in.Exprs = append(in.Exprs, expr)
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil
@ -629,7 +614,6 @@ func (a *Base) ParseHexString(ctx context.Context, in inst.I, lp *lines.Parse) (
break break
} }
} }
in.WidthKnown = true
in.Width = uint16(len(in.Data)) in.Width = uint16(len(in.Data))
in.Final = true in.Final = true
return in, nil return in, nil
@ -641,7 +625,6 @@ func (a *Base) ParseInclude(ctx context.Context, in inst.I, lp *lines.Parse) (in
return in, in.Errorf("Expecting filename, found '%c'", lp.Next()) return in, in.Errorf("Expecting filename, found '%c'", lp.Next())
} }
in.TextArg = lp.Emit() in.TextArg = lp.Emit()
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil
@ -654,7 +637,6 @@ func (a *Base) ParseMacroStart(ctx context.Context, in inst.I, lp *lines.Parse)
return in, in.Errorf("Expecting valid macro name, found '%c'", lp.Next()) return in, in.Errorf("Expecting valid macro name, found '%c'", lp.Next())
} }
in.TextArg = lp.Emit() in.TextArg = lp.Emit()
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil
@ -663,14 +645,12 @@ func (a *Base) ParseMacroStart(ctx context.Context, in inst.I, lp *lines.Parse)
// For assemblers where the macro name is the label, followed by the directive. // For assemblers where the macro name is the label, followed by the directive.
func (a *Base) MarkMacroStart(ctx context.Context, in inst.I, lp *lines.Parse) (inst.I, error) { func (a *Base) MarkMacroStart(ctx context.Context, in inst.I, lp *lines.Parse) (inst.I, error) {
in.TextArg, in.Label = in.Label, "" in.TextArg, in.Label = in.Label, ""
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil
} }
func (a *Base) ParseNoArgDir(ctx context.Context, in inst.I, lp *lines.Parse) (inst.I, error) { func (a *Base) ParseNoArgDir(ctx context.Context, in inst.I, lp *lines.Parse) (inst.I, error) {
in.WidthKnown = true
in.Width = 0 in.Width = 0
in.Final = true in.Final = true
return in, nil return in, nil

View File

@ -294,6 +294,17 @@ func TestMultiline(t *testing.T) {
" EOM", " EOM",
}, },
}, "a533c535a534e536ea", nil, true}, }, "a533c535a534e536ea", nil, true},
// Merlin: DB with unknown addresses
{mm, "DB with unknown addresses", []string{
"ONE = $0123",
"TWO = $4567",
" DB <ONE,<$FFFF,<$FFFF,<TWO",
" DB <THREE,<FOUR",
"THREE = $89ab",
"FOUR = $cdef",
" NOP",
}, nil, "23ffff67abefea", nil, true},
} }
for i, tt := range tests { for i, tt := range tests {

View File

@ -60,6 +60,7 @@ func TestSimpleCommonFunctions(t *testing.T) {
{mm, " BEQ $2347", "{BEQ/rel $2347}", "f000"}, {mm, " BEQ $2347", "{BEQ/rel $2347}", "f000"},
{mm, " DA $12,$34,$1234", "{data/wle $0012,$0034,$1234}", "120034003412"}, {mm, " DA $12,$34,$1234", "{data/wle $0012,$0034,$1234}", "120034003412"},
{mm, " DA $1234", "{data/wle $1234}", "3412"}, {mm, " DA $1234", "{data/wle $1234}", "3412"},
{mm, " DB <L4,<L5", "{data/b (lsb L4),(lsb L5)}", "deef"},
{mm, " DDB $12,$34,$1234", "{data/wbe $0012,$0034,$1234}", "001200341234"}, {mm, " DDB $12,$34,$1234", "{data/wbe $0012,$0034,$1234}", "001200341234"},
{mm, " DFB $12,$34,$1234", "{data/b $0012,$0034,$1234}", "123434"}, {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, " DFB $34,100,$81A2-$77C4,%1011,>$81A2-$77C4", "{data/b $0034,$0064,(- $81a2 $77c4),$000b,(msb (- $81a2 $77c4))}", "3464de0b09"},
@ -239,13 +240,13 @@ func TestSimpleCommonFunctions(t *testing.T) {
t.Errorf(`%d. %s.ParseInstr("%s") => error: %s`, i, tt.f, tt.i, err) t.Errorf(`%d. %s.ParseInstr("%s") => error: %s`, i, tt.f, tt.i, err)
continue continue
} }
if !in.WidthKnown {
t.Errorf(`%d. %s.ParseInstr("%s") => WidthKnown=false`, i, tt.f, tt.i)
continue
}
if in.Line.Parse == nil { if in.Line.Parse == nil {
t.Errorf("Got empty in.Line.Parse on input '%s'", tt.i) t.Errorf("Got empty in.Line.Parse on input '%s'", tt.i)
} }
ctx.Set("L4", 0xbcde)
ctx.Set("L5", 0xcdef)
if in.Type != inst.TypeOrg { if in.Type != inst.TypeOrg {
_, err = in.Compute(ctx, true) _, err = in.Compute(ctx, true)
@ -263,16 +264,13 @@ func TestSimpleCommonFunctions(t *testing.T) {
hx := hex.EncodeToString(in.Data) hx := hex.EncodeToString(in.Data)
// xxxxxx sets the width, but doesn't expect actual data // xxxxxx sets the width, but doesn't expect actual data
if hx != tt.b && (len(tt.b) == 0 || tt.b[0] != 'x') { if hx != tt.b && (len(tt.b) == 0 || tt.b[0] != 'x') {
t.Errorf(`%d. %s.ParseInstr("%s").Data = [%s]; want [%s]`, i, tt.f, tt.i, hx, tt.b) t.Errorf(`%d. %s.ParseInstr("%s").Data = [%s]; want [%s] (%s)`, i, tt.f, tt.i, hx, tt.b, in)
continue continue
} }
// Check length // Check length
w := uint16(len(tt.b) / 2) w := uint16(len(tt.b) / 2)
if !in.WidthKnown {
t.Errorf(`%d. %s.WidthKnown is false`, i, in)
continue
}
if in.Width != w { if in.Width != w {
t.Errorf(`%d. %s.Width=%d; want %d`, i, in, in.Width, w) t.Errorf(`%d. %s.Width=%d; want %d`, i, in, in.Width, w)
continue continue

View File

@ -66,13 +66,10 @@ type I struct {
TextArg string // Text of argument part TextArg string // Text of argument part
Exprs []*expr.E // Expression(s) Exprs []*expr.E // Expression(s)
Data []byte // Actual bytes Data []byte // Actual bytes
WidthKnown bool // Do we know how many bytes this instruction takes yet?
Width uint16 // width in bytes Width uint16 // width in bytes
Final bool // Do we know the actual bytes yet? Final bool // Do we know the actual bytes yet?
Op byte // Opcode Op byte // Opcode
Mode opcodes.AddressingMode // Opcode mode Mode opcodes.AddressingMode // Opcode mode
ZeroMode opcodes.AddressingMode // Possible ZP-option mode
ZeroOp byte // Possible ZP-option Opcode
Value uint16 // For Equates, the value Value uint16 // For Equates, the value
DeclaredLine uint16 // Line number listed in file DeclaredLine uint16 // Line number listed in file
Line *lines.Line // Line object for this line Line *lines.Line // Line object for this line
@ -216,7 +213,6 @@ func (i *I) Compute(c context.Context, final bool) (bool, error) {
} }
// Everything else is zero-width // Everything else is zero-width
i.WidthKnown = true
i.Width = 0 i.Width = 0
i.Final = true i.Final = true
@ -225,7 +221,6 @@ func (i *I) Compute(c context.Context, final bool) (bool, error) {
func (i *I) computeData(c context.Context, final bool) (bool, error) { func (i *I) computeData(c context.Context, final bool) (bool, error) {
if len(i.Data) > 0 { if len(i.Data) > 0 {
i.WidthKnown = true
i.Width = uint16(len(i.Data)) i.Width = uint16(len(i.Data))
i.Final = true i.Final = true
return true, nil return true, nil
@ -274,7 +269,6 @@ func (i *I) computeData(c context.Context, final bool) (bool, error) {
} }
} }
i.Width = width i.Width = width
i.WidthKnown = true
if allFinal { if allFinal {
i.Data = data i.Data = data
i.Final = true i.Final = true
@ -287,7 +281,6 @@ func (i *I) computeBlock(c context.Context, final bool) (bool, error) {
val, err := i.Exprs[0].Eval(c, i.Line) val, err := i.Exprs[0].Eval(c, i.Line)
if err == nil { if err == nil {
i.Value = val i.Value = val
i.WidthKnown = true
i.Final = true i.Final = true
i.Width = val i.Width = val
} else { } else {
@ -299,7 +292,6 @@ func (i *I) computeBlock(c context.Context, final bool) (bool, error) {
} }
func (i *I) computeMustKnow(c context.Context, final bool) (bool, error) { func (i *I) computeMustKnow(c context.Context, final bool) (bool, error) {
i.WidthKnown = true
i.Width = 0 i.Width = 0
i.Final = true i.Final = true
val, err := i.Exprs[0].Eval(c, i.Line) val, err := i.Exprs[0].Eval(c, i.Line)
@ -322,12 +314,6 @@ func (i *I) computeMustKnow(c context.Context, final bool) (bool, error) {
func (i *I) computeOp(c context.Context, final bool) (bool, error) { func (i *I) computeOp(c context.Context, final bool) (bool, error) {
// If the width is not known, we better have a ZeroPage alternative. // If the width is not known, we better have a ZeroPage alternative.
if !i.WidthKnown && (i.ZeroOp == 0 || i.ZeroMode == 0) {
if i.Line.Context != nil && i.Line.Context.Parent != nil {
fmt.Println(i.Line.Context.Parent.Sprintf("foo"))
}
panic(i.Sprintf("Reached computeOp for '%s' with no ZeroPage alternative: %#v [%s]", i.Command, i, i.Line.Text()))
}
// An op with no args would be final already, so we must have an Expression. // An op with no args would be final already, so we must have an Expression.
if len(i.Exprs) == 0 { if len(i.Exprs) == 0 {
panic(fmt.Sprintf("Reached computeOp for '%s' with no expressions", i.Command)) panic(fmt.Sprintf("Reached computeOp for '%s' with no expressions", i.Command))
@ -344,40 +330,11 @@ func (i *I) computeOp(c context.Context, final bool) (bool, error) {
return false, err return false, err
} }
// Already know enough.
if i.WidthKnown {
return false, nil
}
// Do we know the width, even though the value is unknown?
if i.Exprs[0].Width() == 1 {
i.WidthKnown = true
i.Width = 2
i.Op, i.Mode = i.ZeroOp, i.ZeroMode
i.ZeroOp, i.ZeroMode = 0, 0
return false, nil
}
// Okay, we have to set the width: since we don't know, go wide.
i.WidthKnown = true
i.Width = 3
i.ZeroOp, i.ZeroMode = 0, 0
return false, nil return false, nil
} }
// If we got here, we got an actual value. // If we got here, we got an actual value.
// We need to figure out the width
if !i.WidthKnown {
if val < 0x100 {
i.Width = 2
i.Op = i.ZeroOp
i.Mode = i.ZeroMode
} else {
i.Width = 3
}
}
// It's a branch // It's a branch
if i.Mode == opcodes.MODE_RELATIVE { if i.Mode == opcodes.MODE_RELATIVE {
curr := c.GetAddr() curr := c.GetAddr()
@ -391,10 +348,7 @@ func (i *I) computeOp(c context.Context, final bool) (bool, error) {
val = uint16(offset) val = uint16(offset)
} }
i.WidthKnown = true
i.Final = true i.Final = true
i.ZeroOp = 0
i.ZeroMode = 0
switch i.Width { switch i.Width {
case 2: case 2: