1package reg
2
3import (
4	"testing"
5	"testing/quick"
6)
7
8func TestIDFields(t *testing.T) {
9	f := func(v uint8, kind Kind, idx Index) bool {
10		id := newid(v, kind, idx)
11		return id.Kind() == kind && id.Index() == idx
12	}
13	if err := quick.Check(f, nil); err != nil {
14		t.Fatal(err)
15	}
16}
17
18func TestIDIsVirtual(t *testing.T) {
19	cases := []Virtual{
20		GeneralPurpose.Virtual(42, S64),
21		Vector.Virtual(42, S128),
22	}
23	for _, r := range cases {
24		if !r.ID().IsVirtual() {
25			t.FailNow()
26		}
27	}
28}
29
30func TestIDIsPhysical(t *testing.T) {
31	cases := []Physical{AL, AH, AX, EAX, RAX, X1, Y2, Z31}
32	for _, r := range cases {
33		if !r.ID().IsPhysical() {
34			t.FailNow()
35		}
36	}
37}
38
39func TestSpecSize(t *testing.T) {
40	cases := []struct {
41		Spec Spec
42		Size uint
43	}{
44		{S0, 0},
45		{S8L, 1},
46		{S8H, 1},
47		{S16, 2},
48		{S32, 4},
49		{S64, 8},
50		{S128, 16},
51		{S256, 32},
52		{S512, 64},
53	}
54	for _, c := range cases {
55		if c.Spec.Size() != c.Size {
56			t.Errorf("%v.Size() = %d; expect = %d", c.Spec, c.Spec.Size(), c.Size)
57		}
58	}
59}
60
61func TestToVirtual(t *testing.T) {
62	v := GeneralPurpose.Virtual(42, S32)
63	if ToVirtual(v) != v {
64		t.Errorf("ToVirtual(v) != v for virtual register")
65	}
66	if ToVirtual(ECX) != nil {
67		t.Errorf("ToVirtual should be nil for physical registers")
68	}
69}
70
71func TestToPhysical(t *testing.T) {
72	v := GeneralPurpose.Virtual(42, S32)
73	if ToPhysical(v) != nil {
74		t.Errorf("ToPhysical should be nil for virtual registers")
75	}
76	if ToPhysical(ECX) != ECX {
77		t.Errorf("ToPhysical(p) != p for physical register")
78	}
79}
80
81func TestFamilyLookup(t *testing.T) {
82	cases := []struct {
83		Family *Family
84		ID     Index
85		Spec   Spec
86		Expect Physical
87	}{
88		{GeneralPurpose, 0, S8, AL},
89		{GeneralPurpose, 1, S8L, CL},
90		{GeneralPurpose, 2, S8H, DH},
91		{GeneralPurpose, 3, S16, BX},
92		{GeneralPurpose, 9, S32, R9L},
93		{GeneralPurpose, 13, S64, R13},
94		{GeneralPurpose, 13, S512, nil},
95		{GeneralPurpose, 133, S64, nil},
96		{Vector, 1, S128, X1},
97		{Vector, 13, S256, Y13},
98		{Vector, 27, S512, Z27},
99		{Vector, 1, S16, nil},
100		{Vector, 299, S256, nil},
101	}
102	for _, c := range cases {
103		got := c.Family.Lookup(c.ID, c.Spec)
104		if got != c.Expect {
105			t.Errorf("idx=%v spec=%v: lookup got %v expect %v", c.ID, c.Spec, got, c.Expect)
106		}
107	}
108}
109
110func TestPhysicalAs(t *testing.T) {
111	cases := []struct {
112		Register Physical
113		Spec     Spec
114		Expect   Physical
115	}{
116		{DX, S8L, DL},
117		{DX, S8H, DH},
118		{DX, S8, DL},
119		{DX, S16, DX},
120		{DX, S32, EDX},
121		{DX, S64, RDX},
122		{DX, S256, nil},
123	}
124	for _, c := range cases {
125		got := c.Register.as(c.Spec)
126		if got != c.Expect {
127			t.Errorf("%s.as(%v) = %v; expect %v", c.Register.Asm(), c.Spec, got, c.Expect)
128		}
129	}
130}
131
132func TestVirtualAs(t *testing.T) {
133	v := GeneralPurpose.Virtual(0, S64)
134	specs := []Spec{S8, S8L, S8H, S16, S32, S64}
135	for _, s := range specs {
136		if v.as(s).Mask() != s.Mask() {
137			t.FailNow()
138		}
139	}
140}
141
142func TestLookupPhysical(t *testing.T) {
143	cases := []struct {
144		Kind   Kind
145		Index  Index
146		Spec   Spec
147		Expect Physical
148	}{
149		{KindGP, 0, S8L, AL},
150		{KindGP, 1, S8H, CH},
151		{KindGP, 7, S8, DIB},
152		{KindGP, 8, S16, R8W},
153		{KindGP, 9, S32, R9L},
154		{KindGP, 10, S64, R10},
155
156		{KindVector, 7, S128, X7},
157		{KindVector, 17, S256, Y17},
158		{KindVector, 27, S512, Z27},
159	}
160	for _, c := range cases {
161		if got := LookupPhysical(c.Kind, c.Index, c.Spec); !Equal(got, c.Expect) {
162			t.FailNow()
163		}
164	}
165}
166
167func TestLookupIDSelf(t *testing.T) {
168	cases := []Physical{AL, AH, AX, EAX, RAX, X1, Y2, Z31}
169	for _, r := range cases {
170		if got := LookupID(r.ID(), r.spec()); !Equal(got, r) {
171			t.FailNow()
172		}
173	}
174}
175