1 package amd64
2
3 import (
4 "encoding/hex"
5 "testing"
6
7 "github.com/tetratelabs/wazero/internal/asm"
8 "github.com/tetratelabs/wazero/internal/testing/require"
9 )
10
11 func TestAssemblerImpl_CompileStaticConstToRegister(t *testing.T) {
12 a := NewAssembler()
13 t.Run("odd count of bytes", func(t *testing.T) {
14 err := a.CompileStaticConstToRegister(MOVDQU, asm.NewStaticConst([]byte{1}), RegAX)
15 require.Error(t, err)
16 })
17 t.Run("ok", func(t *testing.T) {
18 cons := asm.NewStaticConst([]byte{1, 2, 3, 4})
19 err := a.CompileStaticConstToRegister(MOVDQU, cons, RegAX)
20 require.NoError(t, err)
21 actualNode := a.current
22 require.Equal(t, MOVDQU, actualNode.instruction)
23 require.Equal(t, operandTypesStaticConstToRegister, actualNode.types)
24 require.Equal(t, cons, actualNode.staticConst)
25 })
26 }
27
28 func TestAssemblerImpl_CompileRegisterToStaticConst(t *testing.T) {
29 a := NewAssembler()
30 t.Run("odd count of bytes", func(t *testing.T) {
31 err := a.CompileRegisterToStaticConst(MOVDQU, RegAX, asm.NewStaticConst([]byte{1}))
32 require.Error(t, err)
33 })
34 t.Run("ok", func(t *testing.T) {
35 cons := asm.NewStaticConst([]byte{1, 2, 3, 4})
36 err := a.CompileRegisterToStaticConst(MOVDQU, RegAX, cons)
37 require.NoError(t, err)
38 actualNode := a.current
39 require.Equal(t, MOVDQU, actualNode.instruction)
40 require.Equal(t, operandTypesRegisterToStaticConst, actualNode.types)
41 require.Equal(t, cons, actualNode.staticConst)
42 })
43 }
44
45 func TestAssemblerImpl_maybeFlushConstants(t *testing.T) {
46 t.Run("no consts", func(t *testing.T) {
47 code := asm.CodeSegment{}
48 defer func() { require.NoError(t, code.Unmap()) }()
49
50 a := NewAssembler()
51
52 a.maybeFlushConstants(code.NextCodeSection(), false)
53 a.maybeFlushConstants(code.NextCodeSection(), true)
54 })
55
56 largeData := make([]byte, 256)
57
58 tests := []struct {
59 name string
60 endOfFunction bool
61 dummyBodyBeforeFlush []byte
62 firstUseOffsetInBinary uint64
63 consts [][]byte
64 expectedOffsetForConsts []uint64
65 exp []byte
66 maxDisplacement int
67 }{
68 {
69 name: "end of function",
70 endOfFunction: true,
71 dummyBodyBeforeFlush: []byte{'?', '?', '?', '?'},
72 consts: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8}, {10, 11, 12, 13}},
73 expectedOffsetForConsts: []uint64{4, 4 + 8},
74 firstUseOffsetInBinary: 0,
75 exp: []byte{'?', '?', '?', '?', 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13},
76 maxDisplacement: 1 << 31,
77 },
78 {
79 name: "not flush",
80 endOfFunction: false,
81 dummyBodyBeforeFlush: []byte{'?', '?', '?', '?'},
82 consts: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8}, {10, 11, 12, 13}},
83 firstUseOffsetInBinary: 0,
84 exp: []byte{'?', '?', '?', '?'},
85 maxDisplacement: 1 << 31,
86 },
87 {
88 name: "not end of function but flush - short jump",
89 endOfFunction: false,
90 dummyBodyBeforeFlush: []byte{'?', '?', '?', '?'},
91 consts: [][]byte{{1, 2, 3, 4, 5, 6, 7, 8}, {10, 11, 12, 13}},
92 expectedOffsetForConsts: []uint64{4 + 2, 4 + 2 + 8},
93 firstUseOffsetInBinary: 0,
94 exp: []byte{
95 '?', '?', '?', '?',
96 0xeb, 0x0c,
97 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13,
98 },
99 maxDisplacement: 0,
100 },
101 {
102 name: "not end of function but flush - long jump",
103 endOfFunction: false,
104 dummyBodyBeforeFlush: []byte{'?', '?', '?', '?'},
105 consts: [][]byte{largeData},
106 expectedOffsetForConsts: []uint64{4 + 5},
107 firstUseOffsetInBinary: 0,
108 exp: append([]byte{
109 '?', '?', '?', '?',
110 0xe9, 0x0, 0x1, 0x0, 0x0,
111 }, largeData...),
112 maxDisplacement: 0,
113 },
114 }
115
116 for _, tc := range tests {
117 t.Run(tc.name, func(t *testing.T) {
118 code := asm.CodeSegment{}
119 defer func() { require.NoError(t, code.Unmap()) }()
120
121 a := NewAssembler()
122 a.MaxDisplacementForConstantPool = tc.maxDisplacement
123
124 buf := code.NextCodeSection()
125 buf.AppendBytes(tc.dummyBodyBeforeFlush)
126
127 for i, c := range tc.consts {
128 sc := asm.NewStaticConst(c)
129 a.pool.AddConst(sc, 100)
130 i := i
131 sc.AddOffsetFinalizedCallback(func(offsetOfConstInBinary uint64) {
132 require.Equal(t, tc.expectedOffsetForConsts[i], offsetOfConstInBinary)
133 })
134 }
135
136 a.pool.FirstUseOffsetInBinary = tc.firstUseOffsetInBinary
137 a.maybeFlushConstants(buf, tc.endOfFunction)
138
139 require.Equal(t, tc.exp, buf.Bytes())
140 })
141 }
142 }
143
144 func TestAssemblerImpl_encodeRegisterToStaticConst(t *testing.T) {
145 tests := []struct {
146 name string
147 ins asm.Instruction
148 c []byte
149 reg asm.Register
150 ud2sBeforeConst int
151 exp []byte
152 }{
153 {
154 name: "cmp r12d, dword ptr [rip + 0x14]",
155 ins: CMPL,
156 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
157 reg: RegR12,
158 ud2sBeforeConst: 10,
159 exp: []byte{
160
161
162 0x44, 0x3b, 0x25, 0x14, 0x0, 0x0, 0x0,
163
164 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
165
166 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
167 },
168 },
169 {
170 name: "cmp eax, dword ptr [rip + 0x14]",
171 ins: CMPL,
172 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
173 reg: RegAX,
174 ud2sBeforeConst: 10,
175 exp: []byte{
176
177
178 0x3b, 0x5, 0x14, 0x0, 0x0, 0x0,
179
180 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
181
182 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
183 },
184 },
185 {
186 name: "cmp r12, qword ptr [rip]",
187 ins: CMPQ,
188 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
189 reg: RegR12,
190 ud2sBeforeConst: 0,
191 exp: []byte{
192
193
194 0x4c, 0x3b, 0x25, 0x0, 0x0, 0x0, 0x0,
195 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
196 },
197 },
198 {
199 name: "cmp rsp, qword ptr [rip + 0xa]",
200 ins: CMPQ,
201 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
202 reg: RegSP,
203 ud2sBeforeConst: 5,
204 exp: []byte{
205
206
207 0x48, 0x3b, 0x25, 0xa, 0x0, 0x0, 0x0,
208
209 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
210
211 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
212 },
213 },
214 }
215
216 for _, tc := range tests {
217 tc := tc
218 t.Run(tc.name, func(t *testing.T) {
219 code := asm.CodeSegment{}
220 defer func() { require.NoError(t, code.Unmap()) }()
221
222 a := NewAssembler()
223
224 err := a.CompileRegisterToStaticConst(tc.ins, tc.reg, asm.NewStaticConst(tc.c))
225 require.NoError(t, err)
226
227 for i := 0; i < tc.ud2sBeforeConst; i++ {
228 a.CompileStandAlone(UD2)
229 }
230
231 buf := code.NextCodeSection()
232 err = a.Assemble(buf)
233 require.NoError(t, err)
234
235 actual := buf.Bytes()
236 require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
237 })
238 }
239 }
240
241 func TestAssemblerImpl_encodeStaticConstToRegister(t *testing.T) {
242 tests := []struct {
243 name string
244 ins asm.Instruction
245 c []byte
246 reg asm.Register
247 ud2sBeforeConst int
248 exp []byte
249 }{
250 {
251 name: "movdqu xmm14, xmmword ptr [rip + 0xa]",
252 ins: MOVDQU,
253 c: []byte{
254 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
255 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
256 },
257 reg: RegX14,
258 ud2sBeforeConst: 5,
259 exp: []byte{
260
261
262 0xf3, 0x44, 0xf, 0x6f, 0x35, 0xa, 0x0, 0x0, 0x0,
263
264 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
265
266 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
267 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
268 },
269 },
270 {
271 name: "movupd xmm1, xmmword ptr [rip + 0xa]",
272 ins: MOVUPD,
273 c: []byte{
274 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
275 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
276 },
277 reg: RegX1,
278 ud2sBeforeConst: 5,
279 exp: []byte{
280
281
282 0x66, 0xf, 0x10, 0xd, 0xa, 0x0, 0x0, 0x0,
283
284 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
285
286 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
287 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
288 },
289 },
290 {
291 name: "lea r11, [rip + 0x14]",
292 ins: LEAQ,
293 c: []byte{
294 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
295 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
296 },
297 reg: RegR11,
298 ud2sBeforeConst: 10,
299 exp: []byte{
300
301
302 0x4c, 0x8d, 0x1d, 0x14, 0x0, 0x0, 0x0,
303
304 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
305 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
306
307 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
308 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
309 },
310 },
311 {
312 name: "mov r11d, dword ptr [rip + 0x3c]",
313 ins: MOVL,
314 c: []byte{
315 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
316 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
317 },
318 reg: RegR11,
319 ud2sBeforeConst: 30,
320 exp: []byte{
321
322
323 0x44, 0x8b, 0x1d, 0x3c, 0x0, 0x0, 0x0,
324
325 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
326 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
327 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
328 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
329 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
330 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
331
332 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
333 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
334 },
335 },
336 {
337 name: "movd xmm14, dword ptr [rip + 0x3c]",
338 ins: MOVL,
339 c: []byte{
340 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
341 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
342 },
343 reg: RegX14,
344 ud2sBeforeConst: 30,
345 exp: []byte{
346
347
348 0x66, 0x44, 0xf, 0x6e, 0x35, 0x3c, 0x0, 0x0, 0x0,
349
350 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
351 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
352 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
353 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
354 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
355 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
356
357 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
358 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
359 },
360 },
361 {
362 name: "mov rsp, qword ptr [rip + 0x3c]",
363 ins: MOVQ,
364 c: []byte{
365 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
366 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
367 },
368 reg: RegSP,
369 ud2sBeforeConst: 30,
370 exp: []byte{
371
372
373 0x48, 0x8b, 0x25, 0x3c, 0x0, 0x0, 0x0,
374
375 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
376 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
377 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
378 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
379 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
380 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
381
382 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
383 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
384 },
385 },
386 {
387 name: "movq xmm1, qword ptr [rip + 0x3c]",
388 ins: MOVQ,
389 c: []byte{
390 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
391 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
392 },
393 reg: RegX1,
394 ud2sBeforeConst: 30,
395 exp: []byte{
396
397
398 0xf3, 0xf, 0x7e, 0xd, 0x3c, 0x0, 0x0, 0x0,
399
400 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
401 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
402 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
403 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
404 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
405 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
406
407 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
408 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
409 },
410 },
411 {
412 name: "ucomisd xmm15, qword ptr [rip + 6]",
413 ins: UCOMISD,
414 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
415 reg: RegX15,
416 ud2sBeforeConst: 3,
417 exp: []byte{
418
419
420 0x66, 0x44, 0xf, 0x2e, 0x3d, 0x6, 0x0, 0x0, 0x0,
421
422 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
423
424 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
425 },
426 },
427 {
428 name: "ucomiss xmm15, dword ptr [rip + 6]",
429 ins: UCOMISS,
430 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
431 reg: RegX15,
432 ud2sBeforeConst: 3,
433 exp: []byte{
434
435
436 0x44, 0xf, 0x2e, 0x3d, 0x6, 0x0, 0x0, 0x0,
437
438 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
439
440 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
441 },
442 },
443 {
444 name: "subss xmm13, dword ptr [rip + 0xa]",
445 ins: SUBSS,
446 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
447 reg: RegX13,
448 ud2sBeforeConst: 5,
449 exp: []byte{
450
451
452 0xf3, 0x44, 0xf, 0x5c, 0x2d, 0xa, 0x0, 0x0, 0x0,
453
454 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
455
456 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
457 },
458 },
459 {
460 name: "subsd xmm1, qword ptr [rip + 0xa]",
461 ins: SUBSD,
462 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
463 reg: RegX1,
464 ud2sBeforeConst: 5,
465 exp: []byte{
466
467
468 0xf2, 0xf, 0x5c, 0xd, 0xa, 0x0, 0x0, 0x0,
469
470 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
471
472 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
473 },
474 },
475 {
476 name: "cmp dword ptr [rip + 0x14], r12d",
477 ins: CMPL,
478 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
479 reg: RegR12,
480 ud2sBeforeConst: 10,
481 exp: []byte{
482
483
484 0x44, 0x39, 0x25, 0x14, 0x0, 0x0, 0x0,
485
486 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
487
488 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
489 },
490 },
491 {
492 name: "cmp dword ptr [rip + 0x14], eax",
493 ins: CMPL,
494 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
495 reg: RegAX,
496 ud2sBeforeConst: 10,
497 exp: []byte{
498
499
500 0x39, 0x5, 0x14, 0x0, 0x0, 0x0,
501
502 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
503
504 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
505 },
506 },
507 {
508 name: "cmp qword ptr [rip], r12",
509 ins: CMPQ,
510 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
511 reg: RegR12,
512 ud2sBeforeConst: 0,
513 exp: []byte{
514
515
516 0x4c, 0x39, 0x25, 0x0, 0x0, 0x0, 0x0,
517 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
518 },
519 },
520 {
521 name: "cmp qword ptr [rip + 0xa], rsp",
522 ins: CMPQ,
523 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
524 reg: RegSP,
525 ud2sBeforeConst: 5,
526 exp: []byte{
527
528
529 0x48, 0x39, 0x25, 0xa, 0x0, 0x0, 0x0,
530
531 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
532
533 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
534 },
535 },
536 {
537 name: "ucomiss xmm15, dword ptr [rip + 6]",
538 ins: UCOMISS,
539 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
540 reg: RegX15,
541 ud2sBeforeConst: 3,
542 exp: []byte{
543
544
545 0x44, 0xf, 0x2e, 0x3d, 0x6, 0x0, 0x0, 0x0,
546
547 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
548
549 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
550 },
551 },
552 {
553 name: "subss xmm13, dword ptr [rip + 0xa]",
554 ins: SUBSS,
555 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
556 reg: RegX13,
557 ud2sBeforeConst: 5,
558 exp: []byte{
559
560
561 0xf3, 0x44, 0xf, 0x5c, 0x2d, 0xa, 0x0, 0x0, 0x0,
562
563 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
564
565 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
566 },
567 },
568 {
569 name: "subsd xmm1, qword ptr [rip + 0xa]",
570 ins: SUBSD,
571 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
572 reg: RegX1,
573 ud2sBeforeConst: 5,
574 exp: []byte{
575
576
577 0xf2, 0xf, 0x5c, 0xd, 0xa, 0x0, 0x0, 0x0,
578
579 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
580
581 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
582 },
583 },
584 {
585 name: "add eax, dword ptr [rip + 0xa]",
586 ins: ADDL,
587 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
588 reg: RegAX,
589 ud2sBeforeConst: 5,
590 exp: []byte{
591
592
593 0x3, 0x5, 0xa, 0x0, 0x0, 0x0,
594
595 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
596
597 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
598 },
599 },
600 {
601 name: "add rax, qword ptr [rip + 0xa]",
602 ins: ADDQ,
603 c: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8},
604 reg: RegAX,
605 ud2sBeforeConst: 5,
606 exp: []byte{
607
608
609 0x48, 0x3, 0x5, 0xa, 0x0, 0x0, 0x0,
610
611 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb, 0xf, 0xb,
612
613 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
614 },
615 },
616 }
617
618 for _, tc := range tests {
619 tc := tc
620 t.Run(tc.name, func(t *testing.T) {
621 code := asm.CodeSegment{}
622 defer func() { require.NoError(t, code.Unmap()) }()
623
624 a := NewAssembler()
625
626 err := a.CompileStaticConstToRegister(tc.ins, asm.NewStaticConst(tc.c), tc.reg)
627 require.NoError(t, err)
628
629 for i := 0; i < tc.ud2sBeforeConst; i++ {
630 a.CompileStandAlone(UD2)
631 }
632
633 buf := code.NextCodeSection()
634 err = a.Assemble(buf)
635 require.NoError(t, err)
636
637 actual := buf.Bytes()
638 require.Equal(t, tc.exp, actual, hex.EncodeToString(actual))
639 })
640 }
641 }
642
View as plain text