master
inc 1,285 lines 34.5 KB
Raw
1 /*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2009, 2011 Stefan Weil
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 /* Used for function call generation. */
26 #define TCG_TARGET_CALL_STACK_OFFSET 0
27 #define TCG_TARGET_STACK_ALIGN 8
28 #define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL
29 #define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
30 #define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL
31 #define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL
32
33 static TCGConstraintSetIndex
34 tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
35 {
36 return C_NotImplemented;
37 }
38
39 static const int tcg_target_reg_alloc_order[] = {
40 TCG_REG_R4,
41 TCG_REG_R5,
42 TCG_REG_R6,
43 TCG_REG_R7,
44 TCG_REG_R8,
45 TCG_REG_R9,
46 TCG_REG_R10,
47 TCG_REG_R11,
48 TCG_REG_R12,
49 TCG_REG_R13,
50 TCG_REG_R14,
51 TCG_REG_R15,
52 /* Either 2 or 4 of these are call clobbered, so use them last. */
53 TCG_REG_R3,
54 TCG_REG_R2,
55 TCG_REG_R1,
56 TCG_REG_R0,
57 };
58
59 /* No call arguments via registers. All will be stored on the "stack". */
60 static const int tcg_target_call_iarg_regs[] = { };
61
62 static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
63 {
64 tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
65 tcg_debug_assert(slot >= 0 && slot < 128 / TCG_TARGET_REG_BITS);
66 return TCG_REG_R0 + slot;
67 }
68
69 #ifdef CONFIG_DEBUG_TCG
70 static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
71 "r00",
72 "r01",
73 "r02",
74 "r03",
75 "r04",
76 "r05",
77 "r06",
78 "r07",
79 "r08",
80 "r09",
81 "r10",
82 "r11",
83 "r12",
84 "r13",
85 "r14",
86 "r15",
87 };
88 #endif
89
90 static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
91 intptr_t value, intptr_t addend)
92 {
93 intptr_t diff = value - (intptr_t)(code_ptr + 1);
94
95 tcg_debug_assert(addend == 0);
96 tcg_debug_assert(type == 20);
97
98 if (diff == sextract32(diff, 0, type)) {
99 tcg_patch32(code_ptr, deposit32(*code_ptr, 32 - type, type, diff));
100 return true;
101 }
102 return false;
103 }
104
105 static void stack_bounds_check(TCGReg base, intptr_t offset)
106 {
107 if (base == TCG_REG_CALL_STACK) {
108 tcg_debug_assert(offset >= 0);
109 tcg_debug_assert(offset < (TCG_STATIC_CALL_ARGS_SIZE +
110 TCG_STATIC_FRAME_SIZE));
111 }
112 }
113
114 static void tcg_out_op_l(TCGContext *s, TCGOpcode op, TCGLabel *l0)
115 {
116 tcg_insn_unit insn = 0;
117
118 tcg_out_reloc(s, s->code_ptr, 20, l0, 0);
119 insn = deposit32(insn, 0, 8, op);
120 tcg_out32(s, insn);
121 }
122
123 static void tcg_out_op_p(TCGContext *s, TCGOpcode op, void *p0)
124 {
125 tcg_insn_unit insn = 0;
126 intptr_t diff;
127
128 /* Special case for exit_tb: map null -> 0. */
129 if (p0 == NULL) {
130 diff = 0;
131 } else {
132 diff = p0 - (void *)(s->code_ptr + 1);
133 tcg_debug_assert(diff != 0);
134 if (diff != sextract32(diff, 0, 20)) {
135 tcg_raise_tb_overflow(s);
136 }
137 }
138 insn = deposit32(insn, 0, 8, op);
139 insn = deposit32(insn, 12, 20, diff);
140 tcg_out32(s, insn);
141 }
142
143 static void tcg_out_op_r(TCGContext *s, TCGOpcode op, TCGReg r0)
144 {
145 tcg_insn_unit insn = 0;
146
147 insn = deposit32(insn, 0, 8, op);
148 insn = deposit32(insn, 8, 4, r0);
149 tcg_out32(s, insn);
150 }
151
152 static void tcg_out_op_v(TCGContext *s, TCGOpcode op)
153 {
154 tcg_out32(s, (uint8_t)op);
155 }
156
157 static void tcg_out_op_ri(TCGContext *s, TCGOpcode op, TCGReg r0, int32_t i1)
158 {
159 tcg_insn_unit insn = 0;
160
161 tcg_debug_assert(i1 == sextract32(i1, 0, 20));
162 insn = deposit32(insn, 0, 8, op);
163 insn = deposit32(insn, 8, 4, r0);
164 insn = deposit32(insn, 12, 20, i1);
165 tcg_out32(s, insn);
166 }
167
168 static void tcg_out_op_rl(TCGContext *s, TCGOpcode op, TCGReg r0, TCGLabel *l1)
169 {
170 tcg_insn_unit insn = 0;
171
172 tcg_out_reloc(s, s->code_ptr, 20, l1, 0);
173 insn = deposit32(insn, 0, 8, op);
174 insn = deposit32(insn, 8, 4, r0);
175 tcg_out32(s, insn);
176 }
177
178 static void tcg_out_op_rr(TCGContext *s, TCGOpcode op, TCGReg r0, TCGReg r1)
179 {
180 tcg_insn_unit insn = 0;
181
182 insn = deposit32(insn, 0, 8, op);
183 insn = deposit32(insn, 8, 4, r0);
184 insn = deposit32(insn, 12, 4, r1);
185 tcg_out32(s, insn);
186 }
187
188 static void tcg_out_op_rrm(TCGContext *s, TCGOpcode op,
189 TCGReg r0, TCGReg r1, TCGArg m2)
190 {
191 tcg_insn_unit insn = 0;
192
193 tcg_debug_assert(m2 == extract32(m2, 0, 16));
194 insn = deposit32(insn, 0, 8, op);
195 insn = deposit32(insn, 8, 4, r0);
196 insn = deposit32(insn, 12, 4, r1);
197 insn = deposit32(insn, 16, 16, m2);
198 tcg_out32(s, insn);
199 }
200
201 static void tcg_out_op_rrr(TCGContext *s, TCGOpcode op,
202 TCGReg r0, TCGReg r1, TCGReg r2)
203 {
204 tcg_insn_unit insn = 0;
205
206 insn = deposit32(insn, 0, 8, op);
207 insn = deposit32(insn, 8, 4, r0);
208 insn = deposit32(insn, 12, 4, r1);
209 insn = deposit32(insn, 16, 4, r2);
210 tcg_out32(s, insn);
211 }
212
213 static void tcg_out_op_rrs(TCGContext *s, TCGOpcode op,
214 TCGReg r0, TCGReg r1, intptr_t i2)
215 {
216 tcg_insn_unit insn = 0;
217
218 tcg_debug_assert(i2 == sextract32(i2, 0, 16));
219 insn = deposit32(insn, 0, 8, op);
220 insn = deposit32(insn, 8, 4, r0);
221 insn = deposit32(insn, 12, 4, r1);
222 insn = deposit32(insn, 16, 16, i2);
223 tcg_out32(s, insn);
224 }
225
226 static void tcg_out_op_rrbb(TCGContext *s, TCGOpcode op, TCGReg r0,
227 TCGReg r1, uint8_t b2, uint8_t b3)
228 {
229 tcg_insn_unit insn = 0;
230
231 tcg_debug_assert(b2 == extract32(b2, 0, 6));
232 tcg_debug_assert(b3 == extract32(b3, 0, 6));
233 insn = deposit32(insn, 0, 8, op);
234 insn = deposit32(insn, 8, 4, r0);
235 insn = deposit32(insn, 12, 4, r1);
236 insn = deposit32(insn, 16, 6, b2);
237 insn = deposit32(insn, 22, 6, b3);
238 tcg_out32(s, insn);
239 }
240
241 static void tcg_out_op_rrrc(TCGContext *s, TCGOpcode op,
242 TCGReg r0, TCGReg r1, TCGReg r2, TCGCond c3)
243 {
244 tcg_insn_unit insn = 0;
245
246 insn = deposit32(insn, 0, 8, op);
247 insn = deposit32(insn, 8, 4, r0);
248 insn = deposit32(insn, 12, 4, r1);
249 insn = deposit32(insn, 16, 4, r2);
250 insn = deposit32(insn, 20, 4, c3);
251 tcg_out32(s, insn);
252 }
253
254 static void tcg_out_op_rrrbb(TCGContext *s, TCGOpcode op, TCGReg r0,
255 TCGReg r1, TCGReg r2, uint8_t b3, uint8_t b4)
256 {
257 tcg_insn_unit insn = 0;
258
259 tcg_debug_assert(b3 == extract32(b3, 0, 6));
260 tcg_debug_assert(b4 == extract32(b4, 0, 6));
261 insn = deposit32(insn, 0, 8, op);
262 insn = deposit32(insn, 8, 4, r0);
263 insn = deposit32(insn, 12, 4, r1);
264 insn = deposit32(insn, 16, 4, r2);
265 insn = deposit32(insn, 20, 6, b3);
266 insn = deposit32(insn, 26, 6, b4);
267 tcg_out32(s, insn);
268 }
269
270 static void tcg_out_op_rrrr(TCGContext *s, TCGOpcode op,
271 TCGReg r0, TCGReg r1, TCGReg r2, TCGReg r3)
272 {
273 tcg_insn_unit insn = 0;
274
275 insn = deposit32(insn, 0, 8, op);
276 insn = deposit32(insn, 8, 4, r0);
277 insn = deposit32(insn, 12, 4, r1);
278 insn = deposit32(insn, 16, 4, r2);
279 insn = deposit32(insn, 20, 4, r3);
280 tcg_out32(s, insn);
281 }
282
283 static void tcg_out_op_rrrrrc(TCGContext *s, TCGOpcode op,
284 TCGReg r0, TCGReg r1, TCGReg r2,
285 TCGReg r3, TCGReg r4, TCGCond c5)
286 {
287 tcg_insn_unit insn = 0;
288
289 insn = deposit32(insn, 0, 8, op);
290 insn = deposit32(insn, 8, 4, r0);
291 insn = deposit32(insn, 12, 4, r1);
292 insn = deposit32(insn, 16, 4, r2);
293 insn = deposit32(insn, 20, 4, r3);
294 insn = deposit32(insn, 24, 4, r4);
295 insn = deposit32(insn, 28, 4, c5);
296 tcg_out32(s, insn);
297 }
298
299 static void tcg_out_ldst(TCGContext *s, TCGOpcode op, TCGReg val,
300 TCGReg base, intptr_t offset)
301 {
302 stack_bounds_check(base, offset);
303 if (offset != sextract32(offset, 0, 16)) {
304 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, offset);
305 tcg_out_op_rrr(s, INDEX_op_add, TCG_REG_TMP, TCG_REG_TMP, base);
306 base = TCG_REG_TMP;
307 offset = 0;
308 }
309 tcg_out_op_rrs(s, op, val, base, offset);
310 }
311
312 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg val, TCGReg base,
313 intptr_t offset)
314 {
315 TCGOpcode op = INDEX_op_ld;
316
317 if (type == TCG_TYPE_I32) {
318 op = INDEX_op_ld32u;
319 }
320 tcg_out_ldst(s, op, val, base, offset);
321 }
322
323 static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
324 {
325 tcg_out_op_rr(s, INDEX_op_mov, ret, arg);
326 return true;
327 }
328
329 static void tcg_out_movi(TCGContext *s, TCGType type,
330 TCGReg ret, tcg_target_long arg)
331 {
332 switch (type) {
333 case TCG_TYPE_I32:
334 arg = (int32_t)arg;
335 /* fall through */
336 case TCG_TYPE_I64:
337 break;
338 default:
339 g_assert_not_reached();
340 }
341
342 if (arg == sextract32(arg, 0, 20)) {
343 tcg_out_op_ri(s, INDEX_op_tci_movi, ret, arg);
344 } else {
345 tcg_insn_unit insn = 0;
346
347 new_pool_label(s, arg, 20, s->code_ptr, 0);
348 insn = deposit32(insn, 0, 8, INDEX_op_tci_movl);
349 insn = deposit32(insn, 8, 4, ret);
350 tcg_out32(s, insn);
351 }
352 }
353
354 static void tcg_out_extract(TCGContext *s, TCGType type, TCGReg rd,
355 TCGReg rs, unsigned pos, unsigned len)
356 {
357 tcg_out_op_rrbb(s, INDEX_op_extract, rd, rs, pos, len);
358 }
359
360 static const TCGOutOpExtract outop_extract = {
361 .base.static_constraint = C_O1_I1(r, r),
362 .out_rr = tcg_out_extract,
363 };
364
365 static void tcg_out_sextract(TCGContext *s, TCGType type, TCGReg rd,
366 TCGReg rs, unsigned pos, unsigned len)
367 {
368 tcg_out_op_rrbb(s, INDEX_op_sextract, rd, rs, pos, len);
369 }
370
371 static const TCGOutOpExtract outop_sextract = {
372 .base.static_constraint = C_O1_I1(r, r),
373 .out_rr = tcg_out_sextract,
374 };
375
376 static const TCGOutOpExtract2 outop_extract2 = {
377 .base.static_constraint = C_NotImplemented,
378 };
379
380 static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
381 {
382 tcg_out_sextract(s, type, rd, rs, 0, 8);
383 }
384
385 static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs)
386 {
387 tcg_out_extract(s, TCG_TYPE_REG, rd, rs, 0, 8);
388 }
389
390 static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
391 {
392 tcg_out_sextract(s, type, rd, rs, 0, 16);
393 }
394
395 static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs)
396 {
397 tcg_out_extract(s, TCG_TYPE_REG, rd, rs, 0, 16);
398 }
399
400 static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs)
401 {
402 tcg_out_sextract(s, TCG_TYPE_I64, rd, rs, 0, 32);
403 }
404
405 static void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rs)
406 {
407 tcg_out_extract(s, TCG_TYPE_I64, rd, rs, 0, 32);
408 }
409
410 static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
411 {
412 tcg_out_ext32s(s, rd, rs);
413 }
414
415 static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
416 {
417 tcg_out_ext32u(s, rd, rs);
418 }
419
420 static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
421 {
422 tcg_out_mov(s, TCG_TYPE_I32, rd, rs);
423 }
424
425 static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
426 {
427 return false;
428 }
429
430 static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
431 tcg_target_long imm)
432 {
433 /* This function is only used for passing structs by reference. */
434 g_assert_not_reached();
435 }
436
437 static void tcg_out_call(TCGContext *s, const tcg_insn_unit *func,
438 const TCGHelperInfo *info)
439 {
440 ffi_cif *cif = info->cif;
441 tcg_insn_unit insn = 0;
442 uint8_t which;
443
444 if (cif->rtype == &ffi_type_void) {
445 which = 0;
446 } else {
447 tcg_debug_assert(cif->rtype->size == 4 ||
448 cif->rtype->size == 8 ||
449 cif->rtype->size == 16);
450 which = ctz32(cif->rtype->size) - 1;
451 }
452 new_pool_l2(s, 20, s->code_ptr, 0, (uintptr_t)func, (uintptr_t)cif);
453 insn = deposit32(insn, 0, 8, INDEX_op_call);
454 insn = deposit32(insn, 8, 4, which);
455 tcg_out32(s, insn);
456 }
457
458 static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
459 {
460 tcg_out_op_p(s, INDEX_op_exit_tb, (void *)arg);
461 }
462
463 static void tcg_out_goto_tb(TCGContext *s, int which)
464 {
465 /* indirect jump method. */
466 tcg_out_op_p(s, INDEX_op_goto_tb, (void *)get_jmp_target_addr(s, which));
467 set_jmp_reset_offset(s, which);
468 }
469
470 static void tcg_out_goto_ptr(TCGContext *s, TCGReg a0)
471 {
472 tcg_out_op_r(s, INDEX_op_goto_ptr, a0);
473 }
474
475 void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
476 uintptr_t jmp_rx, uintptr_t jmp_rw)
477 {
478 /* Always indirect, nothing to do */
479 }
480
481 static void tgen_add(TCGContext *s, TCGType type,
482 TCGReg a0, TCGReg a1, TCGReg a2)
483 {
484 tcg_out_op_rrr(s, INDEX_op_add, a0, a1, a2);
485 }
486
487 static const TCGOutOpBinary outop_add = {
488 .base.static_constraint = C_O1_I2(r, r, r),
489 .out_rrr = tgen_add,
490 };
491
492 static TCGConstraintSetIndex cset_addsubcarry(TCGType type, unsigned flags)
493 {
494 return type == TCG_TYPE_REG ? C_O1_I2(r, r, r) : C_NotImplemented;
495 }
496
497 static void tgen_addco(TCGContext *s, TCGType type,
498 TCGReg a0, TCGReg a1, TCGReg a2)
499 {
500 tcg_out_op_rrr(s, INDEX_op_addco, a0, a1, a2);
501 }
502
503 static const TCGOutOpBinary outop_addco = {
504 .base.static_constraint = C_Dynamic,
505 .base.dynamic_constraint = cset_addsubcarry,
506 .out_rrr = tgen_addco,
507 };
508
509 static void tgen_addci(TCGContext *s, TCGType type,
510 TCGReg a0, TCGReg a1, TCGReg a2)
511 {
512 tcg_out_op_rrr(s, INDEX_op_addci, a0, a1, a2);
513 }
514
515 static const TCGOutOpAddSubCarry outop_addci = {
516 .base.static_constraint = C_Dynamic,
517 .base.dynamic_constraint = cset_addsubcarry,
518 .out_rrr = tgen_addci,
519 };
520
521 static void tgen_addcio(TCGContext *s, TCGType type,
522 TCGReg a0, TCGReg a1, TCGReg a2)
523 {
524 tcg_out_op_rrr(s, INDEX_op_addcio, a0, a1, a2);
525 }
526
527 static const TCGOutOpBinary outop_addcio = {
528 .base.static_constraint = C_Dynamic,
529 .base.dynamic_constraint = cset_addsubcarry,
530 .out_rrr = tgen_addcio,
531 };
532
533 static void tcg_out_set_carry(TCGContext *s)
534 {
535 tcg_out_op_v(s, INDEX_op_tci_setcarry);
536 }
537
538 static void tgen_and(TCGContext *s, TCGType type,
539 TCGReg a0, TCGReg a1, TCGReg a2)
540 {
541 tcg_out_op_rrr(s, INDEX_op_and, a0, a1, a2);
542 }
543
544 static const TCGOutOpBinary outop_and = {
545 .base.static_constraint = C_O1_I2(r, r, r),
546 .out_rrr = tgen_and,
547 };
548
549 static void tgen_andc(TCGContext *s, TCGType type,
550 TCGReg a0, TCGReg a1, TCGReg a2)
551 {
552 tcg_out_op_rrr(s, INDEX_op_andc, a0, a1, a2);
553 }
554
555 static const TCGOutOpBinary outop_andc = {
556 .base.static_constraint = C_O1_I2(r, r, r),
557 .out_rrr = tgen_andc,
558 };
559
560 static void tgen_clz(TCGContext *s, TCGType type,
561 TCGReg a0, TCGReg a1, TCGReg a2)
562 {
563 TCGOpcode opc = (type == TCG_TYPE_I32
564 ? INDEX_op_tci_clz32
565 : INDEX_op_clz);
566 tcg_out_op_rrr(s, opc, a0, a1, a2);
567 }
568
569 static const TCGOutOpBinary outop_clz = {
570 .base.static_constraint = C_O1_I2(r, r, r),
571 .out_rrr = tgen_clz,
572 };
573
574 static void tgen_ctz(TCGContext *s, TCGType type,
575 TCGReg a0, TCGReg a1, TCGReg a2)
576 {
577 TCGOpcode opc = (type == TCG_TYPE_I32
578 ? INDEX_op_tci_ctz32
579 : INDEX_op_ctz);
580 tcg_out_op_rrr(s, opc, a0, a1, a2);
581 }
582
583 static const TCGOutOpBinary outop_ctz = {
584 .base.static_constraint = C_O1_I2(r, r, r),
585 .out_rrr = tgen_ctz,
586 };
587
588 static void tgen_deposit(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
589 TCGReg a2, unsigned ofs, unsigned len)
590 {
591 tcg_out_op_rrrbb(s, INDEX_op_deposit, a0, a1, a2, ofs, len);
592 }
593
594 static const TCGOutOpDeposit outop_deposit = {
595 .base.static_constraint = C_O1_I2(r, r, r),
596 .out_rrr = tgen_deposit,
597 };
598
599 static void tgen_divs(TCGContext *s, TCGType type,
600 TCGReg a0, TCGReg a1, TCGReg a2)
601 {
602 TCGOpcode opc = (type == TCG_TYPE_I32
603 ? INDEX_op_tci_divs32
604 : INDEX_op_divs);
605 tcg_out_op_rrr(s, opc, a0, a1, a2);
606 }
607
608 static const TCGOutOpBinary outop_divs = {
609 .base.static_constraint = C_O1_I2(r, r, r),
610 .out_rrr = tgen_divs,
611 };
612
613 static const TCGOutOpDivRem outop_divs2 = {
614 .base.static_constraint = C_NotImplemented,
615 };
616
617 static void tgen_divu(TCGContext *s, TCGType type,
618 TCGReg a0, TCGReg a1, TCGReg a2)
619 {
620 TCGOpcode opc = (type == TCG_TYPE_I32
621 ? INDEX_op_tci_divu32
622 : INDEX_op_divu);
623 tcg_out_op_rrr(s, opc, a0, a1, a2);
624 }
625
626 static const TCGOutOpBinary outop_divu = {
627 .base.static_constraint = C_O1_I2(r, r, r),
628 .out_rrr = tgen_divu,
629 };
630
631 static const TCGOutOpDivRem outop_divu2 = {
632 .base.static_constraint = C_NotImplemented,
633 };
634
635 static void tgen_eqv(TCGContext *s, TCGType type,
636 TCGReg a0, TCGReg a1, TCGReg a2)
637 {
638 tcg_out_op_rrr(s, INDEX_op_eqv, a0, a1, a2);
639 }
640
641 static const TCGOutOpBinary outop_eqv = {
642 .base.static_constraint = C_O1_I2(r, r, r),
643 .out_rrr = tgen_eqv,
644 };
645
646 static void tgen_extrh_i64_i32(TCGContext *s, TCGType t, TCGReg a0, TCGReg a1)
647 {
648 tcg_out_extract(s, TCG_TYPE_I64, a0, a1, 32, 32);
649 }
650
651 static const TCGOutOpUnary outop_extrh_i64_i32 = {
652 .base.static_constraint = C_O1_I1(r, r),
653 .out_rr = tgen_extrh_i64_i32,
654 };
655
656 static void tgen_mul(TCGContext *s, TCGType type,
657 TCGReg a0, TCGReg a1, TCGReg a2)
658 {
659 tcg_out_op_rrr(s, INDEX_op_mul, a0, a1, a2);
660 }
661
662 static const TCGOutOpBinary outop_mul = {
663 .base.static_constraint = C_O1_I2(r, r, r),
664 .out_rrr = tgen_mul,
665 };
666
667 static TCGConstraintSetIndex cset_mul2(TCGType type, unsigned flags)
668 {
669 return type == TCG_TYPE_REG ? C_O2_I2(r, r, r, r) : C_NotImplemented;
670 }
671
672 static void tgen_muls2(TCGContext *s, TCGType type,
673 TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
674 {
675 tcg_out_op_rrrr(s, INDEX_op_muls2, a0, a1, a2, a3);
676 }
677
678 static const TCGOutOpMul2 outop_muls2 = {
679 .base.static_constraint = C_Dynamic,
680 .base.dynamic_constraint = cset_mul2,
681 .out_rrrr = tgen_muls2,
682 };
683
684 static const TCGOutOpBinary outop_mulsh = {
685 .base.static_constraint = C_NotImplemented,
686 };
687
688 static void tgen_mulu2(TCGContext *s, TCGType type,
689 TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
690 {
691 tcg_out_op_rrrr(s, INDEX_op_mulu2, a0, a1, a2, a3);
692 }
693
694 static const TCGOutOpMul2 outop_mulu2 = {
695 .base.static_constraint = C_Dynamic,
696 .base.dynamic_constraint = cset_mul2,
697 .out_rrrr = tgen_mulu2,
698 };
699
700 static const TCGOutOpBinary outop_muluh = {
701 .base.static_constraint = C_NotImplemented,
702 };
703
704 static void tgen_nand(TCGContext *s, TCGType type,
705 TCGReg a0, TCGReg a1, TCGReg a2)
706 {
707 tcg_out_op_rrr(s, INDEX_op_nand, a0, a1, a2);
708 }
709
710 static const TCGOutOpBinary outop_nand = {
711 .base.static_constraint = C_O1_I2(r, r, r),
712 .out_rrr = tgen_nand,
713 };
714
715 static void tgen_nor(TCGContext *s, TCGType type,
716 TCGReg a0, TCGReg a1, TCGReg a2)
717 {
718 tcg_out_op_rrr(s, INDEX_op_nor, a0, a1, a2);
719 }
720
721 static const TCGOutOpBinary outop_nor = {
722 .base.static_constraint = C_O1_I2(r, r, r),
723 .out_rrr = tgen_nor,
724 };
725
726 static void tgen_or(TCGContext *s, TCGType type,
727 TCGReg a0, TCGReg a1, TCGReg a2)
728 {
729 tcg_out_op_rrr(s, INDEX_op_or, a0, a1, a2);
730 }
731
732 static const TCGOutOpBinary outop_or = {
733 .base.static_constraint = C_O1_I2(r, r, r),
734 .out_rrr = tgen_or,
735 };
736
737 static void tgen_orc(TCGContext *s, TCGType type,
738 TCGReg a0, TCGReg a1, TCGReg a2)
739 {
740 tcg_out_op_rrr(s, INDEX_op_orc, a0, a1, a2);
741 }
742
743 static const TCGOutOpBinary outop_orc = {
744 .base.static_constraint = C_O1_I2(r, r, r),
745 .out_rrr = tgen_orc,
746 };
747
748 static void tgen_rems(TCGContext *s, TCGType type,
749 TCGReg a0, TCGReg a1, TCGReg a2)
750 {
751 TCGOpcode opc = (type == TCG_TYPE_I32
752 ? INDEX_op_tci_rems32
753 : INDEX_op_rems);
754 tcg_out_op_rrr(s, opc, a0, a1, a2);
755 }
756
757 static const TCGOutOpBinary outop_rems = {
758 .base.static_constraint = C_O1_I2(r, r, r),
759 .out_rrr = tgen_rems,
760 };
761
762 static void tgen_remu(TCGContext *s, TCGType type,
763 TCGReg a0, TCGReg a1, TCGReg a2)
764 {
765 TCGOpcode opc = (type == TCG_TYPE_I32
766 ? INDEX_op_tci_remu32
767 : INDEX_op_remu);
768 tcg_out_op_rrr(s, opc, a0, a1, a2);
769 }
770
771 static const TCGOutOpBinary outop_remu = {
772 .base.static_constraint = C_O1_I2(r, r, r),
773 .out_rrr = tgen_remu,
774 };
775
776 static void tgen_rotl(TCGContext *s, TCGType type,
777 TCGReg a0, TCGReg a1, TCGReg a2)
778 {
779 TCGOpcode opc = (type == TCG_TYPE_I32
780 ? INDEX_op_tci_rotl32
781 : INDEX_op_rotl);
782 tcg_out_op_rrr(s, opc, a0, a1, a2);
783 }
784
785 static const TCGOutOpBinary outop_rotl = {
786 .base.static_constraint = C_O1_I2(r, r, r),
787 .out_rrr = tgen_rotl,
788 };
789
790 static void tgen_rotr(TCGContext *s, TCGType type,
791 TCGReg a0, TCGReg a1, TCGReg a2)
792 {
793 TCGOpcode opc = (type == TCG_TYPE_I32
794 ? INDEX_op_tci_rotr32
795 : INDEX_op_rotr);
796 tcg_out_op_rrr(s, opc, a0, a1, a2);
797 }
798
799 static const TCGOutOpBinary outop_rotr = {
800 .base.static_constraint = C_O1_I2(r, r, r),
801 .out_rrr = tgen_rotr,
802 };
803
804 static void tgen_sar(TCGContext *s, TCGType type,
805 TCGReg a0, TCGReg a1, TCGReg a2)
806 {
807 if (type < TCG_TYPE_REG) {
808 tcg_out_ext32s(s, TCG_REG_TMP, a1);
809 a1 = TCG_REG_TMP;
810 }
811 tcg_out_op_rrr(s, INDEX_op_sar, a0, a1, a2);
812 }
813
814 static const TCGOutOpBinary outop_sar = {
815 .base.static_constraint = C_O1_I2(r, r, r),
816 .out_rrr = tgen_sar,
817 };
818
819 static void tgen_shl(TCGContext *s, TCGType type,
820 TCGReg a0, TCGReg a1, TCGReg a2)
821 {
822 tcg_out_op_rrr(s, INDEX_op_shl, a0, a1, a2);
823 }
824
825 static const TCGOutOpBinary outop_shl = {
826 .base.static_constraint = C_O1_I2(r, r, r),
827 .out_rrr = tgen_shl,
828 };
829
830 static void tgen_shr(TCGContext *s, TCGType type,
831 TCGReg a0, TCGReg a1, TCGReg a2)
832 {
833 if (type < TCG_TYPE_REG) {
834 tcg_out_ext32u(s, TCG_REG_TMP, a1);
835 a1 = TCG_REG_TMP;
836 }
837 tcg_out_op_rrr(s, INDEX_op_shr, a0, a1, a2);
838 }
839
840 static const TCGOutOpBinary outop_shr = {
841 .base.static_constraint = C_O1_I2(r, r, r),
842 .out_rrr = tgen_shr,
843 };
844
845 static void tgen_sub(TCGContext *s, TCGType type,
846 TCGReg a0, TCGReg a1, TCGReg a2)
847 {
848 tcg_out_op_rrr(s, INDEX_op_sub, a0, a1, a2);
849 }
850
851 static const TCGOutOpSubtract outop_sub = {
852 .base.static_constraint = C_O1_I2(r, r, r),
853 .out_rrr = tgen_sub,
854 };
855
856 static void tgen_subbo(TCGContext *s, TCGType type,
857 TCGReg a0, TCGReg a1, TCGReg a2)
858 {
859 tcg_out_op_rrr(s, INDEX_op_subbo, a0, a1, a2);
860 }
861
862 static const TCGOutOpAddSubCarry outop_subbo = {
863 .base.static_constraint = C_Dynamic,
864 .base.dynamic_constraint = cset_addsubcarry,
865 .out_rrr = tgen_subbo,
866 };
867
868 static void tgen_subbi(TCGContext *s, TCGType type,
869 TCGReg a0, TCGReg a1, TCGReg a2)
870 {
871 tcg_out_op_rrr(s, INDEX_op_subbi, a0, a1, a2);
872 }
873
874 static const TCGOutOpAddSubCarry outop_subbi = {
875 .base.static_constraint = C_Dynamic,
876 .base.dynamic_constraint = cset_addsubcarry,
877 .out_rrr = tgen_subbi,
878 };
879
880 static void tgen_subbio(TCGContext *s, TCGType type,
881 TCGReg a0, TCGReg a1, TCGReg a2)
882 {
883 tcg_out_op_rrr(s, INDEX_op_subbio, a0, a1, a2);
884 }
885
886 static const TCGOutOpAddSubCarry outop_subbio = {
887 .base.static_constraint = C_Dynamic,
888 .base.dynamic_constraint = cset_addsubcarry,
889 .out_rrr = tgen_subbio,
890 };
891
892 static void tcg_out_set_borrow(TCGContext *s)
893 {
894 tcg_out_op_v(s, INDEX_op_tci_setcarry); /* borrow == carry */
895 }
896
897 static const TCGOutOpBinary outop_smax = {
898 .base.static_constraint = C_NotImplemented,
899 };
900
901 static const TCGOutOpBinary outop_smin = {
902 .base.static_constraint = C_NotImplemented,
903 };
904
905 static const TCGOutOpBinary outop_umax = {
906 .base.static_constraint = C_NotImplemented,
907 };
908
909 static const TCGOutOpBinary outop_umin = {
910 .base.static_constraint = C_NotImplemented,
911 };
912
913 static void tgen_xor(TCGContext *s, TCGType type,
914 TCGReg a0, TCGReg a1, TCGReg a2)
915 {
916 tcg_out_op_rrr(s, INDEX_op_xor, a0, a1, a2);
917 }
918
919 static const TCGOutOpBinary outop_xor = {
920 .base.static_constraint = C_O1_I2(r, r, r),
921 .out_rrr = tgen_xor,
922 };
923
924 static void tgen_ctpop(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
925 {
926 tcg_out_op_rr(s, INDEX_op_ctpop, a0, a1);
927 }
928
929 static TCGConstraintSetIndex cset_ctpop(TCGType type, unsigned flags)
930 {
931 return type == TCG_TYPE_REG ? C_O1_I1(r, r) : C_NotImplemented;
932 }
933
934 static const TCGOutOpUnary outop_ctpop = {
935 .base.static_constraint = C_Dynamic,
936 .base.dynamic_constraint = cset_ctpop,
937 .out_rr = tgen_ctpop,
938 };
939
940 static void tgen_bswap16(TCGContext *s, TCGType type,
941 TCGReg a0, TCGReg a1, unsigned flags)
942 {
943 tcg_out_op_rr(s, INDEX_op_bswap16, a0, a1);
944 if (flags & TCG_BSWAP_OS) {
945 tcg_out_sextract(s, TCG_TYPE_REG, a0, a0, 0, 16);
946 }
947 }
948
949 static const TCGOutOpBswap outop_bswap16 = {
950 .base.static_constraint = C_O1_I1(r, r),
951 .out_rr = tgen_bswap16,
952 };
953
954 static void tgen_bswap32(TCGContext *s, TCGType type,
955 TCGReg a0, TCGReg a1, unsigned flags)
956 {
957 tcg_out_op_rr(s, INDEX_op_bswap32, a0, a1);
958 if (flags & TCG_BSWAP_OS) {
959 tcg_out_sextract(s, TCG_TYPE_REG, a0, a0, 0, 32);
960 }
961 }
962
963 static const TCGOutOpBswap outop_bswap32 = {
964 .base.static_constraint = C_O1_I1(r, r),
965 .out_rr = tgen_bswap32,
966 };
967
968 static void tgen_bswap64(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
969 {
970 tcg_out_op_rr(s, INDEX_op_bswap64, a0, a1);
971 }
972
973 static const TCGOutOpUnary outop_bswap64 = {
974 .base.static_constraint = C_O1_I1(r, r),
975 .out_rr = tgen_bswap64,
976 };
977
978 static const TCGOutOpUnary outop_revbit8 = {
979 .base.static_constraint = C_NotImplemented,
980 };
981
982 static const TCGOutOpBswap outop_revbit32 = {
983 .base.static_constraint = C_NotImplemented,
984 };
985
986 static const TCGOutOpUnary outop_revbit64 = {
987 .base.static_constraint = C_NotImplemented,
988 };
989
990 static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
991 {
992 tcg_out_op_rr(s, INDEX_op_neg, a0, a1);
993 }
994
995 static const TCGOutOpUnary outop_neg = {
996 .base.static_constraint = C_O1_I1(r, r),
997 .out_rr = tgen_neg,
998 };
999
1000 static void tgen_not(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
1001 {
1002 tcg_out_op_rr(s, INDEX_op_not, a0, a1);
1003 }
1004
1005 static const TCGOutOpUnary outop_not = {
1006 .base.static_constraint = C_O1_I1(r, r),
1007 .out_rr = tgen_not,
1008 };
1009
1010 static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
1011 TCGReg dest, TCGReg arg1, TCGReg arg2)
1012 {
1013 TCGOpcode opc = (type == TCG_TYPE_I32
1014 ? INDEX_op_tci_setcond32
1015 : INDEX_op_setcond);
1016 tcg_out_op_rrrc(s, opc, dest, arg1, arg2, cond);
1017 }
1018
1019 static const TCGOutOpSetcond outop_setcond = {
1020 .base.static_constraint = C_O1_I2(r, r, r),
1021 .out_rrr = tgen_setcond,
1022 };
1023
1024 static void tgen_negsetcond(TCGContext *s, TCGType type, TCGCond cond,
1025 TCGReg dest, TCGReg arg1, TCGReg arg2)
1026 {
1027 tgen_setcond(s, type, cond, dest, arg1, arg2);
1028 tgen_neg(s, type, dest, dest);
1029 }
1030
1031 static const TCGOutOpSetcond outop_negsetcond = {
1032 .base.static_constraint = C_O1_I2(r, r, r),
1033 .out_rrr = tgen_negsetcond,
1034 };
1035
1036 static void tgen_brcond(TCGContext *s, TCGType type, TCGCond cond,
1037 TCGReg arg0, TCGReg arg1, TCGLabel *l)
1038 {
1039 tgen_setcond(s, type, cond, TCG_REG_TMP, arg0, arg1);
1040 tcg_out_op_rl(s, INDEX_op_brcond, TCG_REG_TMP, l);
1041 }
1042
1043 static const TCGOutOpBrcond outop_brcond = {
1044 .base.static_constraint = C_O0_I2(r, r),
1045 .out_rr = tgen_brcond,
1046 };
1047
1048 static void tgen_movcond(TCGContext *s, TCGType type, TCGCond cond,
1049 TCGReg ret, TCGReg c1, TCGArg c2, bool const_c2,
1050 TCGArg vt, bool const_vt, TCGArg vf, bool consf_vf)
1051 {
1052 TCGOpcode opc = (type == TCG_TYPE_I32
1053 ? INDEX_op_tci_movcond32
1054 : INDEX_op_movcond);
1055 tcg_out_op_rrrrrc(s, opc, ret, c1, c2, vt, vf, cond);
1056 }
1057
1058 static const TCGOutOpMovcond outop_movcond = {
1059 .base.static_constraint = C_O1_I4(r, r, r, r, r),
1060 .out = tgen_movcond,
1061 };
1062
1063 static void tcg_out_mb(TCGContext *s, unsigned a0)
1064 {
1065 tcg_out_op_v(s, INDEX_op_mb);
1066 }
1067
1068 static void tcg_out_br(TCGContext *s, TCGLabel *l)
1069 {
1070 tcg_out_op_l(s, INDEX_op_br, l);
1071 }
1072
1073 static void tgen_ld8u(TCGContext *s, TCGType type, TCGReg dest,
1074 TCGReg base, ptrdiff_t offset)
1075 {
1076 tcg_out_ldst(s, INDEX_op_ld8u, dest, base, offset);
1077 }
1078
1079 static const TCGOutOpLoad outop_ld8u = {
1080 .base.static_constraint = C_O1_I1(r, r),
1081 .out = tgen_ld8u,
1082 };
1083
1084 static void tgen_ld8s(TCGContext *s, TCGType type, TCGReg dest,
1085 TCGReg base, ptrdiff_t offset)
1086 {
1087 tcg_out_ldst(s, INDEX_op_ld8s, dest, base, offset);
1088 }
1089
1090 static const TCGOutOpLoad outop_ld8s = {
1091 .base.static_constraint = C_O1_I1(r, r),
1092 .out = tgen_ld8s,
1093 };
1094
1095 static void tgen_ld16u(TCGContext *s, TCGType type, TCGReg dest,
1096 TCGReg base, ptrdiff_t offset)
1097 {
1098 tcg_out_ldst(s, INDEX_op_ld16u, dest, base, offset);
1099 }
1100
1101 static const TCGOutOpLoad outop_ld16u = {
1102 .base.static_constraint = C_O1_I1(r, r),
1103 .out = tgen_ld16u,
1104 };
1105
1106 static void tgen_ld16s(TCGContext *s, TCGType type, TCGReg dest,
1107 TCGReg base, ptrdiff_t offset)
1108 {
1109 tcg_out_ldst(s, INDEX_op_ld16s, dest, base, offset);
1110 }
1111
1112 static const TCGOutOpLoad outop_ld16s = {
1113 .base.static_constraint = C_O1_I1(r, r),
1114 .out = tgen_ld16s,
1115 };
1116
1117 static void tgen_ld32u(TCGContext *s, TCGType type, TCGReg dest,
1118 TCGReg base, ptrdiff_t offset)
1119 {
1120 tcg_out_ldst(s, INDEX_op_ld32u, dest, base, offset);
1121 }
1122
1123 static const TCGOutOpLoad outop_ld32u = {
1124 .base.static_constraint = C_O1_I1(r, r),
1125 .out = tgen_ld32u,
1126 };
1127
1128 static void tgen_ld32s(TCGContext *s, TCGType type, TCGReg dest,
1129 TCGReg base, ptrdiff_t offset)
1130 {
1131 tcg_out_ldst(s, INDEX_op_ld32s, dest, base, offset);
1132 }
1133
1134 static const TCGOutOpLoad outop_ld32s = {
1135 .base.static_constraint = C_O1_I1(r, r),
1136 .out = tgen_ld32s,
1137 };
1138
1139 static void tgen_st8(TCGContext *s, TCGType type, TCGReg data,
1140 TCGReg base, ptrdiff_t offset)
1141 {
1142 tcg_out_ldst(s, INDEX_op_st8, data, base, offset);
1143 }
1144
1145 static const TCGOutOpStore outop_st8 = {
1146 .base.static_constraint = C_O0_I2(r, r),
1147 .out_r = tgen_st8,
1148 };
1149
1150 static void tgen_st16(TCGContext *s, TCGType type, TCGReg data,
1151 TCGReg base, ptrdiff_t offset)
1152 {
1153 tcg_out_ldst(s, INDEX_op_st16, data, base, offset);
1154 }
1155
1156 static const TCGOutOpStore outop_st16 = {
1157 .base.static_constraint = C_O0_I2(r, r),
1158 .out_r = tgen_st16,
1159 };
1160
1161 static const TCGOutOpStore outop_st = {
1162 .base.static_constraint = C_O0_I2(r, r),
1163 .out_r = tcg_out_st,
1164 };
1165
1166 static void tgen_qemu_ld(TCGContext *s, TCGType type, TCGReg data,
1167 TCGReg addr, MemOpIdx oi)
1168 {
1169 if (oi & ~0xffff) {
1170 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP, oi);
1171 tcg_out_op_rrr(s, INDEX_op_tci_qemu_ld_rrr, data, addr, TCG_REG_TMP);
1172 } else {
1173 tcg_out_op_rrm(s, INDEX_op_qemu_ld, data, addr, oi);
1174 }
1175 }
1176
1177 static const TCGOutOpQemuLdSt outop_qemu_ld = {
1178 .base.static_constraint = C_O1_I1(r, r),
1179 .out = tgen_qemu_ld,
1180 };
1181
1182 static const TCGOutOpQemuLdSt2 outop_qemu_ld2 = {
1183 .base.static_constraint = C_NotImplemented,
1184 };
1185
1186 static void tgen_qemu_st(TCGContext *s, TCGType type, TCGReg data,
1187 TCGReg addr, MemOpIdx oi)
1188 {
1189 if (oi & ~0xffff) {
1190 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP, oi);
1191 tcg_out_op_rrr(s, INDEX_op_tci_qemu_st_rrr, data, addr, TCG_REG_TMP);
1192 } else {
1193 tcg_out_op_rrm(s, INDEX_op_qemu_st, data, addr, oi);
1194 }
1195 }
1196
1197 static const TCGOutOpQemuLdSt outop_qemu_st = {
1198 .base.static_constraint = C_O0_I2(r, r),
1199 .out = tgen_qemu_st,
1200 };
1201
1202 static const TCGOutOpQemuLdSt2 outop_qemu_st2 = {
1203 .base.static_constraint = C_NotImplemented,
1204 };
1205
1206 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg val, TCGReg base,
1207 intptr_t offset)
1208 {
1209 TCGOpcode op = INDEX_op_st;
1210
1211 if (type == TCG_TYPE_I32) {
1212 op = INDEX_op_st32;
1213 }
1214 tcg_out_ldst(s, op, val, base, offset);
1215 }
1216
1217 static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1218 TCGReg base, intptr_t ofs)
1219 {
1220 return false;
1221 }
1222
1223 /* Test if a constant matches the constraint. */
1224 static bool tcg_target_const_match(int64_t val, int ct,
1225 TCGType type, TCGCond cond, int vece)
1226 {
1227 return ct & TCG_CT_CONST;
1228 }
1229
1230 static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
1231 {
1232 memset(p, 0, sizeof(*p) * count);
1233 }
1234
1235 static void tcg_target_init(TCGContext *s)
1236 {
1237 /* The current code uses uint8_t for tcg operations. */
1238 tcg_debug_assert(tcg_op_defs_max <= UINT8_MAX);
1239
1240 /* Registers available for 32 bit operations. */
1241 tcg_target_available_regs[TCG_TYPE_I32] = BIT(TCG_TARGET_NB_REGS) - 1;
1242 /* Registers available for 64 bit operations. */
1243 tcg_target_available_regs[TCG_TYPE_I64] = BIT(TCG_TARGET_NB_REGS) - 1;
1244 /*
1245 * The interpreter "registers" are in the local stack frame and
1246 * cannot be clobbered by the called helper functions. However,
1247 * the interpreter assumes a 128-bit return value and assigns to
1248 * the return value registers.
1249 */
1250 tcg_target_call_clobber_regs =
1251 MAKE_64BIT_MASK(TCG_REG_R0, 128 / TCG_TARGET_REG_BITS);
1252
1253 s->reserved_regs = 0;
1254 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
1255 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
1256
1257 /* The call arguments come first, followed by the temp storage. */
1258 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
1259 TCG_STATIC_FRAME_SIZE);
1260 }
1261
1262 /* Generate global QEMU prologue and epilogue code. */
1263 static inline void tcg_target_qemu_prologue(TCGContext *s)
1264 {
1265 }
1266
1267 static void tcg_out_tb_start(TCGContext *s)
1268 {
1269 /* nothing to do */
1270 }
1271
1272 bool tcg_target_has_memory_bswap(MemOp memop)
1273 {
1274 return true;
1275 }
1276
1277 static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1278 {
1279 g_assert_not_reached();
1280 }
1281
1282 static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1283 {
1284 g_assert_not_reached();
1285 }