]> git.proxmox.com Git - qemu.git/blame - tcg/ppc/tcg-target.c
monitor: fix build breakage for !CONFIG_VNC
[qemu.git] / tcg / ppc / tcg-target.c
CommitLineData
2662e13f
FB
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008 Fabrice Bellard
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
25static uint8_t *tb_ret_addr;
26
6ec85236 27#ifdef _CALL_DARWIN
bf6bca52 28#define LINKAGE_AREA_SIZE 24
2946898b 29#define LR_OFFSET 8
6ec85236 30#elif defined _CALL_AIX
b29fe3ed 31#define LINKAGE_AREA_SIZE 52
32#define LR_OFFSET 8
f9bf2987 33#else
34#define LINKAGE_AREA_SIZE 8
2946898b 35#define LR_OFFSET 4
f9bf2987 36#endif
37
2662e13f 38#define FAST_PATH
35f6b599 39
f6548c0a 40#ifndef GUEST_BASE
41#define GUEST_BASE 0
42#endif
43
44#ifdef CONFIG_USE_GUEST_BASE
45#define TCG_GUEST_BASE_REG 30
46#else
47#define TCG_GUEST_BASE_REG 0
48#endif
49
d4a9eb1f 50#ifndef NDEBUG
2662e13f
FB
51static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
52 "r0",
53 "r1",
f7e2aca8 54 "r2",
2662e13f
FB
55 "r3",
56 "r4",
57 "r5",
58 "r6",
59 "r7",
60 "r8",
61 "r9",
62 "r10",
63 "r11",
64 "r12",
65 "r13",
66 "r14",
67 "r15",
68 "r16",
69 "r17",
70 "r18",
71 "r19",
72 "r20",
73 "r21",
74 "r22",
75 "r23",
76 "r24",
77 "r25",
78 "r26",
79 "r27",
80 "r28",
81 "r29",
82 "r30",
83 "r31"
84};
d4a9eb1f 85#endif
2662e13f
FB
86
87static const int tcg_target_reg_alloc_order[] = {
a35e86c5 88 TCG_REG_R14,
89 TCG_REG_R15,
90 TCG_REG_R16,
91 TCG_REG_R17,
92 TCG_REG_R18,
93 TCG_REG_R19,
94 TCG_REG_R20,
95 TCG_REG_R21,
96 TCG_REG_R22,
97 TCG_REG_R23,
98 TCG_REG_R28,
99 TCG_REG_R29,
100 TCG_REG_R30,
101 TCG_REG_R31,
6ec85236 102#ifdef _CALL_DARWIN
f9bf2987 103 TCG_REG_R2,
104#endif
2662e13f
FB
105 TCG_REG_R3,
106 TCG_REG_R4,
107 TCG_REG_R5,
108 TCG_REG_R6,
109 TCG_REG_R7,
110 TCG_REG_R8,
111 TCG_REG_R9,
112 TCG_REG_R10,
6ec85236 113#ifndef _CALL_DARWIN
2662e13f 114 TCG_REG_R11,
f9bf2987 115#endif
2662e13f 116 TCG_REG_R12,
6ec85236 117#ifndef _CALL_SYSV
2662e13f 118 TCG_REG_R13,
5db3ee79 119#endif
2662e13f
FB
120 TCG_REG_R24,
121 TCG_REG_R25,
122 TCG_REG_R26,
a35e86c5 123 TCG_REG_R27
2662e13f
FB
124};
125
126static const int tcg_target_call_iarg_regs[] = {
127 TCG_REG_R3,
128 TCG_REG_R4,
129 TCG_REG_R5,
130 TCG_REG_R6,
131 TCG_REG_R7,
132 TCG_REG_R8,
133 TCG_REG_R9,
134 TCG_REG_R10
135};
136
137static const int tcg_target_call_oarg_regs[2] = {
138 TCG_REG_R3,
139 TCG_REG_R4
140};
141
142static const int tcg_target_callee_save_regs[] = {
6ec85236 143#ifdef _CALL_DARWIN
f9bf2987 144 TCG_REG_R11,
145 TCG_REG_R13,
b29fe3ed 146#endif
6ec85236 147#ifdef _CALL_AIX
b29fe3ed 148 TCG_REG_R13,
f9bf2987 149#endif
2662e13f
FB
150 TCG_REG_R14,
151 TCG_REG_R15,
152 TCG_REG_R16,
153 TCG_REG_R17,
154 TCG_REG_R18,
155 TCG_REG_R19,
156 TCG_REG_R20,
157 TCG_REG_R21,
158 TCG_REG_R22,
159 TCG_REG_R23,
eb2eb1dc 160 TCG_REG_R24,
161 TCG_REG_R25,
162 TCG_REG_R26,
cea5f9a2 163 TCG_REG_R27, /* currently used for the global env */
2662e13f
FB
164 TCG_REG_R28,
165 TCG_REG_R29,
166 TCG_REG_R30,
167 TCG_REG_R31
168};
169
170static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
171{
932a6909
FB
172 tcg_target_long disp;
173
174 disp = target - (tcg_target_long) pc;
175 if ((disp << 6) >> 6 != disp)
176 tcg_abort ();
177
178 return disp & 0x3fffffc;
2662e13f
FB
179}
180
181static void reloc_pc24 (void *pc, tcg_target_long target)
182{
183 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
184 | reloc_pc24_val (pc, target);
185}
186
187static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
188{
932a6909
FB
189 tcg_target_long disp;
190
191 disp = target - (tcg_target_long) pc;
192 if (disp != (int16_t) disp)
193 tcg_abort ();
194
195 return disp & 0xfffc;
2662e13f
FB
196}
197
198static void reloc_pc14 (void *pc, tcg_target_long target)
199{
200 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
201 | reloc_pc14_val (pc, target);
202}
203
204static void patch_reloc(uint8_t *code_ptr, int type,
205 tcg_target_long value, tcg_target_long addend)
206{
207 value += addend;
208 switch (type) {
209 case R_PPC_REL14:
210 reloc_pc14 (code_ptr, value);
211 break;
212 case R_PPC_REL24:
213 reloc_pc24 (code_ptr, value);
214 break;
215 default:
216 tcg_abort();
217 }
218}
219
220/* maximum number of register used for input function arguments */
221static int tcg_target_get_call_iarg_regs_count(int flags)
222{
b1503cda 223 return ARRAY_SIZE (tcg_target_call_iarg_regs);
2662e13f
FB
224}
225
226/* parse target specific constraints */
227static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
228{
229 const char *ct_str;
230
231 ct_str = *pct_str;
232 switch (ct_str[0]) {
398ce98e 233 case 'A': case 'B': case 'C': case 'D':
234 ct->ct |= TCG_CT_REG;
235 tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
236 break;
2662e13f
FB
237 case 'r':
238 ct->ct |= TCG_CT_REG;
239 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
240 break;
70fa887c 241#ifdef CONFIG_SOFTMMU
2662e13f
FB
242 case 'L': /* qemu_ld constraint */
243 ct->ct |= TCG_CT_REG;
244 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
245 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
246 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
247 break;
248 case 'K': /* qemu_st[8..32] constraint */
249 ct->ct |= TCG_CT_REG;
250 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
251 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
252 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
253 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
254#if TARGET_LONG_BITS == 64
255 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
256#endif
257 break;
258 case 'M': /* qemu_st64 constraint */
259 ct->ct |= TCG_CT_REG;
260 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
261 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
262 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
263 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
264 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
265 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
266 break;
70fa887c 267#else
268 case 'L':
269 case 'K':
270 ct->ct |= TCG_CT_REG;
271 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
272 break;
273 case 'M':
274 ct->ct |= TCG_CT_REG;
275 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
276 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
277 break;
278#endif
2662e13f
FB
279 default:
280 return -1;
281 }
282 ct_str++;
283 *pct_str = ct_str;
284 return 0;
285}
286
287/* test if a constant matches the constraint */
288static int tcg_target_const_match(tcg_target_long val,
289 const TCGArgConstraint *arg_ct)
290{
291 int ct;
292
293 ct = arg_ct->ct;
294 if (ct & TCG_CT_CONST)
295 return 1;
2662e13f
FB
296 return 0;
297}
298
299#define OPCD(opc) ((opc)<<26)
300#define XO31(opc) (OPCD(31)|((opc)<<1))
301#define XO19(opc) (OPCD(19)|((opc)<<1))
302
303#define B OPCD(18)
304#define BC OPCD(16)
305#define LBZ OPCD(34)
306#define LHZ OPCD(40)
307#define LHA OPCD(42)
308#define LWZ OPCD(32)
309#define STB OPCD(38)
310#define STH OPCD(44)
311#define STW OPCD(36)
312
b0809bf7 313#define ADDIC OPCD(12)
2662e13f
FB
314#define ADDI OPCD(14)
315#define ADDIS OPCD(15)
316#define ORI OPCD(24)
317#define ORIS OPCD(25)
318#define XORI OPCD(26)
319#define XORIS OPCD(27)
320#define ANDI OPCD(28)
321#define ANDIS OPCD(29)
322#define MULLI OPCD( 7)
323#define CMPLI OPCD(10)
324#define CMPI OPCD(11)
d616cf1d 325#define SUBFIC OPCD( 8)
2662e13f
FB
326
327#define LWZU OPCD(33)
328#define STWU OPCD(37)
329
a884dcb8 330#define RLWIMI OPCD(20)
2662e13f 331#define RLWINM OPCD(21)
65fe043e 332#define RLWNM OPCD(23)
2662e13f 333
c596defd 334#define BCLR XO19( 16)
2662e13f
FB
335#define BCCTR XO19(528)
336#define CRAND XO19(257)
c596defd 337#define CRANDC XO19(129)
338#define CRNAND XO19(225)
339#define CROR XO19(449)
b0809bf7 340#define CRNOR XO19( 33)
2662e13f
FB
341
342#define EXTSB XO31(954)
343#define EXTSH XO31(922)
344#define ADD XO31(266)
345#define ADDE XO31(138)
346#define ADDC XO31( 10)
347#define AND XO31( 28)
348#define SUBF XO31( 40)
349#define SUBFC XO31( 8)
350#define SUBFE XO31(136)
351#define OR XO31(444)
352#define XOR XO31(316)
353#define MULLW XO31(235)
354#define MULHWU XO31( 11)
355#define DIVW XO31(491)
356#define DIVWU XO31(459)
357#define CMP XO31( 0)
358#define CMPL XO31( 32)
359#define LHBRX XO31(790)
360#define LWBRX XO31(534)
361#define STHBRX XO31(918)
362#define STWBRX XO31(662)
363#define MFSPR XO31(339)
364#define MTSPR XO31(467)
365#define SRAWI XO31(824)
366#define NEG XO31(104)
b0809bf7 367#define MFCR XO31( 19)
368#define CNTLZW XO31( 26)
65fe043e 369#define NOR XO31(124)
370#define ANDC XO31( 60)
371#define ORC XO31(412)
aa77bebd 372#define EQV XO31(284)
373#define NAND XO31(476)
2662e13f
FB
374
375#define LBZX XO31( 87)
4f4a67ae 376#define LHZX XO31(279)
2662e13f
FB
377#define LHAX XO31(343)
378#define LWZX XO31( 23)
379#define STBX XO31(215)
380#define STHX XO31(407)
381#define STWX XO31(151)
382
383#define SPR(a,b) ((((a)<<5)|(b))<<11)
384#define LR SPR(8, 0)
385#define CTR SPR(9, 0)
386
387#define SLW XO31( 24)
388#define SRW XO31(536)
389#define SRAW XO31(792)
390
2662e13f
FB
391#define TW XO31(4)
392#define TRAP (TW | TO (31))
393
394#define RT(r) ((r)<<21)
395#define RS(r) ((r)<<21)
396#define RA(r) ((r)<<16)
397#define RB(r) ((r)<<11)
398#define TO(t) ((t)<<21)
399#define SH(s) ((s)<<11)
400#define MB(b) ((b)<<6)
401#define ME(e) ((e)<<1)
402#define BO(o) ((o)<<21)
403
404#define LK 1
405
406#define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
407#define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
408
409#define BF(n) ((n)<<23)
410#define BI(n, c) (((c)+((n)*4))<<16)
411#define BT(n, c) (((c)+((n)*4))<<21)
412#define BA(n, c) (((c)+((n)*4))<<16)
413#define BB(n, c) (((c)+((n)*4))<<11)
414
415#define BO_COND_TRUE BO (12)
416#define BO_COND_FALSE BO (4)
417#define BO_ALWAYS BO (20)
418
419enum {
420 CR_LT,
421 CR_GT,
422 CR_EQ,
423 CR_SO
424};
425
426static const uint32_t tcg_to_bc[10] = {
427 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
428 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
429 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
430 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
431 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
432 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
433 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
434 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
435 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
436 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
437};
438
3b6dac34 439static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
2662e13f
FB
440{
441 tcg_out32 (s, OR | SAB (arg, ret, arg));
442}
443
444static void tcg_out_movi(TCGContext *s, TCGType type,
445 int ret, tcg_target_long arg)
446{
447 if (arg == (int16_t) arg)
448 tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
449 else {
450 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
451 if (arg & 0xffff)
0a878c47 452 tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
2662e13f
FB
453 }
454}
455
456static void tcg_out_ldst (TCGContext *s, int ret, int addr,
457 int offset, int op1, int op2)
458{
459 if (offset == (int16_t) offset)
460 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
461 else {
462 tcg_out_movi (s, TCG_TYPE_I32, 0, offset);
463 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
464 }
465}
466
932a6909
FB
467static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
468{
469 tcg_target_long disp;
470
471 disp = target - (tcg_target_long) s->code_ptr;
472 if ((disp << 6) >> 6 == disp)
8c5e95d8 473 tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
932a6909
FB
474 else {
475 tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target);
476 tcg_out32 (s, MTSPR | RS (0) | CTR);
477 tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
478 }
479}
480
b29fe3ed 481static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
482{
6ec85236 483#ifdef _CALL_AIX
b29fe3ed 484 int reg;
485
486 if (const_arg) {
487 reg = 2;
488 tcg_out_movi (s, TCG_TYPE_I32, reg, arg);
489 }
490 else reg = arg;
491
492 tcg_out32 (s, LWZ | RT (0) | RA (reg));
493 tcg_out32 (s, MTSPR | RA (0) | CTR);
494 tcg_out32 (s, LWZ | RT (2) | RA (reg) | 4);
495 tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
d9370327 496#else
497 if (const_arg) {
498 tcg_out_b (s, LK, arg);
499 }
500 else {
501 tcg_out32 (s, MTSPR | RS (arg) | LR);
502 tcg_out32 (s, BCLR | BO_ALWAYS | LK);
503 }
b29fe3ed 504#endif
d9370327 505}
b29fe3ed 506
2662e13f 507#if defined(CONFIG_SOFTMMU)
79383c9c
BS
508
509#include "../../softmmu_defs.h"
2662e13f
FB
510
511static void *qemu_ld_helpers[4] = {
512 __ldb_mmu,
513 __ldw_mmu,
514 __ldl_mmu,
515 __ldq_mmu,
516};
517
518static void *qemu_st_helpers[4] = {
519 __stb_mmu,
520 __stw_mmu,
521 __stl_mmu,
522 __stq_mmu,
523};
524#endif
525
526static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
527{
f6548c0a 528 int addr_reg, data_reg, data_reg2, r0, r1, rbase, mem_index, s_bits, bswap;
2662e13f 529#ifdef CONFIG_SOFTMMU
f8edcbaa 530 int r2;
2662e13f
FB
531 void *label1_ptr, *label2_ptr;
532#endif
533#if TARGET_LONG_BITS == 64
534 int addr_reg2;
535#endif
536
537 data_reg = *args++;
538 if (opc == 3)
539 data_reg2 = *args++;
540 else
541 data_reg2 = 0;
542 addr_reg = *args++;
543#if TARGET_LONG_BITS == 64
544 addr_reg2 = *args++;
545#endif
546 mem_index = *args;
547 s_bits = opc & 3;
548
549#ifdef CONFIG_SOFTMMU
550 r0 = 3;
551 r1 = 4;
552 r2 = 0;
f6548c0a 553 rbase = 0;
2662e13f
FB
554
555 tcg_out32 (s, (RLWINM
556 | RA (r0)
557 | RS (addr_reg)
558 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
559 | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
560 | ME (31 - CPU_TLB_ENTRY_BITS)
561 )
562 );
563 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
564 tcg_out32 (s, (LWZU
565 | RT (r1)
566 | RA (r0)
567 | offsetof (CPUState, tlb_table[mem_index][0].addr_read)
568 )
569 );
570 tcg_out32 (s, (RLWINM
571 | RA (r2)
572 | RS (addr_reg)
573 | SH (0)
574 | MB ((32 - s_bits) & 31)
575 | ME (31 - TARGET_PAGE_BITS)
576 )
577 );
578
579 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
580#if TARGET_LONG_BITS == 64
581 tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
582 tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
583 tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
584#endif
585
586 label1_ptr = s->code_ptr;
587#ifdef FAST_PATH
588 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
589#endif
590
591 /* slow path */
592#if TARGET_LONG_BITS == 32
3b6dac34 593 tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg);
2662e13f
FB
594 tcg_out_movi (s, TCG_TYPE_I32, 4, mem_index);
595#else
3b6dac34
RH
596 tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg2);
597 tcg_out_mov (s, TCG_TYPE_I32, 4, addr_reg);
2662e13f
FB
598 tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
599#endif
600
b29fe3ed 601 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
2662e13f
FB
602 switch (opc) {
603 case 0|4:
604 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
605 break;
606 case 1|4:
607 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
608 break;
609 case 0:
610 case 1:
611 case 2:
612 if (data_reg != 3)
3b6dac34 613 tcg_out_mov (s, TCG_TYPE_I32, data_reg, 3);
2662e13f
FB
614 break;
615 case 3:
616 if (data_reg == 3) {
617 if (data_reg2 == 4) {
3b6dac34
RH
618 tcg_out_mov (s, TCG_TYPE_I32, 0, 4);
619 tcg_out_mov (s, TCG_TYPE_I32, 4, 3);
620 tcg_out_mov (s, TCG_TYPE_I32, 3, 0);
2662e13f
FB
621 }
622 else {
3b6dac34
RH
623 tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
624 tcg_out_mov (s, TCG_TYPE_I32, 3, 4);
2662e13f
FB
625 }
626 }
627 else {
3b6dac34
RH
628 if (data_reg != 4) tcg_out_mov (s, TCG_TYPE_I32, data_reg, 4);
629 if (data_reg2 != 3) tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
2662e13f
FB
630 }
631 break;
632 }
633 label2_ptr = s->code_ptr;
634 tcg_out32 (s, B);
635
636 /* label1: fast path */
637#ifdef FAST_PATH
638 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
639#endif
640
641 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
642 tcg_out32 (s, (LWZ
643 | RT (r0)
644 | RA (r0)
355b1943 645 | (offsetof (CPUTLBEntry, addend)
2662e13f
FB
646 - offsetof (CPUTLBEntry, addr_read))
647 ));
648 /* r0 = env->tlb_table[mem_index][index].addend */
649 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
650 /* r0 = env->tlb_table[mem_index][index].addend + addr */
651
652#else /* !CONFIG_SOFTMMU */
653 r0 = addr_reg;
f8edcbaa 654 r1 = 3;
f6548c0a 655 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
2662e13f
FB
656#endif
657
658#ifdef TARGET_WORDS_BIGENDIAN
659 bswap = 0;
660#else
661 bswap = 1;
662#endif
f6548c0a 663
2662e13f
FB
664 switch (opc) {
665 default:
666 case 0:
f6548c0a 667 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
2662e13f
FB
668 break;
669 case 0|4:
f6548c0a 670 tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0));
2662e13f
FB
671 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
672 break;
673 case 1:
f6548c0a 674 if (bswap)
675 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
676 else
677 tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0));
2662e13f
FB
678 break;
679 case 1|4:
680 if (bswap) {
f6548c0a 681 tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0));
2662e13f
FB
682 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
683 }
f6548c0a 684 else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0));
2662e13f
FB
685 break;
686 case 2:
f6548c0a 687 if (bswap)
688 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
689 else
690 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0));
2662e13f
FB
691 break;
692 case 3:
693 if (bswap) {
f6548c0a 694 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
695 tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0));
696 tcg_out32 (s, LWBRX | TAB (data_reg2, rbase, r1));
2662e13f
FB
697 }
698 else {
f6548c0a 699#ifdef CONFIG_USE_GUEST_BASE
700 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
701 tcg_out32 (s, LWZX | TAB (data_reg2, rbase, r0));
702 tcg_out32 (s, LWZX | TAB (data_reg, rbase, r1));
703#else
2662e13f
FB
704 if (r0 == data_reg2) {
705 tcg_out32 (s, LWZ | RT (0) | RA (r0));
706 tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
3b6dac34 707 tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 0);
2662e13f
FB
708 }
709 else {
710 tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
711 tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
712 }
f6548c0a 713#endif
2662e13f
FB
714 }
715 break;
716 }
717
718#ifdef CONFIG_SOFTMMU
719 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
720#endif
721}
722
723static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
724{
f6548c0a 725 int addr_reg, r0, r1, data_reg, data_reg2, mem_index, bswap, rbase;
2662e13f
FB
726#ifdef CONFIG_SOFTMMU
727 int r2, ir;
728 void *label1_ptr, *label2_ptr;
729#endif
730#if TARGET_LONG_BITS == 64
731 int addr_reg2;
732#endif
733
734 data_reg = *args++;
735 if (opc == 3)
736 data_reg2 = *args++;
737 else
738 data_reg2 = 0;
739 addr_reg = *args++;
740#if TARGET_LONG_BITS == 64
741 addr_reg2 = *args++;
742#endif
743 mem_index = *args;
744
745#ifdef CONFIG_SOFTMMU
746 r0 = 3;
747 r1 = 4;
748 r2 = 0;
f6548c0a 749 rbase = 0;
2662e13f
FB
750
751 tcg_out32 (s, (RLWINM
752 | RA (r0)
753 | RS (addr_reg)
754 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
755 | MB (32 - (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS))
756 | ME (31 - CPU_TLB_ENTRY_BITS)
757 )
758 );
759 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
760 tcg_out32 (s, (LWZU
761 | RT (r1)
762 | RA (r0)
763 | offsetof (CPUState, tlb_table[mem_index][0].addr_write)
764 )
765 );
766 tcg_out32 (s, (RLWINM
767 | RA (r2)
768 | RS (addr_reg)
769 | SH (0)
770 | MB ((32 - opc) & 31)
771 | ME (31 - TARGET_PAGE_BITS)
772 )
773 );
774
775 tcg_out32 (s, CMP | (7 << 23) | RA (r2) | RB (r1));
776#if TARGET_LONG_BITS == 64
777 tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
778 tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
779 tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
780#endif
781
782 label1_ptr = s->code_ptr;
783#ifdef FAST_PATH
784 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
785#endif
786
787 /* slow path */
788#if TARGET_LONG_BITS == 32
3b6dac34 789 tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg);
2662e13f
FB
790 ir = 4;
791#else
3b6dac34
RH
792 tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg2);
793 tcg_out_mov (s, TCG_TYPE_I32, 4, addr_reg);
f9bf2987 794#ifdef TCG_TARGET_CALL_ALIGN_ARGS
2662e13f 795 ir = 5;
f9bf2987 796#else
797 ir = 4;
798#endif
2662e13f
FB
799#endif
800
801 switch (opc) {
802 case 0:
803 tcg_out32 (s, (RLWINM
804 | RA (ir)
805 | RS (data_reg)
806 | SH (0)
807 | MB (24)
808 | ME (31)));
809 break;
810 case 1:
811 tcg_out32 (s, (RLWINM
812 | RA (ir)
813 | RS (data_reg)
814 | SH (0)
815 | MB (16)
816 | ME (31)));
817 break;
818 case 2:
3b6dac34 819 tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
2662e13f
FB
820 break;
821 case 3:
f9bf2987 822#ifdef TCG_TARGET_CALL_ALIGN_ARGS
823 ir = 5;
824#endif
3b6dac34
RH
825 tcg_out_mov (s, TCG_TYPE_I32, ir++, data_reg2);
826 tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
2662e13f
FB
827 break;
828 }
829 ir++;
830
831 tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
b29fe3ed 832 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
2662e13f
FB
833 label2_ptr = s->code_ptr;
834 tcg_out32 (s, B);
835
836 /* label1: fast path */
837#ifdef FAST_PATH
838 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
839#endif
840
841 tcg_out32 (s, (LWZ
842 | RT (r0)
843 | RA (r0)
355b1943 844 | (offsetof (CPUTLBEntry, addend)
2662e13f
FB
845 - offsetof (CPUTLBEntry, addr_write))
846 ));
847 /* r0 = env->tlb_table[mem_index][index].addend */
848 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
849 /* r0 = env->tlb_table[mem_index][index].addend + addr */
850
851#else /* !CONFIG_SOFTMMU */
2662e13f 852 r0 = addr_reg;
f6548c0a 853 r1 = 3;
a71836de 854 rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
2662e13f
FB
855#endif
856
857#ifdef TARGET_WORDS_BIGENDIAN
858 bswap = 0;
859#else
860 bswap = 1;
861#endif
862 switch (opc) {
863 case 0:
f6548c0a 864 tcg_out32 (s, STBX | SAB (data_reg, rbase, r0));
2662e13f
FB
865 break;
866 case 1:
f6548c0a 867 if (bswap)
868 tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0));
869 else
870 tcg_out32 (s, STHX | SAB (data_reg, rbase, r0));
2662e13f
FB
871 break;
872 case 2:
f6548c0a 873 if (bswap)
874 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
875 else
876 tcg_out32 (s, STWX | SAB (data_reg, rbase, r0));
2662e13f
FB
877 break;
878 case 3:
879 if (bswap) {
880 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
f6548c0a 881 tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0));
882 tcg_out32 (s, STWBRX | SAB (data_reg2, rbase, r1));
2662e13f
FB
883 }
884 else {
f6548c0a 885#ifdef CONFIG_USE_GUEST_BASE
886 tcg_out32 (s, STWX | SAB (data_reg2, rbase, r0));
887 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
888 tcg_out32 (s, STWX | SAB (data_reg, rbase, r1));
889#else
2662e13f
FB
890 tcg_out32 (s, STW | RS (data_reg2) | RA (r0));
891 tcg_out32 (s, STW | RS (data_reg) | RA (r0) | 4);
f6548c0a 892#endif
2662e13f
FB
893 }
894 break;
895 }
896
897#ifdef CONFIG_SOFTMMU
898 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
899#endif
900}
901
e4d58b41 902static void tcg_target_qemu_prologue (TCGContext *s)
2662e13f 903{
0d5bd363 904 int i, frame_size;
2662e13f
FB
905
906 frame_size = 0
f9bf2987 907 + LINKAGE_AREA_SIZE
2662e13f
FB
908 + TCG_STATIC_CALL_ARGS_SIZE
909 + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
f74b32de 910 + CPU_TEMP_BUF_NLONGS * sizeof(long)
2662e13f
FB
911 ;
912 frame_size = (frame_size + 15) & ~15;
913
f74b32de
BS
914 tcg_set_frame(s, TCG_REG_CALL_STACK, frame_size
915 - CPU_TEMP_BUF_NLONGS * sizeof(long),
916 CPU_TEMP_BUF_NLONGS * sizeof(long));
917
6ec85236 918#ifdef _CALL_AIX
b29fe3ed 919 {
920 uint32_t addr;
921
922 /* First emit adhoc function descriptor */
923 addr = (uint32_t) s->code_ptr + 12;
924 tcg_out32 (s, addr); /* entry point */
925 s->code_ptr += 8; /* skip TOC and environment pointer */
926 }
927#endif
2662e13f
FB
928 tcg_out32 (s, MFSPR | RT (0) | LR);
929 tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
930 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
931 tcg_out32 (s, (STW
932 | RS (tcg_target_callee_save_regs[i])
933 | RA (1)
f9bf2987 934 | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
2662e13f
FB
935 )
936 );
2946898b 937 tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + LR_OFFSET));
2662e13f 938
f6548c0a 939#ifdef CONFIG_USE_GUEST_BASE
b9e946c7
RH
940 if (GUEST_BASE) {
941 tcg_out_movi (s, TCG_TYPE_I32, TCG_GUEST_BASE_REG, GUEST_BASE);
942 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
943 }
f6548c0a 944#endif
945
cea5f9a2
BS
946 tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
947 tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
2662e13f
FB
948 tcg_out32 (s, BCCTR | BO_ALWAYS);
949 tb_ret_addr = s->code_ptr;
950
951 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
952 tcg_out32 (s, (LWZ
953 | RT (tcg_target_callee_save_regs[i])
954 | RA (1)
f9bf2987 955 | (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
2662e13f
FB
956 )
957 );
2946898b 958 tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + LR_OFFSET));
2662e13f
FB
959 tcg_out32 (s, MTSPR | RS (0) | LR);
960 tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
961 tcg_out32 (s, BCLR | BO_ALWAYS);
962}
963
964static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
965 tcg_target_long arg2)
966{
967 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
968}
969
970static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
971 tcg_target_long arg2)
972{
973 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
974}
975
976static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
977{
978 if (!si && rt == ra)
979 return;
980
981 if (si == (int16_t) si)
982 tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
983 else {
984 uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
985 tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
986 tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
987 }
988}
989
c596defd 990static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
991 int const_arg2, int cr)
2662e13f 992{
2662e13f
FB
993 int imm;
994 uint32_t op;
995
2662e13f 996 switch (cond) {
f3f478a7
FB
997 case TCG_COND_EQ:
998 case TCG_COND_NE:
999 if (const_arg2) {
1000 if ((int16_t) arg2 == arg2) {
1001 op = CMPI;
1002 imm = 1;
1003 break;
1004 }
1005 else if ((uint16_t) arg2 == arg2) {
1006 op = CMPLI;
1007 imm = 1;
1008 break;
1009 }
1010 }
1011 op = CMPL;
1012 imm = 0;
1013 break;
1014
1015 case TCG_COND_LT:
1016 case TCG_COND_GE:
1017 case TCG_COND_LE:
1018 case TCG_COND_GT:
1019 if (const_arg2) {
1020 if ((int16_t) arg2 == arg2) {
1021 op = CMPI;
1022 imm = 1;
1023 break;
1024 }
1025 }
1026 op = CMP;
1027 imm = 0;
1028 break;
1029
1030 case TCG_COND_LTU:
1031 case TCG_COND_GEU:
1032 case TCG_COND_LEU:
1033 case TCG_COND_GTU:
1034 if (const_arg2) {
1035 if ((uint16_t) arg2 == arg2) {
1036 op = CMPLI;
1037 imm = 1;
1038 break;
1039 }
1040 }
1041 op = CMPL;
1042 imm = 0;
1043 break;
1044
2662e13f
FB
1045 default:
1046 tcg_abort ();
1047 }
c596defd 1048 op |= BF (cr);
2662e13f
FB
1049
1050 if (imm)
1051 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
1052 else {
1053 if (const_arg2) {
1054 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
1055 tcg_out32 (s, op | RA (arg1) | RB (0));
1056 }
1057 else
1058 tcg_out32 (s, op | RA (arg1) | RB (arg2));
1059 }
1060
c596defd 1061}
1062
1063static void tcg_out_bc (TCGContext *s, int bc, int label_index)
1064{
1065 TCGLabel *l = &s->labels[label_index];
1066
0a878c47 1067 if (l->has_value)
c596defd 1068 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
2662e13f 1069 else {
0a878c47 1070 uint16_t val = *(uint16_t *) &s->code_ptr[2];
1071
1072 /* Thanks to Andrzej Zaborowski */
c596defd 1073 tcg_out32 (s, bc | (val & 0xfffc));
2662e13f
FB
1074 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
1075 }
1076}
1077
b0809bf7 1078static void tcg_out_cr7eq_from_cond (TCGContext *s, const TCGArg *args,
1079 const int *const_args)
c596defd 1080{
8a56e840
RH
1081 TCGCond cond = args[4];
1082 int op;
c596defd 1083 struct { int bit1; int bit2; int cond2; } bits[] = {
1084 [TCG_COND_LT ] = { CR_LT, CR_LT, TCG_COND_LT },
1085 [TCG_COND_LE ] = { CR_LT, CR_GT, TCG_COND_LT },
1086 [TCG_COND_GT ] = { CR_GT, CR_GT, TCG_COND_GT },
1087 [TCG_COND_GE ] = { CR_GT, CR_LT, TCG_COND_GT },
1088 [TCG_COND_LTU] = { CR_LT, CR_LT, TCG_COND_LTU },
1089 [TCG_COND_LEU] = { CR_LT, CR_GT, TCG_COND_LTU },
1090 [TCG_COND_GTU] = { CR_GT, CR_GT, TCG_COND_GTU },
1091 [TCG_COND_GEU] = { CR_GT, CR_LT, TCG_COND_GTU },
1092 }, *b = &bits[cond];
1093
1094 switch (cond) {
2662e13f 1095 case TCG_COND_EQ:
2662e13f 1096 case TCG_COND_NE:
e924c485 1097 op = (cond == TCG_COND_EQ) ? CRAND : CRNAND;
1098 tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 6);
1099 tcg_out_cmp (s, cond, args[1], args[3], const_args[3], 7);
1100 tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
2662e13f
FB
1101 break;
1102 case TCG_COND_LT:
2662e13f 1103 case TCG_COND_LE:
2662e13f 1104 case TCG_COND_GT:
2662e13f 1105 case TCG_COND_GE:
2662e13f 1106 case TCG_COND_LTU:
2662e13f 1107 case TCG_COND_LEU:
2662e13f 1108 case TCG_COND_GTU:
2662e13f 1109 case TCG_COND_GEU:
c596defd 1110 op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
1111 tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
efe72c8d 1112 tcg_out_cmp (s, tcg_unsigned_cond (cond), args[0], args[2],
1113 const_args[2], 7);
606257c6 1114 tcg_out32 (s, op | BT (7, CR_EQ) | BA (5, CR_EQ) | BB (7, b->bit2));
c596defd 1115 tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
2662e13f
FB
1116 break;
1117 default:
1118 tcg_abort();
1119 }
b0809bf7 1120}
1121
8a56e840 1122static void tcg_out_setcond (TCGContext *s, TCGCond cond, TCGArg arg0,
b0809bf7 1123 TCGArg arg1, TCGArg arg2, int const_arg2)
1124{
1125 int crop, sh, arg;
1126
1127 switch (cond) {
1128 case TCG_COND_EQ:
1129 if (const_arg2) {
1130 if (!arg2) {
1131 arg = arg1;
1132 }
1133 else {
1134 arg = 0;
1135 if ((uint16_t) arg2 == arg2) {
1136 tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
1137 }
1138 else {
1139 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
1140 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1141 }
1142 }
1143 }
1144 else {
1145 arg = 0;
1146 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1147 }
1148 tcg_out32 (s, CNTLZW | RS (arg) | RA (0));
1149 tcg_out32 (s, (RLWINM
1150 | RA (arg0)
1151 | RS (0)
1152 | SH (27)
1153 | MB (5)
1154 | ME (31)
1155 )
1156 );
27a7797b 1157 break;
b0809bf7 1158
1159 case TCG_COND_NE:
1160 if (const_arg2) {
1161 if (!arg2) {
1162 arg = arg1;
1163 }
1164 else {
1165 arg = 0;
1166 if ((uint16_t) arg2 == arg2) {
1167 tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2);
1168 }
1169 else {
1170 tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
1171 tcg_out32 (s, XOR | SAB (arg1, 0, 0));
1172 }
1173 }
1174 }
1175 else {
1176 arg = 0;
1177 tcg_out32 (s, XOR | SAB (arg1, 0, arg2));
1178 }
1179
1180 if (arg == arg1 && arg1 == arg0) {
1181 tcg_out32 (s, ADDIC | RT (0) | RA (arg) | 0xffff);
1182 tcg_out32 (s, SUBFE | TAB (arg0, 0, arg));
1183 }
1184 else {
1185 tcg_out32 (s, ADDIC | RT (arg0) | RA (arg) | 0xffff);
1186 tcg_out32 (s, SUBFE | TAB (arg0, arg0, arg));
1187 }
27a7797b 1188 break;
1189
1190 case TCG_COND_GT:
1191 case TCG_COND_GTU:
1192 sh = 30;
1193 crop = 0;
1194 goto crtest;
b0809bf7 1195
b0809bf7 1196 case TCG_COND_LT:
27a7797b 1197 case TCG_COND_LTU:
b0809bf7 1198 sh = 29;
1199 crop = 0;
27a7797b 1200 goto crtest;
b0809bf7 1201
b0809bf7 1202 case TCG_COND_GE:
27a7797b 1203 case TCG_COND_GEU:
b0809bf7 1204 sh = 31;
1205 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT);
27a7797b 1206 goto crtest;
b0809bf7 1207
b0809bf7 1208 case TCG_COND_LE:
27a7797b 1209 case TCG_COND_LEU:
b0809bf7 1210 sh = 31;
1211 crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT);
27a7797b 1212 crtest:
1213 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
1214 if (crop) tcg_out32 (s, crop);
1215 tcg_out32 (s, MFCR | RT (0));
1216 tcg_out32 (s, (RLWINM
1217 | RA (arg0)
1218 | RS (0)
1219 | SH (sh)
1220 | MB (31)
1221 | ME (31)
1222 )
1223 );
b0809bf7 1224 break;
1225
1226 default:
1227 tcg_abort ();
1228 }
b0809bf7 1229}
1230
1231static void tcg_out_setcond2 (TCGContext *s, const TCGArg *args,
1232 const int *const_args)
1233{
1234 tcg_out_cr7eq_from_cond (s, args + 1, const_args + 1);
1235 tcg_out32 (s, MFCR | RT (0));
1236 tcg_out32 (s, (RLWINM
1237 | RA (args[0])
1238 | RS (0)
1239 | SH (31)
1240 | MB (31)
1241 | ME (31)
1242 )
1243 );
1244}
1245
8a56e840 1246static void tcg_out_brcond (TCGContext *s, TCGCond cond,
b0809bf7 1247 TCGArg arg1, TCGArg arg2, int const_arg2,
1248 int label_index)
1249{
1250 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
1251 tcg_out_bc (s, tcg_to_bc[cond], label_index);
1252}
1253
1254/* XXX: we implement it at the target level to avoid having to
1255 handle cross basic blocks temporaries */
1256static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
1257 const int *const_args)
1258{
1259 tcg_out_cr7eq_from_cond (s, args, const_args);
1260 tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), args[5]);
2662e13f
FB
1261}
1262
52781543 1263void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr)
1264{
1265 uint32_t *ptr;
1266 long disp = addr - jmp_addr;
1267 unsigned long patch_size;
1268
1269 ptr = (uint32_t *)jmp_addr;
1270
1271 if ((disp << 6) >> 6 != disp) {
1272 ptr[0] = 0x3c000000 | (addr >> 16); /* lis 0,addr@ha */
1273 ptr[1] = 0x60000000 | (addr & 0xffff); /* la 0,addr@l(0) */
1274 ptr[2] = 0x7c0903a6; /* mtctr 0 */
1275 ptr[3] = 0x4e800420; /* brctr */
1276 patch_size = 16;
1277 } else {
1278 /* patch the branch destination */
1279 if (disp != 16) {
1280 *ptr = 0x48000000 | (disp & 0x03fffffc); /* b disp */
1281 patch_size = 4;
1282 } else {
1283 ptr[0] = 0x60000000; /* nop */
1284 ptr[1] = 0x60000000;
1285 ptr[2] = 0x60000000;
1286 ptr[3] = 0x60000000;
1287 patch_size = 16;
1288 }
1289 }
1290 /* flush icache */
1291 flush_icache_range(jmp_addr, jmp_addr + patch_size);
1292}
1293
a9751609 1294static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
2662e13f
FB
1295 const int *const_args)
1296{
1297 switch (opc) {
1298 case INDEX_op_exit_tb:
1299 tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
932a6909 1300 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
2662e13f
FB
1301 break;
1302 case INDEX_op_goto_tb:
1303 if (s->tb_jmp_offset) {
1304 /* direct jump method */
932a6909 1305
2662e13f 1306 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
0a878c47 1307 s->code_ptr += 16;
932a6909
FB
1308 }
1309 else {
2662e13f
FB
1310 tcg_abort ();
1311 }
1312 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1313 break;
1314 case INDEX_op_br:
1315 {
1316 TCGLabel *l = &s->labels[args[0]];
1317
1318 if (l->has_value) {
932a6909 1319 tcg_out_b (s, 0, l->u.value);
2662e13f
FB
1320 }
1321 else {
0a878c47 1322 uint32_t val = *(uint32_t *) s->code_ptr;
1323
1324 /* Thanks to Andrzej Zaborowski */
1325 tcg_out32 (s, B | (val & 0x3fffffc));
2662e13f
FB
1326 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1327 }
1328 }
1329 break;
1330 case INDEX_op_call:
b29fe3ed 1331 tcg_out_call (s, args[0], const_args[0]);
2662e13f
FB
1332 break;
1333 case INDEX_op_jmp:
1334 if (const_args[0]) {
932a6909 1335 tcg_out_b (s, 0, args[0]);
2662e13f
FB
1336 }
1337 else {
1338 tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
1339 tcg_out32 (s, BCCTR | BO_ALWAYS);
1340 }
1341 break;
1342 case INDEX_op_movi_i32:
1343 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1344 break;
1345 case INDEX_op_ld8u_i32:
1346 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1347 break;
1348 case INDEX_op_ld8s_i32:
1349 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1350 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1351 break;
1352 case INDEX_op_ld16u_i32:
1353 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1354 break;
1355 case INDEX_op_ld16s_i32:
1356 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1357 break;
1358 case INDEX_op_ld_i32:
1359 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1360 break;
1361 case INDEX_op_st8_i32:
1362 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1363 break;
1364 case INDEX_op_st16_i32:
1365 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1366 break;
1367 case INDEX_op_st_i32:
1368 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1369 break;
1370
1371 case INDEX_op_add_i32:
1372 if (const_args[2])
1373 ppc_addi (s, args[0], args[1], args[2]);
1374 else
1375 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1376 break;
1377 case INDEX_op_sub_i32:
1378 if (const_args[2])
1379 ppc_addi (s, args[0], args[1], -args[2]);
1380 else
1381 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1382 break;
1383
1384 case INDEX_op_and_i32:
1385 if (const_args[2]) {
c45851c4 1386 uint32_t c;
1387
1388 c = args[2];
1389
1390 if (!c) {
1391 tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
1392 break;
1393 }
1394#ifdef __PPU__
1395 uint32_t t, n;
1396 int mb, me;
1397
1398 n = c ^ -(c & 1);
1399 t = n + (n & -n);
1400
1401 if ((t & (t - 1)) == 0) {
1402 int lzc, tzc;
1403
1404 if ((c & 0x80000001) == 0x80000001) {
1405 lzc = clz32 (n);
1406 tzc = ctz32 (n);
1407
1408 mb = 32 - tzc;
1409 me = lzc - 1;
1410 }
1411 else {
1412 lzc = clz32 (c);
1413 tzc = ctz32 (c);
1414
1415 mb = lzc;
1416 me = 31 - tzc;
1417 }
1418
1419 tcg_out32 (s, (RLWINM
1420 | RA (args[0])
1421 | RS (args[1])
1422 | SH (0)
1423 | MB (mb)
1424 | ME (me)
1425 )
1426 );
1427 }
1428 else
1429#endif /* !__PPU__ */
1430 {
1431 if ((c & 0xffff) == c)
1432 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | c);
1433 else if ((c & 0xffff0000) == c)
1434 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1435 | ((c >> 16) & 0xffff));
1436 else {
1437 tcg_out_movi (s, TCG_TYPE_I32, 0, c);
1438 tcg_out32 (s, AND | SAB (args[1], args[0], 0));
1439 }
2662e13f
FB
1440 }
1441 }
1442 else
1443 tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1444 break;
1445 case INDEX_op_or_i32:
1446 if (const_args[2]) {
000a2d86 1447 if (args[2] & 0xffff) {
1448 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0])
1449 | (args[2] & 0xffff));
1450 if (args[2] >> 16)
1451 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
2662e13f 1452 | ((args[2] >> 16) & 0xffff));
2662e13f
FB
1453 }
1454 else {
000a2d86 1455 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
1456 | ((args[2] >> 16) & 0xffff));
2662e13f
FB
1457 }
1458 }
1459 else
1460 tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1461 break;
1462 case INDEX_op_xor_i32:
1463 if (const_args[2]) {
000a2d86 1464 if ((args[2] & 0xffff) == args[2])
1465 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
1466 | (args[2] & 0xffff));
1467 else if ((args[2] & 0xffff0000) == args[2])
1468 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
1469 | ((args[2] >> 16) & 0xffff));
2662e13f 1470 else {
000a2d86 1471 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1472 tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
2662e13f
FB
1473 }
1474 }
1475 else
1476 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1477 break;
65fe043e 1478 case INDEX_op_andc_i32:
1479 tcg_out32 (s, ANDC | SAB (args[1], args[0], args[2]));
1480 break;
1481 case INDEX_op_orc_i32:
1482 tcg_out32 (s, ORC | SAB (args[1], args[0], args[2]));
1483 break;
aa77bebd 1484 case INDEX_op_eqv_i32:
1485 tcg_out32 (s, EQV | SAB (args[1], args[0], args[2]));
1486 break;
1487 case INDEX_op_nand_i32:
1488 tcg_out32 (s, NAND | SAB (args[1], args[0], args[2]));
1489 break;
1490 case INDEX_op_nor_i32:
1491 tcg_out32 (s, NOR | SAB (args[1], args[0], args[2]));
1492 break;
2662e13f
FB
1493
1494 case INDEX_op_mul_i32:
1495 if (const_args[2]) {
1496 if (args[2] == (int16_t) args[2])
1497 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1498 | (args[2] & 0xffff));
1499 else {
1500 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1501 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1502 }
1503 }
1504 else
1505 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1506 break;
77b73de6 1507
1508 case INDEX_op_div_i32:
1509 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1510 break;
1511
1512 case INDEX_op_divu_i32:
1513 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1514 break;
1515
1516 case INDEX_op_rem_i32:
1517 tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1518 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1519 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1520 break;
1521
1522 case INDEX_op_remu_i32:
1523 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1524 tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1525 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1526 break;
1527
2662e13f
FB
1528 case INDEX_op_mulu2_i32:
1529 if (args[0] == args[2] || args[0] == args[3]) {
1530 tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
1531 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
3b6dac34 1532 tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
2662e13f
FB
1533 }
1534 else {
1535 tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
1536 tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1537 }
1538 break;
2662e13f
FB
1539
1540 case INDEX_op_shl_i32:
1541 if (const_args[2]) {
000a2d86 1542 tcg_out32 (s, (RLWINM
1543 | RA (args[0])
1544 | RS (args[1])
1545 | SH (args[2])
1546 | MB (0)
1547 | ME (31 - args[2])
1548 )
1549 );
2662e13f
FB
1550 }
1551 else
1552 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1553 break;
1554 case INDEX_op_shr_i32:
1555 if (const_args[2]) {
000a2d86 1556 tcg_out32 (s, (RLWINM
1557 | RA (args[0])
1558 | RS (args[1])
1559 | SH (32 - args[2])
1560 | MB (args[2])
1561 | ME (31)
1562 )
1563 );
2662e13f
FB
1564 }
1565 else
1566 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1567 break;
1568 case INDEX_op_sar_i32:
1569 if (const_args[2])
1570 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1571 else
1572 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1573 break;
65fe043e 1574 case INDEX_op_rotl_i32:
1575 {
1576 int op = 0
1577 | RA (args[0])
1578 | RS (args[1])
1579 | MB (0)
1580 | ME (31)
1581 | (const_args[2] ? RLWINM | SH (args[2])
1582 : RLWNM | RB (args[2]))
1583 ;
1584 tcg_out32 (s, op);
1585 }
1586 break;
1587 case INDEX_op_rotr_i32:
1588 if (const_args[2]) {
1589 if (!args[2]) {
3b6dac34 1590 tcg_out_mov (s, TCG_TYPE_I32, args[0], args[1]);
65fe043e 1591 }
1592 else {
1593 tcg_out32 (s, RLWINM
1594 | RA (args[0])
1595 | RS (args[1])
1596 | SH (32 - args[2])
1597 | MB (0)
1598 | ME (31)
1599 );
1600 }
1601 }
1602 else {
d616cf1d 1603 tcg_out32 (s, SUBFIC | RT (0) | RA (args[2]) | 32);
65fe043e 1604 tcg_out32 (s, RLWNM
1605 | RA (args[0])
1606 | RS (args[1])
1607 | RB (0)
1608 | MB (0)
1609 | ME (31)
1610 );
1611 }
1612 break;
2662e13f
FB
1613
1614 case INDEX_op_add2_i32:
1615 if (args[0] == args[3] || args[0] == args[5]) {
1616 tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
1617 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
3b6dac34 1618 tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
2662e13f
FB
1619 }
1620 else {
1621 tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
1622 tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1623 }
1624 break;
1625 case INDEX_op_sub2_i32:
1626 if (args[0] == args[3] || args[0] == args[5]) {
1627 tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
1628 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
3b6dac34 1629 tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
2662e13f
FB
1630 }
1631 else {
1632 tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
1633 tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1634 }
1635 break;
1636
1637 case INDEX_op_brcond_i32:
1638 /*
1639 args[0] = r0
1640 args[1] = r1
1641 args[2] = cond
1642 args[3] = r1 is const
1643 args[4] = label_index
1644 */
1645 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
1646 break;
1647 case INDEX_op_brcond2_i32:
1648 tcg_out_brcond2(s, args, const_args);
1649 break;
1650
1651 case INDEX_op_neg_i32:
1652 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1653 break;
1654
65fe043e 1655 case INDEX_op_not_i32:
36368cf0 1656 tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
65fe043e 1657 break;
1658
2662e13f
FB
1659 case INDEX_op_qemu_ld8u:
1660 tcg_out_qemu_ld(s, args, 0);
1661 break;
1662 case INDEX_op_qemu_ld8s:
1663 tcg_out_qemu_ld(s, args, 0 | 4);
1664 break;
1665 case INDEX_op_qemu_ld16u:
1666 tcg_out_qemu_ld(s, args, 1);
1667 break;
1668 case INDEX_op_qemu_ld16s:
1669 tcg_out_qemu_ld(s, args, 1 | 4);
1670 break;
86feb1c8 1671 case INDEX_op_qemu_ld32:
2662e13f
FB
1672 tcg_out_qemu_ld(s, args, 2);
1673 break;
1674 case INDEX_op_qemu_ld64:
1675 tcg_out_qemu_ld(s, args, 3);
1676 break;
1677 case INDEX_op_qemu_st8:
1678 tcg_out_qemu_st(s, args, 0);
1679 break;
1680 case INDEX_op_qemu_st16:
1681 tcg_out_qemu_st(s, args, 1);
1682 break;
1683 case INDEX_op_qemu_st32:
1684 tcg_out_qemu_st(s, args, 2);
1685 break;
1686 case INDEX_op_qemu_st64:
1687 tcg_out_qemu_st(s, args, 3);
1688 break;
1689
e46b9681 1690 case INDEX_op_ext8s_i32:
1691 tcg_out32 (s, EXTSB | RS (args[1]) | RA (args[0]));
1692 break;
65fe043e 1693 case INDEX_op_ext8u_i32:
1694 tcg_out32 (s, RLWINM
1695 | RA (args[0])
1696 | RS (args[1])
1697 | SH (0)
1698 | MB (24)
1699 | ME (31)
1700 );
1701 break;
e46b9681 1702 case INDEX_op_ext16s_i32:
1703 tcg_out32 (s, EXTSH | RS (args[1]) | RA (args[0]));
1704 break;
65fe043e 1705 case INDEX_op_ext16u_i32:
1706 tcg_out32 (s, RLWINM
1707 | RA (args[0])
1708 | RS (args[1])
1709 | SH (0)
1710 | MB (16)
1711 | ME (31)
1712 );
1713 break;
e46b9681 1714
b0809bf7 1715 case INDEX_op_setcond_i32:
1716 tcg_out_setcond (s, args[3], args[0], args[1], args[2], const_args[2]);
1717 break;
1718 case INDEX_op_setcond2_i32:
1719 tcg_out_setcond2 (s, args, const_args);
1720 break;
1721
a884dcb8 1722 case INDEX_op_bswap16_i32:
1723 /* Stolen from gcc's builtin_bswap16 */
1724
1725 /* a1 = abcd */
1726
1727 /* r0 = (a1 << 8) & 0xff00 # 00d0 */
1728 tcg_out32 (s, RLWINM
1729 | RA (0)
1730 | RS (args[1])
1731 | SH (8)
1732 | MB (16)
1733 | ME (23)
1734 );
1735
1736 /* a0 = rotate_left (a1, 24) & 0xff # 000c */
1737 tcg_out32 (s, RLWINM
1738 | RA (args[0])
1739 | RS (args[1])
1740 | SH (24)
1741 | MB (24)
1742 | ME (31)
1743 );
1744
1745 /* a0 = a0 | r0 # 00dc */
1746 tcg_out32 (s, OR | SAB (0, args[0], args[0]));
1747 break;
1748
1749 case INDEX_op_bswap32_i32:
1750 /* Stolen from gcc's builtin_bswap32 */
1751 {
1752 int a0 = args[0];
1753
1754 /* a1 = args[1] # abcd */
1755
1756 if (a0 == args[1]) {
1757 a0 = 0;
1758 }
1759
1760 /* a0 = rotate_left (a1, 8) # bcda */
1761 tcg_out32 (s, RLWINM
1762 | RA (a0)
1763 | RS (args[1])
1764 | SH (8)
1765 | MB (0)
1766 | ME (31)
1767 );
1768
1769 /* a0 = (a0 & ~0xff000000) | ((a1 << 24) & 0xff000000) # dcda */
1770 tcg_out32 (s, RLWIMI
1771 | RA (a0)
1772 | RS (args[1])
1773 | SH (24)
1774 | MB (0)
1775 | ME (7)
1776 );
1777
1778 /* a0 = (a0 & ~0x0000ff00) | ((a1 << 24) & 0x0000ff00) # dcba */
1779 tcg_out32 (s, RLWIMI
1780 | RA (a0)
1781 | RS (args[1])
1782 | SH (24)
1783 | MB (16)
1784 | ME (23)
1785 );
1786
1787 if (!a0) {
3b6dac34 1788 tcg_out_mov (s, TCG_TYPE_I32, args[0], a0);
a884dcb8 1789 }
1790 }
1791 break;
1792
2662e13f
FB
1793 default:
1794 tcg_dump_ops (s, stderr);
1795 tcg_abort ();
1796 }
1797}
1798
1799static const TCGTargetOpDef ppc_op_defs[] = {
1800 { INDEX_op_exit_tb, { } },
1801 { INDEX_op_goto_tb, { } },
932a6909
FB
1802 { INDEX_op_call, { "ri" } },
1803 { INDEX_op_jmp, { "ri" } },
2662e13f
FB
1804 { INDEX_op_br, { } },
1805
1806 { INDEX_op_mov_i32, { "r", "r" } },
1807 { INDEX_op_movi_i32, { "r" } },
1808 { INDEX_op_ld8u_i32, { "r", "r" } },
1809 { INDEX_op_ld8s_i32, { "r", "r" } },
1810 { INDEX_op_ld16u_i32, { "r", "r" } },
1811 { INDEX_op_ld16s_i32, { "r", "r" } },
1812 { INDEX_op_ld_i32, { "r", "r" } },
1813 { INDEX_op_st8_i32, { "r", "r" } },
1814 { INDEX_op_st16_i32, { "r", "r" } },
1815 { INDEX_op_st_i32, { "r", "r" } },
1816
1817 { INDEX_op_add_i32, { "r", "r", "ri" } },
1818 { INDEX_op_mul_i32, { "r", "r", "ri" } },
77b73de6 1819 { INDEX_op_div_i32, { "r", "r", "r" } },
1820 { INDEX_op_divu_i32, { "r", "r", "r" } },
1821 { INDEX_op_rem_i32, { "r", "r", "r" } },
1822 { INDEX_op_remu_i32, { "r", "r", "r" } },
2662e13f 1823 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
2662e13f
FB
1824 { INDEX_op_sub_i32, { "r", "r", "ri" } },
1825 { INDEX_op_and_i32, { "r", "r", "ri" } },
1826 { INDEX_op_or_i32, { "r", "r", "ri" } },
1827 { INDEX_op_xor_i32, { "r", "r", "ri" } },
1828
1829 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1830 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1831 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1832
65fe043e 1833 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1834 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1835
2662e13f
FB
1836 { INDEX_op_brcond_i32, { "r", "ri" } },
1837
1838 { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1839 { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1840 { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1841
1842 { INDEX_op_neg_i32, { "r", "r" } },
65fe043e 1843 { INDEX_op_not_i32, { "r", "r" } },
1844
1845 { INDEX_op_andc_i32, { "r", "r", "r" } },
1846 { INDEX_op_orc_i32, { "r", "r", "r" } },
aa77bebd 1847 { INDEX_op_eqv_i32, { "r", "r", "r" } },
1848 { INDEX_op_nand_i32, { "r", "r", "r" } },
1849 { INDEX_op_nor_i32, { "r", "r", "r" } },
2662e13f 1850
b0809bf7 1851 { INDEX_op_setcond_i32, { "r", "r", "ri" } },
1852 { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1853
a884dcb8 1854 { INDEX_op_bswap16_i32, { "r", "r" } },
1855 { INDEX_op_bswap32_i32, { "r", "r" } },
1856
2662e13f
FB
1857#if TARGET_LONG_BITS == 32
1858 { INDEX_op_qemu_ld8u, { "r", "L" } },
1859 { INDEX_op_qemu_ld8s, { "r", "L" } },
1860 { INDEX_op_qemu_ld16u, { "r", "L" } },
1861 { INDEX_op_qemu_ld16s, { "r", "L" } },
86feb1c8 1862 { INDEX_op_qemu_ld32, { "r", "L" } },
2662e13f
FB
1863 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1864
1865 { INDEX_op_qemu_st8, { "K", "K" } },
1866 { INDEX_op_qemu_st16, { "K", "K" } },
1867 { INDEX_op_qemu_st32, { "K", "K" } },
1868 { INDEX_op_qemu_st64, { "M", "M", "M" } },
1869#else
1870 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1871 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1872 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1873 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
86feb1c8 1874 { INDEX_op_qemu_ld32, { "r", "L", "L" } },
2662e13f
FB
1875 { INDEX_op_qemu_ld64, { "r", "L", "L", "L" } },
1876
1877 { INDEX_op_qemu_st8, { "K", "K", "K" } },
1878 { INDEX_op_qemu_st16, { "K", "K", "K" } },
1879 { INDEX_op_qemu_st32, { "K", "K", "K" } },
1880 { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
1881#endif
1882
e46b9681 1883 { INDEX_op_ext8s_i32, { "r", "r" } },
65fe043e 1884 { INDEX_op_ext8u_i32, { "r", "r" } },
e46b9681 1885 { INDEX_op_ext16s_i32, { "r", "r" } },
65fe043e 1886 { INDEX_op_ext16u_i32, { "r", "r" } },
e46b9681 1887
2662e13f
FB
1888 { -1 },
1889};
1890
e4d58b41 1891static void tcg_target_init(TCGContext *s)
2662e13f
FB
1892{
1893 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1894 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1895 (1 << TCG_REG_R0) |
6ec85236 1896#ifdef _CALL_DARWIN
f9bf2987 1897 (1 << TCG_REG_R2) |
1898#endif
2662e13f
FB
1899 (1 << TCG_REG_R3) |
1900 (1 << TCG_REG_R4) |
1901 (1 << TCG_REG_R5) |
1902 (1 << TCG_REG_R6) |
1903 (1 << TCG_REG_R7) |
1904 (1 << TCG_REG_R8) |
1905 (1 << TCG_REG_R9) |
1906 (1 << TCG_REG_R10) |
1907 (1 << TCG_REG_R11) |
1908 (1 << TCG_REG_R12)
1909 );
1910
1911 tcg_regset_clear(s->reserved_regs);
1912 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
1913 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
6ec85236 1914#ifndef _CALL_DARWIN
2662e13f 1915 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
f9bf2987 1916#endif
6ec85236 1917#ifdef _CALL_SYSV
5db3ee79 1918 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13);
1919#endif
2662e13f
FB
1920
1921 tcg_add_target_add_op_defs(ppc_op_defs);
1922}