]> git.proxmox.com Git - qemu.git/blame - tcg/tci/tcg-target.c
Merge remote-tracking branch 'sstabellini/compile-xs' into staging
[qemu.git] / tcg / tci / tcg-target.c
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
25/* TODO list:
26 * - See TODO comments in code.
27 */
28
29/* Marker for missing code. */
30#define TODO() \
31 do { \
32 fprintf(stderr, "TODO %s:%u: %s()\n", \
33 __FILE__, __LINE__, __func__); \
34 tcg_abort(); \
35 } while (0)
36
37/* Single bit n. */
38#define BIT(n) (1 << (n))
39
40/* Bitfield n...m (in 32 bit value). */
41#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
42
43/* Used for function call generation. */
44#define TCG_REG_CALL_STACK TCG_REG_R4
45#define TCG_TARGET_STACK_ALIGN 16
46#define TCG_TARGET_CALL_STACK_OFFSET 0
47
48/* TODO: documentation. */
49static uint8_t *tb_ret_addr;
50
51/* Macros used in tcg_target_op_defs. */
52#define R "r"
53#define RI "ri"
54#if TCG_TARGET_REG_BITS == 32
55# define R64 "r", "r"
56#else
57# define R64 "r"
58#endif
59#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
60# define L "L", "L"
61# define S "S", "S"
62#else
63# define L "L"
64# define S "S"
65#endif
66
67/* TODO: documentation. */
68static const TCGTargetOpDef tcg_target_op_defs[] = {
69 { INDEX_op_exit_tb, { NULL } },
70 { INDEX_op_goto_tb, { NULL } },
71 { INDEX_op_call, { RI } },
72 { INDEX_op_jmp, { RI } },
73 { INDEX_op_br, { NULL } },
74
75 { INDEX_op_mov_i32, { R, R } },
76 { INDEX_op_movi_i32, { R } },
77
78 { INDEX_op_ld8u_i32, { R, R } },
79 { INDEX_op_ld8s_i32, { R, R } },
80 { INDEX_op_ld16u_i32, { R, R } },
81 { INDEX_op_ld16s_i32, { R, R } },
82 { INDEX_op_ld_i32, { R, R } },
83 { INDEX_op_st8_i32, { R, R } },
84 { INDEX_op_st16_i32, { R, R } },
85 { INDEX_op_st_i32, { R, R } },
86
87 { INDEX_op_add_i32, { R, RI, RI } },
88 { INDEX_op_sub_i32, { R, RI, RI } },
89 { INDEX_op_mul_i32, { R, RI, RI } },
90#if TCG_TARGET_HAS_div_i32
91 { INDEX_op_div_i32, { R, R, R } },
92 { INDEX_op_divu_i32, { R, R, R } },
93 { INDEX_op_rem_i32, { R, R, R } },
94 { INDEX_op_remu_i32, { R, R, R } },
95#elif TCG_TARGET_HAS_div2_i32
96 { INDEX_op_div2_i32, { R, R, "0", "1", R } },
97 { INDEX_op_divu2_i32, { R, R, "0", "1", R } },
98#endif
99 /* TODO: Does R, RI, RI result in faster code than R, R, RI?
100 If both operands are constants, we can optimize. */
101 { INDEX_op_and_i32, { R, RI, RI } },
102#if TCG_TARGET_HAS_andc_i32
103 { INDEX_op_andc_i32, { R, RI, RI } },
104#endif
105#if TCG_TARGET_HAS_eqv_i32
106 { INDEX_op_eqv_i32, { R, RI, RI } },
107#endif
108#if TCG_TARGET_HAS_nand_i32
109 { INDEX_op_nand_i32, { R, RI, RI } },
110#endif
111#if TCG_TARGET_HAS_nor_i32
112 { INDEX_op_nor_i32, { R, RI, RI } },
113#endif
114 { INDEX_op_or_i32, { R, RI, RI } },
115#if TCG_TARGET_HAS_orc_i32
116 { INDEX_op_orc_i32, { R, RI, RI } },
117#endif
118 { INDEX_op_xor_i32, { R, RI, RI } },
119 { INDEX_op_shl_i32, { R, RI, RI } },
120 { INDEX_op_shr_i32, { R, RI, RI } },
121 { INDEX_op_sar_i32, { R, RI, RI } },
122#if TCG_TARGET_HAS_rot_i32
123 { INDEX_op_rotl_i32, { R, RI, RI } },
124 { INDEX_op_rotr_i32, { R, RI, RI } },
125#endif
126
127 { INDEX_op_brcond_i32, { R, RI } },
128
129 { INDEX_op_setcond_i32, { R, R, RI } },
130#if TCG_TARGET_REG_BITS == 64
131 { INDEX_op_setcond_i64, { R, R, RI } },
132#endif /* TCG_TARGET_REG_BITS == 64 */
133
134#if TCG_TARGET_REG_BITS == 32
135 /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
136 { INDEX_op_add2_i32, { R, R, R, R, R, R } },
137 { INDEX_op_sub2_i32, { R, R, R, R, R, R } },
138 { INDEX_op_brcond2_i32, { R, R, RI, RI } },
139 { INDEX_op_mulu2_i32, { R, R, R, R } },
140 { INDEX_op_setcond2_i32, { R, R, R, RI, RI } },
141#endif
142
143#if TCG_TARGET_HAS_not_i32
144 { INDEX_op_not_i32, { R, R } },
145#endif
146#if TCG_TARGET_HAS_neg_i32
147 { INDEX_op_neg_i32, { R, R } },
148#endif
149
150#if TCG_TARGET_REG_BITS == 64
151 { INDEX_op_mov_i64, { R, R } },
152 { INDEX_op_movi_i64, { R } },
153
154 { INDEX_op_ld8u_i64, { R, R } },
155 { INDEX_op_ld8s_i64, { R, R } },
156 { INDEX_op_ld16u_i64, { R, R } },
157 { INDEX_op_ld16s_i64, { R, R } },
158 { INDEX_op_ld32u_i64, { R, R } },
159 { INDEX_op_ld32s_i64, { R, R } },
160 { INDEX_op_ld_i64, { R, R } },
161
162 { INDEX_op_st8_i64, { R, R } },
163 { INDEX_op_st16_i64, { R, R } },
164 { INDEX_op_st32_i64, { R, R } },
165 { INDEX_op_st_i64, { R, R } },
166
167 { INDEX_op_add_i64, { R, RI, RI } },
168 { INDEX_op_sub_i64, { R, RI, RI } },
169 { INDEX_op_mul_i64, { R, RI, RI } },
170#if TCG_TARGET_HAS_div_i64
171 { INDEX_op_div_i64, { R, R, R } },
172 { INDEX_op_divu_i64, { R, R, R } },
173 { INDEX_op_rem_i64, { R, R, R } },
174 { INDEX_op_remu_i64, { R, R, R } },
175#elif TCG_TARGET_HAS_div2_i64
176 { INDEX_op_div2_i64, { R, R, "0", "1", R } },
177 { INDEX_op_divu2_i64, { R, R, "0", "1", R } },
178#endif
179 { INDEX_op_and_i64, { R, RI, RI } },
180#if TCG_TARGET_HAS_andc_i64
181 { INDEX_op_andc_i64, { R, RI, RI } },
182#endif
183#if TCG_TARGET_HAS_eqv_i64
184 { INDEX_op_eqv_i64, { R, RI, RI } },
185#endif
186#if TCG_TARGET_HAS_nand_i64
187 { INDEX_op_nand_i64, { R, RI, RI } },
188#endif
189#if TCG_TARGET_HAS_nor_i64
190 { INDEX_op_nor_i64, { R, RI, RI } },
191#endif
192 { INDEX_op_or_i64, { R, RI, RI } },
193#if TCG_TARGET_HAS_orc_i64
194 { INDEX_op_orc_i64, { R, RI, RI } },
195#endif
196 { INDEX_op_xor_i64, { R, RI, RI } },
197 { INDEX_op_shl_i64, { R, RI, RI } },
198 { INDEX_op_shr_i64, { R, RI, RI } },
199 { INDEX_op_sar_i64, { R, RI, RI } },
200#if TCG_TARGET_HAS_rot_i64
201 { INDEX_op_rotl_i64, { R, RI, RI } },
202 { INDEX_op_rotr_i64, { R, RI, RI } },
203#endif
204 { INDEX_op_brcond_i64, { R, RI } },
205
206#if TCG_TARGET_HAS_ext8s_i64
207 { INDEX_op_ext8s_i64, { R, R } },
208#endif
209#if TCG_TARGET_HAS_ext16s_i64
210 { INDEX_op_ext16s_i64, { R, R } },
211#endif
212#if TCG_TARGET_HAS_ext32s_i64
213 { INDEX_op_ext32s_i64, { R, R } },
214#endif
215#if TCG_TARGET_HAS_ext8u_i64
216 { INDEX_op_ext8u_i64, { R, R } },
217#endif
218#if TCG_TARGET_HAS_ext16u_i64
219 { INDEX_op_ext16u_i64, { R, R } },
220#endif
221#if TCG_TARGET_HAS_ext32u_i64
222 { INDEX_op_ext32u_i64, { R, R } },
223#endif
224#if TCG_TARGET_HAS_bswap16_i64
225 { INDEX_op_bswap16_i64, { R, R } },
226#endif
227#if TCG_TARGET_HAS_bswap32_i64
228 { INDEX_op_bswap32_i64, { R, R } },
229#endif
230#if TCG_TARGET_HAS_bswap64_i64
231 { INDEX_op_bswap64_i64, { R, R } },
232#endif
233#if TCG_TARGET_HAS_not_i64
234 { INDEX_op_not_i64, { R, R } },
235#endif
236#if TCG_TARGET_HAS_neg_i64
237 { INDEX_op_neg_i64, { R, R } },
238#endif
239#endif /* TCG_TARGET_REG_BITS == 64 */
240
241 { INDEX_op_qemu_ld8u, { R, L } },
242 { INDEX_op_qemu_ld8s, { R, L } },
243 { INDEX_op_qemu_ld16u, { R, L } },
244 { INDEX_op_qemu_ld16s, { R, L } },
245 { INDEX_op_qemu_ld32, { R, L } },
246#if TCG_TARGET_REG_BITS == 64
247 { INDEX_op_qemu_ld32u, { R, L } },
248 { INDEX_op_qemu_ld32s, { R, L } },
249#endif
250 { INDEX_op_qemu_ld64, { R64, L } },
251
252 { INDEX_op_qemu_st8, { R, S } },
253 { INDEX_op_qemu_st16, { R, S } },
254 { INDEX_op_qemu_st32, { R, S } },
255 { INDEX_op_qemu_st64, { R64, S } },
256
257#if TCG_TARGET_HAS_ext8s_i32
258 { INDEX_op_ext8s_i32, { R, R } },
259#endif
260#if TCG_TARGET_HAS_ext16s_i32
261 { INDEX_op_ext16s_i32, { R, R } },
262#endif
263#if TCG_TARGET_HAS_ext8u_i32
264 { INDEX_op_ext8u_i32, { R, R } },
265#endif
266#if TCG_TARGET_HAS_ext16u_i32
267 { INDEX_op_ext16u_i32, { R, R } },
268#endif
269
270#if TCG_TARGET_HAS_bswap16_i32
271 { INDEX_op_bswap16_i32, { R, R } },
272#endif
273#if TCG_TARGET_HAS_bswap32_i32
274 { INDEX_op_bswap32_i32, { R, R } },
275#endif
276
277 { -1 },
278};
279
280static const int tcg_target_reg_alloc_order[] = {
281 TCG_REG_R0,
282 TCG_REG_R1,
283 TCG_REG_R2,
284 TCG_REG_R3,
285#if 0 /* used for TCG_REG_CALL_STACK */
286 TCG_REG_R4,
287#endif
288 TCG_REG_R5,
289 TCG_REG_R6,
290 TCG_REG_R7,
291#if TCG_TARGET_NB_REGS >= 16
292 TCG_REG_R8,
293 TCG_REG_R9,
294 TCG_REG_R10,
295 TCG_REG_R11,
296 TCG_REG_R12,
297 TCG_REG_R13,
298 TCG_REG_R14,
299 TCG_REG_R15,
300#endif
301};
302
303#if MAX_OPC_PARAM_IARGS != 4
304# error Fix needed, number of supported input arguments changed!
305#endif
306
307static const int tcg_target_call_iarg_regs[] = {
308 TCG_REG_R0,
309 TCG_REG_R1,
310 TCG_REG_R2,
311 TCG_REG_R3,
312#if TCG_TARGET_REG_BITS == 32
313 /* 32 bit hosts need 2 * MAX_OPC_PARAM_IARGS registers. */
314#if 0 /* used for TCG_REG_CALL_STACK */
315 TCG_REG_R4,
316#endif
317 TCG_REG_R5,
318 TCG_REG_R6,
319 TCG_REG_R7,
320#if TCG_TARGET_NB_REGS >= 16
321 TCG_REG_R8,
322#else
323# error Too few input registers available
324#endif
325#endif
326};
327
328static const int tcg_target_call_oarg_regs[] = {
329 TCG_REG_R0,
330#if TCG_TARGET_REG_BITS == 32
331 TCG_REG_R1
332#endif
333};
334
335#ifndef NDEBUG
336static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
337 "r00",
338 "r01",
339 "r02",
340 "r03",
341 "r04",
342 "r05",
343 "r06",
344 "r07",
345#if TCG_TARGET_NB_REGS >= 16
346 "r08",
347 "r09",
348 "r10",
349 "r11",
350 "r12",
351 "r13",
352 "r14",
353 "r15",
354#if TCG_TARGET_NB_REGS >= 32
355 "r16",
356 "r17",
357 "r18",
358 "r19",
359 "r20",
360 "r21",
361 "r22",
362 "r23",
363 "r24",
364 "r25",
365 "r26",
366 "r27",
367 "r28",
368 "r29",
369 "r30",
370 "r31"
371#endif
372#endif
373};
374#endif
375
7316329a
SW
376static void patch_reloc(uint8_t *code_ptr, int type,
377 tcg_target_long value, tcg_target_long addend)
378{
379 /* tcg_out_reloc always uses the same type, addend. */
380 assert(type == sizeof(tcg_target_long));
381 assert(addend == 0);
382 assert(value != 0);
383 *(tcg_target_long *)code_ptr = value;
384}
385
386/* Parse target specific constraints. */
387static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
388{
389 const char *ct_str = *pct_str;
390 switch (ct_str[0]) {
391 case 'r':
392 case 'L': /* qemu_ld constraint */
393 case 'S': /* qemu_st constraint */
394 ct->ct |= TCG_CT_REG;
395 tcg_regset_set32(ct->u.regs, 0, BIT(TCG_TARGET_NB_REGS) - 1);
396 break;
397 default:
398 return -1;
399 }
400 ct_str++;
401 *pct_str = ct_str;
402 return 0;
403}
404
405#if defined(CONFIG_DEBUG_TCG_INTERPRETER)
406/* Show current bytecode. Used by tcg interpreter. */
407void tci_disas(uint8_t opc)
408{
409 const TCGOpDef *def = &tcg_op_defs[opc];
410 fprintf(stderr, "TCG %s %u, %u, %u\n",
411 def->name, def->nb_oargs, def->nb_iargs, def->nb_cargs);
412}
413#endif
414
415/* Write value (native size). */
416static void tcg_out_i(TCGContext *s, tcg_target_ulong v)
417{
418 *(tcg_target_ulong *)s->code_ptr = v;
419 s->code_ptr += sizeof(tcg_target_ulong);
420}
421
422/* Write 64 bit value. */
423static void tcg_out64(TCGContext *s, uint64_t v)
424{
425 *(uint64_t *)s->code_ptr = v;
426 s->code_ptr += sizeof(v);
427}
428
429/* Write opcode. */
430static void tcg_out_op_t(TCGContext *s, TCGOpcode op)
431{
432 tcg_out8(s, op);
433 tcg_out8(s, 0);
434}
435
436/* Write register. */
437static void tcg_out_r(TCGContext *s, TCGArg t0)
438{
439 assert(t0 < TCG_TARGET_NB_REGS);
440 tcg_out8(s, t0);
441}
442
443/* Write register or constant (native size). */
444static void tcg_out_ri(TCGContext *s, int const_arg, TCGArg arg)
445{
446 if (const_arg) {
447 assert(const_arg == 1);
448 tcg_out8(s, TCG_CONST);
449 tcg_out_i(s, arg);
450 } else {
451 tcg_out_r(s, arg);
452 }
453}
454
455/* Write register or constant (32 bit). */
456static void tcg_out_ri32(TCGContext *s, int const_arg, TCGArg arg)
457{
458 if (const_arg) {
459 assert(const_arg == 1);
460 tcg_out8(s, TCG_CONST);
461 tcg_out32(s, arg);
462 } else {
463 tcg_out_r(s, arg);
464 }
465}
466
467#if TCG_TARGET_REG_BITS == 64
468/* Write register or constant (64 bit). */
469static void tcg_out_ri64(TCGContext *s, int const_arg, TCGArg arg)
470{
471 if (const_arg) {
472 assert(const_arg == 1);
473 tcg_out8(s, TCG_CONST);
474 tcg_out64(s, arg);
475 } else {
476 tcg_out_r(s, arg);
477 }
478}
479#endif
480
481/* Write label. */
482static void tci_out_label(TCGContext *s, TCGArg arg)
483{
484 TCGLabel *label = &s->labels[arg];
485 if (label->has_value) {
486 tcg_out_i(s, label->u.value);
487 assert(label->u.value);
488 } else {
489 tcg_out_reloc(s, s->code_ptr, sizeof(tcg_target_ulong), arg, 0);
3c01ae0e 490 s->code_ptr += sizeof(tcg_target_ulong);
7316329a
SW
491 }
492}
493
2a534aff 494static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
7316329a
SW
495 tcg_target_long arg2)
496{
497 uint8_t *old_code_ptr = s->code_ptr;
498 if (type == TCG_TYPE_I32) {
499 tcg_out_op_t(s, INDEX_op_ld_i32);
500 tcg_out_r(s, ret);
501 tcg_out_r(s, arg1);
502 tcg_out32(s, arg2);
503 } else {
504 assert(type == TCG_TYPE_I64);
505#if TCG_TARGET_REG_BITS == 64
506 tcg_out_op_t(s, INDEX_op_ld_i64);
507 tcg_out_r(s, ret);
508 tcg_out_r(s, arg1);
509 assert(arg2 == (uint32_t)arg2);
510 tcg_out32(s, arg2);
511#else
512 TODO();
513#endif
514 }
515 old_code_ptr[1] = s->code_ptr - old_code_ptr;
516}
517
2a534aff 518static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
7316329a
SW
519{
520 uint8_t *old_code_ptr = s->code_ptr;
521 assert(ret != arg);
522#if TCG_TARGET_REG_BITS == 32
523 tcg_out_op_t(s, INDEX_op_mov_i32);
524#else
525 tcg_out_op_t(s, INDEX_op_mov_i64);
526#endif
527 tcg_out_r(s, ret);
528 tcg_out_r(s, arg);
529 old_code_ptr[1] = s->code_ptr - old_code_ptr;
530}
531
532static void tcg_out_movi(TCGContext *s, TCGType type,
2a534aff 533 TCGReg t0, tcg_target_long arg)
7316329a
SW
534{
535 uint8_t *old_code_ptr = s->code_ptr;
536 uint32_t arg32 = arg;
537 if (type == TCG_TYPE_I32 || arg == arg32) {
538 tcg_out_op_t(s, INDEX_op_movi_i32);
539 tcg_out_r(s, t0);
540 tcg_out32(s, arg32);
541 } else {
542 assert(type == TCG_TYPE_I64);
543#if TCG_TARGET_REG_BITS == 64
544 tcg_out_op_t(s, INDEX_op_movi_i64);
545 tcg_out_r(s, t0);
546 tcg_out64(s, arg);
547#else
548 TODO();
549#endif
550 }
551 old_code_ptr[1] = s->code_ptr - old_code_ptr;
552}
553
554static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
555 const int *const_args)
556{
557 uint8_t *old_code_ptr = s->code_ptr;
558
559 tcg_out_op_t(s, opc);
560
561 switch (opc) {
562 case INDEX_op_exit_tb:
563 tcg_out64(s, args[0]);
564 break;
565 case INDEX_op_goto_tb:
566 if (s->tb_jmp_offset) {
567 /* Direct jump method. */
568 assert(args[0] < ARRAY_SIZE(s->tb_jmp_offset));
569 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
570 tcg_out32(s, 0);
571 } else {
572 /* Indirect jump method. */
573 TODO();
574 }
575 assert(args[0] < ARRAY_SIZE(s->tb_next_offset));
576 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
577 break;
578 case INDEX_op_br:
579 tci_out_label(s, args[0]);
580 break;
581 case INDEX_op_call:
582 tcg_out_ri(s, const_args[0], args[0]);
583 break;
584 case INDEX_op_jmp:
585 TODO();
586 break;
587 case INDEX_op_setcond_i32:
588 tcg_out_r(s, args[0]);
589 tcg_out_r(s, args[1]);
590 tcg_out_ri32(s, const_args[2], args[2]);
591 tcg_out8(s, args[3]); /* condition */
592 break;
593#if TCG_TARGET_REG_BITS == 32
594 case INDEX_op_setcond2_i32:
595 /* setcond2_i32 cond, t0, t1_low, t1_high, t2_low, t2_high */
596 tcg_out_r(s, args[0]);
597 tcg_out_r(s, args[1]);
598 tcg_out_r(s, args[2]);
599 tcg_out_ri32(s, const_args[3], args[3]);
600 tcg_out_ri32(s, const_args[4], args[4]);
601 tcg_out8(s, args[5]); /* condition */
602 break;
603#elif TCG_TARGET_REG_BITS == 64
604 case INDEX_op_setcond_i64:
605 tcg_out_r(s, args[0]);
606 tcg_out_r(s, args[1]);
607 tcg_out_ri64(s, const_args[2], args[2]);
608 tcg_out8(s, args[3]); /* condition */
609 break;
610#endif
611 case INDEX_op_movi_i32:
612 TODO(); /* Handled by tcg_out_movi? */
613 break;
614 case INDEX_op_ld8u_i32:
615 case INDEX_op_ld8s_i32:
616 case INDEX_op_ld16u_i32:
617 case INDEX_op_ld16s_i32:
618 case INDEX_op_ld_i32:
619 case INDEX_op_st8_i32:
620 case INDEX_op_st16_i32:
621 case INDEX_op_st_i32:
622 case INDEX_op_ld8u_i64:
623 case INDEX_op_ld8s_i64:
624 case INDEX_op_ld16u_i64:
625 case INDEX_op_ld16s_i64:
626 case INDEX_op_ld32u_i64:
627 case INDEX_op_ld32s_i64:
628 case INDEX_op_ld_i64:
629 case INDEX_op_st8_i64:
630 case INDEX_op_st16_i64:
631 case INDEX_op_st32_i64:
632 case INDEX_op_st_i64:
633 tcg_out_r(s, args[0]);
634 tcg_out_r(s, args[1]);
635 assert(args[2] == (uint32_t)args[2]);
636 tcg_out32(s, args[2]);
637 break;
638 case INDEX_op_add_i32:
639 case INDEX_op_sub_i32:
640 case INDEX_op_mul_i32:
641 case INDEX_op_and_i32:
642 case INDEX_op_andc_i32: /* Optional (TCG_TARGET_HAS_andc_i32). */
643 case INDEX_op_eqv_i32: /* Optional (TCG_TARGET_HAS_eqv_i32). */
644 case INDEX_op_nand_i32: /* Optional (TCG_TARGET_HAS_nand_i32). */
645 case INDEX_op_nor_i32: /* Optional (TCG_TARGET_HAS_nor_i32). */
646 case INDEX_op_or_i32:
647 case INDEX_op_orc_i32: /* Optional (TCG_TARGET_HAS_orc_i32). */
648 case INDEX_op_xor_i32:
649 case INDEX_op_shl_i32:
650 case INDEX_op_shr_i32:
651 case INDEX_op_sar_i32:
652 case INDEX_op_rotl_i32: /* Optional (TCG_TARGET_HAS_rot_i32). */
653 case INDEX_op_rotr_i32: /* Optional (TCG_TARGET_HAS_rot_i32). */
654 tcg_out_r(s, args[0]);
655 tcg_out_ri32(s, const_args[1], args[1]);
656 tcg_out_ri32(s, const_args[2], args[2]);
657 break;
658
659#if TCG_TARGET_REG_BITS == 64
660 case INDEX_op_mov_i64:
661 case INDEX_op_movi_i64:
662 TODO();
663 break;
664 case INDEX_op_add_i64:
665 case INDEX_op_sub_i64:
666 case INDEX_op_mul_i64:
667 case INDEX_op_and_i64:
668 case INDEX_op_andc_i64: /* Optional (TCG_TARGET_HAS_andc_i64). */
669 case INDEX_op_eqv_i64: /* Optional (TCG_TARGET_HAS_eqv_i64). */
670 case INDEX_op_nand_i64: /* Optional (TCG_TARGET_HAS_nand_i64). */
671 case INDEX_op_nor_i64: /* Optional (TCG_TARGET_HAS_nor_i64). */
672 case INDEX_op_or_i64:
673 case INDEX_op_orc_i64: /* Optional (TCG_TARGET_HAS_orc_i64). */
674 case INDEX_op_xor_i64:
675 case INDEX_op_shl_i64:
676 case INDEX_op_shr_i64:
677 case INDEX_op_sar_i64:
678 /* TODO: Implementation of rotl_i64, rotr_i64 missing in tci.c. */
679 case INDEX_op_rotl_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */
680 case INDEX_op_rotr_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */
681 tcg_out_r(s, args[0]);
682 tcg_out_ri64(s, const_args[1], args[1]);
683 tcg_out_ri64(s, const_args[2], args[2]);
684 break;
685 case INDEX_op_div_i64: /* Optional (TCG_TARGET_HAS_div_i64). */
686 case INDEX_op_divu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */
687 case INDEX_op_rem_i64: /* Optional (TCG_TARGET_HAS_div_i64). */
688 case INDEX_op_remu_i64: /* Optional (TCG_TARGET_HAS_div_i64). */
689 TODO();
690 break;
691 case INDEX_op_div2_i64: /* Optional (TCG_TARGET_HAS_div2_i64). */
692 case INDEX_op_divu2_i64: /* Optional (TCG_TARGET_HAS_div2_i64). */
693 TODO();
694 break;
695 case INDEX_op_brcond_i64:
696 tcg_out_r(s, args[0]);
697 tcg_out_ri64(s, const_args[1], args[1]);
698 tcg_out8(s, args[2]); /* condition */
699 tci_out_label(s, args[3]);
700 break;
701 case INDEX_op_bswap16_i64: /* Optional (TCG_TARGET_HAS_bswap16_i64). */
702 case INDEX_op_bswap32_i64: /* Optional (TCG_TARGET_HAS_bswap32_i64). */
703 case INDEX_op_bswap64_i64: /* Optional (TCG_TARGET_HAS_bswap64_i64). */
704 case INDEX_op_not_i64: /* Optional (TCG_TARGET_HAS_not_i64). */
705 case INDEX_op_neg_i64: /* Optional (TCG_TARGET_HAS_neg_i64). */
706 case INDEX_op_ext8s_i64: /* Optional (TCG_TARGET_HAS_ext8s_i64). */
707 case INDEX_op_ext8u_i64: /* Optional (TCG_TARGET_HAS_ext8u_i64). */
708 case INDEX_op_ext16s_i64: /* Optional (TCG_TARGET_HAS_ext16s_i64). */
709 case INDEX_op_ext16u_i64: /* Optional (TCG_TARGET_HAS_ext16u_i64). */
710 case INDEX_op_ext32s_i64: /* Optional (TCG_TARGET_HAS_ext32s_i64). */
711 case INDEX_op_ext32u_i64: /* Optional (TCG_TARGET_HAS_ext32u_i64). */
712#endif /* TCG_TARGET_REG_BITS == 64 */
713 case INDEX_op_neg_i32: /* Optional (TCG_TARGET_HAS_neg_i32). */
714 case INDEX_op_not_i32: /* Optional (TCG_TARGET_HAS_not_i32). */
715 case INDEX_op_ext8s_i32: /* Optional (TCG_TARGET_HAS_ext8s_i32). */
716 case INDEX_op_ext16s_i32: /* Optional (TCG_TARGET_HAS_ext16s_i32). */
717 case INDEX_op_ext8u_i32: /* Optional (TCG_TARGET_HAS_ext8u_i32). */
718 case INDEX_op_ext16u_i32: /* Optional (TCG_TARGET_HAS_ext16u_i32). */
719 case INDEX_op_bswap16_i32: /* Optional (TCG_TARGET_HAS_bswap16_i32). */
720 case INDEX_op_bswap32_i32: /* Optional (TCG_TARGET_HAS_bswap32_i32). */
721 tcg_out_r(s, args[0]);
722 tcg_out_r(s, args[1]);
723 break;
724 case INDEX_op_div_i32: /* Optional (TCG_TARGET_HAS_div_i32). */
725 case INDEX_op_divu_i32: /* Optional (TCG_TARGET_HAS_div_i32). */
726 case INDEX_op_rem_i32: /* Optional (TCG_TARGET_HAS_div_i32). */
727 case INDEX_op_remu_i32: /* Optional (TCG_TARGET_HAS_div_i32). */
728 tcg_out_r(s, args[0]);
729 tcg_out_ri32(s, const_args[1], args[1]);
730 tcg_out_ri32(s, const_args[2], args[2]);
731 break;
732 case INDEX_op_div2_i32: /* Optional (TCG_TARGET_HAS_div2_i32). */
733 case INDEX_op_divu2_i32: /* Optional (TCG_TARGET_HAS_div2_i32). */
734 TODO();
735 break;
736#if TCG_TARGET_REG_BITS == 32
737 case INDEX_op_add2_i32:
738 case INDEX_op_sub2_i32:
739 tcg_out_r(s, args[0]);
740 tcg_out_r(s, args[1]);
741 tcg_out_r(s, args[2]);
742 tcg_out_r(s, args[3]);
743 tcg_out_r(s, args[4]);
744 tcg_out_r(s, args[5]);
745 break;
746 case INDEX_op_brcond2_i32:
747 tcg_out_r(s, args[0]);
748 tcg_out_r(s, args[1]);
749 tcg_out_ri32(s, const_args[2], args[2]);
750 tcg_out_ri32(s, const_args[3], args[3]);
751 tcg_out8(s, args[4]); /* condition */
752 tci_out_label(s, args[5]);
753 break;
754 case INDEX_op_mulu2_i32:
755 tcg_out_r(s, args[0]);
756 tcg_out_r(s, args[1]);
757 tcg_out_r(s, args[2]);
758 tcg_out_r(s, args[3]);
759 break;
760#endif
761 case INDEX_op_brcond_i32:
762 tcg_out_r(s, args[0]);
763 tcg_out_ri32(s, const_args[1], args[1]);
764 tcg_out8(s, args[2]); /* condition */
765 tci_out_label(s, args[3]);
766 break;
767 case INDEX_op_qemu_ld8u:
768 case INDEX_op_qemu_ld8s:
769 case INDEX_op_qemu_ld16u:
770 case INDEX_op_qemu_ld16s:
771 case INDEX_op_qemu_ld32:
772#if TCG_TARGET_REG_BITS == 64
773 case INDEX_op_qemu_ld32s:
774 case INDEX_op_qemu_ld32u:
775#endif
776 tcg_out_r(s, *args++);
777 tcg_out_r(s, *args++);
778#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
779 tcg_out_r(s, *args++);
780#endif
781#ifdef CONFIG_SOFTMMU
782 tcg_out_i(s, *args);
783#endif
784 break;
785 case INDEX_op_qemu_ld64:
786 tcg_out_r(s, *args++);
787#if TCG_TARGET_REG_BITS == 32
788 tcg_out_r(s, *args++);
789#endif
790 tcg_out_r(s, *args++);
791#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
792 tcg_out_r(s, *args++);
793#endif
794#ifdef CONFIG_SOFTMMU
795 tcg_out_i(s, *args);
796#endif
797 break;
798 case INDEX_op_qemu_st8:
799 case INDEX_op_qemu_st16:
800 case INDEX_op_qemu_st32:
e141ab52
BS
801#ifdef CONFIG_TCG_PASS_AREG0
802 tcg_out_r(s, TCG_AREG0);
803#endif
7316329a
SW
804 tcg_out_r(s, *args++);
805 tcg_out_r(s, *args++);
806#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
807 tcg_out_r(s, *args++);
808#endif
809#ifdef CONFIG_SOFTMMU
810 tcg_out_i(s, *args);
811#endif
812 break;
813 case INDEX_op_qemu_st64:
e141ab52
BS
814#ifdef CONFIG_TCG_PASS_AREG0
815 tcg_out_r(s, TCG_AREG0);
816#endif
7316329a
SW
817 tcg_out_r(s, *args++);
818#if TCG_TARGET_REG_BITS == 32
819 tcg_out_r(s, *args++);
820#endif
821 tcg_out_r(s, *args++);
822#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
823 tcg_out_r(s, *args++);
824#endif
825#ifdef CONFIG_SOFTMMU
826 tcg_out_i(s, *args);
827#endif
828 break;
829 case INDEX_op_end:
830 TODO();
831 break;
832 default:
833 fprintf(stderr, "Missing: %s\n", tcg_op_defs[opc].name);
834 tcg_abort();
835 }
836 old_code_ptr[1] = s->code_ptr - old_code_ptr;
837}
838
2a534aff 839static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
7316329a
SW
840 tcg_target_long arg2)
841{
842 uint8_t *old_code_ptr = s->code_ptr;
843 if (type == TCG_TYPE_I32) {
844 tcg_out_op_t(s, INDEX_op_st_i32);
845 tcg_out_r(s, arg);
846 tcg_out_r(s, arg1);
847 tcg_out32(s, arg2);
848 } else {
849 assert(type == TCG_TYPE_I64);
850#if TCG_TARGET_REG_BITS == 64
851 tcg_out_op_t(s, INDEX_op_st_i64);
852 tcg_out_r(s, arg);
853 tcg_out_r(s, arg1);
854 tcg_out32(s, arg2);
855#else
856 TODO();
857#endif
858 }
859 old_code_ptr[1] = s->code_ptr - old_code_ptr;
860}
861
862/* Test if a constant matches the constraint. */
863static int tcg_target_const_match(tcg_target_long val,
864 const TCGArgConstraint *arg_ct)
865{
866 /* No need to return 0 or 1, 0 or != 0 is good enough. */
867 return arg_ct->ct & TCG_CT_CONST;
868}
869
870/* Maximum number of register used for input function arguments. */
871static int tcg_target_get_call_iarg_regs_count(int flags)
872{
873 return ARRAY_SIZE(tcg_target_call_iarg_regs);
874}
875
876static void tcg_target_init(TCGContext *s)
877{
878#if defined(CONFIG_DEBUG_TCG_INTERPRETER)
879 const char *envval = getenv("DEBUG_TCG");
880 if (envval) {
eeacee4d 881 cpu_set_log(strtol(envval, NULL, 0));
7316329a
SW
882 }
883#endif
884
885 /* The current code uses uint8_t for tcg operations. */
886 assert(ARRAY_SIZE(tcg_op_defs) <= UINT8_MAX);
887
888 /* Registers available for 32 bit operations. */
889 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0,
890 BIT(TCG_TARGET_NB_REGS) - 1);
891 /* Registers available for 64 bit operations. */
892 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0,
893 BIT(TCG_TARGET_NB_REGS) - 1);
894 /* TODO: Which registers should be set here? */
895 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
896 BIT(TCG_TARGET_NB_REGS) - 1);
897 tcg_regset_clear(s->reserved_regs);
898 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
899 tcg_add_target_add_op_defs(tcg_target_op_defs);
9349b4f9 900 tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
7316329a
SW
901 CPU_TEMP_BUF_NLONGS * sizeof(long));
902}
903
904/* Generate global QEMU prologue and epilogue code. */
905static void tcg_target_qemu_prologue(TCGContext *s)
906{
907 tb_ret_addr = s->code_ptr;
908}