Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/tests/AssemblyBuilderA64.test.cpp
2723 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "Luau/AssemblyBuilderA64.h"
3
#include "Luau/StringUtils.h"
4
#include "ScopedFlags.h"
5
6
#include "doctest.h"
7
8
#include <string.h>
9
10
11
using namespace Luau::CodeGen;
12
using namespace Luau::CodeGen::A64;
13
14
static std::string bytecodeAsArray(const std::vector<uint8_t>& bytecode)
15
{
16
std::string result = "{";
17
18
for (size_t i = 0; i < bytecode.size(); i++)
19
Luau::formatAppend(result, "%s0x%02x", i == 0 ? "" : ", ", bytecode[i]);
20
21
return result.append("}");
22
}
23
24
static std::string bytecodeAsArray(const std::vector<uint32_t>& code)
25
{
26
std::string result = "{";
27
28
for (size_t i = 0; i < code.size(); i++)
29
Luau::formatAppend(result, "%s0x%08x", i == 0 ? "" : ", ", code[i]);
30
31
return result.append("}");
32
}
33
34
class AssemblyBuilderA64Fixture
35
{
36
public:
37
bool check(void (*f)(AssemblyBuilderA64& build), std::vector<uint32_t> code, std::vector<uint8_t> data = {}, unsigned int features = 0)
38
{
39
AssemblyBuilderA64 build(/* logText= */ false, features);
40
41
f(build);
42
43
build.finalize();
44
45
if (build.code != code)
46
{
47
printf("Expected code: %s\nReceived code: %s\n", bytecodeAsArray(code).c_str(), bytecodeAsArray(build.code).c_str());
48
return false;
49
}
50
51
if (build.data != data)
52
{
53
printf("Expected data: %s\nReceived data: %s\n", bytecodeAsArray(data).c_str(), bytecodeAsArray(build.data).c_str());
54
return false;
55
}
56
57
return true;
58
}
59
};
60
61
// armconverter.com can be used to validate instruction sequences
62
TEST_SUITE_BEGIN("A64Assembly");
63
64
#define SINGLE_COMPARE(inst, ...) \
65
CHECK(check( \
66
[](AssemblyBuilderA64& build) \
67
{ \
68
build.inst; \
69
}, \
70
{__VA_ARGS__} \
71
))
72
73
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Unary")
74
{
75
SINGLE_COMPARE(neg(x0, x1), 0xCB0103E0);
76
SINGLE_COMPARE(neg(w0, w1), 0x4B0103E0);
77
SINGLE_COMPARE(mvn_(x0, x1), 0xAA2103E0);
78
79
SINGLE_COMPARE(clz(x0, x1), 0xDAC01020);
80
SINGLE_COMPARE(clz(w0, w1), 0x5AC01020);
81
SINGLE_COMPARE(rbit(x0, x1), 0xDAC00020);
82
SINGLE_COMPARE(rbit(w0, w1), 0x5AC00020);
83
SINGLE_COMPARE(rev(w0, w1), 0x5AC00820);
84
SINGLE_COMPARE(rev(x0, x1), 0xDAC00C20);
85
}
86
87
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Binary")
88
{
89
// reg, reg
90
SINGLE_COMPARE(add(x0, x1, x2), 0x8B020020);
91
SINGLE_COMPARE(add(w0, w1, w2), 0x0B020020);
92
SINGLE_COMPARE(add(x0, x1, x2, 7), 0x8B021C20);
93
SINGLE_COMPARE(add(x0, x1, x2, -7), 0x8B421C20);
94
SINGLE_COMPARE(sub(x0, x1, x2), 0xCB020020);
95
SINGLE_COMPARE(and_(x0, x1, x2), 0x8A020020);
96
SINGLE_COMPARE(and_(x0, x1, x2, 7), 0x8A021C20);
97
SINGLE_COMPARE(and_(x0, x1, x2, -7), 0x8A421C20);
98
SINGLE_COMPARE(bic(x0, x1, x2), 0x8A220020);
99
SINGLE_COMPARE(orr(x0, x1, x2), 0xAA020020);
100
SINGLE_COMPARE(eor(x0, x1, x2), 0xCA020020);
101
SINGLE_COMPARE(lsl(x0, x1, x2), 0x9AC22020);
102
SINGLE_COMPARE(lsl(w0, w1, w2), 0x1AC22020);
103
SINGLE_COMPARE(lsr(x0, x1, x2), 0x9AC22420);
104
SINGLE_COMPARE(asr(x0, x1, x2), 0x9AC22820);
105
SINGLE_COMPARE(ror(x0, x1, x2), 0x9AC22C20);
106
SINGLE_COMPARE(cmp(x0, x1), 0xEB01001F);
107
SINGLE_COMPARE(tst(x0, x1), 0xEA01001F);
108
109
// reg, imm
110
SINGLE_COMPARE(add(x3, x7, uint16_t(78)), 0x910138E3);
111
SINGLE_COMPARE(add(w3, w7, uint16_t(78)), 0x110138E3);
112
SINGLE_COMPARE(sub(w3, w7, uint16_t(78)), 0x510138E3);
113
SINGLE_COMPARE(cmp(w0, uint16_t(42)), 0x7100A81F);
114
}
115
116
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "BinaryExtended")
117
{
118
// reg, reg
119
SINGLE_COMPARE(add(x0, x1, w2, 3), 0x8B224C20);
120
SINGLE_COMPARE(sub(x0, x1, w2, 3), 0xCB224C20);
121
}
122
123
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "BinaryImm")
124
{
125
// instructions
126
SINGLE_COMPARE(and_(w1, w2, 1), 0x12000041);
127
SINGLE_COMPARE(orr(w1, w2, 1), 0x32000041);
128
SINGLE_COMPARE(eor(w1, w2, 1), 0x52000041);
129
SINGLE_COMPARE(tst(w1, 1), 0x7200003f);
130
131
// various mask forms
132
SINGLE_COMPARE(and_(w0, w0, 1), 0x12000000);
133
SINGLE_COMPARE(and_(w0, w0, 3), 0x12000400);
134
SINGLE_COMPARE(and_(w0, w0, 7), 0x12000800);
135
SINGLE_COMPARE(and_(w0, w0, 2147483647), 0x12007800);
136
SINGLE_COMPARE(and_(w0, w0, 6), 0x121F0400);
137
SINGLE_COMPARE(and_(w0, w0, 12), 0x121E0400);
138
SINGLE_COMPARE(and_(w0, w0, 2147483648), 0x12010000);
139
140
// shifts
141
SINGLE_COMPARE(lsl(w1, w2, 1), 0x531F7841);
142
SINGLE_COMPARE(lsl(x1, x2, 1), 0xD37FF841);
143
SINGLE_COMPARE(lsr(w1, w2, 1), 0x53017C41);
144
SINGLE_COMPARE(lsr(x1, x2, 1), 0xD341FC41);
145
SINGLE_COMPARE(asr(w1, w2, 1), 0x13017C41);
146
SINGLE_COMPARE(asr(x1, x2, 1), 0x9341FC41);
147
SINGLE_COMPARE(ror(w1, w2, 1), 0x13820441);
148
SINGLE_COMPARE(ror(x1, x2, 1), 0x93C20441);
149
}
150
151
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Bitfield")
152
{
153
SINGLE_COMPARE(ubfiz(x1, x2, 37, 5), 0xD35B1041);
154
SINGLE_COMPARE(ubfx(x1, x2, 37, 5), 0xD365A441);
155
SINGLE_COMPARE(sbfiz(x1, x2, 37, 5), 0x935B1041);
156
SINGLE_COMPARE(sbfx(x1, x2, 37, 5), 0x9365A441);
157
158
SINGLE_COMPARE(ubfiz(w1, w2, 17, 5), 0x530F1041);
159
SINGLE_COMPARE(ubfx(w1, w2, 17, 5), 0x53115441);
160
SINGLE_COMPARE(sbfiz(w1, w2, 17, 5), 0x130F1041);
161
SINGLE_COMPARE(sbfx(w1, w2, 17, 5), 0x13115441);
162
}
163
164
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Loads")
165
{
166
// address forms
167
SINGLE_COMPARE(ldr(x0, x1), 0xF9400020);
168
SINGLE_COMPARE(ldr(x0, mem(x1, 8)), 0xF9400420);
169
SINGLE_COMPARE(ldr(x0, mem(x1, x7)), 0xF8676820);
170
SINGLE_COMPARE(ldr(x0, mem(x1, -7)), 0xF85F9020);
171
172
// load sizes
173
SINGLE_COMPARE(ldr(x0, x1), 0xF9400020);
174
SINGLE_COMPARE(ldr(w0, x1), 0xB9400020);
175
SINGLE_COMPARE(ldrb(w0, x1), 0x39400020);
176
SINGLE_COMPARE(ldrh(w0, x1), 0x79400020);
177
SINGLE_COMPARE(ldrsb(x0, x1), 0x39800020);
178
SINGLE_COMPARE(ldrsb(w0, x1), 0x39C00020);
179
SINGLE_COMPARE(ldrsh(x0, x1), 0x79800020);
180
SINGLE_COMPARE(ldrsh(w0, x1), 0x79C00020);
181
SINGLE_COMPARE(ldrsw(x0, x1), 0xB9800020);
182
183
// load sizes x offset scaling
184
SINGLE_COMPARE(ldr(x0, mem(x1, 8)), 0xF9400420);
185
SINGLE_COMPARE(ldr(w0, mem(x1, 8)), 0xB9400820);
186
SINGLE_COMPARE(ldrb(w0, mem(x1, 8)), 0x39402020);
187
SINGLE_COMPARE(ldrh(w0, mem(x1, 8)), 0x79401020);
188
SINGLE_COMPARE(ldrsb(w0, mem(x1, 8)), 0x39C02020);
189
SINGLE_COMPARE(ldrsh(w0, mem(x1, 8)), 0x79C01020);
190
191
// paired loads
192
SINGLE_COMPARE(ldp(x0, x1, mem(x2, 8)), 0xA9408440);
193
SINGLE_COMPARE(ldp(w0, w1, mem(x2, -8)), 0x297F0440);
194
}
195
196
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Stores")
197
{
198
// address forms
199
SINGLE_COMPARE(str(x0, x1), 0xF9000020);
200
SINGLE_COMPARE(str(x0, mem(x1, 8)), 0xF9000420);
201
SINGLE_COMPARE(str(x0, mem(x1, x7)), 0xF8276820);
202
SINGLE_COMPARE(strh(w0, mem(x1, -7)), 0x781F9020);
203
204
// store sizes
205
SINGLE_COMPARE(str(x0, x1), 0xF9000020);
206
SINGLE_COMPARE(str(w0, x1), 0xB9000020);
207
SINGLE_COMPARE(strb(w0, x1), 0x39000020);
208
SINGLE_COMPARE(strh(w0, x1), 0x79000020);
209
210
// store sizes x offset scaling
211
SINGLE_COMPARE(str(x0, mem(x1, 8)), 0xF9000420);
212
SINGLE_COMPARE(str(w0, mem(x1, 8)), 0xB9000820);
213
SINGLE_COMPARE(strb(w0, mem(x1, 8)), 0x39002020);
214
SINGLE_COMPARE(strh(w0, mem(x1, 8)), 0x79001020);
215
216
// paired stores
217
SINGLE_COMPARE(stp(x0, x1, mem(x2, 8)), 0xA9008440);
218
SINGLE_COMPARE(stp(w0, w1, mem(x2, -8)), 0x293F0440);
219
}
220
221
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Moves")
222
{
223
SINGLE_COMPARE(mov(x0, x1), 0xAA0103E0);
224
SINGLE_COMPARE(mov(w0, w1), 0x2A0103E0);
225
SINGLE_COMPARE(mov(q0, q1), 0x4EA11C20);
226
227
SINGLE_COMPARE(movz(x0, 42), 0xD2800540);
228
SINGLE_COMPARE(movz(w0, 42), 0x52800540);
229
SINGLE_COMPARE(movn(x0, 42), 0x92800540);
230
SINGLE_COMPARE(movn(w0, 42), 0x12800540);
231
SINGLE_COMPARE(movk(x0, 42, 16), 0xF2A00540);
232
233
CHECK(check(
234
[](AssemblyBuilderA64& build)
235
{
236
build.mov(x0, 42);
237
},
238
{0xD2800540}
239
));
240
241
CHECK(check(
242
[](AssemblyBuilderA64& build)
243
{
244
build.mov(x0, 424242);
245
},
246
{0xD28F2640, 0xF2A000C0}
247
));
248
249
CHECK(check(
250
[](AssemblyBuilderA64& build)
251
{
252
build.mov(x0, -42);
253
},
254
{0x92800520}
255
));
256
257
CHECK(check(
258
[](AssemblyBuilderA64& build)
259
{
260
build.mov(x0, -424242);
261
},
262
{0x928F2620, 0xF2BFFF20}
263
));
264
265
CHECK(check(
266
[](AssemblyBuilderA64& build)
267
{
268
build.mov(x0, -65536);
269
},
270
{0x929FFFE0}
271
));
272
273
CHECK(check(
274
[](AssemblyBuilderA64& build)
275
{
276
build.mov(x0, -65537);
277
},
278
{0x92800000, 0xF2BFFFC0}
279
));
280
}
281
282
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "ControlFlow")
283
{
284
// Jump back
285
CHECK(check(
286
[](AssemblyBuilderA64& build)
287
{
288
Label start = build.setLabel();
289
build.mov(x0, x1);
290
build.b(ConditionA64::Equal, start);
291
},
292
{0xAA0103E0, 0x54FFFFE0}
293
));
294
295
// Jump forward
296
CHECK(check(
297
[](AssemblyBuilderA64& build)
298
{
299
Label skip;
300
build.b(ConditionA64::Equal, skip);
301
build.mov(x0, x1);
302
build.setLabel(skip);
303
},
304
{0x54000040, 0xAA0103E0}
305
));
306
307
// Jumps
308
CHECK(check(
309
[](AssemblyBuilderA64& build)
310
{
311
Label skip;
312
build.b(ConditionA64::Equal, skip);
313
build.cbz(x0, skip);
314
build.cbnz(x0, skip);
315
build.tbz(x0, 5, skip);
316
build.tbnz(x0, 5, skip);
317
build.setLabel(skip);
318
build.b(skip);
319
build.bl(skip);
320
},
321
{0x540000A0, 0xB4000080, 0xB5000060, 0x36280040, 0x37280020, 0x14000000, 0x97ffffff}
322
));
323
324
// Basic control flow
325
SINGLE_COMPARE(br(x0), 0xD61F0000);
326
SINGLE_COMPARE(blr(x0), 0xD63F0000);
327
SINGLE_COMPARE(ret(), 0xD65F03C0);
328
}
329
330
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "StackOps")
331
{
332
SINGLE_COMPARE(mov(x0, sp), 0x910003E0);
333
SINGLE_COMPARE(mov(sp, x0), 0x9100001F);
334
335
SINGLE_COMPARE(add(sp, sp, uint16_t(4)), 0x910013FF);
336
SINGLE_COMPARE(sub(sp, sp, uint16_t(4)), 0xD10013FF);
337
338
SINGLE_COMPARE(add(x0, sp, uint16_t(4)), 0x910013E0);
339
SINGLE_COMPARE(sub(sp, x0, uint16_t(4)), 0xD100101F);
340
341
SINGLE_COMPARE(ldr(x0, mem(sp, 8)), 0xF94007E0);
342
SINGLE_COMPARE(str(x0, mem(sp, 8)), 0xF90007E0);
343
}
344
345
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Constants")
346
{
347
// clang-format off
348
CHECK(check(
349
[](AssemblyBuilderA64& build) {
350
char arr[12] = "hello world";
351
build.adr(x0, arr, 12);
352
build.adr(x0, uint64_t(0x1234567887654321));
353
build.adr(x0, 1.0);
354
},
355
{
356
0x10ffffa0, 0x10ffff20, 0x10fffec0
357
},
358
{
359
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,
360
0x21, 0x43, 0x65, 0x87, 0x78, 0x56, 0x34, 0x12,
361
0x00, 0x00, 0x00, 0x00, // 4b padding to align double
362
'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0x0,
363
}));
364
// clang-format on
365
}
366
367
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "AddressOfLabel")
368
{
369
// clang-format off
370
CHECK(check(
371
[](AssemblyBuilderA64& build) {
372
Label label;
373
build.adr(x0, label);
374
build.add(x0, x0, x0);
375
build.setLabel(label);
376
},
377
{
378
0x10000040, 0x8b000000,
379
}));
380
// clang-format on
381
}
382
383
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "FPBasic")
384
{
385
SINGLE_COMPARE(fmov(d0, d1), 0x1E604020);
386
SINGLE_COMPARE(fmov(d0, x1), 0x9E670020);
387
SINGLE_COMPARE(fmov(x3, d2), 0x9E660043);
388
}
389
390
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "FPMath")
391
{
392
SINGLE_COMPARE(fabs(d1, d2), 0x1E60C041);
393
SINGLE_COMPARE(fabs(s1, s2), 0x1E20C041);
394
SINGLE_COMPARE(fabs(q1, q2), 0x4EA0F841);
395
SINGLE_COMPARE(fadd(d1, d2, d3), 0x1E632841);
396
SINGLE_COMPARE(fadd(s29, s29, s28), 0x1E3C2BBD);
397
SINGLE_COMPARE(fadd(q29, q29, q28), 0x4E3CD7BD);
398
SINGLE_COMPARE(fdiv(d1, d2, d3), 0x1E631841);
399
SINGLE_COMPARE(fdiv(s29, s29, s28), 0x1E3C1BBD);
400
SINGLE_COMPARE(fdiv(q29, q29, q28), 0x6E3CFFBD);
401
SINGLE_COMPARE(fmul(d1, d2, d3), 0x1E630841);
402
SINGLE_COMPARE(fmul(s29, s29, s28), 0x1E3C0BBD);
403
SINGLE_COMPARE(fmul(q29, q29, q28), 0x6E3CDFBD);
404
SINGLE_COMPARE(fneg(d1, d2), 0x1E614041);
405
SINGLE_COMPARE(fneg(s30, s30), 0x1E2143DE);
406
SINGLE_COMPARE(fneg(q30, q30), 0x6EA0FBDE);
407
SINGLE_COMPARE(fsqrt(d1, d2), 0x1E61C041);
408
SINGLE_COMPARE(fsub(d1, d2, d3), 0x1E633841);
409
SINGLE_COMPARE(fsub(s29, s29, s28), 0x1E3C3BBD);
410
SINGLE_COMPARE(fsub(q29, q29, q28), 0x4EBCD7BD);
411
412
SINGLE_COMPARE(faddp(s29, s28), 0x7E30DB9D);
413
SINGLE_COMPARE(faddp(d29, d28), 0x7E70DB9D);
414
415
SINGLE_COMPARE(frinta(d1, d2), 0x1E664041);
416
SINGLE_COMPARE(frintm(d1, d2), 0x1E654041);
417
SINGLE_COMPARE(frintp(d1, d2), 0x1E64C041);
418
419
SINGLE_COMPARE(frinta(s1, s2), 0x1E264041);
420
SINGLE_COMPARE(frintm(s1, s2), 0x1E254041);
421
SINGLE_COMPARE(frintp(s1, s2), 0x1E24C041);
422
423
SINGLE_COMPARE(frinta(q1, q2), 0x6E218841);
424
SINGLE_COMPARE(frintm(q1, q2), 0x4E219841);
425
SINGLE_COMPARE(frintp(q1, q2), 0x4EA18841);
426
427
SINGLE_COMPARE(fcvt(s1, d2), 0x1E624041);
428
SINGLE_COMPARE(fcvt(d1, s2), 0x1E22C041);
429
430
SINGLE_COMPARE(fcvtzs(w1, d2), 0x1E780041);
431
SINGLE_COMPARE(fcvtzs(x1, d2), 0x9E780041);
432
SINGLE_COMPARE(fcvtzu(w1, d2), 0x1E790041);
433
SINGLE_COMPARE(fcvtzu(x1, d2), 0x9E790041);
434
435
SINGLE_COMPARE(scvtf(d1, w2), 0x1E620041);
436
SINGLE_COMPARE(scvtf(d1, x2), 0x9E620041);
437
438
SINGLE_COMPARE(ucvtf(d1, w2), 0x1E630041);
439
SINGLE_COMPARE(ucvtf(d1, x2), 0x9E630041);
440
SINGLE_COMPARE(ucvtf(s1, w2), 0x1E230041);
441
SINGLE_COMPARE(ucvtf(s1, x2), 0x9E230041);
442
443
CHECK(check(
444
[](AssemblyBuilderA64& build)
445
{
446
build.fjcvtzs(w1, d2);
447
},
448
{0x1E7E0041},
449
{},
450
A64::Feature_JSCVT
451
));
452
}
453
454
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "FPLoadStore")
455
{
456
// address forms
457
SINGLE_COMPARE(ldr(d0, x1), 0xFD400020);
458
SINGLE_COMPARE(ldr(d0, mem(x1, 8)), 0xFD400420);
459
SINGLE_COMPARE(ldr(d0, mem(x1, x7)), 0xFC676820);
460
SINGLE_COMPARE(ldr(d0, mem(x1, -7)), 0xFC5F9020);
461
SINGLE_COMPARE(str(d0, x1), 0xFD000020);
462
SINGLE_COMPARE(str(d0, mem(x1, 8)), 0xFD000420);
463
SINGLE_COMPARE(str(d0, mem(x1, x7)), 0xFC276820);
464
SINGLE_COMPARE(str(d0, mem(x1, -7)), 0xFC1F9020);
465
466
// load/store sizes
467
SINGLE_COMPARE(ldr(s0, x1), 0xBD400020);
468
SINGLE_COMPARE(ldr(d0, x1), 0xFD400020);
469
SINGLE_COMPARE(ldr(q0, x1), 0x3DC00020);
470
SINGLE_COMPARE(str(s0, x1), 0xBD000020);
471
SINGLE_COMPARE(str(d0, x1), 0xFD000020);
472
SINGLE_COMPARE(str(q0, x1), 0x3D800020);
473
474
// load/store sizes x offset scaling
475
SINGLE_COMPARE(ldr(q0, mem(x1, 16)), 0x3DC00420);
476
SINGLE_COMPARE(ldr(d0, mem(x1, 16)), 0xFD400820);
477
SINGLE_COMPARE(ldr(s0, mem(x1, 16)), 0xBD401020);
478
SINGLE_COMPARE(str(q0, mem(x1, 16)), 0x3D800420);
479
SINGLE_COMPARE(str(d0, mem(x1, 16)), 0xFD000820);
480
SINGLE_COMPARE(str(s0, mem(x1, 16)), 0xBD001020);
481
}
482
483
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "FPInsertExtract")
484
{
485
SINGLE_COMPARE(ins_4s(q29, w17, 3), 0x4E1C1E3D);
486
SINGLE_COMPARE(ins_4s(q31, 0, q29, 0), 0x6E0407BF);
487
SINGLE_COMPARE(dup_4s(s29, q31, 2), 0x5E1407FD);
488
SINGLE_COMPARE(dup_4s(q29, q30, 0), 0x4E0407DD);
489
SINGLE_COMPARE(umov_4s(w1, q30, 3), 0x0E1C3FC1);
490
SINGLE_COMPARE(umov_4s(w13, q1, 1), 0x0E0C3C2D);
491
492
SINGLE_COMPARE(bit(q1, q2, q3), 0x6EA31C41);
493
SINGLE_COMPARE(bif(q1, q2, q3), 0x6EE31C41);
494
}
495
496
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "FPCompare")
497
{
498
SINGLE_COMPARE(fcmp(d0, d1), 0x1E612000);
499
SINGLE_COMPARE(fcmpz(d1), 0x1E602028);
500
501
SINGLE_COMPARE(fcmeq_4s(q1, q2, q3), 0x4E23E441);
502
SINGLE_COMPARE(fcmgt_4s(q1, q2, q3), 0x6EA3E441);
503
}
504
505
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "FPImm")
506
{
507
SINGLE_COMPARE(fmov(d0, 0.0), 0x2F00E400);
508
SINGLE_COMPARE(fmov(d0, 0.125), 0x1E681000);
509
SINGLE_COMPARE(fmov(d0, -0.125), 0x1E781000);
510
SINGLE_COMPARE(fmov(d0, 1.9375), 0x1E6FF000);
511
512
SINGLE_COMPARE(fmov(q0, 0.0), 0x4F000400);
513
SINGLE_COMPARE(fmov(q0, 0.125), 0x4F02F400);
514
SINGLE_COMPARE(fmov(q0, -0.125), 0x4F06F400);
515
SINGLE_COMPARE(fmov(q0, 1.9375), 0x4F03F7E0);
516
517
CHECK(!AssemblyBuilderA64::isFmovSupportedFp64(-0.0));
518
CHECK(!AssemblyBuilderA64::isFmovSupportedFp64(0.12389));
519
}
520
521
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "AddressOffsetSize")
522
{
523
SINGLE_COMPARE(ldr(w0, mem(x1, 16)), 0xB9401020);
524
SINGLE_COMPARE(ldr(x0, mem(x1, 16)), 0xF9400820);
525
SINGLE_COMPARE(ldr(d0, mem(x1, 16)), 0xFD400820);
526
SINGLE_COMPARE(ldr(q0, mem(x1, 16)), 0x3DC00420);
527
528
SINGLE_COMPARE(str(w0, mem(x1, 16)), 0xB9001020);
529
SINGLE_COMPARE(str(x0, mem(x1, 16)), 0xF9000820);
530
SINGLE_COMPARE(str(d0, mem(x1, 16)), 0xFD000820);
531
SINGLE_COMPARE(str(q0, mem(x1, 16)), 0x3D800420);
532
}
533
534
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Conditionals")
535
{
536
SINGLE_COMPARE(csel(x0, x1, x2, ConditionA64::Equal), 0x9A820020);
537
SINGLE_COMPARE(csel(w0, w1, w2, ConditionA64::Equal), 0x1A820020);
538
SINGLE_COMPARE(fcsel(d0, d1, d2, ConditionA64::Equal), 0x1E620C20);
539
540
SINGLE_COMPARE(cset(x1, ConditionA64::Less), 0x9A9FA7E1);
541
}
542
543
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "Undefined")
544
{
545
SINGLE_COMPARE(udf(), 0x00000000);
546
}
547
548
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "PrePostIndexing")
549
{
550
SINGLE_COMPARE(ldr(x0, mem(x1, 1)), 0xF8401020);
551
SINGLE_COMPARE(ldr(x0, mem(x1, 1, AddressKindA64::pre)), 0xF8401C20);
552
SINGLE_COMPARE(ldr(x0, mem(x1, 1, AddressKindA64::post)), 0xF8401420);
553
554
SINGLE_COMPARE(ldr(q0, mem(x1, 1)), 0x3CC01020);
555
SINGLE_COMPARE(ldr(q0, mem(x1, 1, AddressKindA64::pre)), 0x3CC01C20);
556
SINGLE_COMPARE(ldr(q0, mem(x1, 1, AddressKindA64::post)), 0x3CC01420);
557
558
SINGLE_COMPARE(str(x0, mem(x1, 1)), 0xF8001020);
559
SINGLE_COMPARE(str(x0, mem(x1, 1, AddressKindA64::pre)), 0xF8001C20);
560
SINGLE_COMPARE(str(x0, mem(x1, 1, AddressKindA64::post)), 0xF8001420);
561
562
SINGLE_COMPARE(str(q0, mem(x1, 1)), 0x3C801020);
563
SINGLE_COMPARE(str(q0, mem(x1, 1, AddressKindA64::pre)), 0x3C801C20);
564
SINGLE_COMPARE(str(q0, mem(x1, 1, AddressKindA64::post)), 0x3C801420);
565
}
566
567
TEST_CASE_FIXTURE(AssemblyBuilderA64Fixture, "SIMDMath")
568
{
569
SINGLE_COMPARE(fadd(q0, q1, q2), 0x4E22D420);
570
SINGLE_COMPARE(fsub(q0, q1, q2), 0x4EA2D420);
571
SINGLE_COMPARE(fmul(q0, q1, q2), 0x6E22DC20);
572
SINGLE_COMPARE(fdiv(q0, q1, q2), 0x6E22FC20);
573
SINGLE_COMPARE(fneg(q0, q1), 0x6EA0F820);
574
}
575
576
TEST_CASE("LogTest")
577
{
578
AssemblyBuilderA64 build(/* logText= */ true);
579
580
build.add(sp, sp, uint16_t(4));
581
build.add(w0, w1, w2);
582
build.add(x0, x1, x2, 2);
583
build.add(x0, x1, x2, -2);
584
build.add(w7, w8, uint16_t(5));
585
build.add(x7, x8, uint16_t(5));
586
build.ldr(x7, x8);
587
build.ldr(x7, mem(x8, 8));
588
build.ldr(x7, mem(x8, x9));
589
build.mov(x1, x2);
590
build.movk(x1, 42, 16);
591
build.cmp(x1, x2);
592
build.blr(x0);
593
594
Label l;
595
build.b(ConditionA64::Plus, l);
596
build.cbz(x7, l);
597
598
build.ldp(x0, x1, mem(x8, 8));
599
build.adr(x0, l);
600
601
build.fabs(d1, d2);
602
build.ldr(q1, x2);
603
604
build.csel(x0, x1, x2, ConditionA64::Equal);
605
build.cset(x0, ConditionA64::Equal);
606
607
build.fcmp(d0, d1);
608
build.fcmpz(d0);
609
610
build.fmov(d0, 0.25);
611
build.tbz(x0, 5, l);
612
613
build.fcvt(s1, d2);
614
615
build.ubfx(x1, x2, 37, 5);
616
617
build.ldr(x0, mem(x1, 1));
618
build.ldr(x0, mem(x1, 1, AddressKindA64::pre));
619
build.ldr(x0, mem(x1, 1, AddressKindA64::post));
620
621
build.add(x1, x2, w3, 3);
622
623
build.ins_4s(q29, w17, 3);
624
build.ins_4s(q31, 1, q29, 2);
625
build.dup_4s(s29, q31, 2);
626
build.dup_4s(q29, q30, 0);
627
build.umov_4s(w1, q30, 3);
628
build.fmul(q0, q1, q2);
629
630
build.fcmeq_4s(q2, q0, q1);
631
build.bit(q1, q0, q2);
632
633
build.setLabel(l);
634
build.ret();
635
636
build.finalize();
637
638
std::string expected = R"(
639
add sp,sp,#4
640
add w0,w1,w2
641
add x0,x1,x2 LSL #2
642
add x0,x1,x2 LSR #2
643
add w7,w8,#5
644
add x7,x8,#5
645
ldr x7,[x8]
646
ldr x7,[x8,#8]
647
ldr x7,[x8,x9]
648
mov x1,x2
649
movk x1,#42 LSL #16
650
cmp x1,x2
651
blr x0
652
b.pl .L1
653
cbz x7,.L1
654
ldp x0,x1,[x8,#8]
655
adr x0,.L1
656
fabs d1,d2
657
ldr q1,[x2]
658
csel x0,x1,x2,eq
659
cset x0,eq
660
fcmp d0,d1
661
fcmp d0,#0
662
fmov d0,#0.25
663
tbz x0,#5,.L1
664
fcvt s1,d2
665
ubfx x1,x2,#3705
666
ldr x0,[x1,#1]
667
ldr x0,[x1,#1]!
668
ldr x0,[x1]!,#1
669
add x1,x2,w3 UXTW #3
670
ins v29.s[3],w17
671
ins v31.s[1],v29.s[2]
672
dup s29,v31.s[2]
673
dup v29.4s,v30.s[0]
674
umov w1,v30.s[3]
675
fmul v0.4s,v1.4s,v2.4s
676
fcmeq v2.4s,v0.4s,v1.4s
677
bit v1.16b,v0.16b,v2.16b
678
.L1:
679
ret
680
)";
681
682
CHECK("\n" + build.text == expected);
683
}
684
685
TEST_SUITE_END();
686
687