add Symbol type to operand
This commit is contained in:
@@ -10,17 +10,35 @@ type Op interface {
|
|||||||
Asm() string
|
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 {
|
type Mem struct {
|
||||||
Disp int
|
Symbol Symbol
|
||||||
Base reg.Register
|
Disp int
|
||||||
Index reg.Register
|
Base reg.Register
|
||||||
Scale uint8
|
Index reg.Register
|
||||||
|
Scale uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Mem) Asm() string {
|
func (m Mem) Asm() string {
|
||||||
a := ""
|
a := m.Symbol.String()
|
||||||
if m.Disp != 0 {
|
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 {
|
if m.Base != nil {
|
||||||
a += fmt.Sprintf("(%s)", m.Base.Asm())
|
a += fmt.Sprintf("(%s)", m.Base.Asm())
|
||||||
|
|||||||
@@ -7,6 +7,23 @@ import (
|
|||||||
"github.com/mmcloughlin/avo/reg"
|
"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) {
|
func TestMemAsm(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Mem Mem
|
Mem Mem
|
||||||
@@ -14,11 +31,16 @@ func TestMemAsm(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{Mem{Base: reg.EAX}, "(AX)"},
|
{Mem{Base: reg.EAX}, "(AX)"},
|
||||||
{Mem{Disp: 16, Base: reg.RAX}, "16(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: 4}, "(R11)(AX*4)"},
|
||||||
{Mem{Base: reg.R11, Index: reg.RAX, Scale: 1}, "(R11)(AX*1)"},
|
{Mem{Base: reg.R11, Index: reg.RAX, Scale: 1}, "(R11)(AX*1)"},
|
||||||
{Mem{Base: reg.R11, Index: reg.RAX}, "(R11)"},
|
{Mem{Base: reg.R11, Index: reg.RAX}, "(R11)"},
|
||||||
{Mem{Base: reg.R11, Scale: 8}, "(R11)"},
|
{Mem{Base: reg.R11, Scale: 8}, "(R11)"},
|
||||||
{Mem{Disp: 2048, Base: reg.R11, Index: reg.RAX, Scale: 8}, "2048(R11)(AX*8)"},
|
{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 {
|
for _, c := range cases {
|
||||||
got := c.Mem.Asm()
|
got := c.Mem.Asm()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ func TestSpecBytes(t *testing.T) {
|
|||||||
Spec Spec
|
Spec Spec
|
||||||
Bytes uint
|
Bytes uint
|
||||||
}{
|
}{
|
||||||
|
{S0, 0},
|
||||||
{S8L, 1},
|
{S8L, 1},
|
||||||
{S8H, 1},
|
{S8H, 1},
|
||||||
{S16, 2},
|
{S16, 2},
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ func (r register) register() {}
|
|||||||
type Spec uint16
|
type Spec uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
S0 Spec = 0x0 // zero value reserved for pseudo registers
|
||||||
S8L Spec = 0x1
|
S8L Spec = 0x1
|
||||||
S8H Spec = 0x2
|
S8H Spec = 0x2
|
||||||
S8 = S8L
|
S8 = S8L
|
||||||
|
|||||||
14
reg/x86.go
14
reg/x86.go
@@ -2,13 +2,15 @@ package reg
|
|||||||
|
|
||||||
// Register families.
|
// Register families.
|
||||||
const (
|
const (
|
||||||
GP Kind = iota
|
Internal Kind = iota
|
||||||
|
GP
|
||||||
MMX
|
MMX
|
||||||
SSEAVX
|
SSEAVX
|
||||||
Mask
|
Mask
|
||||||
)
|
)
|
||||||
|
|
||||||
var Families = []*Family{
|
var Families = []*Family{
|
||||||
|
Pseudo,
|
||||||
GeneralPurpose,
|
GeneralPurpose,
|
||||||
SIMD,
|
SIMD,
|
||||||
}
|
}
|
||||||
@@ -25,6 +27,16 @@ func FamilyOfKind(k Kind) *Family {
|
|||||||
return familiesByKind[k]
|
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.
|
// General purpose registers.
|
||||||
var (
|
var (
|
||||||
GeneralPurpose = &Family{Kind: GP}
|
GeneralPurpose = &Family{Kind: GP}
|
||||||
|
|||||||
Reference in New Issue
Block a user