diff --git a/asm/asm.go b/asm/asm.go index 3edbbfb..4a286ad 100644 --- a/asm/asm.go +++ b/asm/asm.go @@ -65,7 +65,7 @@ func (a *Assembler) Load(filename string, prefix int) error { return err } - if _, err := a.passInst(&in, a.Flavor.SetWidthsOnFirstPass(), false); err != nil { + if _, err := a.passInst(&in, false); err != nil { return err } @@ -143,15 +143,8 @@ func (a *Assembler) AssembleWithPrefix(filename string, prefix int) error { return err } - // Setwidth pass if necessary. - if !a.Flavor.SetWidthsOnFirstPass() { - if _, err := a.Pass(true, false); err != nil { - return err - } - } - // Final pass. - if _, err := a.Pass(true, true); err != nil { + if _, err := a.Pass(true); err != nil { return err } return nil @@ -198,23 +191,18 @@ func (a *Assembler) initPass() { } } -// passInst performs a pass on a single instruction. Depending on -// whether the instruction width can be determined, it updates or -// clears the current address. If setWidth is true, it forces the -// instruction to decide its final width. If final is true, and the -// instruction cannot be finalized, it returns an error. -func (a *Assembler) passInst(in *inst.I, setWidth, final bool) (isFinal bool, err error) { +// passInst performs a pass on a single instruction. It forces the +// instruction to decide its width, but may not know all the +// arguments. If final is true, and the instruction cannot be +// finalized, it returns an error. +func (a *Assembler) passInst(in *inst.I, final bool) (isFinal bool, err error) { // fmt.Printf("PLUGH: in.Compute(a.Flavor, true, true) on %s\n", in) - isFinal, err = in.Compute(a.Flavor, setWidth, final) - // fmt.Printf("PLUGH: isFinal=%v, in.Final=%v, in.WidthKnown=%v, in.MinWidth=%v\n", isFinal, in.Final, in.WidthKnown, in.MinWidth) + isFinal, err = in.Compute(a.Flavor, final) + // fmt.Printf("PLUGH: isFinal=%v, in.Final=%v, in.WidthKnown=%v, in.Width=%v\n", isFinal, in.Final, in.WidthKnown, in.Width) if err != nil { return false, err } - if in.WidthKnown && in.MinWidth != in.MaxWidth { - panic(fmt.Sprintf("inst.I %s: WidthKnown=true, but MinWidth=%d, MaxWidth=%d", in, in.MinWidth, in.MaxWidth)) - } - // Update address if a.Flavor.AddrKnown() { addr, _ := a.Flavor.GetAddr() @@ -222,7 +210,7 @@ func (a *Assembler) passInst(in *inst.I, setWidth, final bool) (isFinal bool, er in.AddrKnown = true if in.WidthKnown { - a.Flavor.SetAddr(addr + in.MinWidth) + a.Flavor.SetAddr(addr + in.Width) } else { a.Flavor.ClearAddr(in.Sprintf("lost known address")) } @@ -231,25 +219,23 @@ func (a *Assembler) passInst(in *inst.I, setWidth, final bool) (isFinal bool, er return isFinal, nil } -// Pass performs an assembly pass. If setWidth is true, it causes all -// instructions to set their final width. If final is true, it returns -// an error for any instruction that cannot be finalized. -func (a *Assembler) Pass(setWidth, final bool) (isFinal bool, err error) { - // fmt.Printf("PLUGH: Pass(%v, %v): %d instructions\n", setWidth, final, len(a.Insts)) - setWidth = setWidth || final // final ⊢ setWidth - +// Pass performs an assembly pass. It causes all instructions to set +// their final width. If final is true, it returns an error for any +// instruction that cannot be finalized. +func (a *Assembler) Pass(final bool) (isFinal bool, err error) { + // fmt.Printf("PLUGH: Pass(%v): %d instructions\n", final, len(a.Insts)) a.initPass() isFinal = true for _, in := range a.Insts { - instFinal, err := a.passInst(in, setWidth, final) + instFinal, err := a.passInst(in, final) if err != nil { return false, err } if final && !instFinal { return false, in.Errorf("cannot finalize instruction: %s", in) } - // fmt.Printf("PLUGH: instFinal=%v, in.Final=%v, in.WidthKnown=%v, in.MinWidth=%v\n", instFinal, in.Final, in.WidthKnown, in.MinWidth) + // fmt.Printf("PLUGH: instFinal=%v, in.Final=%v, in.WidthKnown=%v, in.Width=%v\n", instFinal, in.Final, in.WidthKnown, in.Width) isFinal = isFinal && instFinal } @@ -284,7 +270,7 @@ func (a *Assembler) Membuf() (*membuf.Membuf, error) { if !in.AddrKnown { return nil, in.Errorf("address unknown: %s", in) } - if in.MinWidth > 0 { + if in.Width > 0 { m.Write(int(in.Addr), in.Data) } } diff --git a/asm/cmd/a2as/runtest.sh b/asm/cmd/a2as/runtest.sh index ad82e05..a53ac9b 100755 --- a/asm/cmd/a2as/runtest.sh +++ b/asm/cmd/a2as/runtest.sh @@ -2,6 +2,21 @@ go run a2as.go --in ../../../../goapple2/source/redbook/monitor.asm --out monito go run a2as.go --in ../../../../goapple2/source/redbook/miniasm.asm --out miniasm.rom --flavor redbooka --listing miniasm.lst --prefix=-1 go run a2as.go --in ../../../../goapple2/source/redbook/sweet16.asm --out sweet16.rom --flavor redbooka --listing sweet16.lst --prefix=-1 go run a2as.go --in ../../../../goapple2/source/redbook/fp.asm --out fp.rom --flavor redbookb --listing fp.lst --prefix=-1 -go run a2as.go --in ../../../../goapple2/source/redbook/misc-f699.asm --out misc-f699.rom --flavor redbooka --listing misc-f699.lst --prefix=0 +go run a2as.go --in ../../../../goapple2/source/redbook/misc-f669.asm --out misc-f669.rom --flavor redbooka --listing misc-f669.lst --prefix=0 go run a2as.go --in ../../../../goapple2/source/redbook/intbasic.asm --out intbasic.rom --flavor merlin --listing intbasic.lst --prefix=-1 +go run a2as.go --in ../../../../goapple2/source/applesoft/S.acf --out applesoft.rom --flavor scma --listing applesoft.lst --prefix=-1 +MD5_APPLESOFT=$(md5 -q applesoft.rom) +[[ $MD5_APPLESOFT == '84bfbe89c9cd96e589c4d4cb01df4c4a' ]] || echo 'Wrong checksum for applesoft.rom' +MD5_FP=$(md5 -q fp.rom) +[[ $MD5_FP == '76ae6287e5e96471dc95e95eb93ba06d' ]] || echo 'Wrong checksum for fp.rom' +MD5_INTBASIC=$(md5 -q intbasic.rom) +[[ $MD5_INTBASIC == 'c22d8f7ebb54608c8718b66454ca691f' ]] || echo 'Wrong checksum for intbasic.rom' +MD5_MINIASM=$(md5 -q miniasm.rom) +[[ $MD5_MINIASM == 'e64882d56c485ee88d2bfaf4b642c2f9' ]] || echo 'Wrong checksum for miniasm.rom' +MD5_MISC_F669=$(md5 -q misc-f669.rom) +[[ $MD5_MISC_F669 == 'eccaef17e6340b54c309b87ffb6f6f22' ]] || echo 'Wrong checksum for misc-f669.rom' +MD5_MONITOR=$(md5 -q monitor.rom) +[[ $MD5_MONITOR == 'bc0163ca04c463e06f99fb029ad21b1f' ]] || echo 'Wrong checksum for monitor.rom' +MD5_SWEET16=$(md5 -q sweet16.rom) +[[ $MD5_SWEET16 == '93e148f5e30cdd574fd1bb3c26798787' ]] || echo 'Wrong checksum for sweet16.rom' diff --git a/asm/flavors/as65/as65.go b/asm/flavors/as65/as65.go index 3ef8967..9895083 100644 --- a/asm/flavors/as65/as65.go +++ b/asm/flavors/as65/as65.go @@ -33,10 +33,6 @@ func (a *AS65) DefaultOrigin() (uint16, error) { return 0, nil } -func (a *AS65) SetWidthsOnFirstPass() bool { - return false -} - func (a *AS65) ReplaceMacroArgs(line string, args []string, kwargs map[string]string) (string, error) { panic("AS65.ReplaceMacroArgs not implemented yet.") } diff --git a/asm/flavors/common/common.go b/asm/flavors/common/common.go index 0ce924e..43cb945 100644 --- a/asm/flavors/common/common.go +++ b/asm/flavors/common/common.go @@ -26,8 +26,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect } in.Op = op.Byte in.WidthKnown = true - in.MinWidth = 2 - in.MaxWidth = 2 + in.Width = 2 in.Mode = opcodes.MODE_INDIRECT_X return in, nil case 'y': @@ -39,8 +38,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect return in, fmt.Errorf("%s (addr),Y doesn't have a wide variant", in.Command) } in.WidthKnown = true - in.MinWidth = 2 - in.MaxWidth = 2 + in.Width = 2 in.Mode = opcodes.MODE_INDIRECT_Y in.Op = op.Byte return in, nil @@ -51,8 +49,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect } in.Op = op.Byte in.WidthKnown = true - in.MinWidth = 3 - in.MaxWidth = 3 + in.Width = 3 in.Mode = opcodes.MODE_INDIRECT return in, nil } @@ -70,8 +67,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect in.Op = op.Byte in.WidthKnown = true - in.MinWidth = 2 - in.MaxWidth = 2 + in.Width = 2 in.Mode = opcodes.MODE_RELATIVE return in, nil } @@ -84,8 +80,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect } in.Op = op.Byte in.WidthKnown = true - in.MinWidth = 2 - in.MaxWidth = 2 + in.Width = 2 in.Mode = opcodes.MODE_IMMEDIATE return in, nil } @@ -117,8 +112,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect } in.Op = opWide.Byte in.WidthKnown = true - in.MinWidth = 3 - in.MaxWidth = 3 + in.Width = 3 in.Mode = wide return in, nil } @@ -131,8 +125,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect } in.Op = opZp.Byte in.WidthKnown = true - in.MinWidth = 2 - in.MaxWidth = 2 + in.Width = 2 in.Mode = zp return in, nil } @@ -140,8 +133,7 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect if forceWide { in.Op = opWide.Byte in.WidthKnown = true - in.MinWidth = 3 - in.MaxWidth = 3 + in.Width = 3 in.Mode = wide return in, nil } @@ -157,7 +149,6 @@ func DecodeOp(c context.Context, in inst.I, summary opcodes.OpSummary, indirect in.ZeroOp = opZp.Byte in.Mode = wide in.ZeroMode = zp - in.MinWidth = 2 - in.MaxWidth = 3 + in.Width = 2 return in, nil } diff --git a/asm/flavors/flavors.go b/asm/flavors/flavors.go index db4cedf..57391a2 100644 --- a/asm/flavors/flavors.go +++ b/asm/flavors/flavors.go @@ -9,7 +9,6 @@ import ( type F interface { ParseInstr(Line lines.Line) (inst.I, error) DefaultOrigin() (uint16, error) - SetWidthsOnFirstPass() bool ReplaceMacroArgs(line string, args []string, kwargs map[string]string) (string, error) LocalMacroLabels() bool context.Context diff --git a/asm/flavors/merlin/merlin.go b/asm/flavors/merlin/merlin.go index 26442f8..ef5ddd1 100644 --- a/asm/flavors/merlin/merlin.go +++ b/asm/flavors/merlin/merlin.go @@ -163,11 +163,6 @@ func (m *Merlin) DefaultOrigin() (uint16, error) { return 0x8000, nil } -func (m *Merlin) SetWidthsOnFirstPass() bool { - // TODO(zellyn): figure this out - return true -} - func (m *Merlin) ParseInclude(in inst.I, lp *lines.Parse) (inst.I, error) { lp.IgnoreRun(whitespace) lp.AcceptUntil(";") @@ -182,8 +177,7 @@ func (m *Merlin) ParseInclude(in inst.I, lp *lines.Parse) (inst.I, error) { } in.TextArg = prefix + filename in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } diff --git a/asm/flavors/oldschool/oldschool.go b/asm/flavors/oldschool/oldschool.go index 1c4a258..2b3c149 100644 --- a/asm/flavors/oldschool/oldschool.go +++ b/asm/flavors/oldschool/oldschool.go @@ -128,10 +128,6 @@ func (a *Base) DefaultOrigin() (uint16, error) { return 0x0800, nil } -func (a *Base) SetWidthsOnFirstPass() bool { - return true -} - // ParseCmd parses the "command" part of an instruction: we expect to be // looking at a non-whitespace character. func (a *Base) ParseCmd(in inst.I, lp *lines.Parse) (inst.I, error) { @@ -248,8 +244,7 @@ func (a *Base) ParseOpArgs(in inst.I, lp *lines.Parse, summary opcodes.OpSummary op := summary.Ops[0] in.Data = []byte{op.Byte} in.WidthKnown = true - in.MinWidth = 1 - in.MaxWidth = 1 + in.Width = 1 in.Final = true in.Mode = opcodes.MODE_IMPLIED return in, nil @@ -277,8 +272,7 @@ func (a *Base) ParseOpArgs(in inst.I, lp *lines.Parse, summary opcodes.OpSummary } in.Data = []byte{op.Byte} in.WidthKnown = true - in.MinWidth = 1 - in.MaxWidth = 1 + in.Width = 1 in.Final = true in.Mode = opcodes.MODE_A return in, nil @@ -307,8 +301,7 @@ func (a *Base) ParseOpArgs(in inst.I, lp *lines.Parse, summary opcodes.OpSummary } in.Data = []byte{op.Byte} in.WidthKnown = true - in.MinWidth = 1 - in.MaxWidth = 1 + in.Width = 1 in.Final = true in.Mode = opcodes.MODE_A in.Exprs = nil @@ -358,8 +351,7 @@ func (a *Base) ParseAddress(in inst.I, lp *lines.Parse) (inst.I, error) { } in.Exprs = append(in.Exprs, expr) in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } @@ -434,8 +426,7 @@ func (a *Base) ParseDo(in inst.I, lp *lines.Parse) (inst.I, error) { } in.Exprs = append(in.Exprs, expr) in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } @@ -448,8 +439,7 @@ func (a *Base) ParseEquate(in inst.I, lp *lines.Parse) (inst.I, error) { } in.Exprs = append(in.Exprs, expr) in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } @@ -486,8 +476,7 @@ func (a *Base) ParseInclude(in inst.I, lp *lines.Parse) (inst.I, error) { } in.TextArg = lp.Emit() in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } @@ -500,8 +489,7 @@ func (a *Base) ParseMacroStart(in inst.I, lp *lines.Parse) (inst.I, error) { } in.TextArg = lp.Emit() in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } @@ -510,16 +498,14 @@ func (a *Base) ParseMacroStart(in inst.I, lp *lines.Parse) (inst.I, error) { func (a *Base) MarkMacroStart(in inst.I, lp *lines.Parse) (inst.I, error) { in.TextArg, in.Label = in.Label, "" in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } func (a *Base) ParseNoArgDir(in inst.I, lp *lines.Parse) (inst.I, error) { in.WidthKnown = true - in.MinWidth = 0 - in.MaxWidth = 0 + in.Width = 0 in.Final = true return in, nil } diff --git a/asm/flavors/redbook/redbook.go b/asm/flavors/redbook/redbook.go index b90f6cd..51f26f1 100644 --- a/asm/flavors/redbook/redbook.go +++ b/asm/flavors/redbook/redbook.go @@ -36,6 +36,7 @@ func newRedbook() *RedBook { r.CommentChar = ';' r.MsbChars = "/" r.ImmediateChars = "#" + r.HexCommas = oldschool.ReqOptional r.Directives = map[string]oldschool.DirectiveInfo{ "ORG": {inst.TypeOrg, r.ParseAddress, 0}, @@ -48,12 +49,7 @@ func newRedbook() *RedBook { "DDB": {inst.TypeData, r.ParseData, inst.DataWordsBe}, "ASC": {inst.TypeData, r.ParseAscii, inst.DataAscii}, "DCI": {inst.TypeData, r.ParseAscii, inst.DataAsciiFlip}, - ".DO": {inst.TypeIfdef, r.ParseDo, 0}, - ".ELSE": {inst.TypeIfdefElse, r.ParseNoArgDir, 0}, - ".FIN": {inst.TypeIfdefEnd, r.ParseNoArgDir, 0}, - ".MA": {inst.TypeMacroStart, r.ParseMacroStart, 0}, - ".EM": {inst.TypeMacroEnd, r.ParseNoArgDir, 0}, - ".US": {inst.TypeNone, r.ParseNotImplemented, 0}, + "HEX": {inst.TypeData, r.ParseHexString, inst.DataBytes}, "PAGE": {inst.TypeNone, nil, 0}, // New page "TITLE": {inst.TypeNone, nil, 0}, // Title "SBTL": {inst.TypeNone, nil, 0}, // Subtitle diff --git a/asm/flavors/tests/assemble_test.go b/asm/flavors/tests/assemble_test.go index 18a406c..700af7a 100644 --- a/asm/flavors/tests/assemble_test.go +++ b/asm/flavors/tests/assemble_test.go @@ -305,19 +305,13 @@ func TestMultiline(t *testing.T) { t.Errorf(`%d("%s" - %T): tt.a.Load("TESTFILE") failed: %s`, i, tt.name, tt.a.Flavor, err) continue } - if !tt.a.Flavor.SetWidthsOnFirstPass() { - if _, err := tt.a.Pass(true, false); err != nil { - t.Errorf(`%d("%s" - %T): tt.a.Pass(true, false) failed: %s`, i, tt.name, tt.a.Flavor, err) - continue - } - } - isFinal, err := tt.a.Pass(true, true) + isFinal, err := tt.a.Pass(true) if err != nil { - t.Errorf(`%d("%s" - %T): tt.a.Pass(true, true) failed: %s`, i, tt.name, tt.a.Flavor, err) + t.Errorf(`%d("%s" - %T): tt.a.Pass(true) failed: %s`, i, tt.name, tt.a.Flavor, err) continue } if !isFinal { - t.Errorf(`%d("%s" - %T): tt.a.Pass(true, true) couldn't finalize`, i, tt.name, tt.a.Flavor) + t.Errorf(`%d("%s" - %T): tt.a.Pass(true) couldn't finalize`, i, tt.name, tt.a.Flavor) continue } diff --git a/asm/flavors/tests/simple_parse_test.go b/asm/flavors/tests/simple_parse_test.go index de9fe4a..c463964 100644 --- a/asm/flavors/tests/simple_parse_test.go +++ b/asm/flavors/tests/simple_parse_test.go @@ -237,9 +237,9 @@ func TestSimpleCommonFunctions(t *testing.T) { if inst.Line.Parse == nil { t.Errorf("Got empty inst.Line.Parse on input '%s'", tt.i) } - _, err = inst.Compute(tt.a, true, true) + _, err = inst.Compute(tt.a, true) if err != nil { - t.Errorf(`%d. %T.ParseInstr("%s"): %s.Compute(tt.a, true, true) => error: %s`, i, tt.a, tt.i, inst, err) + t.Errorf(`%d. %T.ParseInstr("%s"): %s.Compute(tt.a, true) => error: %s`, i, tt.a, tt.i, inst, err) continue } if inst.String() != tt.p { @@ -261,12 +261,8 @@ func TestSimpleCommonFunctions(t *testing.T) { 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) + if inst.Width != w { + t.Errorf(`%d. %s.Width=%d; want %d`, i, inst, inst.Width, w) continue } } diff --git a/asm/inst/instruction.go b/asm/inst/instruction.go index 56ca253..f2bb4b2 100644 --- a/asm/inst/instruction.go +++ b/asm/inst/instruction.go @@ -63,8 +63,7 @@ type I struct { Exprs []*expr.E // Expression(s) Data []byte // Actual bytes WidthKnown bool // Do we know how many bytes this instruction takes yet? - MinWidth uint16 // minimum width in bytes - MaxWidth uint16 // maximum width in bytes + Width uint16 // width in bytes Final bool // Do we know the actual bytes yet? Op byte // Opcode Mode opcodes.AddressingMode // Opcode mode @@ -192,11 +191,11 @@ func (i I) String() string { } // Compute attempts to finalize the instruction. -func (i *I) Compute(c context.Context, setWidth bool, final bool) (bool, error) { +func (i *I) Compute(c context.Context, final bool) (bool, error) { if i.Type == TypeEqu || i.Type == TypeTarget || i.Type == TypeOrg { - return i.computeMustKnow(c, setWidth, final) + return i.computeMustKnow(c, final) } - if err := i.computeLabel(c, setWidth, final); err != nil { + if err := i.computeLabel(c, final); err != nil { return false, err } if i.Final { @@ -204,17 +203,16 @@ func (i *I) Compute(c context.Context, setWidth bool, final bool) (bool, error) } switch i.Type { case TypeOp: - return i.computeOp(c, setWidth, final) + return i.computeOp(c, final) case TypeData: - return i.computeData(c, setWidth, final) + return i.computeData(c, final) case TypeBlock: - return i.computeBlock(c, setWidth, final) + return i.computeBlock(c, final) } // Everything else is zero-width i.WidthKnown = true - i.MinWidth = 0 - i.MaxWidth = 0 + i.Width = 0 i.Final = true return true, nil @@ -244,7 +242,7 @@ func (i *I) FixLabels(labeler context.Labeler) error { } // computeLabel attempts to compute equates and label values. -func (i *I) computeLabel(c context.Context, setWidth bool, final bool) error { +func (i *I) computeLabel(c context.Context, final bool) error { if i.Label == "" { return nil } @@ -266,11 +264,10 @@ func (i *I) computeLabel(c context.Context, setWidth bool, final bool) error { return nil } -func (i *I) computeData(c context.Context, setWidth bool, final bool) (bool, error) { +func (i *I) computeData(c context.Context, final bool) (bool, error) { if len(i.Data) > 0 { i.WidthKnown = true - i.MinWidth = uint16(len(i.Data)) - i.MaxWidth = i.MinWidth + i.Width = uint16(len(i.Data)) i.Final = true return true, nil } @@ -317,8 +314,7 @@ func (i *I) computeData(c context.Context, setWidth bool, final bool) (bool, err panic(fmt.Sprintf("Unknown data variant handed to computeData: %d", i.Var)) } } - i.MinWidth = width - i.MaxWidth = width + i.Width = width i.WidthKnown = true if allFinal { i.Data = data @@ -328,26 +324,24 @@ func (i *I) computeData(c context.Context, setWidth bool, final bool) (bool, err return i.Final, nil } -func (i *I) computeBlock(c context.Context, setWidth bool, final bool) (bool, error) { +func (i *I) computeBlock(c context.Context, final bool) (bool, error) { val, err := i.Exprs[0].Eval(c, i.Line) if err == nil { i.Value = val i.WidthKnown = true i.Final = true - i.MinWidth = val - i.MaxWidth = val + i.Width = val } else { - if setWidth || final { + if final { return false, i.Errorf("block storage with unknown size") } } return i.Final, nil } -func (i *I) computeMustKnow(c context.Context, setWidth bool, final bool) (bool, error) { +func (i *I) computeMustKnow(c context.Context, final bool) (bool, error) { i.WidthKnown = true - i.MinWidth = 0 - i.MaxWidth = 0 + i.Width = 0 i.Final = true val, err := i.Exprs[0].Eval(c, i.Line) if err != nil { @@ -364,13 +358,13 @@ func (i *I) computeMustKnow(c context.Context, setWidth bool, final bool) (bool, // Don't handle labels. return true, nil } - if err := i.computeLabel(c, setWidth, final); err != nil { + if err := i.computeLabel(c, final); err != nil { return false, err } return true, nil } -func (i *I) computeOp(c context.Context, setWidth bool, 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 !i.WidthKnown && (i.ZeroOp == 0 || i.ZeroMode == 0) { if i.Line.Context != nil && i.Line.Context.Parent != nil { @@ -402,20 +396,15 @@ func (i *I) computeOp(c context.Context, setWidth bool, final bool) (bool, error // Do we know the width, even though the value is unknown? if i.Exprs[0].Width() == 1 { i.WidthKnown = true - i.MinWidth, i.MaxWidth = 2, 2 + i.Width = 2 i.Op, i.Mode = i.ZeroOp, i.ZeroMode i.ZeroOp, i.ZeroMode = 0, 0 return false, nil } - // Don't know the width, but don't care on this pass. - if !setWidth { - return false, nil - } - // Okay, we have to set the width: since we don't know, go wide. i.WidthKnown = true - i.MinWidth, i.MaxWidth = 3, 3 + i.Width = 3 i.ZeroOp, i.ZeroMode = 0, 0 return false, nil } @@ -425,14 +414,11 @@ func (i *I) computeOp(c context.Context, setWidth bool, final bool) (bool, error // We need to figure out the width if !i.WidthKnown { if val < 0x100 { - i.MinWidth = 2 - i.MaxWidth = 2 + i.Width = 2 i.Op = i.ZeroOp i.Mode = i.ZeroMode } else { - i.MinWidth = 3 - i.MaxWidth = 3 - + i.Width = 3 } } @@ -461,7 +447,7 @@ func (i *I) computeOp(c context.Context, setWidth bool, final bool) (bool, error i.ZeroOp = 0 i.ZeroMode = 0 - switch i.MinWidth { + switch i.Width { case 2: // TODO(zellyn): Warn if > 0xff i.Data = []byte{i.Op, byte(val)}