Simplified: it's now a two-pass assembler. More to come.

This commit is contained in:
Zellyn Hunter 2014-08-08 15:55:33 -07:00
parent 3da6efc546
commit 17d0dc1d69
11 changed files with 87 additions and 148 deletions

View File

@ -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)
}
}

View File

@ -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'

View File

@ -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.")
}

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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)}