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