Skip to content

Commit 2e4edf4

Browse files
committed
cmd/internal/obj/x86: add oclass function tests
To make refactoring/optimizations easier in future. Change-Id: I158f52af7c72849df1d6bd9334b3ce9dd199318f Reviewed-on: https://go-review.googlesource.com/c/go/+/175357 Run-TryBot: Iskander Sharipov <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 83f205f commit 2e4edf4

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed

src/cmd/internal/obj/x86/asm_test.go

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,214 @@ import (
99
"testing"
1010
)
1111

12+
type oclassTest struct {
13+
arg *obj.Addr
14+
want int // Expected oclass return value for a given arg
15+
}
16+
17+
// Filled inside init, because it's easier to do with helper functions.
18+
var (
19+
oclassTestsAMD64 []*oclassTest
20+
oclassTests386 []*oclassTest
21+
)
22+
1223
func init() {
1324
// Required for tests that access any of
1425
// opindex/ycover/reg/regrex global tables.
1526
var ctxt obj.Link
1627
instinit(&ctxt)
28+
29+
regAddr := func(reg int16) *obj.Addr {
30+
return &obj.Addr{Type: obj.TYPE_REG, Reg: reg}
31+
}
32+
immAddr := func(v int64) *obj.Addr {
33+
return &obj.Addr{Type: obj.TYPE_CONST, Offset: v}
34+
}
35+
regListAddr := func(regFrom, regTo int16) *obj.Addr {
36+
return &obj.Addr{Type: obj.TYPE_REGLIST, Offset: EncodeRegisterRange(regFrom, regTo)}
37+
}
38+
memAddr := func(base, index int16) *obj.Addr {
39+
return &obj.Addr{Type: obj.TYPE_MEM, Reg: base, Index: index}
40+
}
41+
42+
// TODO(quasilyte): oclass doesn't return Yxxx for X/Y regs with
43+
// ID higher than 7. We don't encode such instructions, but this
44+
// behavior seems inconsistent. It should probably either
45+
// never check for arch or do it in all cases.
46+
47+
oclassTestsCommon := []*oclassTest{
48+
{&obj.Addr{Type: obj.TYPE_NONE}, Ynone},
49+
{&obj.Addr{Type: obj.TYPE_BRANCH}, Ybr},
50+
{&obj.Addr{Type: obj.TYPE_TEXTSIZE}, Ytextsize},
51+
52+
{&obj.Addr{Type: obj.TYPE_INDIR, Name: obj.NAME_EXTERN}, Yindir},
53+
{&obj.Addr{Type: obj.TYPE_INDIR, Name: obj.NAME_GOTREF}, Yindir},
54+
55+
{&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_AUTO}, Yiauto},
56+
{&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_PARAM}, Yiauto},
57+
{&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN}, Yiauto},
58+
{&obj.Addr{Type: obj.TYPE_ADDR, Sym: &obj.LSym{Name: "runtime.duff"}}, Yi32},
59+
{&obj.Addr{Type: obj.TYPE_ADDR, Offset: 4}, Yu7},
60+
{&obj.Addr{Type: obj.TYPE_ADDR, Offset: 255}, Yu8},
61+
62+
{immAddr(0), Yi0},
63+
{immAddr(1), Yi1},
64+
{immAddr(2), Yu2},
65+
{immAddr(3), Yu2},
66+
{immAddr(4), Yu7},
67+
{immAddr(86), Yu7},
68+
{immAddr(127), Yu7},
69+
{immAddr(128), Yu8},
70+
{immAddr(200), Yu8},
71+
{immAddr(255), Yu8},
72+
{immAddr(-1), Yi8},
73+
{immAddr(-100), Yi8},
74+
{immAddr(-128), Yi8},
75+
76+
{regAddr(REG_AL), Yal},
77+
{regAddr(REG_AX), Yax},
78+
{regAddr(REG_DL), Yrb},
79+
{regAddr(REG_DH), Yrb},
80+
{regAddr(REG_BH), Yrb},
81+
{regAddr(REG_CL), Ycl},
82+
{regAddr(REG_CX), Ycx},
83+
{regAddr(REG_DX), Yrx},
84+
{regAddr(REG_BX), Yrx},
85+
{regAddr(REG_F0), Yf0},
86+
{regAddr(REG_F3), Yrf},
87+
{regAddr(REG_F7), Yrf},
88+
{regAddr(REG_M0), Ymr},
89+
{regAddr(REG_M3), Ymr},
90+
{regAddr(REG_M7), Ymr},
91+
{regAddr(REG_X0), Yxr0},
92+
{regAddr(REG_X6), Yxr},
93+
{regAddr(REG_X13), Yxr},
94+
{regAddr(REG_X20), YxrEvex},
95+
{regAddr(REG_X31), YxrEvex},
96+
{regAddr(REG_Y0), Yyr},
97+
{regAddr(REG_Y6), Yyr},
98+
{regAddr(REG_Y13), Yyr},
99+
{regAddr(REG_Y20), YyrEvex},
100+
{regAddr(REG_Y31), YyrEvex},
101+
{regAddr(REG_Z0), Yzr},
102+
{regAddr(REG_Z6), Yzr},
103+
{regAddr(REG_K0), Yk0},
104+
{regAddr(REG_K5), Yknot0},
105+
{regAddr(REG_K7), Yknot0},
106+
{regAddr(REG_CS), Ycs},
107+
{regAddr(REG_SS), Yss},
108+
{regAddr(REG_DS), Yds},
109+
{regAddr(REG_ES), Yes},
110+
{regAddr(REG_FS), Yfs},
111+
{regAddr(REG_GS), Ygs},
112+
{regAddr(REG_TLS), Ytls},
113+
{regAddr(REG_GDTR), Ygdtr},
114+
{regAddr(REG_IDTR), Yidtr},
115+
{regAddr(REG_LDTR), Yldtr},
116+
{regAddr(REG_MSW), Ymsw},
117+
{regAddr(REG_TASK), Ytask},
118+
{regAddr(REG_CR0), Ycr0},
119+
{regAddr(REG_CR5), Ycr5},
120+
{regAddr(REG_CR8), Ycr8},
121+
{regAddr(REG_DR0), Ydr0},
122+
{regAddr(REG_DR5), Ydr5},
123+
{regAddr(REG_DR7), Ydr7},
124+
{regAddr(REG_TR0), Ytr0},
125+
{regAddr(REG_TR5), Ytr5},
126+
{regAddr(REG_TR7), Ytr7},
127+
128+
{regListAddr(REG_X0, REG_X3), YxrEvexMulti4},
129+
{regListAddr(REG_X4, REG_X7), YxrEvexMulti4},
130+
{regListAddr(REG_Y0, REG_Y3), YyrEvexMulti4},
131+
{regListAddr(REG_Y4, REG_Y7), YyrEvexMulti4},
132+
{regListAddr(REG_Z0, REG_Z3), YzrMulti4},
133+
{regListAddr(REG_Z4, REG_Z7), YzrMulti4},
134+
135+
{memAddr(REG_AL, REG_NONE), Ym},
136+
{memAddr(REG_AL, REG_SI), Ym},
137+
{memAddr(REG_SI, REG_CX), Ym},
138+
{memAddr(REG_DI, REG_X0), Yxvm},
139+
{memAddr(REG_DI, REG_X7), Yxvm},
140+
{memAddr(REG_DI, REG_Y0), Yyvm},
141+
{memAddr(REG_DI, REG_Y7), Yyvm},
142+
{memAddr(REG_DI, REG_Z0), Yzvm},
143+
{memAddr(REG_DI, REG_Z7), Yzvm},
144+
}
145+
146+
oclassTestsAMD64 = []*oclassTest{
147+
{immAddr(-200), Ys32},
148+
{immAddr(500), Ys32},
149+
{immAddr(0x7FFFFFFF), Ys32},
150+
{immAddr(0x7FFFFFFF + 1), Yi32},
151+
{immAddr(0xFFFFFFFF), Yi32},
152+
{immAddr(0xFFFFFFFF + 1), Yi64},
153+
154+
{regAddr(REG_BPB), Yrb},
155+
{regAddr(REG_SIB), Yrb},
156+
{regAddr(REG_DIB), Yrb},
157+
{regAddr(REG_R8B), Yrb},
158+
{regAddr(REG_R12B), Yrb},
159+
{regAddr(REG_R8), Yrl},
160+
{regAddr(REG_R13), Yrl},
161+
{regAddr(REG_R15), Yrl},
162+
{regAddr(REG_SP), Yrl},
163+
{regAddr(REG_SI), Yrl},
164+
{regAddr(REG_DI), Yrl},
165+
{regAddr(REG_Z13), Yzr},
166+
{regAddr(REG_Z20), Yzr},
167+
{regAddr(REG_Z31), Yzr},
168+
169+
{regListAddr(REG_X10, REG_X13), YxrEvexMulti4},
170+
{regListAddr(REG_X24, REG_X27), YxrEvexMulti4},
171+
{regListAddr(REG_Y10, REG_Y13), YyrEvexMulti4},
172+
{regListAddr(REG_Y24, REG_Y27), YyrEvexMulti4},
173+
{regListAddr(REG_Z10, REG_Z13), YzrMulti4},
174+
{regListAddr(REG_Z24, REG_Z27), YzrMulti4},
175+
176+
{memAddr(REG_DI, REG_X20), YxvmEvex},
177+
{memAddr(REG_DI, REG_X27), YxvmEvex},
178+
{memAddr(REG_DI, REG_Y20), YyvmEvex},
179+
{memAddr(REG_DI, REG_Y27), YyvmEvex},
180+
{memAddr(REG_DI, REG_Z20), Yzvm},
181+
{memAddr(REG_DI, REG_Z27), Yzvm},
182+
}
183+
184+
oclassTests386 = []*oclassTest{
185+
{&obj.Addr{Type: obj.TYPE_ADDR, Name: obj.NAME_EXTERN, Sym: &obj.LSym{}}, Yi32},
186+
187+
{immAddr(-200), Yi32},
188+
189+
{regAddr(REG_SP), Yrl32},
190+
{regAddr(REG_SI), Yrl32},
191+
{regAddr(REG_DI), Yrl32},
192+
}
193+
194+
// Add tests that are arch-independent for all sets.
195+
oclassTestsAMD64 = append(oclassTestsAMD64, oclassTestsCommon...)
196+
oclassTests386 = append(oclassTests386, oclassTestsCommon...)
197+
}
198+
199+
func TestOclass(t *testing.T) {
200+
runTest := func(t *testing.T, ctxt *obj.Link, tests []*oclassTest) {
201+
var p obj.Prog
202+
for _, test := range tests {
203+
have := oclass(ctxt, &p, test.arg)
204+
if have != test.want {
205+
t.Errorf("oclass(%q):\nhave: %d\nwant: %d",
206+
obj.Dconv(&p, test.arg), have, test.want)
207+
}
208+
}
209+
}
210+
211+
t.Run("AMD64", func(t *testing.T) {
212+
ctxtAMD64 := obj.Linknew(&Linkamd64)
213+
runTest(t, ctxtAMD64, oclassTestsAMD64)
214+
})
215+
216+
t.Run("386", func(t *testing.T) {
217+
ctxt386 := obj.Linknew(&Link386)
218+
runTest(t, ctxt386, oclassTests386)
219+
})
17220
}
18221

19222
func TestRegisterListEncDec(t *testing.T) {

0 commit comments

Comments
 (0)