1
2
3
4
5 package arm64
6
7 import (
8 "testing"
9 )
10
11
12 func TestOperandParsing(t *testing.T) {
13 tests := []struct {
14 name string
15 template string
16 resultInArg0 bool
17
18
19 wantTokenText []string
20
21
22 wantTypes []OperandType
23 wantIsDest []bool
24
25
26 wantCount int
27 wantClasses []string
28 wantRoles []string
29 wantListNums []int
30 }{
31 {
32 name: "ADD simple binary - from add_advsimd.xml",
33 template: "ADD <Vd>.<T>, <Vn>.<T>, <Vm>.<T>",
34 resultInArg0: false,
35 wantTokenText: []string{"<Vd>.<T>", "<Vn>.<T>", "<Vm>.<T>"},
36 wantTypes: []OperandType{OperandVReg, OperandVReg, OperandVReg},
37 wantIsDest: []bool{true, false, false},
38 wantCount: 3,
39 wantClasses: []string{"vreg", "vreg", "vreg"},
40 wantRoles: []string{"destination", "op0", "op1"},
41 wantListNums: []int{-1, -1, -1},
42 },
43 {
44 name: "TBL with list operand - from tbl_advsimd.xml",
45 template: "TBL <Vd>.8B, { <Vn>.16B, <Vn+1>.16B }, <Vm>.8B",
46 resultInArg0: false,
47 wantTokenText: []string{"<Vd>.8B", "{ <Vn>.16B, <Vn+1>.16B }", "<Vm>.8B"},
48 wantTypes: []OperandType{OperandVReg, OperandList, OperandVReg},
49 wantIsDest: []bool{true, false, false},
50 wantCount: 3,
51 wantClasses: []string{"vreg", "vreg", "vreg"},
52 wantRoles: []string{"destination", "op0", "op1"},
53 wantListNums: []int{-1, 0, -1},
54 },
55 {
56 name: "MOVI with optional LSL modifier - from movi_advsimd.xml",
57 template: "MOVI <Vd>.4S, #<imm8>{, LSL #<amount>}",
58 resultInArg0: false,
59 wantTokenText: []string{"<Vd>.4S", "#<imm8>{, LSL #<amount>}"},
60 wantTypes: []OperandType{OperandVReg, OperandImm},
61 wantIsDest: []bool{true, false},
62 wantCount: 2,
63 wantClasses: []string{"vreg", "immediate"},
64 wantRoles: []string{"destination", "imm8"},
65 wantListNums: []int{-1, -1},
66 },
67 {
68 name: "BIC with optional LSL modifier - from bic_advsimd_imm.xml",
69 template: "BIC <Vd>.2S, #<imm8>{, LSL #<amount>}",
70 resultInArg0: false,
71 wantTokenText: []string{"<Vd>.2S", "#<imm8>{, LSL #<amount>}"},
72 wantTypes: []OperandType{OperandVReg, OperandImm},
73 wantIsDest: []bool{true, false},
74 wantCount: 2,
75 wantClasses: []string{"vreg", "immediate"},
76 wantRoles: []string{"destination", "imm8"},
77 wantListNums: []int{-1, -1},
78 },
79 {
80 name: "INS element to element - from ins_advsimd_elt.xml",
81 template: "INS <Vd>.4S[<index1>], <Vn>.4S[<index2>]",
82 resultInArg0: true,
83 wantTokenText: []string{"<Vd>.4S[<index1>]", "<Vn>.4S[<index2>]"},
84 wantTypes: []OperandType{OperandVElem, OperandVElem},
85 wantIsDest: []bool{true, false},
86 wantCount: 5,
87 wantClasses: []string{"vreg", "immediate", "immediate", "vreg", "vreg"},
88 wantRoles: []string{"destination", "destination_i", "op0_i", "original", "op0"},
89 wantListNums: []int{-1, -1, -1, -1, -1},
90 },
91 {
92 name: "INS general register to element - from ins_advsimd_gen.xml",
93 template: "INS <Vd>.4S[<index1>], <Wn>",
94 resultInArg0: false,
95 wantTokenText: []string{"<Vd>.4S[<index1>]", "<Wn>"},
96 wantTypes: []OperandType{OperandVElem, OperandGReg},
97 wantIsDest: []bool{true, false},
98 wantCount: 4,
99 wantClasses: []string{"vreg", "immediate", "vreg", "greg"},
100 wantRoles: []string{"destination", "destination_i", "original", "op0"},
101 wantListNums: []int{-1, -1, -1, -1},
102 },
103 {
104 name: "UMOV to general register - from umov_advsimd.xml",
105 template: "UMOV <Wd>, <Vn>.4S[<index>]",
106 resultInArg0: false,
107 wantTokenText: []string{"<Wd>", "<Vn>.4S[<index>]"},
108 wantTypes: []OperandType{OperandGReg, OperandVElem},
109 wantIsDest: []bool{true, false},
110 wantCount: 3,
111 wantClasses: []string{"greg", "immediate", "vreg"},
112 wantRoles: []string{"destination", "op0_i", "op0"},
113 wantListNums: []int{-1, -1, -1},
114 },
115 {
116 name: "SHL immediate - from shl_advsimd.xml",
117 template: "SHL <Vd>.<T>, <Vn>.<T>, #<shift>",
118 resultInArg0: false,
119 wantTokenText: []string{"<Vd>.<T>", "<Vn>.<T>", "#<shift>"},
120 wantTypes: []OperandType{OperandVReg, OperandVReg, OperandImm},
121 wantIsDest: []bool{true, false, false},
122 wantCount: 3,
123 wantClasses: []string{"vreg", "immediate", "vreg"},
124 wantRoles: []string{"destination", "shift", "op0"},
125 wantListNums: []int{-1, -1, -1},
126 },
127 {
128 name: "TBX with list (with resultInArg0) - from tbx_advsimd.xml",
129 template: "TBX <Vd>.8B, { <Vn>.16B, <Vn+1>.16B }, <Vm>.8B",
130 resultInArg0: true,
131 wantTokenText: []string{"<Vd>.8B", "{ <Vn>.16B, <Vn+1>.16B }", "<Vm>.8B"},
132 wantTypes: []OperandType{OperandVReg, OperandList, OperandVReg},
133 wantIsDest: []bool{true, false, false},
134 wantCount: 4,
135 wantClasses: []string{"vreg", "vreg", "vreg", "vreg"},
136 wantRoles: []string{"destination", "original", "op0", "op1"},
137 wantListNums: []int{-1, -1, 0, -1},
138 },
139 }
140
141 for _, tt := range tests {
142 t.Run(tt.name, func(t *testing.T) {
143
144 tokens := tokenizeTemplate(tt.template)
145
146 if !requireEqual(t, len(tt.wantTokenText), len(tokens)) {
147 return
148 }
149
150 for i := range tokens {
151 requireEqual(t, tt.wantTokenText[i], tokens[i].text)
152 requireEqual(t, i, tokens[i].asmPos)
153 }
154
155
156 parsed := classifyTokens(tokens)
157
158 if !requireEqual(t, len(tt.wantTypes), len(parsed)) {
159 return
160 }
161
162 for i := range parsed {
163 requireEqual(t, tt.wantTypes[i], parsed[i].operandType)
164 requireEqual(t, tt.wantIsDest[i], parsed[i].isDestination)
165 }
166
167
168 operands := buildOperandList(parsed, tt.resultInArg0)
169
170 if !requireEqual(t, tt.wantCount, len(operands)) {
171 return
172 }
173
174 for i := range operands {
175 requireEqual(t, tt.wantClasses[i], operands[i].Class)
176 requireEqual(t, tt.wantRoles[i], operands[i].Role)
177 requireEqual(t, tt.wantListNums[i], operands[i].ListNumber)
178 }
179 })
180 }
181 }
182
183
184 func TestOperandInstantiateBits(t *testing.T) {
185 tests := []struct {
186 name string
187 mnemonic string
188 arrangement Arrangement
189 wantBits int
190 }{
191 {
192 name: "INS 16B element - 8-bit greg",
193 mnemonic: "INS",
194 arrangement: Arrangement{
195 arrangement: "16B",
196 bits: 128,
197 elemBits: 8,
198 lanes: 16,
199 baseType: "uint",
200 },
201 wantBits: 8,
202 },
203 {
204 name: "INS 8H element - 16-bit greg",
205 mnemonic: "INS",
206 arrangement: Arrangement{
207 arrangement: "8H",
208 bits: 128,
209 elemBits: 16,
210 lanes: 8,
211 baseType: "uint",
212 },
213 wantBits: 16,
214 },
215 {
216 name: "INS 4S element - 32-bit greg",
217 mnemonic: "INS",
218 arrangement: Arrangement{
219 arrangement: "4S",
220 bits: 128,
221 elemBits: 32,
222 lanes: 4,
223 baseType: "uint",
224 },
225 wantBits: 32,
226 },
227 {
228 name: "INS 2D element - 64-bit greg",
229 mnemonic: "INS",
230 arrangement: Arrangement{
231 arrangement: "2D",
232 bits: 128,
233 elemBits: 64,
234 lanes: 2,
235 baseType: "uint",
236 },
237 wantBits: 64,
238 },
239 }
240
241 for _, tt := range tests {
242 t.Run(tt.name, func(t *testing.T) {
243 op := &Operand{
244 Type: OperandGReg,
245 Class: "greg",
246 Role: "op0",
247 ListNumber: -1,
248 }
249 op.instantiate(tt.arrangement, DefaultArngs, 1, tt.mnemonic)
250 requireEqual(t, tt.wantBits, op.Bits)
251 })
252 }
253 }
254
View as plain text