diff --git a/operand/types.go b/operand/types.go index d53ac31..9952213 100644 --- a/operand/types.go +++ b/operand/types.go @@ -10,17 +10,35 @@ type Op interface { Asm() string } +type Symbol struct { + Name string + Static bool +} + +func (s Symbol) String() string { + n := s.Name + if s.Static { + n += "<>" + } + return n +} + type Mem struct { - Disp int - Base reg.Register - Index reg.Register - Scale uint8 + Symbol Symbol + Disp int + Base reg.Register + Index reg.Register + Scale uint8 } func (m Mem) Asm() string { - a := "" + a := m.Symbol.String() if m.Disp != 0 { - a += fmt.Sprintf("%d", m.Disp) + if a == "" { + a += fmt.Sprintf("%d", m.Disp) + } else { + a += fmt.Sprintf("%+d", m.Disp) + } } if m.Base != nil { a += fmt.Sprintf("(%s)", m.Base.Asm()) diff --git a/operand/types_test.go b/operand/types_test.go index e3e13d7..c9cf89e 100644 --- a/operand/types_test.go +++ b/operand/types_test.go @@ -7,6 +7,23 @@ import ( "github.com/mmcloughlin/avo/reg" ) +func TestSymbolString(t *testing.T) { + cases := []struct { + Symbol Symbol + Expect string + }{ + {Symbol{}, ""}, + {Symbol{Name: "name"}, "name"}, + {Symbol{Name: "static", Static: true}, "static<>"}, + } + for _, c := range cases { + got := c.Symbol.String() + if got != c.Expect { + t.Errorf("%#v.String() = %s expected %s", c.Symbol, got, c.Expect) + } + } +} + func TestMemAsm(t *testing.T) { cases := []struct { Mem Mem @@ -14,11 +31,16 @@ func TestMemAsm(t *testing.T) { }{ {Mem{Base: reg.EAX}, "(AX)"}, {Mem{Disp: 16, Base: reg.RAX}, "16(AX)"}, + {Mem{Disp: -7, Base: reg.RAX}, "-7(AX)"}, {Mem{Base: reg.R11, Index: reg.RAX, Scale: 4}, "(R11)(AX*4)"}, {Mem{Base: reg.R11, Index: reg.RAX, Scale: 1}, "(R11)(AX*1)"}, {Mem{Base: reg.R11, Index: reg.RAX}, "(R11)"}, {Mem{Base: reg.R11, Scale: 8}, "(R11)"}, {Mem{Disp: 2048, Base: reg.R11, Index: reg.RAX, Scale: 8}, "2048(R11)(AX*8)"}, + {Mem{Symbol: Symbol{Name: "foo"}, Base: reg.StaticBase}, "foo(SB)"}, + {Mem{Symbol: Symbol{Name: "foo"}, Base: reg.StaticBase, Disp: 4}, "foo+4(SB)"}, + {Mem{Symbol: Symbol{Name: "foo"}, Base: reg.StaticBase, Disp: -7}, "foo-7(SB)"}, + {Mem{Symbol: Symbol{Name: "bar", Static: true}, Base: reg.StaticBase, Disp: 4, Index: reg.R11, Scale: 4}, "bar<>+4(SB)(R11*4)"}, } for _, c := range cases { got := c.Mem.Asm() diff --git a/reg/reg_test.go b/reg/reg_test.go index 14ee949..9959e4b 100644 --- a/reg/reg_test.go +++ b/reg/reg_test.go @@ -7,6 +7,7 @@ func TestSpecBytes(t *testing.T) { Spec Spec Bytes uint }{ + {S0, 0}, {S8L, 1}, {S8H, 1}, {S16, 2}, diff --git a/reg/types.go b/reg/types.go index 7a227c7..7876804 100644 --- a/reg/types.go +++ b/reg/types.go @@ -140,6 +140,7 @@ func (r register) register() {} type Spec uint16 const ( + S0 Spec = 0x0 // zero value reserved for pseudo registers S8L Spec = 0x1 S8H Spec = 0x2 S8 = S8L diff --git a/reg/x86.go b/reg/x86.go index 9385231..3f91baf 100644 --- a/reg/x86.go +++ b/reg/x86.go @@ -2,13 +2,15 @@ package reg // Register families. const ( - GP Kind = iota + Internal Kind = iota + GP MMX SSEAVX Mask ) var Families = []*Family{ + Pseudo, GeneralPurpose, SIMD, } @@ -25,6 +27,16 @@ func FamilyOfKind(k Kind) *Family { return familiesByKind[k] } +// Pseudo registers. +var ( + Pseudo = &Family{Kind: Internal} + + FramePointer = Pseudo.define(S0, 0, "FP") + ProgramCounter = Pseudo.define(S0, 0, "PC") + StaticBase = Pseudo.define(S0, 0, "SB") + StackPointer = Pseudo.define(S0, 0, "SP") +) + // General purpose registers. var ( GeneralPurpose = &Family{Kind: GP}