]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/tci/tcg-target.c.inc
tcg/aarch64: Merge tcg_out_callr into tcg_out_call
[mirror_qemu.git] / tcg / tci / tcg-target.c.inc
CommitLineData
7316329a
SW
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
65089889 25#include "../tcg-pool.c.inc"
7316329a 26
63b29fda
RH
27static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
28{
29 switch (op) {
6eea0434
RH
30 case INDEX_op_goto_ptr:
31 return C_O0_I1(r);
32
63b29fda
RH
33 case INDEX_op_ld8u_i32:
34 case INDEX_op_ld8s_i32:
35 case INDEX_op_ld16u_i32:
36 case INDEX_op_ld16s_i32:
37 case INDEX_op_ld_i32:
38 case INDEX_op_ld8u_i64:
39 case INDEX_op_ld8s_i64:
40 case INDEX_op_ld16u_i64:
41 case INDEX_op_ld16s_i64:
42 case INDEX_op_ld32u_i64:
43 case INDEX_op_ld32s_i64:
44 case INDEX_op_ld_i64:
45 case INDEX_op_not_i32:
46 case INDEX_op_not_i64:
47 case INDEX_op_neg_i32:
48 case INDEX_op_neg_i64:
49 case INDEX_op_ext8s_i32:
50 case INDEX_op_ext8s_i64:
51 case INDEX_op_ext16s_i32:
52 case INDEX_op_ext16s_i64:
53 case INDEX_op_ext8u_i32:
54 case INDEX_op_ext8u_i64:
55 case INDEX_op_ext16u_i32:
56 case INDEX_op_ext16u_i64:
57 case INDEX_op_ext32s_i64:
58 case INDEX_op_ext32u_i64:
59 case INDEX_op_ext_i32_i64:
60 case INDEX_op_extu_i32_i64:
61 case INDEX_op_bswap16_i32:
62 case INDEX_op_bswap16_i64:
63 case INDEX_op_bswap32_i32:
64 case INDEX_op_bswap32_i64:
65 case INDEX_op_bswap64_i64:
0f10d7c5
RH
66 case INDEX_op_extract_i32:
67 case INDEX_op_extract_i64:
68 case INDEX_op_sextract_i32:
69 case INDEX_op_sextract_i64:
5255f48c
RH
70 case INDEX_op_ctpop_i32:
71 case INDEX_op_ctpop_i64:
63b29fda
RH
72 return C_O1_I1(r, r);
73
74 case INDEX_op_st8_i32:
75 case INDEX_op_st16_i32:
76 case INDEX_op_st_i32:
77 case INDEX_op_st8_i64:
78 case INDEX_op_st16_i64:
79 case INDEX_op_st32_i64:
80 case INDEX_op_st_i64:
81 return C_O0_I2(r, r);
82
83 case INDEX_op_div_i32:
84 case INDEX_op_div_i64:
85 case INDEX_op_divu_i32:
86 case INDEX_op_divu_i64:
87 case INDEX_op_rem_i32:
88 case INDEX_op_rem_i64:
89 case INDEX_op_remu_i32:
90 case INDEX_op_remu_i64:
63b29fda
RH
91 case INDEX_op_add_i32:
92 case INDEX_op_add_i64:
93 case INDEX_op_sub_i32:
94 case INDEX_op_sub_i64:
95 case INDEX_op_mul_i32:
96 case INDEX_op_mul_i64:
97 case INDEX_op_and_i32:
98 case INDEX_op_and_i64:
99 case INDEX_op_andc_i32:
100 case INDEX_op_andc_i64:
101 case INDEX_op_eqv_i32:
102 case INDEX_op_eqv_i64:
103 case INDEX_op_nand_i32:
104 case INDEX_op_nand_i64:
105 case INDEX_op_nor_i32:
106 case INDEX_op_nor_i64:
107 case INDEX_op_or_i32:
108 case INDEX_op_or_i64:
109 case INDEX_op_orc_i32:
110 case INDEX_op_orc_i64:
111 case INDEX_op_xor_i32:
112 case INDEX_op_xor_i64:
113 case INDEX_op_shl_i32:
114 case INDEX_op_shl_i64:
115 case INDEX_op_shr_i32:
116 case INDEX_op_shr_i64:
117 case INDEX_op_sar_i32:
118 case INDEX_op_sar_i64:
119 case INDEX_op_rotl_i32:
120 case INDEX_op_rotl_i64:
121 case INDEX_op_rotr_i32:
122 case INDEX_op_rotr_i64:
2f74f45e
RH
123 case INDEX_op_setcond_i32:
124 case INDEX_op_setcond_i64:
63b29fda
RH
125 case INDEX_op_deposit_i32:
126 case INDEX_op_deposit_i64:
5255f48c
RH
127 case INDEX_op_clz_i32:
128 case INDEX_op_clz_i64:
129 case INDEX_op_ctz_i32:
130 case INDEX_op_ctz_i64:
79dd3a4f 131 return C_O1_I2(r, r, r);
63b29fda
RH
132
133 case INDEX_op_brcond_i32:
134 case INDEX_op_brcond_i64:
2f74f45e 135 return C_O0_I2(r, r);
7316329a 136
63b29fda 137 case INDEX_op_add2_i32:
08096b1a 138 case INDEX_op_add2_i64:
63b29fda 139 case INDEX_op_sub2_i32:
08096b1a 140 case INDEX_op_sub2_i64:
63b29fda 141 return C_O2_I4(r, r, r, r, r, r);
08096b1a
RH
142
143#if TCG_TARGET_REG_BITS == 32
63b29fda 144 case INDEX_op_brcond2_i32:
2f74f45e 145 return C_O0_I4(r, r, r, r);
f6db0d8d
RH
146#endif
147
63b29fda 148 case INDEX_op_mulu2_i32:
f6db0d8d
RH
149 case INDEX_op_mulu2_i64:
150 case INDEX_op_muls2_i32:
151 case INDEX_op_muls2_i64:
63b29fda 152 return C_O2_I2(r, r, r, r);
df093c19
RH
153
154 case INDEX_op_movcond_i32:
155 case INDEX_op_movcond_i64:
63b29fda 156 case INDEX_op_setcond2_i32:
2f74f45e 157 return C_O1_I4(r, r, r, r, r);
f69d277e 158
63b29fda
RH
159 case INDEX_op_qemu_ld_i32:
160 return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
161 ? C_O1_I1(r, r)
162 : C_O1_I2(r, r, r));
163 case INDEX_op_qemu_ld_i64:
164 return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, r)
165 : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, r)
166 : C_O2_I2(r, r, r, r));
167 case INDEX_op_qemu_st_i32:
168 return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
169 ? C_O0_I2(r, r)
170 : C_O0_I3(r, r, r));
171 case INDEX_op_qemu_st_i64:
172 return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(r, r)
173 : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(r, r, r)
174 : C_O0_I4(r, r, r, r));
175
176 default:
177 g_assert_not_reached();
f69d277e 178 }
f69d277e
RH
179}
180
7316329a 181static const int tcg_target_reg_alloc_order[] = {
7316329a
SW
182 TCG_REG_R2,
183 TCG_REG_R3,
7316329a 184 TCG_REG_R4,
7316329a
SW
185 TCG_REG_R5,
186 TCG_REG_R6,
187 TCG_REG_R7,
7316329a
SW
188 TCG_REG_R8,
189 TCG_REG_R9,
190 TCG_REG_R10,
191 TCG_REG_R11,
192 TCG_REG_R12,
193 TCG_REG_R13,
194 TCG_REG_R14,
195 TCG_REG_R15,
bcb81061
RH
196 TCG_REG_R1,
197 TCG_REG_R0,
7316329a
SW
198};
199
7b7d8b2d
RH
200/* No call arguments via registers. All will be stored on the "stack". */
201static const int tcg_target_call_iarg_regs[] = { };
7316329a
SW
202
203static const int tcg_target_call_oarg_regs[] = {
204 TCG_REG_R0,
205#if TCG_TARGET_REG_BITS == 32
206 TCG_REG_R1
207#endif
208};
209
8d8fdbae 210#ifdef CONFIG_DEBUG_TCG
7316329a
SW
211static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
212 "r00",
213 "r01",
214 "r02",
215 "r03",
216 "r04",
217 "r05",
218 "r06",
219 "r07",
7316329a
SW
220 "r08",
221 "r09",
222 "r10",
223 "r11",
224 "r12",
225 "r13",
226 "r14",
227 "r15",
7316329a
SW
228};
229#endif
230
6ac17786 231static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
2ba7fae2 232 intptr_t value, intptr_t addend)
7316329a 233{
65089889 234 intptr_t diff = value - (intptr_t)(code_ptr + 1);
7316329a 235
65089889
RH
236 tcg_debug_assert(addend == 0);
237 tcg_debug_assert(type == 20);
7316329a 238
65089889
RH
239 if (diff == sextract32(diff, 0, type)) {
240 tcg_patch32(code_ptr, deposit32(*code_ptr, 32 - type, type, diff));
241 return true;
7316329a 242 }
65089889 243 return false;
7316329a
SW
244}
245
53f40556
RH
246static void stack_bounds_check(TCGReg base, target_long offset)
247{
248 if (base == TCG_REG_CALL_STACK) {
7b7d8b2d
RH
249 tcg_debug_assert(offset >= 0);
250 tcg_debug_assert(offset < (TCG_STATIC_CALL_ARGS_SIZE +
251 TCG_STATIC_FRAME_SIZE));
53f40556
RH
252 }
253}
254
b9dcd21a
RH
255static void tcg_out_op_l(TCGContext *s, TCGOpcode op, TCGLabel *l0)
256{
65089889 257 tcg_insn_unit insn = 0;
b9dcd21a 258
65089889
RH
259 tcg_out_reloc(s, s->code_ptr, 20, l0, 0);
260 insn = deposit32(insn, 0, 8, op);
261 tcg_out32(s, insn);
b9dcd21a
RH
262}
263
7aa295c5
RH
264static void tcg_out_op_p(TCGContext *s, TCGOpcode op, void *p0)
265{
65089889
RH
266 tcg_insn_unit insn = 0;
267 intptr_t diff;
7aa295c5 268
65089889
RH
269 /* Special case for exit_tb: map null -> 0. */
270 if (p0 == NULL) {
271 diff = 0;
272 } else {
273 diff = p0 - (void *)(s->code_ptr + 1);
274 tcg_debug_assert(diff != 0);
275 if (diff != sextract32(diff, 0, 20)) {
276 tcg_raise_tb_overflow(s);
277 }
278 }
279 insn = deposit32(insn, 0, 8, op);
280 insn = deposit32(insn, 12, 20, diff);
281 tcg_out32(s, insn);
7aa295c5
RH
282}
283
6eea0434
RH
284static void tcg_out_op_r(TCGContext *s, TCGOpcode op, TCGReg r0)
285{
286 tcg_insn_unit insn = 0;
287
288 insn = deposit32(insn, 0, 8, op);
289 insn = deposit32(insn, 8, 4, r0);
290 tcg_out32(s, insn);
291}
292
87713c04
RH
293static void tcg_out_op_v(TCGContext *s, TCGOpcode op)
294{
65089889 295 tcg_out32(s, (uint8_t)op);
87713c04
RH
296}
297
98f9b467
RH
298static void tcg_out_op_ri(TCGContext *s, TCGOpcode op, TCGReg r0, int32_t i1)
299{
65089889 300 tcg_insn_unit insn = 0;
98f9b467 301
65089889
RH
302 tcg_debug_assert(i1 == sextract32(i1, 0, 20));
303 insn = deposit32(insn, 0, 8, op);
304 insn = deposit32(insn, 8, 4, r0);
305 insn = deposit32(insn, 12, 20, i1);
306 tcg_out32(s, insn);
98f9b467 307}
98f9b467 308
fc8ec9e1
RH
309static void tcg_out_op_rl(TCGContext *s, TCGOpcode op, TCGReg r0, TCGLabel *l1)
310{
65089889 311 tcg_insn_unit insn = 0;
fc8ec9e1 312
65089889
RH
313 tcg_out_reloc(s, s->code_ptr, 20, l1, 0);
314 insn = deposit32(insn, 0, 8, op);
315 insn = deposit32(insn, 8, 4, r0);
316 tcg_out32(s, insn);
fc8ec9e1
RH
317}
318
ffe86eb0
RH
319static void tcg_out_op_rr(TCGContext *s, TCGOpcode op, TCGReg r0, TCGReg r1)
320{
65089889 321 tcg_insn_unit insn = 0;
ffe86eb0 322
65089889
RH
323 insn = deposit32(insn, 0, 8, op);
324 insn = deposit32(insn, 8, 4, r0);
325 insn = deposit32(insn, 12, 4, r1);
326 tcg_out32(s, insn);
ffe86eb0
RH
327}
328
6f00d7af
RH
329static void tcg_out_op_rrm(TCGContext *s, TCGOpcode op,
330 TCGReg r0, TCGReg r1, TCGArg m2)
331{
65089889 332 tcg_insn_unit insn = 0;
6f00d7af 333
65089889
RH
334 tcg_debug_assert(m2 == extract32(m2, 0, 12));
335 insn = deposit32(insn, 0, 8, op);
336 insn = deposit32(insn, 8, 4, r0);
337 insn = deposit32(insn, 12, 4, r1);
338 insn = deposit32(insn, 20, 12, m2);
339 tcg_out32(s, insn);
6f00d7af
RH
340}
341
549d0396
RH
342static void tcg_out_op_rrr(TCGContext *s, TCGOpcode op,
343 TCGReg r0, TCGReg r1, TCGReg r2)
344{
65089889 345 tcg_insn_unit insn = 0;
549d0396 346
65089889
RH
347 insn = deposit32(insn, 0, 8, op);
348 insn = deposit32(insn, 8, 4, r0);
349 insn = deposit32(insn, 12, 4, r1);
350 insn = deposit32(insn, 16, 4, r2);
351 tcg_out32(s, insn);
549d0396
RH
352}
353
fe8c47cb
RH
354static void tcg_out_op_rrs(TCGContext *s, TCGOpcode op,
355 TCGReg r0, TCGReg r1, intptr_t i2)
7316329a 356{
65089889 357 tcg_insn_unit insn = 0;
fe8c47cb 358
65089889
RH
359 tcg_debug_assert(i2 == sextract32(i2, 0, 16));
360 insn = deposit32(insn, 0, 8, op);
361 insn = deposit32(insn, 8, 4, r0);
362 insn = deposit32(insn, 12, 4, r1);
363 insn = deposit32(insn, 16, 16, i2);
364 tcg_out32(s, insn);
fe8c47cb
RH
365}
366
0f10d7c5
RH
367static void tcg_out_op_rrbb(TCGContext *s, TCGOpcode op, TCGReg r0,
368 TCGReg r1, uint8_t b2, uint8_t b3)
369{
370 tcg_insn_unit insn = 0;
371
372 tcg_debug_assert(b2 == extract32(b2, 0, 6));
373 tcg_debug_assert(b3 == extract32(b3, 0, 6));
374 insn = deposit32(insn, 0, 8, op);
375 insn = deposit32(insn, 8, 4, r0);
376 insn = deposit32(insn, 12, 4, r1);
377 insn = deposit32(insn, 16, 6, b2);
378 insn = deposit32(insn, 22, 6, b3);
379 tcg_out32(s, insn);
380}
381
bd42124b
RH
382static void tcg_out_op_rrrc(TCGContext *s, TCGOpcode op,
383 TCGReg r0, TCGReg r1, TCGReg r2, TCGCond c3)
384{
65089889 385 tcg_insn_unit insn = 0;
bd42124b 386
65089889
RH
387 insn = deposit32(insn, 0, 8, op);
388 insn = deposit32(insn, 8, 4, r0);
389 insn = deposit32(insn, 12, 4, r1);
390 insn = deposit32(insn, 16, 4, r2);
391 insn = deposit32(insn, 20, 4, c3);
392 tcg_out32(s, insn);
bd42124b
RH
393}
394
6f00d7af
RH
395static void tcg_out_op_rrrm(TCGContext *s, TCGOpcode op,
396 TCGReg r0, TCGReg r1, TCGReg r2, TCGArg m3)
397{
65089889 398 tcg_insn_unit insn = 0;
6f00d7af 399
65089889
RH
400 tcg_debug_assert(m3 == extract32(m3, 0, 12));
401 insn = deposit32(insn, 0, 8, op);
402 insn = deposit32(insn, 8, 4, r0);
403 insn = deposit32(insn, 12, 4, r1);
404 insn = deposit32(insn, 16, 4, r2);
405 insn = deposit32(insn, 20, 12, m3);
406 tcg_out32(s, insn);
6f00d7af
RH
407}
408
37e112e8
RH
409static void tcg_out_op_rrrbb(TCGContext *s, TCGOpcode op, TCGReg r0,
410 TCGReg r1, TCGReg r2, uint8_t b3, uint8_t b4)
411{
65089889 412 tcg_insn_unit insn = 0;
37e112e8 413
65089889
RH
414 tcg_debug_assert(b3 == extract32(b3, 0, 6));
415 tcg_debug_assert(b4 == extract32(b4, 0, 6));
416 insn = deposit32(insn, 0, 8, op);
417 insn = deposit32(insn, 8, 4, r0);
418 insn = deposit32(insn, 12, 4, r1);
419 insn = deposit32(insn, 16, 4, r2);
420 insn = deposit32(insn, 20, 6, b3);
421 insn = deposit32(insn, 26, 6, b4);
422 tcg_out32(s, insn);
37e112e8
RH
423}
424
65089889
RH
425static void tcg_out_op_rrrrr(TCGContext *s, TCGOpcode op, TCGReg r0,
426 TCGReg r1, TCGReg r2, TCGReg r3, TCGReg r4)
6f00d7af 427{
65089889 428 tcg_insn_unit insn = 0;
6f00d7af 429
65089889
RH
430 insn = deposit32(insn, 0, 8, op);
431 insn = deposit32(insn, 8, 4, r0);
432 insn = deposit32(insn, 12, 4, r1);
433 insn = deposit32(insn, 16, 4, r2);
434 insn = deposit32(insn, 20, 4, r3);
435 insn = deposit32(insn, 24, 4, r4);
436 tcg_out32(s, insn);
6f00d7af
RH
437}
438
db492ebb
RH
439static void tcg_out_op_rrrr(TCGContext *s, TCGOpcode op,
440 TCGReg r0, TCGReg r1, TCGReg r2, TCGReg r3)
441{
65089889 442 tcg_insn_unit insn = 0;
db492ebb 443
65089889
RH
444 insn = deposit32(insn, 0, 8, op);
445 insn = deposit32(insn, 8, 4, r0);
446 insn = deposit32(insn, 12, 4, r1);
447 insn = deposit32(insn, 16, 4, r2);
448 insn = deposit32(insn, 20, 4, r3);
449 tcg_out32(s, insn);
db492ebb
RH
450}
451
223abacd
RH
452static void tcg_out_op_rrrrrc(TCGContext *s, TCGOpcode op,
453 TCGReg r0, TCGReg r1, TCGReg r2,
454 TCGReg r3, TCGReg r4, TCGCond c5)
455{
65089889 456 tcg_insn_unit insn = 0;
223abacd 457
65089889
RH
458 insn = deposit32(insn, 0, 8, op);
459 insn = deposit32(insn, 8, 4, r0);
460 insn = deposit32(insn, 12, 4, r1);
461 insn = deposit32(insn, 16, 4, r2);
462 insn = deposit32(insn, 20, 4, r3);
463 insn = deposit32(insn, 24, 4, r4);
464 insn = deposit32(insn, 28, 4, c5);
465 tcg_out32(s, insn);
223abacd 466}
ab5b8a3f
RH
467
468static void tcg_out_op_rrrrrr(TCGContext *s, TCGOpcode op,
469 TCGReg r0, TCGReg r1, TCGReg r2,
470 TCGReg r3, TCGReg r4, TCGReg r5)
471{
65089889 472 tcg_insn_unit insn = 0;
ab5b8a3f 473
65089889
RH
474 insn = deposit32(insn, 0, 8, op);
475 insn = deposit32(insn, 8, 4, r0);
476 insn = deposit32(insn, 12, 4, r1);
477 insn = deposit32(insn, 16, 4, r2);
478 insn = deposit32(insn, 20, 4, r3);
479 insn = deposit32(insn, 24, 4, r4);
480 insn = deposit32(insn, 28, 4, r5);
481 tcg_out32(s, insn);
ab5b8a3f 482}
223abacd 483
65089889
RH
484static void tcg_out_ldst(TCGContext *s, TCGOpcode op, TCGReg val,
485 TCGReg base, intptr_t offset)
486{
487 stack_bounds_check(base, offset);
488 if (offset != sextract32(offset, 0, 16)) {
489 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, offset);
490 tcg_out_op_rrr(s, (TCG_TARGET_REG_BITS == 32
491 ? INDEX_op_add_i32 : INDEX_op_add_i64),
492 TCG_REG_TMP, TCG_REG_TMP, base);
493 base = TCG_REG_TMP;
494 offset = 0;
495 }
496 tcg_out_op_rrs(s, op, val, base, offset);
497}
498
fe8c47cb
RH
499static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg val, TCGReg base,
500 intptr_t offset)
501{
fe8c47cb
RH
502 switch (type) {
503 case TCG_TYPE_I32:
65089889 504 tcg_out_ldst(s, INDEX_op_ld_i32, val, base, offset);
fe8c47cb 505 break;
7316329a 506#if TCG_TARGET_REG_BITS == 64
fe8c47cb 507 case TCG_TYPE_I64:
65089889 508 tcg_out_ldst(s, INDEX_op_ld_i64, val, base, offset);
fe8c47cb 509 break;
7316329a 510#endif
fe8c47cb
RH
511 default:
512 g_assert_not_reached();
7316329a 513 }
7316329a
SW
514}
515
78113e83 516static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
7316329a 517{
ffe86eb0
RH
518 switch (type) {
519 case TCG_TYPE_I32:
520 tcg_out_op_rr(s, INDEX_op_mov_i32, ret, arg);
521 break;
522#if TCG_TARGET_REG_BITS == 64
523 case TCG_TYPE_I64:
524 tcg_out_op_rr(s, INDEX_op_mov_i64, ret, arg);
525 break;
7316329a 526#endif
ffe86eb0
RH
527 default:
528 g_assert_not_reached();
529 }
78113e83 530 return true;
7316329a
SW
531}
532
533static void tcg_out_movi(TCGContext *s, TCGType type,
98f9b467 534 TCGReg ret, tcg_target_long arg)
7316329a 535{
98f9b467
RH
536 switch (type) {
537 case TCG_TYPE_I32:
7316329a 538#if TCG_TARGET_REG_BITS == 64
65089889
RH
539 arg = (int32_t)arg;
540 /* fall through */
98f9b467 541 case TCG_TYPE_I64:
7316329a 542#endif
65089889 543 break;
98f9b467
RH
544 default:
545 g_assert_not_reached();
7316329a 546 }
65089889
RH
547
548 if (arg == sextract32(arg, 0, 20)) {
549 tcg_out_op_ri(s, INDEX_op_tci_movi, ret, arg);
550 } else {
551 tcg_insn_unit insn = 0;
552
553 new_pool_label(s, arg, 20, s->code_ptr, 0);
554 insn = deposit32(insn, 0, 8, INDEX_op_tci_movl);
555 insn = deposit32(insn, 8, 4, ret);
556 tcg_out32(s, insn);
557 }
7316329a
SW
558}
559
7b7d8b2d
RH
560static void tcg_out_call(TCGContext *s, const tcg_insn_unit *func,
561 ffi_cif *cif)
dddbb2e1 562{
65089889 563 tcg_insn_unit insn = 0;
7b7d8b2d
RH
564 uint8_t which;
565
566 if (cif->rtype == &ffi_type_void) {
567 which = 0;
568 } else if (cif->rtype->size == 4) {
569 which = 1;
570 } else {
571 tcg_debug_assert(cif->rtype->size == 8);
572 which = 2;
573 }
65089889
RH
574 new_pool_l2(s, 20, s->code_ptr, 0, (uintptr_t)func, (uintptr_t)cif);
575 insn = deposit32(insn, 0, 8, INDEX_op_call);
576 insn = deposit32(insn, 8, 4, which);
577 tcg_out32(s, insn);
dddbb2e1
RH
578}
579
c764f8cc
RH
580#if TCG_TARGET_REG_BITS == 64
581# define CASE_32_64(x) \
582 case glue(glue(INDEX_op_, x), _i64): \
583 case glue(glue(INDEX_op_, x), _i32):
584# define CASE_64(x) \
585 case glue(glue(INDEX_op_, x), _i64):
586#else
587# define CASE_32_64(x) \
588 case glue(glue(INDEX_op_, x), _i32):
589# define CASE_64(x)
590#endif
591
5e8892db
MR
592static void tcg_out_op(TCGContext *s, TCGOpcode opc,
593 const TCGArg args[TCG_MAX_OP_ARGS],
594 const int const_args[TCG_MAX_OP_ARGS])
7316329a 595{
0d57d36a
RH
596 TCGOpcode exts;
597
7316329a
SW
598 switch (opc) {
599 case INDEX_op_exit_tb:
7aa295c5 600 tcg_out_op_p(s, opc, (void *)args[0]);
7316329a 601 break;
c764f8cc 602
7316329a 603 case INDEX_op_goto_tb:
1670a2b9
RH
604 tcg_debug_assert(s->tb_jmp_insn_offset == 0);
605 /* indirect jump method. */
7aa295c5 606 tcg_out_op_p(s, opc, s->tb_jmp_target_addr + args[0]);
9f754620 607 set_jmp_reset_offset(s, args[0]);
7316329a 608 break;
88c3e909 609
6eea0434
RH
610 case INDEX_op_goto_ptr:
611 tcg_out_op_r(s, opc, args[0]);
612 break;
613
7316329a 614 case INDEX_op_br:
b9dcd21a 615 tcg_out_op_l(s, opc, arg_label(args[0]));
7316329a 616 break;
88c3e909
RH
617
618 CASE_32_64(setcond)
bd42124b 619 tcg_out_op_rrrc(s, opc, args[0], args[1], args[2], args[3]);
7316329a 620 break;
88c3e909 621
df093c19 622 CASE_32_64(movcond)
7316329a 623 case INDEX_op_setcond2_i32:
223abacd
RH
624 tcg_out_op_rrrrrc(s, opc, args[0], args[1], args[2],
625 args[3], args[4], args[5]);
7316329a 626 break;
a73605a7
RH
627
628 CASE_32_64(ld8u)
629 CASE_32_64(ld8s)
630 CASE_32_64(ld16u)
631 CASE_32_64(ld16s)
7316329a 632 case INDEX_op_ld_i32:
a73605a7
RH
633 CASE_64(ld32u)
634 CASE_64(ld32s)
635 CASE_64(ld)
636 CASE_32_64(st8)
637 CASE_32_64(st16)
7316329a 638 case INDEX_op_st_i32:
a73605a7
RH
639 CASE_64(st32)
640 CASE_64(st)
65089889 641 tcg_out_ldst(s, opc, args[0], args[1], args[2]);
7316329a 642 break;
c764f8cc
RH
643
644 CASE_32_64(add)
645 CASE_32_64(sub)
646 CASE_32_64(mul)
647 CASE_32_64(and)
648 CASE_32_64(or)
649 CASE_32_64(xor)
650 CASE_32_64(andc) /* Optional (TCG_TARGET_HAS_andc_*). */
651 CASE_32_64(orc) /* Optional (TCG_TARGET_HAS_orc_*). */
652 CASE_32_64(eqv) /* Optional (TCG_TARGET_HAS_eqv_*). */
653 CASE_32_64(nand) /* Optional (TCG_TARGET_HAS_nand_*). */
654 CASE_32_64(nor) /* Optional (TCG_TARGET_HAS_nor_*). */
655 CASE_32_64(shl)
656 CASE_32_64(shr)
657 CASE_32_64(sar)
658 CASE_32_64(rotl) /* Optional (TCG_TARGET_HAS_rot_*). */
659 CASE_32_64(rotr) /* Optional (TCG_TARGET_HAS_rot_*). */
660 CASE_32_64(div) /* Optional (TCG_TARGET_HAS_div_*). */
661 CASE_32_64(divu) /* Optional (TCG_TARGET_HAS_div_*). */
662 CASE_32_64(rem) /* Optional (TCG_TARGET_HAS_div_*). */
663 CASE_32_64(remu) /* Optional (TCG_TARGET_HAS_div_*). */
5255f48c
RH
664 CASE_32_64(clz) /* Optional (TCG_TARGET_HAS_clz_*). */
665 CASE_32_64(ctz) /* Optional (TCG_TARGET_HAS_ctz_*). */
549d0396 666 tcg_out_op_rrr(s, opc, args[0], args[1], args[2]);
7316329a 667 break;
da9a5e0b
RH
668
669 CASE_32_64(deposit) /* Optional (TCG_TARGET_HAS_deposit_*). */
79dd3a4f
RH
670 {
671 TCGArg pos = args[3], len = args[4];
672 TCGArg max = opc == INDEX_op_deposit_i32 ? 32 : 64;
673
674 tcg_debug_assert(pos < max);
675 tcg_debug_assert(pos + len <= max);
676
37e112e8 677 tcg_out_op_rrrbb(s, opc, args[0], args[1], args[2], pos, len);
79dd3a4f 678 }
0f10d7c5
RH
679 break;
680
681 CASE_32_64(extract) /* Optional (TCG_TARGET_HAS_extract_*). */
682 CASE_32_64(sextract) /* Optional (TCG_TARGET_HAS_sextract_*). */
683 {
684 TCGArg pos = args[2], len = args[3];
685 TCGArg max = tcg_op_defs[opc].flags & TCG_OPF_64BIT ? 64 : 32;
686
687 tcg_debug_assert(pos < max);
688 tcg_debug_assert(pos + len <= max);
689
690 tcg_out_op_rrbb(s, opc, args[0], args[1], pos, len);
691 }
e24dc9fe 692 break;
7316329a 693
88c3e909 694 CASE_32_64(brcond)
fc8ec9e1
RH
695 tcg_out_op_rrrc(s, (opc == INDEX_op_brcond_i32
696 ? INDEX_op_setcond_i32 : INDEX_op_setcond_i64),
697 TCG_REG_TMP, args[0], args[1], args[2]);
698 tcg_out_op_rl(s, opc, TCG_REG_TMP, arg_label(args[3]));
7316329a 699 break;
1e9ac766
RH
700
701 CASE_32_64(neg) /* Optional (TCG_TARGET_HAS_neg_*). */
702 CASE_32_64(not) /* Optional (TCG_TARGET_HAS_not_*). */
703 CASE_32_64(ext8s) /* Optional (TCG_TARGET_HAS_ext8s_*). */
704 CASE_32_64(ext8u) /* Optional (TCG_TARGET_HAS_ext8u_*). */
705 CASE_32_64(ext16s) /* Optional (TCG_TARGET_HAS_ext16s_*). */
706 CASE_32_64(ext16u) /* Optional (TCG_TARGET_HAS_ext16u_*). */
707 CASE_64(ext32s) /* Optional (TCG_TARGET_HAS_ext32s_i64). */
708 CASE_64(ext32u) /* Optional (TCG_TARGET_HAS_ext32u_i64). */
709 CASE_64(ext_i32)
710 CASE_64(extu_i32)
5255f48c 711 CASE_32_64(ctpop) /* Optional (TCG_TARGET_HAS_ctpop_*). */
0d57d36a
RH
712 case INDEX_op_bswap32_i32: /* Optional (TCG_TARGET_HAS_bswap32_i32). */
713 case INDEX_op_bswap64_i64: /* Optional (TCG_TARGET_HAS_bswap64_i64). */
ffe86eb0 714 tcg_out_op_rr(s, opc, args[0], args[1]);
7316329a 715 break;
c764f8cc 716
0d57d36a
RH
717 case INDEX_op_bswap16_i32: /* Optional (TCG_TARGET_HAS_bswap16_i32). */
718 exts = INDEX_op_ext16s_i32;
719 goto do_bswap;
720 case INDEX_op_bswap16_i64: /* Optional (TCG_TARGET_HAS_bswap16_i64). */
721 exts = INDEX_op_ext16s_i64;
722 goto do_bswap;
723 case INDEX_op_bswap32_i64: /* Optional (TCG_TARGET_HAS_bswap32_i64). */
724 exts = INDEX_op_ext32s_i64;
725 do_bswap:
726 /* The base tci bswaps zero-extend, and ignore high bits. */
727 tcg_out_op_rr(s, opc, args[0], args[1]);
728 if (args[2] & TCG_BSWAP_OS) {
729 tcg_out_op_rr(s, exts, args[0], args[0]);
730 }
731 break;
732
08096b1a
RH
733 CASE_32_64(add2)
734 CASE_32_64(sub2)
ab5b8a3f
RH
735 tcg_out_op_rrrrrr(s, opc, args[0], args[1], args[2],
736 args[3], args[4], args[5]);
7316329a 737 break;
08096b1a
RH
738
739#if TCG_TARGET_REG_BITS == 32
7316329a 740 case INDEX_op_brcond2_i32:
fc8ec9e1
RH
741 tcg_out_op_rrrrrc(s, INDEX_op_setcond2_i32, TCG_REG_TMP,
742 args[0], args[1], args[2], args[3], args[4]);
743 tcg_out_op_rl(s, INDEX_op_brcond_i32, TCG_REG_TMP, arg_label(args[5]));
7316329a 744 break;
f6db0d8d
RH
745#endif
746
747 CASE_32_64(mulu2)
748 CASE_32_64(muls2)
db492ebb 749 tcg_out_op_rrrr(s, opc, args[0], args[1], args[2], args[3]);
7316329a 750 break;
88c3e909 751
76782fab 752 case INDEX_op_qemu_ld_i32:
76782fab 753 case INDEX_op_qemu_st_i32:
6f00d7af
RH
754 if (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS) {
755 tcg_out_op_rrm(s, opc, args[0], args[1], args[2]);
756 } else {
757 tcg_out_op_rrrm(s, opc, args[0], args[1], args[2], args[3]);
76782fab 758 }
7316329a 759 break;
a73605a7
RH
760
761 case INDEX_op_qemu_ld_i64:
76782fab 762 case INDEX_op_qemu_st_i64:
6f00d7af
RH
763 if (TCG_TARGET_REG_BITS == 64) {
764 tcg_out_op_rrm(s, opc, args[0], args[1], args[2]);
765 } else if (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS) {
766 tcg_out_op_rrrm(s, opc, args[0], args[1], args[2], args[3]);
767 } else {
65089889
RH
768 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP, args[4]);
769 tcg_out_op_rrrrr(s, opc, args[0], args[1],
770 args[2], args[3], TCG_REG_TMP);
76782fab 771 }
7316329a 772 break;
c764f8cc 773
a1e69e2f 774 case INDEX_op_mb:
87713c04 775 tcg_out_op_v(s, opc);
a1e69e2f 776 break;
c764f8cc 777
96d0ee7f
RH
778 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
779 case INDEX_op_mov_i64:
96d0ee7f 780 case INDEX_op_call: /* Always emitted via tcg_out_call. */
7316329a 781 default:
7316329a
SW
782 tcg_abort();
783 }
7316329a
SW
784}
785
fe8c47cb
RH
786static void tcg_out_st(TCGContext *s, TCGType type, TCGReg val, TCGReg base,
787 intptr_t offset)
7316329a 788{
fe8c47cb
RH
789 switch (type) {
790 case TCG_TYPE_I32:
2ccf40f0 791 tcg_out_ldst(s, INDEX_op_st_i32, val, base, offset);
fe8c47cb 792 break;
7316329a 793#if TCG_TARGET_REG_BITS == 64
fe8c47cb 794 case TCG_TYPE_I64:
2ccf40f0 795 tcg_out_ldst(s, INDEX_op_st_i64, val, base, offset);
fe8c47cb 796 break;
7316329a 797#endif
fe8c47cb
RH
798 default:
799 g_assert_not_reached();
7316329a 800 }
7316329a
SW
801}
802
59d7c14e
RH
803static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
804 TCGReg base, intptr_t ofs)
805{
806 return false;
807}
808
7316329a 809/* Test if a constant matches the constraint. */
a4fbbd77 810static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
7316329a 811{
a4fbbd77 812 return ct & TCG_CT_CONST;
7316329a
SW
813}
814
65089889
RH
815static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
816{
817 memset(p, 0, sizeof(*p) * count);
818}
819
7316329a
SW
820static void tcg_target_init(TCGContext *s)
821{
7316329a 822 /* The current code uses uint8_t for tcg operations. */
eabb7b91 823 tcg_debug_assert(tcg_op_defs_max <= UINT8_MAX);
7316329a
SW
824
825 /* Registers available for 32 bit operations. */
f46934df 826 tcg_target_available_regs[TCG_TYPE_I32] = BIT(TCG_TARGET_NB_REGS) - 1;
7316329a 827 /* Registers available for 64 bit operations. */
f46934df 828 tcg_target_available_regs[TCG_TYPE_I64] = BIT(TCG_TARGET_NB_REGS) - 1;
b6139eb0
RH
829 /*
830 * The interpreter "registers" are in the local stack frame and
831 * cannot be clobbered by the called helper functions. However,
832 * the interpreter assumes a 64-bit return value and assigns to
833 * the return value registers.
834 */
835 tcg_target_call_clobber_regs =
836 MAKE_64BIT_MASK(TCG_REG_R0, 64 / TCG_TARGET_REG_BITS);
ee79c356 837
ccb1bb66 838 s->reserved_regs = 0;
baa94c0d 839 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
7316329a 840 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
ee79c356 841
7b7d8b2d
RH
842 /* The call arguments come first, followed by the temp storage. */
843 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
844 TCG_STATIC_FRAME_SIZE);
7316329a
SW
845}
846
847/* Generate global QEMU prologue and epilogue code. */
4699ca6d 848static inline void tcg_target_qemu_prologue(TCGContext *s)
7316329a 849{
7316329a 850}