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