Ruby  3.1.4p223 (2023-03-30 revision HEAD)
yjit_asm_tests.c
1 // For MAP_ANONYMOUS on GNU/Linux
2 #define _GNU_SOURCE 1
3 
4 #include <stdarg.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <assert.h>
9 
10 // This test executable doesn't compile with the rest of Ruby
11 // so we need to define a rb_bug().
12 _Noreturn
13 static void rb_bug(const char *message, ...)
14 {
15  va_list args;
16  va_start(args, message);
17  vfprintf(stderr, message, args);
18  va_end(args);
19  abort();
20 }
21 
22 #include "yjit_asm.c"
23 
24 // Print the bytes in a code block
25 void print_bytes(codeblock_t* cb)
26 {
27  for (uint32_t i = 0; i < cb->write_pos; ++i)
28  {
29  printf("%02X", (int)*cb_get_ptr(cb, i));
30  }
31 
32  printf("\n");
33 }
34 
35 // Check that the code block contains the given sequence of bytes
36 void check_bytes(codeblock_t* cb, const char* bytes)
37 {
38  printf("checking encoding: %s\n", bytes);
39 
40  size_t len = strlen(bytes);
41  assert (len % 2 == 0);
42  size_t num_bytes = len / 2;
43 
44  if (cb->write_pos != num_bytes)
45  {
46  fprintf(stderr, "incorrect encoding length, expected %ld, got %d\n",
47  num_bytes,
48  cb->write_pos
49  );
50  printf("%s\n", bytes);
51  print_bytes(cb);
52  exit(-1);
53  }
54 
55  for (uint32_t i = 0; i < num_bytes; ++i)
56  {
57  char byte_str[] = {0, 0, 0, 0};
58  strncpy(byte_str, bytes + (2 * i), 2);
59  char* endptr;
60  long int byte = strtol(byte_str, &endptr, 16);
61 
62  uint8_t cb_byte = *cb_get_ptr(cb, i);
63 
64  if (cb_byte != byte)
65  {
66  fprintf(stderr, "incorrect encoding at position %d, expected %02X, got %02X\n",
67  i,
68  (int)byte,
69  (int)cb_byte
70  );
71  printf("%s\n", bytes);
72  print_bytes(cb);
73  exit(-1);
74  }
75  }
76 }
77 
78 void run_assembler_tests(void)
79 {
80  printf("Running assembler tests\n");
81 
82  codeblock_t cb_obj;
83  codeblock_t* cb = &cb_obj;
84  uint8_t* mem_block = alloc_exec_mem(4096);
85  cb_init(cb, mem_block, 4096);
86 
87  // add
88  cb_set_pos(cb, 0); add(cb, CL, imm_opnd(3)); check_bytes(cb, "80C103");
89  cb_set_pos(cb, 0); add(cb, CL, BL); check_bytes(cb, "00D9");
90  cb_set_pos(cb, 0); add(cb, CL, SPL); check_bytes(cb, "4000E1");
91  cb_set_pos(cb, 0); add(cb, CX, BX); check_bytes(cb, "6601D9");
92  cb_set_pos(cb, 0); add(cb, RAX, RBX); check_bytes(cb, "4801D8");
93  cb_set_pos(cb, 0); add(cb, ECX, EDX); check_bytes(cb, "01D1");
94  cb_set_pos(cb, 0); add(cb, RDX, R14); check_bytes(cb, "4C01F2");
95  cb_set_pos(cb, 0); add(cb, mem_opnd(64, RAX, 0), RDX); check_bytes(cb, "480110");
96  cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 0)); check_bytes(cb, "480310");
97  cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 8)); check_bytes(cb, "48035008");
98  cb_set_pos(cb, 0); add(cb, RDX, mem_opnd(64, RAX, 255)); check_bytes(cb, "480390FF000000");
99  cb_set_pos(cb, 0); add(cb, mem_opnd(64, RAX, 127), imm_opnd(255)); check_bytes(cb, "4881407FFF000000");
100  cb_set_pos(cb, 0); add(cb, mem_opnd(32, RAX, 0), EDX); check_bytes(cb, "0110");
101  cb_set_pos(cb, 0); add(cb, RSP, imm_opnd(8)); check_bytes(cb, "4883C408");
102  cb_set_pos(cb, 0); add(cb, ECX, imm_opnd(8)); check_bytes(cb, "83C108");
103  cb_set_pos(cb, 0); add(cb, ECX, imm_opnd(255)); check_bytes(cb, "81C1FF000000");
104 
105  // and
106  cb_set_pos(cb, 0); and(cb, EBP, R12D); check_bytes(cb, "4421E5");
107  cb_set_pos(cb, 0); and(cb, mem_opnd(64, RAX, 0), imm_opnd(0x08)); check_bytes(cb, "48832008");
108 
109  // call
110  {
111  cb_set_pos(cb, 0);
112  uint32_t fn_label = cb_new_label(cb, "foo");
113  call_label(cb, fn_label);
114  cb_link_labels(cb);
115  check_bytes(cb, "E8FBFFFFFF");
116  }
117  cb_set_pos(cb, 0); call(cb, RAX); check_bytes(cb, "FFD0");
118  cb_set_pos(cb, 0); call(cb, mem_opnd(64, RSP, 8)); check_bytes(cb, "FF542408");
119 
120  // cmovcc
121  cb_set_pos(cb, 0); cmovg(cb, ESI, EDI); check_bytes(cb, "0F4FF7");
122  cb_set_pos(cb, 0); cmovg(cb, ESI, mem_opnd(32, RBP, 12)); check_bytes(cb, "0F4F750C");
123  cb_set_pos(cb, 0); cmovl(cb, EAX, ECX); check_bytes(cb, "0F4CC1");
124  cb_set_pos(cb, 0); cmovl(cb, RBX, RBP); check_bytes(cb, "480F4CDD");
125  cb_set_pos(cb, 0); cmovle(cb, ESI, mem_opnd(32, RSP, 4)); check_bytes(cb, "0F4E742404");
126 
127  // cmp
128  cb_set_pos(cb, 0); cmp(cb, CL, DL); check_bytes(cb, "38D1");
129  cb_set_pos(cb, 0); cmp(cb, ECX, EDI); check_bytes(cb, "39F9");
130  cb_set_pos(cb, 0); cmp(cb, RDX, mem_opnd(64, R12, 0)); check_bytes(cb, "493B1424");
131  cb_set_pos(cb, 0); cmp(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883F802");
132 
133  // cqo
134  cb_set_pos(cb, 0); cqo(cb); check_bytes(cb, "4899");
135 
136  // div
137  /*
138  test(
139  delegate void (CodeBlock cb) { cb.div(X86Opnd(EDX)); },
140  "F7F2"
141  );
142  test(
143  delegate void (CodeBlock cb) { cb.div(X86Opnd(32, RSP, -12)); },
144  "F77424F4"
145  );
146  */
147 
148  // jcc to label
149  {
150  cb_set_pos(cb, 0);
151  uint32_t loop_label = cb_new_label(cb, "loop");
152  jge_label(cb, loop_label);
153  cb_link_labels(cb);
154  check_bytes(cb, "0F8DFAFFFFFF");
155  }
156  {
157  cb_set_pos(cb, 0);
158  uint32_t loop_label = cb_new_label(cb, "loop");
159  jo_label(cb, loop_label);
160  cb_link_labels(cb);
161  check_bytes(cb, "0F80FAFFFFFF");
162  }
163 
164  // jmp to label
165  {
166  cb_set_pos(cb, 0);
167  uint32_t loop_label = cb_new_label(cb, "loop");
168  jmp_label(cb, loop_label);
169  cb_link_labels(cb);
170  check_bytes(cb, "E9FBFFFFFF");
171  }
172 
173  // jmp with RM operand
174  cb_set_pos(cb, 0); jmp_rm(cb, R12); check_bytes(cb, "41FFE4");
175 
176  // lea
177  cb_set_pos(cb, 0); lea(cb, RDX, mem_opnd(64, RCX, 8)); check_bytes(cb, "488D5108");
178  cb_set_pos(cb, 0); lea(cb, RAX, mem_opnd(8, RIP, 0)); check_bytes(cb, "488D0500000000");
179  cb_set_pos(cb, 0); lea(cb, RAX, mem_opnd(8, RIP, 5)); check_bytes(cb, "488D0505000000");
180  cb_set_pos(cb, 0); lea(cb, RDI, mem_opnd(8, RIP, 5)); check_bytes(cb, "488D3D05000000");
181 
182  // mov
183  cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(7)); check_bytes(cb, "B807000000");
184  cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(-3)); check_bytes(cb, "B8FDFFFFFF");
185  cb_set_pos(cb, 0); mov(cb, R15, imm_opnd(3)); check_bytes(cb, "41BF03000000");
186  cb_set_pos(cb, 0); mov(cb, EAX, EBX); check_bytes(cb, "89D8");
187  cb_set_pos(cb, 0); mov(cb, EAX, ECX); check_bytes(cb, "89C8");
188  cb_set_pos(cb, 0); mov(cb, EDX, mem_opnd(32, RBX, 128)); check_bytes(cb, "8B9380000000");
189 
190  // Test `mov rax, 3` => `mov eax, 3` optimization
191  cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(0x34)); check_bytes(cb, "41B834000000");
192  cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(0x80000000)); check_bytes(cb, "49B80000008000000000");
193  cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(-1)); check_bytes(cb, "49B8FFFFFFFFFFFFFFFF");
194 
195  cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(0x34)); check_bytes(cb, "B834000000");
196  cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(0x80000000)); check_bytes(cb, "48B80000008000000000");
197  cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(-52)); check_bytes(cb, "48B8CCFFFFFFFFFFFFFF");
198  cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(-1)); check_bytes(cb, "48B8FFFFFFFFFFFFFFFF");
199  /*
200  test(
201  delegate void (CodeBlock cb) { cb.mov(X86Opnd(AL), X86Opnd(8, RCX, 0, 1, RDX)); },
202  "8A0411"
203  );
204  */
205  cb_set_pos(cb, 0); mov(cb, CL, R9B); check_bytes(cb, "4488C9");
206  cb_set_pos(cb, 0); mov(cb, RBX, RAX); check_bytes(cb, "4889C3");
207  cb_set_pos(cb, 0); mov(cb, RDI, RBX); check_bytes(cb, "4889DF");
208  cb_set_pos(cb, 0); mov(cb, SIL, imm_opnd(11)); check_bytes(cb, "40B60B");
209  cb_set_pos(cb, 0); mov(cb, mem_opnd(8, RSP, 0), imm_opnd(-3)); check_bytes(cb, "C60424FD");
210  cb_set_pos(cb, 0); mov(cb, mem_opnd(64, RDI, 8), imm_opnd(1)); check_bytes(cb, "48C7470801000000");
211 
212  // movsx
213  cb_set_pos(cb, 0); movsx(cb, AX, AL); check_bytes(cb, "660FBEC0");
214  cb_set_pos(cb, 0); movsx(cb, EDX, AL); check_bytes(cb, "0FBED0");
215  cb_set_pos(cb, 0); movsx(cb, RAX, BL); check_bytes(cb, "480FBEC3");
216  cb_set_pos(cb, 0); movsx(cb, ECX, AX); check_bytes(cb, "0FBFC8");
217  cb_set_pos(cb, 0); movsx(cb, R11, CL); check_bytes(cb, "4C0FBED9");
218  cb_set_pos(cb, 0); movsx(cb, R10, mem_opnd(32, RSP, 12)); check_bytes(cb, "4C6354240C");
219  cb_set_pos(cb, 0); movsx(cb, RAX, mem_opnd(8, RSP, 0)); check_bytes(cb, "480FBE0424");
220 
221  // neg
222  cb_set_pos(cb, 0); neg(cb, RAX); check_bytes(cb, "48F7D8");
223 
224  // nop
225  cb_set_pos(cb, 0); nop(cb, 1); check_bytes(cb, "90");
226 
227  // not
228  cb_set_pos(cb, 0); not(cb, AX); check_bytes(cb, "66F7D0");
229  cb_set_pos(cb, 0); not(cb, EAX); check_bytes(cb, "F7D0");
230  cb_set_pos(cb, 0); not(cb, mem_opnd(64, R12, 0)); check_bytes(cb, "49F71424");
231  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 301)); check_bytes(cb, "F794242D010000");
232  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 0)); check_bytes(cb, "F71424");
233  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 3)); check_bytes(cb, "F7542403");
234  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RBP, 0)); check_bytes(cb, "F75500");
235  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RBP, 13)); check_bytes(cb, "F7550D");
236  cb_set_pos(cb, 0); not(cb, RAX); check_bytes(cb, "48F7D0");
237  cb_set_pos(cb, 0); not(cb, R11); check_bytes(cb, "49F7D3");
238  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RAX, 0)); check_bytes(cb, "F710");
239  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSI, 0)); check_bytes(cb, "F716");
240  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDI, 0)); check_bytes(cb, "F717");
241  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, 55)); check_bytes(cb, "F75237");
242  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, 1337)); check_bytes(cb, "F79239050000");
243  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, -55)); check_bytes(cb, "F752C9");
244  cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, -555)); check_bytes(cb, "F792D5FDFFFF");
245  /*
246  test(
247  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 0, 1, RBX)); },
248  "F71418"
249  );
250  test(
251  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 0, 1, R12)); },
252  "42F71420"
253  );
254  test(
255  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 0, 1, R12)); },
256  "43F71427"
257  );
258  test(
259  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 1, R12)); },
260  "43F7542705"
261  );
262  test(
263  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 8, R12)); },
264  "43F754E705"
265  );
266  test(
267  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 8, R13)); },
268  "43F754EF05"
269  );
270  test(
271  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R12, 5, 4, R9)); },
272  "43F7548C05"
273  );
274  test(
275  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R12, 301, 4, R9)); },
276  "43F7948C2D010000"
277  );
278  test(
279  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 5, 4, RDX)); },
280  "F7549005"
281  );
282  test(
283  delegate void (CodeBlock cb) { cb.not(X86Opnd(64, RAX, 0, 2, RDX)); },
284  "48F71450"
285  );
286  test(
287  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RSP, 0, 1, RBX)); },
288  "F7141C"
289  );
290  test(
291  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RSP, 3, 1, RBX)); },
292  "F7541C03"
293  );
294  test(
295  delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RBP, 13, 1, RDX)); },
296  "F754150D"
297  );
298  */
299 
300  // or
301  cb_set_pos(cb, 0); or(cb, EDX, ESI); check_bytes(cb, "09F2");
302 
303  // pop
304  cb_set_pos(cb, 0); pop(cb, RAX); check_bytes(cb, "58");
305  cb_set_pos(cb, 0); pop(cb, RBX); check_bytes(cb, "5B");
306  cb_set_pos(cb, 0); pop(cb, RSP); check_bytes(cb, "5C");
307  cb_set_pos(cb, 0); pop(cb, RBP); check_bytes(cb, "5D");
308  cb_set_pos(cb, 0); pop(cb, R12); check_bytes(cb, "415C");
309  cb_set_pos(cb, 0); pop(cb, mem_opnd(64, RAX, 0)); check_bytes(cb, "8F00");
310  cb_set_pos(cb, 0); pop(cb, mem_opnd(64, R8, 0)); check_bytes(cb, "418F00");
311  cb_set_pos(cb, 0); pop(cb, mem_opnd(64, R8, 3)); check_bytes(cb, "418F4003");
312  cb_set_pos(cb, 0); pop(cb, mem_opnd_sib(64, RAX, RCX, 8, 3)); check_bytes(cb, "8F44C803");
313  cb_set_pos(cb, 0); pop(cb, mem_opnd_sib(64, R8, RCX, 8, 3)); check_bytes(cb, "418F44C803");
314 
315  // push
316  cb_set_pos(cb, 0); push(cb, RAX); check_bytes(cb, "50");
317  cb_set_pos(cb, 0); push(cb, RBX); check_bytes(cb, "53");
318  cb_set_pos(cb, 0); push(cb, R12); check_bytes(cb, "4154");
319  cb_set_pos(cb, 0); push(cb, mem_opnd(64, RAX, 0)); check_bytes(cb, "FF30");
320  cb_set_pos(cb, 0); push(cb, mem_opnd(64, R8, 0)); check_bytes(cb, "41FF30");
321  cb_set_pos(cb, 0); push(cb, mem_opnd(64, R8, 3)); check_bytes(cb, "41FF7003");
322  cb_set_pos(cb, 0); push(cb, mem_opnd_sib(64, RAX, RCX, 8, 3)); check_bytes(cb, "FF74C803");
323  cb_set_pos(cb, 0); push(cb, mem_opnd_sib(64, R8, RCX, 8, 3)); check_bytes(cb, "41FF74C803");
324 
325  // ret
326  cb_set_pos(cb, 0); ret(cb); check_bytes(cb, "C3");
327 
328  // sal
329  cb_set_pos(cb, 0); sal(cb, CX, imm_opnd(1)); check_bytes(cb, "66D1E1");
330  cb_set_pos(cb, 0); sal(cb, ECX, imm_opnd(1)); check_bytes(cb, "D1E1");
331  cb_set_pos(cb, 0); sal(cb, EBP, imm_opnd(5)); check_bytes(cb, "C1E505");
332  cb_set_pos(cb, 0); sal(cb, mem_opnd(32, RSP, 68), imm_opnd(1)); check_bytes(cb, "D1642444");
333 
334  // sar
335  cb_set_pos(cb, 0); sar(cb, EDX, imm_opnd(1)); check_bytes(cb, "D1FA");
336 
337  // shr
338  cb_set_pos(cb, 0); shr(cb, R14, imm_opnd(7)); check_bytes(cb, "49C1EE07");
339 
340  /*
341  // sqrtsd
342  test(
343  delegate void (CodeBlock cb) { cb.sqrtsd(X86Opnd(XMM2), X86Opnd(XMM6)); },
344  "F20F51D6"
345  );
346  */
347 
348  // sub
349  cb_set_pos(cb, 0); sub(cb, EAX, imm_opnd(1)); check_bytes(cb, "83E801");
350  cb_set_pos(cb, 0); sub(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883E802");
351 
352  // test
353  cb_set_pos(cb, 0); test(cb, AL, AL); check_bytes(cb, "84C0");
354  cb_set_pos(cb, 0); test(cb, AX, AX); check_bytes(cb, "6685C0");
355  cb_set_pos(cb, 0); test(cb, CL, imm_opnd(8)); check_bytes(cb, "F6C108");
356  cb_set_pos(cb, 0); test(cb, DL, imm_opnd(7)); check_bytes(cb, "F6C207");
357  cb_set_pos(cb, 0); test(cb, RCX, imm_opnd(8)); check_bytes(cb, "F6C108");
358  cb_set_pos(cb, 0); test(cb, mem_opnd(8, RDX, 8), imm_opnd(8)); check_bytes(cb, "F6420808");
359  cb_set_pos(cb, 0); test(cb, mem_opnd(8, RDX, 8), imm_opnd(255)); check_bytes(cb, "F64208FF");
360  cb_set_pos(cb, 0); test(cb, DX, imm_opnd(0xFFFF)); check_bytes(cb, "66F7C2FFFF");
361  cb_set_pos(cb, 0); test(cb, mem_opnd(16, RDX, 8), imm_opnd(0xFFFF)); check_bytes(cb, "66F74208FFFF");
362  cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, 0), imm_opnd(1)); check_bytes(cb, "F60601");
363  cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, 16), imm_opnd(1)); check_bytes(cb, "F6461001");
364  cb_set_pos(cb, 0); test(cb, mem_opnd(8, RSI, -16), imm_opnd(1)); check_bytes(cb, "F646F001");
365  cb_set_pos(cb, 0); test(cb, mem_opnd(32, RSI, 64), EAX); check_bytes(cb, "854640");
366  cb_set_pos(cb, 0); test(cb, mem_opnd(64, RDI, 42), RAX); check_bytes(cb, "4885472A");
367  cb_set_pos(cb, 0); test(cb, RAX, RAX); check_bytes(cb, "4885C0");
368  cb_set_pos(cb, 0); test(cb, RAX, RSI); check_bytes(cb, "4885F0");
369  cb_set_pos(cb, 0); test(cb, mem_opnd(64, RSI, 64), imm_opnd(~0x08)); check_bytes(cb, "48F74640F7FFFFFF");
370 
371  // xchg
372  cb_set_pos(cb, 0); xchg(cb, RAX, RCX); check_bytes(cb, "4891");
373  cb_set_pos(cb, 0); xchg(cb, RAX, R13); check_bytes(cb, "4995");
374  cb_set_pos(cb, 0); xchg(cb, RCX, RBX); check_bytes(cb, "4887D9");
375  cb_set_pos(cb, 0); xchg(cb, R9, R15); check_bytes(cb, "4D87F9");
376 
377  // xor
378  cb_set_pos(cb, 0); xor(cb, EAX, EAX); check_bytes(cb, "31C0");
379 
380  printf("Assembler tests done\n");
381 }
382 
383 void assert_equal(int expected, int actual)
384 {
385  if (expected != actual) {
386  fprintf(stderr, "expected %d, got %d\n", expected, actual);
387  exit(-1);
388  }
389 }
390 
391 void run_runtime_tests(void)
392 {
393  printf("Running runtime tests\n");
394 
395  codeblock_t codeblock;
396  codeblock_t* cb = &codeblock;
397 
398  uint8_t* mem_block = alloc_exec_mem(4096);
399  cb_init(cb, mem_block, 4096);
400 
401  int (*function)(void);
402  function = (int (*)(void))mem_block;
403 
404  #define TEST(BODY) cb_set_pos(cb, 0); BODY ret(cb); cb_mark_all_executable(cb); assert_equal(7, function());
405 
406  // add
407  TEST({ mov(cb, RAX, imm_opnd(0)); add(cb, RAX, imm_opnd(7)); })
408  TEST({ mov(cb, RAX, imm_opnd(0)); mov(cb, RCX, imm_opnd(7)); add(cb, RAX, RCX); })
409 
410  // and
411  TEST({ mov(cb, RAX, imm_opnd(31)); and(cb, RAX, imm_opnd(7)); })
412  TEST({ mov(cb, RAX, imm_opnd(31)); mov(cb, RCX, imm_opnd(7)); and(cb, RAX, RCX); })
413 
414  // or
415  TEST({ mov(cb, RAX, imm_opnd(3)); or(cb, RAX, imm_opnd(4)); })
416  TEST({ mov(cb, RAX, imm_opnd(3)); mov(cb, RCX, imm_opnd(4)); or(cb, RAX, RCX); })
417 
418  // push/pop
419  TEST({ mov(cb, RCX, imm_opnd(7)); push(cb, RCX); pop(cb, RAX); })
420 
421  // shr
422  TEST({ mov(cb, RAX, imm_opnd(31)); shr(cb, RAX, imm_opnd(2)); })
423 
424  // sub
425  TEST({ mov(cb, RAX, imm_opnd(12)); sub(cb, RAX, imm_opnd(5)); })
426  TEST({ mov(cb, RAX, imm_opnd(12)); mov(cb, RCX, imm_opnd(5)); sub(cb, RAX, RCX); })
427 
428  // xor
429  TEST({ mov(cb, RAX, imm_opnd(13)); xor(cb, RAX, imm_opnd(10)); })
430  TEST({ mov(cb, RAX, imm_opnd(13)); mov(cb, RCX, imm_opnd(10)); xor(cb, RAX, RCX); })
431 
432  #undef TEST
433 
434  printf("Runtime tests done\n");
435 }
436 
437 int main(int argc, char** argv)
438 {
439  run_assembler_tests();
440  run_runtime_tests();
441 
442  return 0;
443 }
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:802
Defines old _.