From 498b6c5a7d4764909591315363b41b3f3a0b4dff Mon Sep 17 00:00:00 2001 From: Zellyn Hunter Date: Tue, 9 Sep 2014 17:32:15 -0700 Subject: [PATCH] Only call compute on second pass. --- asm/asm.go | 46 ++++++--------- asm/flavors/oldschool/oldschool.go | 4 +- asm/flavors/tests/simple_parse_test.go | 6 +- asm/inst/instruction.go | 79 +++++++++----------------- 4 files changed, 49 insertions(+), 86 deletions(-) diff --git a/asm/asm.go b/asm/asm.go index 5c31b32..6228fff 100644 --- a/asm/asm.go +++ b/asm/asm.go @@ -71,10 +71,15 @@ func (a *Assembler) Load(filename string, prefix int) error { return parseErr } - if _, err := a.passInst(&in, false); err != nil { - return err + if in.Type == inst.TypeOrg { + a.Ctx.SetAddr(in.Addr) } + // Update address + addr := a.Ctx.GetAddr() + in.Addr = addr + a.Ctx.SetAddr(addr + in.Width) + switch in.Type { case inst.TypeUnknown: if parseErr != nil { @@ -200,41 +205,26 @@ func (a *Assembler) initPass() { a.Ctx.SetAddr(a.Flavor.DefaultOrigin()) } -// 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) { - if in.Type == inst.TypeOrg { - a.Ctx.SetAddr(in.Addr) - return true, nil - } - isFinal, err = in.Compute(a.Ctx, final) - if err != nil { - return false, err - } - - // Update address - addr := a.Ctx.GetAddr() - in.Addr = addr - a.Ctx.SetAddr(addr + in.Width) - - return isFinal, nil -} - // Pass2 performs the second assembly pass. It returns an error for // any instruction that cannot be finalized. func (a *Assembler) Pass2() error { a.initPass() for _, in := range a.Insts { - instFinal, err := a.passInst(in, true) + if in.Type == inst.TypeOrg { + a.Ctx.SetAddr(in.Addr) + continue + } + + err := in.Compute(a.Ctx) if err != nil { return err } - if !instFinal { - return in.Errorf("cannot finalize instruction: %s", in) - } + + // Update address + addr := a.Ctx.GetAddr() + in.Addr = addr + a.Ctx.SetAddr(addr + in.Width) } return nil diff --git a/asm/flavors/oldschool/oldschool.go b/asm/flavors/oldschool/oldschool.go index 384c46f..00f8ebd 100644 --- a/asm/flavors/oldschool/oldschool.go +++ b/asm/flavors/oldschool/oldschool.go @@ -581,11 +581,11 @@ func (a *Base) ParseEquate(ctx context.Context, in inst.I, lp *lines.Parse) (ins return in, err } - xyzzy, err := expr.Eval(ctx, in.Line) + val, err := expr.Eval(ctx, in.Line) if err != nil { return in, err } - _ = xyzzy + ctx.Set(in.Label, val) in.Exprs = append(in.Exprs, expr) in.Width = 0 in.Final = true diff --git a/asm/flavors/tests/simple_parse_test.go b/asm/flavors/tests/simple_parse_test.go index 1e8ef6e..d78739f 100644 --- a/asm/flavors/tests/simple_parse_test.go +++ b/asm/flavors/tests/simple_parse_test.go @@ -248,10 +248,8 @@ func TestSimpleCommonFunctions(t *testing.T) { ctx.Set("L5", 0xcdef) if in.Type != inst.TypeOrg { - _, err = in.Compute(ctx, true) - - if err != nil { - t.Errorf(`%d. %s.ParseInstr("%s"): %s.Compute(tt.f, true) => error: %s`, i, tt.f, tt.i, in, err) + if err = in.Compute(ctx); err != nil { + t.Errorf(`%d. %s.ParseInstr("%s"): %s.Compute(tt.f) => error: %s`, i, tt.f, tt.i, in, err) continue } } diff --git a/asm/inst/instruction.go b/asm/inst/instruction.go index d4b4bd4..f3fd8de 100644 --- a/asm/inst/instruction.go +++ b/asm/inst/instruction.go @@ -191,42 +191,36 @@ func (i I) String() string { } // Compute attempts to finalize the instruction. -func (i *I) Compute(c context.Context, final bool) (bool, error) { - // xyzzy - remove - if i.Type == TypeOrg { - panic("Compute called with TypeOrg") - return true, nil - } +func (i *I) Compute(c context.Context) error { if i.Type == TypeEqu || i.Type == TypeTarget { - return i.computeMustKnow(c, final) + return i.computeMustKnow(c) } if i.Final { - return true, nil + return nil } switch i.Type { case TypeOp: - return i.computeOp(c, final) + return i.computeOp(c) case TypeData: - return i.computeData(c, final) + return i.computeData(c) case TypeBlock: - return i.computeBlock(c, final) + panic("Compute called with TypeBlock") } // Everything else is zero-width i.Width = 0 i.Final = true - return true, nil + return nil } -func (i *I) computeData(c context.Context, final bool) (bool, error) { +func (i *I) computeData(c context.Context) error { if len(i.Data) > 0 { i.Width = uint16(len(i.Data)) i.Final = true - return true, nil + return nil } - allFinal := true data := []byte{} var width uint16 for _, e := range i.Exprs { @@ -240,15 +234,9 @@ func (i *I) computeData(c context.Context, final bool) (bool, error) { w = 2 } width += w - val, labelMissing, err := e.CheckedEval(c, i.Line) - if err != nil && !labelMissing { - return false, err - } - if labelMissing { - allFinal = false - if final { - return false, err - } + val, err := e.Eval(c, i.Line) + if err != nil { + return err } switch i.Var { case VarMixed: @@ -269,12 +257,9 @@ func (i *I) computeData(c context.Context, final bool) (bool, error) { } } i.Width = width - if allFinal { - i.Data = data - i.Final = true - } - - return i.Final, nil + i.Data = data + i.Final = true + return nil } func (i *I) computeBlock(c context.Context, final bool) (bool, error) { @@ -291,46 +276,36 @@ func (i *I) computeBlock(c context.Context, final bool) (bool, error) { return i.Final, nil } -func (i *I) computeMustKnow(c context.Context, final bool) (bool, error) { +func (i *I) computeMustKnow(c context.Context) error { i.Width = 0 i.Final = true val, err := i.Exprs[0].Eval(c, i.Line) if err != nil { - return false, err + return err } i.Value = val switch i.Type { case TypeTarget: - return false, errors.New("Target not implemented yet.") + return errors.New("Target not implemented yet.") case TypeOrg: c.SetAddr(val) case TypeEqu: c.Set(i.Label, val) // Don't handle labels. - return true, nil + return nil } - return true, nil + return nil } -func (i *I) computeOp(c context.Context, final bool) (bool, error) { - // If the width is not known, we better have a ZeroPage alternative. +func (i *I) computeOp(c context.Context) error { // An op with no args would be final already, so we must have an Expression. if len(i.Exprs) == 0 { panic(fmt.Sprintf("Reached computeOp for '%s' with no expressions", i.Command)) } - val, labelMissing, err := i.Exprs[0].CheckedEval(c, i.Line) + val, err := i.Exprs[0].Eval(c, i.Line) // A real error - if !labelMissing && err != nil { - return false, err - } - - if labelMissing { - // Don't know, do care. - if final { - return false, err - } - - return false, nil + if err != nil { + return err } // If we got here, we got an actual value. @@ -340,10 +315,10 @@ func (i *I) computeOp(c context.Context, final bool) (bool, error) { curr := c.GetAddr() offset := int32(val) - (int32(curr) + 2) if offset > 127 { - return false, i.Errorf("%s cannot jump forward %d (max 127) from $%04x to $%04x", i.Command, offset, curr+2, val) + return i.Errorf("%s cannot jump forward %d (max 127) from $%04x to $%04x", i.Command, offset, curr+2, val) } if offset < -128 { - return false, i.Errorf("%s cannot jump back %d (max -128) from $%04x to $%04x", i.Command, offset, curr+2, val) + return i.Errorf("%s cannot jump back %d (max -128) from $%04x to $%04x", i.Command, offset, curr+2, val) } val = uint16(offset) } @@ -359,7 +334,7 @@ func (i *I) computeOp(c context.Context, final bool) (bool, error) { default: panic(fmt.Sprintf("computeOp reached erroneously for '%s'", i.Command)) } - return true, nil + return nil } func (i I) Errorf(format string, a ...interface{}) error {