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