@@ -9,11 +9,214 @@ import (
9
9
"testing"
10
10
)
11
11
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
+
12
23
func init () {
13
24
// Required for tests that access any of
14
25
// opindex/ycover/reg/regrex global tables.
15
26
var ctxt obj.Link
16
27
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):\n have: %d\n want: %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
+ })
17
220
}
18
221
19
222
func TestRegisterListEncDec (t * testing.T ) {
0 commit comments