Statistics
| Branch: | Revision:

root / tcg / ppc / tcg-target.c @ 8c5e95d8

History | View | Annotate | Download (40.9 kB)

1 2662e13f bellard
/*
2 2662e13f bellard
 * Tiny Code Generator for QEMU
3 2662e13f bellard
 *
4 2662e13f bellard
 * Copyright (c) 2008 Fabrice Bellard
5 2662e13f bellard
 *
6 2662e13f bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 2662e13f bellard
 * of this software and associated documentation files (the "Software"), to deal
8 2662e13f bellard
 * in the Software without restriction, including without limitation the rights
9 2662e13f bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 2662e13f bellard
 * copies of the Software, and to permit persons to whom the Software is
11 2662e13f bellard
 * furnished to do so, subject to the following conditions:
12 2662e13f bellard
 *
13 2662e13f bellard
 * The above copyright notice and this permission notice shall be included in
14 2662e13f bellard
 * all copies or substantial portions of the Software.
15 2662e13f bellard
 *
16 2662e13f bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 2662e13f bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 2662e13f bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 2662e13f bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 2662e13f bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 2662e13f bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 2662e13f bellard
 * THE SOFTWARE.
23 2662e13f bellard
 */
24 2662e13f bellard
25 2662e13f bellard
static uint8_t *tb_ret_addr;
26 2662e13f bellard
27 2662e13f bellard
#define FAST_PATH
28 2662e13f bellard
#if TARGET_PHYS_ADDR_BITS <= 32
29 2662e13f bellard
#define ADDEND_OFFSET 0
30 2662e13f bellard
#else
31 2662e13f bellard
#define ADDEND_OFFSET 4
32 2662e13f bellard
#endif
33 2662e13f bellard
34 2662e13f bellard
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35 2662e13f bellard
    "r0",
36 2662e13f bellard
    "r1",
37 2662e13f bellard
    "rp",
38 2662e13f bellard
    "r3",
39 2662e13f bellard
    "r4",
40 2662e13f bellard
    "r5",
41 2662e13f bellard
    "r6",
42 2662e13f bellard
    "r7",
43 2662e13f bellard
    "r8",
44 2662e13f bellard
    "r9",
45 2662e13f bellard
    "r10",
46 2662e13f bellard
    "r11",
47 2662e13f bellard
    "r12",
48 2662e13f bellard
    "r13",
49 2662e13f bellard
    "r14",
50 2662e13f bellard
    "r15",
51 2662e13f bellard
    "r16",
52 2662e13f bellard
    "r17",
53 2662e13f bellard
    "r18",
54 2662e13f bellard
    "r19",
55 2662e13f bellard
    "r20",
56 2662e13f bellard
    "r21",
57 2662e13f bellard
    "r22",
58 2662e13f bellard
    "r23",
59 2662e13f bellard
    "r24",
60 2662e13f bellard
    "r25",
61 2662e13f bellard
    "r26",
62 2662e13f bellard
    "r27",
63 2662e13f bellard
    "r28",
64 2662e13f bellard
    "r29",
65 2662e13f bellard
    "r30",
66 2662e13f bellard
    "r31"
67 2662e13f bellard
};
68 2662e13f bellard
69 2662e13f bellard
static const int tcg_target_reg_alloc_order[] = {
70 a35e86c5 malc
    TCG_REG_R14,
71 a35e86c5 malc
    TCG_REG_R15,
72 a35e86c5 malc
    TCG_REG_R16,
73 a35e86c5 malc
    TCG_REG_R17,
74 a35e86c5 malc
    TCG_REG_R18,
75 a35e86c5 malc
    TCG_REG_R19,
76 a35e86c5 malc
    TCG_REG_R20,
77 a35e86c5 malc
    TCG_REG_R21,
78 a35e86c5 malc
    TCG_REG_R22,
79 a35e86c5 malc
    TCG_REG_R23,
80 a35e86c5 malc
    TCG_REG_R28,
81 a35e86c5 malc
    TCG_REG_R29,
82 a35e86c5 malc
    TCG_REG_R30,
83 a35e86c5 malc
    TCG_REG_R31,
84 2662e13f bellard
    TCG_REG_R3,
85 2662e13f bellard
    TCG_REG_R4,
86 2662e13f bellard
    TCG_REG_R5,
87 2662e13f bellard
    TCG_REG_R6,
88 2662e13f bellard
    TCG_REG_R7,
89 2662e13f bellard
    TCG_REG_R8,
90 2662e13f bellard
    TCG_REG_R9,
91 2662e13f bellard
    TCG_REG_R10,
92 2662e13f bellard
    TCG_REG_R11,
93 2662e13f bellard
    TCG_REG_R12,
94 2662e13f bellard
    TCG_REG_R13,
95 a35e86c5 malc
    TCG_REG_R0,
96 a35e86c5 malc
    TCG_REG_R1,
97 a35e86c5 malc
    TCG_REG_R2,
98 2662e13f bellard
    TCG_REG_R24,
99 2662e13f bellard
    TCG_REG_R25,
100 2662e13f bellard
    TCG_REG_R26,
101 a35e86c5 malc
    TCG_REG_R27
102 2662e13f bellard
};
103 2662e13f bellard
104 2662e13f bellard
static const int tcg_target_call_iarg_regs[] = {
105 2662e13f bellard
    TCG_REG_R3,
106 2662e13f bellard
    TCG_REG_R4,
107 2662e13f bellard
    TCG_REG_R5,
108 2662e13f bellard
    TCG_REG_R6,
109 2662e13f bellard
    TCG_REG_R7,
110 2662e13f bellard
    TCG_REG_R8,
111 2662e13f bellard
    TCG_REG_R9,
112 2662e13f bellard
    TCG_REG_R10
113 2662e13f bellard
};
114 2662e13f bellard
115 2662e13f bellard
static const int tcg_target_call_oarg_regs[2] = {
116 2662e13f bellard
    TCG_REG_R3,
117 2662e13f bellard
    TCG_REG_R4
118 2662e13f bellard
};
119 2662e13f bellard
120 2662e13f bellard
static const int tcg_target_callee_save_regs[] = {
121 2662e13f bellard
    TCG_REG_R14,
122 2662e13f bellard
    TCG_REG_R15,
123 2662e13f bellard
    TCG_REG_R16,
124 2662e13f bellard
    TCG_REG_R17,
125 2662e13f bellard
    TCG_REG_R18,
126 2662e13f bellard
    TCG_REG_R19,
127 2662e13f bellard
    TCG_REG_R20,
128 2662e13f bellard
    TCG_REG_R21,
129 2662e13f bellard
    TCG_REG_R22,
130 2662e13f bellard
    TCG_REG_R23,
131 2662e13f bellard
    TCG_REG_R28,
132 2662e13f bellard
    TCG_REG_R29,
133 2662e13f bellard
    TCG_REG_R30,
134 2662e13f bellard
    TCG_REG_R31
135 2662e13f bellard
};
136 2662e13f bellard
137 2662e13f bellard
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
138 2662e13f bellard
{
139 932a6909 bellard
    tcg_target_long disp;
140 932a6909 bellard
141 932a6909 bellard
    disp = target - (tcg_target_long) pc;
142 932a6909 bellard
    if ((disp << 6) >> 6 != disp)
143 932a6909 bellard
        tcg_abort ();
144 932a6909 bellard
145 932a6909 bellard
    return disp & 0x3fffffc;
146 2662e13f bellard
}
147 2662e13f bellard
148 2662e13f bellard
static void reloc_pc24 (void *pc, tcg_target_long target)
149 2662e13f bellard
{
150 2662e13f bellard
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
151 2662e13f bellard
        | reloc_pc24_val (pc, target);
152 2662e13f bellard
}
153 2662e13f bellard
154 2662e13f bellard
static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
155 2662e13f bellard
{
156 932a6909 bellard
    tcg_target_long disp;
157 932a6909 bellard
158 932a6909 bellard
    disp = target - (tcg_target_long) pc;
159 932a6909 bellard
    if (disp != (int16_t) disp)
160 932a6909 bellard
        tcg_abort ();
161 932a6909 bellard
162 932a6909 bellard
    return disp & 0xfffc;
163 2662e13f bellard
}
164 2662e13f bellard
165 2662e13f bellard
static void reloc_pc14 (void *pc, tcg_target_long target)
166 2662e13f bellard
{
167 2662e13f bellard
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
168 2662e13f bellard
        | reloc_pc14_val (pc, target);
169 2662e13f bellard
}
170 2662e13f bellard
171 2662e13f bellard
static void patch_reloc(uint8_t *code_ptr, int type,
172 2662e13f bellard
                        tcg_target_long value, tcg_target_long addend)
173 2662e13f bellard
{
174 2662e13f bellard
    value += addend;
175 2662e13f bellard
    switch (type) {
176 2662e13f bellard
    case R_PPC_REL14:
177 2662e13f bellard
        reloc_pc14 (code_ptr, value);
178 2662e13f bellard
        break;
179 2662e13f bellard
    case R_PPC_REL24:
180 2662e13f bellard
        reloc_pc24 (code_ptr, value);
181 2662e13f bellard
        break;
182 2662e13f bellard
    default:
183 2662e13f bellard
        tcg_abort();
184 2662e13f bellard
    }
185 2662e13f bellard
}
186 2662e13f bellard
187 2662e13f bellard
/* maximum number of register used for input function arguments */
188 2662e13f bellard
static int tcg_target_get_call_iarg_regs_count(int flags)
189 2662e13f bellard
{
190 2662e13f bellard
    return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]);
191 2662e13f bellard
}
192 2662e13f bellard
193 2662e13f bellard
/* parse target specific constraints */
194 2662e13f bellard
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
195 2662e13f bellard
{
196 2662e13f bellard
    const char *ct_str;
197 2662e13f bellard
198 2662e13f bellard
    ct_str = *pct_str;
199 2662e13f bellard
    switch (ct_str[0]) {
200 398ce98e malc
    case 'A': case 'B': case 'C': case 'D':
201 398ce98e malc
        ct->ct |= TCG_CT_REG;
202 398ce98e malc
        tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
203 398ce98e malc
        break;
204 2662e13f bellard
    case 'r':
205 2662e13f bellard
        ct->ct |= TCG_CT_REG;
206 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
207 2662e13f bellard
        break;
208 2662e13f bellard
    case 'L':                   /* qemu_ld constraint */
209 2662e13f bellard
        ct->ct |= TCG_CT_REG;
210 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
211 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
212 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
213 2662e13f bellard
        break;
214 2662e13f bellard
    case 'K':                   /* qemu_st[8..32] constraint */
215 2662e13f bellard
        ct->ct |= TCG_CT_REG;
216 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
217 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
218 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
219 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
220 2662e13f bellard
#if TARGET_LONG_BITS == 64
221 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
222 2662e13f bellard
#endif
223 2662e13f bellard
        break;
224 2662e13f bellard
    case 'M':                   /* qemu_st64 constraint */
225 2662e13f bellard
        ct->ct |= TCG_CT_REG;
226 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
227 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
228 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
229 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
230 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
231 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
232 2662e13f bellard
        break;
233 2662e13f bellard
    default:
234 2662e13f bellard
        return -1;
235 2662e13f bellard
    }
236 2662e13f bellard
    ct_str++;
237 2662e13f bellard
    *pct_str = ct_str;
238 2662e13f bellard
    return 0;
239 2662e13f bellard
}
240 2662e13f bellard
241 2662e13f bellard
/* test if a constant matches the constraint */
242 2662e13f bellard
static int tcg_target_const_match(tcg_target_long val,
243 2662e13f bellard
                                  const TCGArgConstraint *arg_ct)
244 2662e13f bellard
{
245 2662e13f bellard
    int ct;
246 2662e13f bellard
247 2662e13f bellard
    ct = arg_ct->ct;
248 2662e13f bellard
    if (ct & TCG_CT_CONST)
249 2662e13f bellard
        return 1;
250 2662e13f bellard
    return 0;
251 2662e13f bellard
}
252 2662e13f bellard
253 2662e13f bellard
#define OPCD(opc) ((opc)<<26)
254 2662e13f bellard
#define XO31(opc) (OPCD(31)|((opc)<<1))
255 2662e13f bellard
#define XO19(opc) (OPCD(19)|((opc)<<1))
256 2662e13f bellard
257 2662e13f bellard
#define B      OPCD(18)
258 2662e13f bellard
#define BC     OPCD(16)
259 2662e13f bellard
#define LBZ    OPCD(34)
260 2662e13f bellard
#define LHZ    OPCD(40)
261 2662e13f bellard
#define LHA    OPCD(42)
262 2662e13f bellard
#define LWZ    OPCD(32)
263 2662e13f bellard
#define STB    OPCD(38)
264 2662e13f bellard
#define STH    OPCD(44)
265 2662e13f bellard
#define STW    OPCD(36)
266 2662e13f bellard
267 2662e13f bellard
#define ADDI   OPCD(14)
268 2662e13f bellard
#define ADDIS  OPCD(15)
269 2662e13f bellard
#define ORI    OPCD(24)
270 2662e13f bellard
#define ORIS   OPCD(25)
271 2662e13f bellard
#define XORI   OPCD(26)
272 2662e13f bellard
#define XORIS  OPCD(27)
273 2662e13f bellard
#define ANDI   OPCD(28)
274 2662e13f bellard
#define ANDIS  OPCD(29)
275 2662e13f bellard
#define MULLI  OPCD( 7)
276 2662e13f bellard
#define CMPLI  OPCD(10)
277 2662e13f bellard
#define CMPI   OPCD(11)
278 2662e13f bellard
279 2662e13f bellard
#define LWZU   OPCD(33)
280 2662e13f bellard
#define STWU   OPCD(37)
281 2662e13f bellard
282 2662e13f bellard
#define RLWINM OPCD(21)
283 2662e13f bellard
284 c596defd malc
#define BCLR   XO19( 16)
285 2662e13f bellard
#define BCCTR  XO19(528)
286 2662e13f bellard
#define CRAND  XO19(257)
287 c596defd malc
#define CRANDC XO19(129)
288 c596defd malc
#define CRNAND XO19(225)
289 c596defd malc
#define CROR   XO19(449)
290 2662e13f bellard
291 2662e13f bellard
#define EXTSB  XO31(954)
292 2662e13f bellard
#define EXTSH  XO31(922)
293 2662e13f bellard
#define ADD    XO31(266)
294 2662e13f bellard
#define ADDE   XO31(138)
295 2662e13f bellard
#define ADDC   XO31( 10)
296 2662e13f bellard
#define AND    XO31( 28)
297 2662e13f bellard
#define SUBF   XO31( 40)
298 2662e13f bellard
#define SUBFC  XO31(  8)
299 2662e13f bellard
#define SUBFE  XO31(136)
300 2662e13f bellard
#define OR     XO31(444)
301 2662e13f bellard
#define XOR    XO31(316)
302 2662e13f bellard
#define MULLW  XO31(235)
303 2662e13f bellard
#define MULHWU XO31( 11)
304 2662e13f bellard
#define DIVW   XO31(491)
305 2662e13f bellard
#define DIVWU  XO31(459)
306 2662e13f bellard
#define CMP    XO31(  0)
307 2662e13f bellard
#define CMPL   XO31( 32)
308 2662e13f bellard
#define LHBRX  XO31(790)
309 2662e13f bellard
#define LWBRX  XO31(534)
310 2662e13f bellard
#define STHBRX XO31(918)
311 2662e13f bellard
#define STWBRX XO31(662)
312 2662e13f bellard
#define MFSPR  XO31(339)
313 2662e13f bellard
#define MTSPR  XO31(467)
314 2662e13f bellard
#define SRAWI  XO31(824)
315 2662e13f bellard
#define NEG    XO31(104)
316 2662e13f bellard
317 2662e13f bellard
#define LBZX   XO31( 87)
318 2662e13f bellard
#define LHZX   XO31(276)
319 2662e13f bellard
#define LHAX   XO31(343)
320 2662e13f bellard
#define LWZX   XO31( 23)
321 2662e13f bellard
#define STBX   XO31(215)
322 2662e13f bellard
#define STHX   XO31(407)
323 2662e13f bellard
#define STWX   XO31(151)
324 2662e13f bellard
325 2662e13f bellard
#define SPR(a,b) ((((a)<<5)|(b))<<11)
326 2662e13f bellard
#define LR     SPR(8, 0)
327 2662e13f bellard
#define CTR    SPR(9, 0)
328 2662e13f bellard
329 2662e13f bellard
#define SLW    XO31( 24)
330 2662e13f bellard
#define SRW    XO31(536)
331 2662e13f bellard
#define SRAW   XO31(792)
332 2662e13f bellard
333 2662e13f bellard
#define LMW    OPCD(46)
334 2662e13f bellard
#define STMW   OPCD(47)
335 2662e13f bellard
336 2662e13f bellard
#define TW     XO31(4)
337 2662e13f bellard
#define TRAP   (TW | TO (31))
338 2662e13f bellard
339 2662e13f bellard
#define RT(r) ((r)<<21)
340 2662e13f bellard
#define RS(r) ((r)<<21)
341 2662e13f bellard
#define RA(r) ((r)<<16)
342 2662e13f bellard
#define RB(r) ((r)<<11)
343 2662e13f bellard
#define TO(t) ((t)<<21)
344 2662e13f bellard
#define SH(s) ((s)<<11)
345 2662e13f bellard
#define MB(b) ((b)<<6)
346 2662e13f bellard
#define ME(e) ((e)<<1)
347 2662e13f bellard
#define BO(o) ((o)<<21)
348 2662e13f bellard
349 2662e13f bellard
#define LK    1
350 2662e13f bellard
351 2662e13f bellard
#define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
352 2662e13f bellard
#define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
353 2662e13f bellard
354 2662e13f bellard
#define BF(n)    ((n)<<23)
355 2662e13f bellard
#define BI(n, c) (((c)+((n)*4))<<16)
356 2662e13f bellard
#define BT(n, c) (((c)+((n)*4))<<21)
357 2662e13f bellard
#define BA(n, c) (((c)+((n)*4))<<16)
358 2662e13f bellard
#define BB(n, c) (((c)+((n)*4))<<11)
359 2662e13f bellard
360 2662e13f bellard
#define BO_COND_TRUE  BO (12)
361 2662e13f bellard
#define BO_COND_FALSE BO (4)
362 2662e13f bellard
#define BO_ALWAYS     BO (20)
363 2662e13f bellard
364 2662e13f bellard
enum {
365 2662e13f bellard
    CR_LT,
366 2662e13f bellard
    CR_GT,
367 2662e13f bellard
    CR_EQ,
368 2662e13f bellard
    CR_SO
369 2662e13f bellard
};
370 2662e13f bellard
371 2662e13f bellard
static const uint32_t tcg_to_bc[10] = {
372 2662e13f bellard
    [TCG_COND_EQ]  = BC | BI (7, CR_EQ) | BO_COND_TRUE,
373 2662e13f bellard
    [TCG_COND_NE]  = BC | BI (7, CR_EQ) | BO_COND_FALSE,
374 2662e13f bellard
    [TCG_COND_LT]  = BC | BI (7, CR_LT) | BO_COND_TRUE,
375 2662e13f bellard
    [TCG_COND_GE]  = BC | BI (7, CR_LT) | BO_COND_FALSE,
376 2662e13f bellard
    [TCG_COND_LE]  = BC | BI (7, CR_GT) | BO_COND_FALSE,
377 2662e13f bellard
    [TCG_COND_GT]  = BC | BI (7, CR_GT) | BO_COND_TRUE,
378 2662e13f bellard
    [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
379 2662e13f bellard
    [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
380 2662e13f bellard
    [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
381 2662e13f bellard
    [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
382 2662e13f bellard
};
383 2662e13f bellard
384 2662e13f bellard
static void tcg_out_mov(TCGContext *s, int ret, int arg)
385 2662e13f bellard
{
386 2662e13f bellard
    tcg_out32 (s, OR | SAB (arg, ret, arg));
387 2662e13f bellard
}
388 2662e13f bellard
389 2662e13f bellard
static void tcg_out_movi(TCGContext *s, TCGType type,
390 2662e13f bellard
                         int ret, tcg_target_long arg)
391 2662e13f bellard
{
392 2662e13f bellard
    if (arg == (int16_t) arg)
393 2662e13f bellard
        tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
394 2662e13f bellard
    else {
395 2662e13f bellard
        tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
396 2662e13f bellard
        if (arg & 0xffff)
397 0a878c47 malc
            tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
398 2662e13f bellard
    }
399 2662e13f bellard
}
400 2662e13f bellard
401 2662e13f bellard
static void tcg_out_ldst (TCGContext *s, int ret, int addr,
402 2662e13f bellard
                          int offset, int op1, int op2)
403 2662e13f bellard
{
404 2662e13f bellard
    if (offset == (int16_t) offset)
405 2662e13f bellard
        tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
406 2662e13f bellard
    else {
407 2662e13f bellard
        tcg_out_movi (s, TCG_TYPE_I32, 0, offset);
408 2662e13f bellard
        tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
409 2662e13f bellard
    }
410 2662e13f bellard
}
411 2662e13f bellard
412 932a6909 bellard
static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
413 932a6909 bellard
{
414 932a6909 bellard
    tcg_target_long disp;
415 932a6909 bellard
416 932a6909 bellard
    disp = target - (tcg_target_long) s->code_ptr;
417 932a6909 bellard
    if ((disp << 6) >> 6 == disp)
418 8c5e95d8 malc
        tcg_out32 (s, B | (disp & 0x3fffffc) | mask);
419 932a6909 bellard
    else {
420 932a6909 bellard
        tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target);
421 932a6909 bellard
        tcg_out32 (s, MTSPR | RS (0) | CTR);
422 932a6909 bellard
        tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
423 932a6909 bellard
    }
424 932a6909 bellard
}
425 932a6909 bellard
426 2662e13f bellard
#if defined(CONFIG_SOFTMMU)
427 2662e13f bellard
extern void __ldb_mmu(void);
428 2662e13f bellard
extern void __ldw_mmu(void);
429 2662e13f bellard
extern void __ldl_mmu(void);
430 2662e13f bellard
extern void __ldq_mmu(void);
431 2662e13f bellard
432 2662e13f bellard
extern void __stb_mmu(void);
433 2662e13f bellard
extern void __stw_mmu(void);
434 2662e13f bellard
extern void __stl_mmu(void);
435 2662e13f bellard
extern void __stq_mmu(void);
436 2662e13f bellard
437 2662e13f bellard
static void *qemu_ld_helpers[4] = {
438 2662e13f bellard
    __ldb_mmu,
439 2662e13f bellard
    __ldw_mmu,
440 2662e13f bellard
    __ldl_mmu,
441 2662e13f bellard
    __ldq_mmu,
442 2662e13f bellard
};
443 2662e13f bellard
444 2662e13f bellard
static void *qemu_st_helpers[4] = {
445 2662e13f bellard
    __stb_mmu,
446 2662e13f bellard
    __stw_mmu,
447 2662e13f bellard
    __stl_mmu,
448 2662e13f bellard
    __stq_mmu,
449 2662e13f bellard
};
450 2662e13f bellard
#endif
451 2662e13f bellard
452 2662e13f bellard
static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
453 2662e13f bellard
{
454 2662e13f bellard
    int addr_reg, data_reg, data_reg2, r0, mem_index, s_bits, bswap;
455 2662e13f bellard
#ifdef CONFIG_SOFTMMU
456 2662e13f bellard
    int r1, r2;
457 2662e13f bellard
    void *label1_ptr, *label2_ptr;
458 2662e13f bellard
#endif
459 2662e13f bellard
#if TARGET_LONG_BITS == 64
460 2662e13f bellard
    int addr_reg2;
461 2662e13f bellard
#endif
462 2662e13f bellard
463 2662e13f bellard
    data_reg = *args++;
464 2662e13f bellard
    if (opc == 3)
465 2662e13f bellard
        data_reg2 = *args++;
466 2662e13f bellard
    else
467 2662e13f bellard
        data_reg2 = 0;
468 2662e13f bellard
    addr_reg = *args++;
469 2662e13f bellard
#if TARGET_LONG_BITS == 64
470 2662e13f bellard
    addr_reg2 = *args++;
471 2662e13f bellard
#endif
472 2662e13f bellard
    mem_index = *args;
473 2662e13f bellard
    s_bits = opc & 3;
474 2662e13f bellard
475 2662e13f bellard
#ifdef CONFIG_SOFTMMU
476 2662e13f bellard
    r0 = 3;
477 2662e13f bellard
    r1 = 4;
478 2662e13f bellard
    r2 = 0;
479 2662e13f bellard
480 2662e13f bellard
    tcg_out32 (s, (RLWINM
481 2662e13f bellard
                   | RA (r0)
482 2662e13f bellard
                   | RS (addr_reg)
483 2662e13f bellard
                   | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
484 2662e13f bellard
                   | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
485 2662e13f bellard
                   | ME (31 - CPU_TLB_ENTRY_BITS)
486 2662e13f bellard
                   )
487 2662e13f bellard
        );
488 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
489 2662e13f bellard
    tcg_out32 (s, (LWZU
490 2662e13f bellard
                   | RT (r1)
491 2662e13f bellard
                   | RA (r0)
492 2662e13f bellard
                   | offsetof (CPUState, tlb_table[mem_index][0].addr_read)
493 2662e13f bellard
                   )
494 2662e13f bellard
        );
495 2662e13f bellard
    tcg_out32 (s, (RLWINM
496 2662e13f bellard
                   | RA (r2)
497 2662e13f bellard
                   | RS (addr_reg)
498 2662e13f bellard
                   | SH (0)
499 2662e13f bellard
                   | MB ((32 - s_bits) & 31)
500 2662e13f bellard
                   | ME (31 - TARGET_PAGE_BITS)
501 2662e13f bellard
                   )
502 2662e13f bellard
        );
503 2662e13f bellard
504 2662e13f bellard
    tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
505 2662e13f bellard
#if TARGET_LONG_BITS == 64
506 2662e13f bellard
    tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
507 2662e13f bellard
    tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
508 2662e13f bellard
    tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
509 2662e13f bellard
#endif
510 2662e13f bellard
511 2662e13f bellard
    label1_ptr = s->code_ptr;
512 2662e13f bellard
#ifdef FAST_PATH
513 2662e13f bellard
    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
514 2662e13f bellard
#endif
515 2662e13f bellard
516 2662e13f bellard
    /* slow path */
517 2662e13f bellard
#if TARGET_LONG_BITS == 32
518 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg);
519 2662e13f bellard
    tcg_out_movi (s, TCG_TYPE_I32, 4, mem_index);
520 2662e13f bellard
#else
521 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg2);
522 2662e13f bellard
    tcg_out_mov (s, 4, addr_reg);
523 2662e13f bellard
    tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
524 2662e13f bellard
#endif
525 2662e13f bellard
526 932a6909 bellard
    tcg_out_b (s, LK, (tcg_target_long) qemu_ld_helpers[s_bits]);
527 2662e13f bellard
    switch (opc) {
528 2662e13f bellard
    case 0|4:
529 2662e13f bellard
        tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
530 2662e13f bellard
        break;
531 2662e13f bellard
    case 1|4:
532 2662e13f bellard
        tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
533 2662e13f bellard
        break;
534 2662e13f bellard
    case 0:
535 2662e13f bellard
    case 1:
536 2662e13f bellard
    case 2:
537 2662e13f bellard
        if (data_reg != 3)
538 2662e13f bellard
            tcg_out_mov (s, data_reg, 3);
539 2662e13f bellard
        break;
540 2662e13f bellard
    case 3:
541 2662e13f bellard
        if (data_reg == 3) {
542 2662e13f bellard
            if (data_reg2 == 4) {
543 2662e13f bellard
                tcg_out_mov (s, 0, 4);
544 2662e13f bellard
                tcg_out_mov (s, 4, 3);
545 2662e13f bellard
                tcg_out_mov (s, 3, 0);
546 2662e13f bellard
            }
547 2662e13f bellard
            else {
548 2662e13f bellard
                tcg_out_mov (s, data_reg2, 3);
549 2662e13f bellard
                tcg_out_mov (s, 3, 4);
550 2662e13f bellard
            }
551 2662e13f bellard
        }
552 2662e13f bellard
        else {
553 2662e13f bellard
            if (data_reg != 4) tcg_out_mov (s, data_reg, 4);
554 2662e13f bellard
            if (data_reg2 != 3) tcg_out_mov (s, data_reg2, 3);
555 2662e13f bellard
        }
556 2662e13f bellard
        break;
557 2662e13f bellard
    }
558 2662e13f bellard
    label2_ptr = s->code_ptr;
559 2662e13f bellard
    tcg_out32 (s, B);
560 2662e13f bellard
561 2662e13f bellard
    /* label1: fast path */
562 2662e13f bellard
#ifdef FAST_PATH
563 2662e13f bellard
    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
564 2662e13f bellard
#endif
565 2662e13f bellard
566 2662e13f bellard
    /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
567 2662e13f bellard
    tcg_out32 (s, (LWZ
568 2662e13f bellard
                   | RT (r0)
569 2662e13f bellard
                   | RA (r0)
570 2662e13f bellard
                   | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
571 2662e13f bellard
                      - offsetof (CPUTLBEntry, addr_read))
572 2662e13f bellard
                   ));
573 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend */
574 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
575 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend + addr */
576 2662e13f bellard
577 2662e13f bellard
#else  /* !CONFIG_SOFTMMU */
578 2662e13f bellard
    r0 = addr_reg;
579 2662e13f bellard
#endif
580 2662e13f bellard
581 2662e13f bellard
#ifdef TARGET_WORDS_BIGENDIAN
582 2662e13f bellard
    bswap = 0;
583 2662e13f bellard
#else
584 2662e13f bellard
    bswap = 1;
585 2662e13f bellard
#endif
586 2662e13f bellard
    switch (opc) {
587 2662e13f bellard
    default:
588 2662e13f bellard
    case 0:
589 2662e13f bellard
        tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
590 2662e13f bellard
        break;
591 2662e13f bellard
    case 0|4:
592 2662e13f bellard
        tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
593 2662e13f bellard
        tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
594 2662e13f bellard
        break;
595 2662e13f bellard
    case 1:
596 2662e13f bellard
        if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
597 2662e13f bellard
        else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0));
598 2662e13f bellard
        break;
599 2662e13f bellard
    case 1|4:
600 2662e13f bellard
        if (bswap) {
601 2662e13f bellard
            tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
602 2662e13f bellard
            tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
603 2662e13f bellard
        }
604 2662e13f bellard
        else tcg_out32 (s, LHA | RT (data_reg) | RA (r0));
605 2662e13f bellard
        break;
606 2662e13f bellard
    case 2:
607 2662e13f bellard
        if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
608 2662e13f bellard
        else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0));
609 2662e13f bellard
        break;
610 2662e13f bellard
    case 3:
611 2662e13f bellard
        if (bswap) {
612 2662e13f bellard
            if (r0 == data_reg) {
613 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (0) | RB (r0));
614 2662e13f bellard
                tcg_out32 (s, ADDI | RT (r0) | RA (r0) |  4);
615 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
616 2662e13f bellard
                tcg_out_mov (s, data_reg, 0);
617 2662e13f bellard
            }
618 2662e13f bellard
            else {
619 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
620 2662e13f bellard
                tcg_out32 (s, ADDI | RT (r0) | RA (r0) |  4);
621 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
622 2662e13f bellard
            }
623 2662e13f bellard
        }
624 2662e13f bellard
        else {
625 2662e13f bellard
            if (r0 == data_reg2) {
626 2662e13f bellard
                tcg_out32 (s, LWZ | RT (0) | RA (r0));
627 2662e13f bellard
                tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
628 2662e13f bellard
                tcg_out_mov (s, data_reg2, 0);
629 2662e13f bellard
            }
630 2662e13f bellard
            else {
631 2662e13f bellard
                tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
632 2662e13f bellard
                tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
633 2662e13f bellard
            }
634 2662e13f bellard
        }
635 2662e13f bellard
        break;
636 2662e13f bellard
    }
637 2662e13f bellard
638 2662e13f bellard
#ifdef CONFIG_SOFTMMU
639 2662e13f bellard
    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
640 2662e13f bellard
#endif
641 2662e13f bellard
}
642 2662e13f bellard
643 2662e13f bellard
static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
644 2662e13f bellard
{
645 2662e13f bellard
    int addr_reg, r0, r1, data_reg, data_reg2, mem_index, bswap;
646 2662e13f bellard
#ifdef CONFIG_SOFTMMU
647 2662e13f bellard
    int r2, ir;
648 2662e13f bellard
    void *label1_ptr, *label2_ptr;
649 2662e13f bellard
#endif
650 2662e13f bellard
#if TARGET_LONG_BITS == 64
651 2662e13f bellard
    int addr_reg2;
652 2662e13f bellard
#endif
653 2662e13f bellard
654 2662e13f bellard
    data_reg = *args++;
655 2662e13f bellard
    if (opc == 3)
656 2662e13f bellard
        data_reg2 = *args++;
657 2662e13f bellard
    else
658 2662e13f bellard
        data_reg2 = 0;
659 2662e13f bellard
    addr_reg = *args++;
660 2662e13f bellard
#if TARGET_LONG_BITS == 64
661 2662e13f bellard
    addr_reg2 = *args++;
662 2662e13f bellard
#endif
663 2662e13f bellard
    mem_index = *args;
664 2662e13f bellard
665 2662e13f bellard
#ifdef CONFIG_SOFTMMU
666 2662e13f bellard
    r0 = 3;
667 2662e13f bellard
    r1 = 4;
668 2662e13f bellard
    r2 = 0;
669 2662e13f bellard
670 2662e13f bellard
    tcg_out32 (s, (RLWINM
671 2662e13f bellard
                   | RA (r0)
672 2662e13f bellard
                   | RS (addr_reg)
673 2662e13f bellard
                   | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
674 2662e13f bellard
                   | MB (32 - (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS))
675 2662e13f bellard
                   | ME (31 - CPU_TLB_ENTRY_BITS)
676 2662e13f bellard
                   )
677 2662e13f bellard
        );
678 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
679 2662e13f bellard
    tcg_out32 (s, (LWZU
680 2662e13f bellard
                   | RT (r1)
681 2662e13f bellard
                   | RA (r0)
682 2662e13f bellard
                   | offsetof (CPUState, tlb_table[mem_index][0].addr_write)
683 2662e13f bellard
                   )
684 2662e13f bellard
        );
685 2662e13f bellard
    tcg_out32 (s, (RLWINM
686 2662e13f bellard
                   | RA (r2)
687 2662e13f bellard
                   | RS (addr_reg)
688 2662e13f bellard
                   | SH (0)
689 2662e13f bellard
                   | MB ((32 - opc) & 31)
690 2662e13f bellard
                   | ME (31 - TARGET_PAGE_BITS)
691 2662e13f bellard
                   )
692 2662e13f bellard
        );
693 2662e13f bellard
694 2662e13f bellard
    tcg_out32 (s, CMP | (7 << 23) | RA (r2) | RB (r1));
695 2662e13f bellard
#if TARGET_LONG_BITS == 64
696 2662e13f bellard
    tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
697 2662e13f bellard
    tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
698 2662e13f bellard
    tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
699 2662e13f bellard
#endif
700 2662e13f bellard
701 2662e13f bellard
    label1_ptr = s->code_ptr;
702 2662e13f bellard
#ifdef FAST_PATH
703 2662e13f bellard
    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
704 2662e13f bellard
#endif
705 2662e13f bellard
706 2662e13f bellard
    /* slow path */
707 2662e13f bellard
#if TARGET_LONG_BITS == 32
708 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg);
709 2662e13f bellard
    ir = 4;
710 2662e13f bellard
#else
711 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg2);
712 2662e13f bellard
    tcg_out_mov (s, 4, addr_reg);
713 2662e13f bellard
    ir = 5;
714 2662e13f bellard
#endif
715 2662e13f bellard
716 2662e13f bellard
    switch (opc) {
717 2662e13f bellard
    case 0:
718 2662e13f bellard
        tcg_out32 (s, (RLWINM
719 2662e13f bellard
                       | RA (ir)
720 2662e13f bellard
                       | RS (data_reg)
721 2662e13f bellard
                       | SH (0)
722 2662e13f bellard
                       | MB (24)
723 2662e13f bellard
                       | ME (31)));
724 2662e13f bellard
        break;
725 2662e13f bellard
    case 1:
726 2662e13f bellard
        tcg_out32 (s, (RLWINM
727 2662e13f bellard
                       | RA (ir)
728 2662e13f bellard
                       | RS (data_reg)
729 2662e13f bellard
                       | SH (0)
730 2662e13f bellard
                       | MB (16)
731 2662e13f bellard
                       | ME (31)));
732 2662e13f bellard
        break;
733 2662e13f bellard
    case 2:
734 2662e13f bellard
        tcg_out_mov (s, ir, data_reg);
735 2662e13f bellard
        break;
736 2662e13f bellard
    case 3:
737 2662e13f bellard
        tcg_out_mov (s, 5, data_reg2);
738 2662e13f bellard
        tcg_out_mov (s, 6, data_reg);
739 2662e13f bellard
        ir = 6;
740 2662e13f bellard
        break;
741 2662e13f bellard
    }
742 2662e13f bellard
    ir++;
743 2662e13f bellard
744 2662e13f bellard
    tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
745 932a6909 bellard
    tcg_out_b (s, LK, (tcg_target_long) qemu_st_helpers[opc]);
746 2662e13f bellard
    label2_ptr = s->code_ptr;
747 2662e13f bellard
    tcg_out32 (s, B);
748 2662e13f bellard
749 2662e13f bellard
    /* label1: fast path */
750 2662e13f bellard
#ifdef FAST_PATH
751 2662e13f bellard
    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
752 2662e13f bellard
#endif
753 2662e13f bellard
754 2662e13f bellard
    tcg_out32 (s, (LWZ
755 2662e13f bellard
                   | RT (r0)
756 2662e13f bellard
                   | RA (r0)
757 2662e13f bellard
                   | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
758 2662e13f bellard
                      - offsetof (CPUTLBEntry, addr_write))
759 2662e13f bellard
                   ));
760 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend */
761 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
762 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend + addr */
763 2662e13f bellard
764 2662e13f bellard
#else  /* !CONFIG_SOFTMMU */
765 2662e13f bellard
    r1 = 4;
766 2662e13f bellard
    r0 = addr_reg;
767 2662e13f bellard
#endif
768 2662e13f bellard
769 2662e13f bellard
#ifdef TARGET_WORDS_BIGENDIAN
770 2662e13f bellard
    bswap = 0;
771 2662e13f bellard
#else
772 2662e13f bellard
    bswap = 1;
773 2662e13f bellard
#endif
774 2662e13f bellard
    switch (opc) {
775 2662e13f bellard
    case 0:
776 2662e13f bellard
        tcg_out32 (s, STB | RS (data_reg) | RA (r0));
777 2662e13f bellard
        break;
778 2662e13f bellard
    case 1:
779 2662e13f bellard
        if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0));
780 2662e13f bellard
        else tcg_out32 (s, STH | RS (data_reg) | RA (r0));
781 2662e13f bellard
        break;
782 2662e13f bellard
    case 2:
783 2662e13f bellard
        if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
784 2662e13f bellard
        else tcg_out32 (s, STW | RS (data_reg) | RA (r0));
785 2662e13f bellard
        break;
786 2662e13f bellard
    case 3:
787 2662e13f bellard
        if (bswap) {
788 2662e13f bellard
            tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
789 2662e13f bellard
            tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
790 2662e13f bellard
            tcg_out32 (s, STWBRX | RS (data_reg2) | RA (0) | RB (r1));
791 2662e13f bellard
        }
792 2662e13f bellard
        else {
793 2662e13f bellard
            tcg_out32 (s, STW | RS (data_reg2) | RA (r0));
794 2662e13f bellard
            tcg_out32 (s, STW | RS (data_reg) | RA (r0) | 4);
795 2662e13f bellard
        }
796 2662e13f bellard
        break;
797 2662e13f bellard
    }
798 2662e13f bellard
799 2662e13f bellard
#ifdef CONFIG_SOFTMMU
800 2662e13f bellard
    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
801 2662e13f bellard
#endif
802 2662e13f bellard
}
803 2662e13f bellard
804 2662e13f bellard
void tcg_target_qemu_prologue (TCGContext *s)
805 2662e13f bellard
{
806 0d5bd363 malc
    int i, frame_size;
807 2662e13f bellard
808 2662e13f bellard
    frame_size = 0
809 2662e13f bellard
        + 4                     /* back chain */
810 2662e13f bellard
        + 4                     /* LR */
811 2662e13f bellard
        + TCG_STATIC_CALL_ARGS_SIZE
812 2662e13f bellard
        + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
813 2662e13f bellard
        ;
814 2662e13f bellard
    frame_size = (frame_size + 15) & ~15;
815 2662e13f bellard
816 2662e13f bellard
    tcg_out32 (s, MFSPR | RT (0) | LR);
817 2662e13f bellard
    tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
818 2662e13f bellard
    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
819 2662e13f bellard
        tcg_out32 (s, (STW
820 2662e13f bellard
                       | RS (tcg_target_callee_save_regs[i])
821 2662e13f bellard
                       | RA (1)
822 2662e13f bellard
                       | (i * 4 + 8 + TCG_STATIC_CALL_ARGS_SIZE)
823 2662e13f bellard
                       )
824 2662e13f bellard
            );
825 17ca26e7 malc
    tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + 4));
826 2662e13f bellard
827 2662e13f bellard
    tcg_out32 (s, MTSPR | RS (3) | CTR);
828 2662e13f bellard
    tcg_out32 (s, BCCTR | BO_ALWAYS);
829 2662e13f bellard
    tb_ret_addr = s->code_ptr;
830 2662e13f bellard
831 2662e13f bellard
    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
832 2662e13f bellard
        tcg_out32 (s, (LWZ
833 2662e13f bellard
                       | RT (tcg_target_callee_save_regs[i])
834 2662e13f bellard
                       | RA (1)
835 2662e13f bellard
                       | (i * 4 + 8 + TCG_STATIC_CALL_ARGS_SIZE)
836 2662e13f bellard
                       )
837 2662e13f bellard
            );
838 17ca26e7 malc
    tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + 4));
839 2662e13f bellard
    tcg_out32 (s, MTSPR | RS (0) | LR);
840 2662e13f bellard
    tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
841 2662e13f bellard
    tcg_out32 (s, BCLR | BO_ALWAYS);
842 2662e13f bellard
}
843 2662e13f bellard
844 2662e13f bellard
static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
845 2662e13f bellard
                        tcg_target_long arg2)
846 2662e13f bellard
{
847 2662e13f bellard
    tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
848 2662e13f bellard
}
849 2662e13f bellard
850 2662e13f bellard
static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
851 2662e13f bellard
                        tcg_target_long arg2)
852 2662e13f bellard
{
853 2662e13f bellard
    tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
854 2662e13f bellard
}
855 2662e13f bellard
856 2662e13f bellard
static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
857 2662e13f bellard
{
858 2662e13f bellard
    if (!si && rt == ra)
859 2662e13f bellard
        return;
860 2662e13f bellard
861 2662e13f bellard
    if (si == (int16_t) si)
862 2662e13f bellard
        tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
863 2662e13f bellard
    else {
864 2662e13f bellard
        uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
865 2662e13f bellard
        tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
866 2662e13f bellard
        tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
867 2662e13f bellard
    }
868 2662e13f bellard
}
869 2662e13f bellard
870 2662e13f bellard
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
871 2662e13f bellard
{
872 2662e13f bellard
    ppc_addi (s, reg, reg, val);
873 2662e13f bellard
}
874 2662e13f bellard
875 c596defd malc
static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
876 c596defd malc
                         int const_arg2, int cr)
877 2662e13f bellard
{
878 2662e13f bellard
    int imm;
879 2662e13f bellard
    uint32_t op;
880 2662e13f bellard
881 2662e13f bellard
    switch (cond) {
882 f3f478a7 bellard
    case TCG_COND_EQ:
883 f3f478a7 bellard
    case TCG_COND_NE:
884 f3f478a7 bellard
        if (const_arg2) {
885 f3f478a7 bellard
            if ((int16_t) arg2 == arg2) {
886 f3f478a7 bellard
                op = CMPI;
887 f3f478a7 bellard
                imm = 1;
888 f3f478a7 bellard
                break;
889 f3f478a7 bellard
            }
890 f3f478a7 bellard
            else if ((uint16_t) arg2 == arg2) {
891 f3f478a7 bellard
                op = CMPLI;
892 f3f478a7 bellard
                imm = 1;
893 f3f478a7 bellard
                break;
894 f3f478a7 bellard
            }
895 f3f478a7 bellard
        }
896 f3f478a7 bellard
        op = CMPL;
897 f3f478a7 bellard
        imm = 0;
898 f3f478a7 bellard
        break;
899 f3f478a7 bellard
900 f3f478a7 bellard
    case TCG_COND_LT:
901 f3f478a7 bellard
    case TCG_COND_GE:
902 f3f478a7 bellard
    case TCG_COND_LE:
903 f3f478a7 bellard
    case TCG_COND_GT:
904 f3f478a7 bellard
        if (const_arg2) {
905 f3f478a7 bellard
            if ((int16_t) arg2 == arg2) {
906 f3f478a7 bellard
                op = CMPI;
907 f3f478a7 bellard
                imm = 1;
908 f3f478a7 bellard
                break;
909 f3f478a7 bellard
            }
910 f3f478a7 bellard
        }
911 f3f478a7 bellard
        op = CMP;
912 f3f478a7 bellard
        imm = 0;
913 f3f478a7 bellard
        break;
914 f3f478a7 bellard
915 f3f478a7 bellard
    case TCG_COND_LTU:
916 f3f478a7 bellard
    case TCG_COND_GEU:
917 f3f478a7 bellard
    case TCG_COND_LEU:
918 f3f478a7 bellard
    case TCG_COND_GTU:
919 f3f478a7 bellard
        if (const_arg2) {
920 f3f478a7 bellard
            if ((uint16_t) arg2 == arg2) {
921 f3f478a7 bellard
                op = CMPLI;
922 f3f478a7 bellard
                imm = 1;
923 f3f478a7 bellard
                break;
924 f3f478a7 bellard
            }
925 f3f478a7 bellard
        }
926 f3f478a7 bellard
        op = CMPL;
927 f3f478a7 bellard
        imm = 0;
928 f3f478a7 bellard
        break;
929 f3f478a7 bellard
930 2662e13f bellard
    default:
931 2662e13f bellard
        tcg_abort ();
932 2662e13f bellard
    }
933 c596defd malc
    op |= BF (cr);
934 2662e13f bellard
935 2662e13f bellard
    if (imm)
936 2662e13f bellard
        tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
937 2662e13f bellard
    else {
938 2662e13f bellard
        if (const_arg2) {
939 2662e13f bellard
            tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
940 2662e13f bellard
            tcg_out32 (s, op | RA (arg1) | RB (0));
941 2662e13f bellard
        }
942 2662e13f bellard
        else
943 2662e13f bellard
            tcg_out32 (s, op | RA (arg1) | RB (arg2));
944 2662e13f bellard
    }
945 2662e13f bellard
946 c596defd malc
}
947 c596defd malc
948 c596defd malc
static void tcg_out_bc (TCGContext *s, int bc, int label_index)
949 c596defd malc
{
950 c596defd malc
    TCGLabel *l = &s->labels[label_index];
951 c596defd malc
952 0a878c47 malc
    if (l->has_value)
953 c596defd malc
        tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value));
954 2662e13f bellard
    else {
955 0a878c47 malc
        uint16_t val = *(uint16_t *) &s->code_ptr[2];
956 0a878c47 malc
957 0a878c47 malc
        /* Thanks to Andrzej Zaborowski */
958 c596defd malc
        tcg_out32 (s, bc | (val & 0xfffc));
959 2662e13f bellard
        tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
960 2662e13f bellard
    }
961 2662e13f bellard
}
962 2662e13f bellard
963 c596defd malc
static void tcg_out_brcond (TCGContext *s, int cond,
964 c596defd malc
                            TCGArg arg1, TCGArg arg2, int const_arg2,
965 c596defd malc
                            int label_index)
966 c596defd malc
{
967 c596defd malc
    tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7);
968 c596defd malc
    tcg_out_bc (s, tcg_to_bc[cond], label_index);
969 c596defd malc
}
970 c596defd malc
971 2662e13f bellard
/* XXX: we implement it at the target level to avoid having to
972 2662e13f bellard
   handle cross basic blocks temporaries */
973 c596defd malc
static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
974 c596defd malc
                             const int *const_args)
975 2662e13f bellard
{
976 c596defd malc
    int cond = args[4], label_index = args[5], op;
977 c596defd malc
    struct { int bit1; int bit2; int cond2; } bits[] = {
978 c596defd malc
        [TCG_COND_LT ] = { CR_LT, CR_LT, TCG_COND_LT  },
979 c596defd malc
        [TCG_COND_LE ] = { CR_LT, CR_GT, TCG_COND_LT  },
980 c596defd malc
        [TCG_COND_GT ] = { CR_GT, CR_GT, TCG_COND_GT  },
981 c596defd malc
        [TCG_COND_GE ] = { CR_GT, CR_LT, TCG_COND_GT  },
982 c596defd malc
        [TCG_COND_LTU] = { CR_LT, CR_LT, TCG_COND_LTU },
983 c596defd malc
        [TCG_COND_LEU] = { CR_LT, CR_GT, TCG_COND_LTU },
984 c596defd malc
        [TCG_COND_GTU] = { CR_GT, CR_GT, TCG_COND_GTU },
985 c596defd malc
        [TCG_COND_GEU] = { CR_GT, CR_LT, TCG_COND_GTU },
986 c596defd malc
    }, *b = &bits[cond];
987 c596defd malc
988 c596defd malc
    switch (cond) {
989 2662e13f bellard
    case TCG_COND_EQ:
990 c596defd malc
        tcg_out_cmp (s, TCG_COND_EQ, args[0], args[2], const_args[2], 6);
991 c596defd malc
        tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 7);
992 c596defd malc
        tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
993 2662e13f bellard
        break;
994 2662e13f bellard
    case TCG_COND_NE:
995 c596defd malc
        tcg_out_cmp (s, TCG_COND_NE, args[0], args[2], const_args[2], 6);
996 c596defd malc
        tcg_out_cmp (s, TCG_COND_NE, args[1], args[3], const_args[3], 7);
997 c596defd malc
        tcg_out32 (s, CRNAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
998 2662e13f bellard
        break;
999 2662e13f bellard
    case TCG_COND_LT:
1000 2662e13f bellard
    case TCG_COND_LE:
1001 2662e13f bellard
    case TCG_COND_GT:
1002 2662e13f bellard
    case TCG_COND_GE:
1003 2662e13f bellard
    case TCG_COND_LTU:
1004 2662e13f bellard
    case TCG_COND_LEU:
1005 2662e13f bellard
    case TCG_COND_GTU:
1006 2662e13f bellard
    case TCG_COND_GEU:
1007 c596defd malc
        op = (b->bit1 != b->bit2) ? CRANDC : CRAND;
1008 c596defd malc
        tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5);
1009 c596defd malc
        tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 6);
1010 c596defd malc
        tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 7);
1011 c596defd malc
        tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, b->bit2));
1012 c596defd malc
        tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ));
1013 2662e13f bellard
        break;
1014 2662e13f bellard
    default:
1015 2662e13f bellard
        tcg_abort();
1016 2662e13f bellard
    }
1017 c596defd malc
1018 c596defd malc
    tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), label_index);
1019 2662e13f bellard
}
1020 2662e13f bellard
1021 2662e13f bellard
static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1022 2662e13f bellard
                       const int *const_args)
1023 2662e13f bellard
{
1024 2662e13f bellard
    switch (opc) {
1025 2662e13f bellard
    case INDEX_op_exit_tb:
1026 2662e13f bellard
        tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
1027 932a6909 bellard
        tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
1028 2662e13f bellard
        break;
1029 2662e13f bellard
    case INDEX_op_goto_tb:
1030 2662e13f bellard
        if (s->tb_jmp_offset) {
1031 2662e13f bellard
            /* direct jump method */
1032 932a6909 bellard
1033 2662e13f bellard
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1034 0a878c47 malc
            s->code_ptr += 16;
1035 932a6909 bellard
        }
1036 932a6909 bellard
        else {
1037 2662e13f bellard
            tcg_abort ();
1038 2662e13f bellard
        }
1039 2662e13f bellard
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1040 2662e13f bellard
        break;
1041 2662e13f bellard
    case INDEX_op_br:
1042 2662e13f bellard
        {
1043 2662e13f bellard
            TCGLabel *l = &s->labels[args[0]];
1044 2662e13f bellard
1045 2662e13f bellard
            if (l->has_value) {
1046 932a6909 bellard
                tcg_out_b (s, 0, l->u.value);
1047 2662e13f bellard
            }
1048 2662e13f bellard
            else {
1049 0a878c47 malc
                uint32_t val = *(uint32_t *) s->code_ptr;
1050 0a878c47 malc
1051 0a878c47 malc
                /* Thanks to Andrzej Zaborowski */
1052 0a878c47 malc
                tcg_out32 (s, B | (val & 0x3fffffc));
1053 2662e13f bellard
                tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1054 2662e13f bellard
            }
1055 2662e13f bellard
        }
1056 2662e13f bellard
        break;
1057 2662e13f bellard
    case INDEX_op_call:
1058 2662e13f bellard
        if (const_args[0]) {
1059 932a6909 bellard
            tcg_out_b (s, LK, args[0]);
1060 2662e13f bellard
        }
1061 2662e13f bellard
        else {
1062 2662e13f bellard
            tcg_out32 (s, MTSPR | RS (args[0]) | LR);
1063 2662e13f bellard
            tcg_out32 (s, BCLR | BO_ALWAYS | LK);
1064 2662e13f bellard
        }
1065 2662e13f bellard
        break;
1066 2662e13f bellard
    case INDEX_op_jmp:
1067 2662e13f bellard
        if (const_args[0]) {
1068 932a6909 bellard
            tcg_out_b (s, 0, args[0]);
1069 2662e13f bellard
        }
1070 2662e13f bellard
        else {
1071 2662e13f bellard
            tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
1072 2662e13f bellard
            tcg_out32 (s, BCCTR | BO_ALWAYS);
1073 2662e13f bellard
        }
1074 2662e13f bellard
        break;
1075 2662e13f bellard
    case INDEX_op_movi_i32:
1076 2662e13f bellard
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1077 2662e13f bellard
        break;
1078 2662e13f bellard
    case INDEX_op_ld8u_i32:
1079 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1080 2662e13f bellard
        break;
1081 2662e13f bellard
    case INDEX_op_ld8s_i32:
1082 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1083 2662e13f bellard
        tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1084 2662e13f bellard
        break;
1085 2662e13f bellard
    case INDEX_op_ld16u_i32:
1086 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1087 2662e13f bellard
        break;
1088 2662e13f bellard
    case INDEX_op_ld16s_i32:
1089 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1090 2662e13f bellard
        break;
1091 2662e13f bellard
    case INDEX_op_ld_i32:
1092 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1093 2662e13f bellard
        break;
1094 2662e13f bellard
    case INDEX_op_st8_i32:
1095 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1096 2662e13f bellard
        break;
1097 2662e13f bellard
    case INDEX_op_st16_i32:
1098 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1099 2662e13f bellard
        break;
1100 2662e13f bellard
    case INDEX_op_st_i32:
1101 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1102 2662e13f bellard
        break;
1103 2662e13f bellard
1104 2662e13f bellard
    case INDEX_op_add_i32:
1105 2662e13f bellard
        if (const_args[2])
1106 2662e13f bellard
            ppc_addi (s, args[0], args[1], args[2]);
1107 2662e13f bellard
        else
1108 2662e13f bellard
            tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1109 2662e13f bellard
        break;
1110 2662e13f bellard
    case INDEX_op_sub_i32:
1111 2662e13f bellard
        if (const_args[2])
1112 2662e13f bellard
            ppc_addi (s, args[0], args[1], -args[2]);
1113 2662e13f bellard
        else
1114 2662e13f bellard
            tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1115 2662e13f bellard
        break;
1116 2662e13f bellard
1117 2662e13f bellard
    case INDEX_op_and_i32:
1118 2662e13f bellard
        if (const_args[2]) {
1119 2662e13f bellard
            if (!args[2])
1120 2662e13f bellard
                tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
1121 2662e13f bellard
            else {
1122 2662e13f bellard
                if ((args[2] & 0xffff) == args[2])
1123 2662e13f bellard
                    tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
1124 2662e13f bellard
                else if ((args[2] & 0xffff0000) == args[2])
1125 2662e13f bellard
                    tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1126 2662e13f bellard
                               | ((args[2] >> 16) & 0xffff));
1127 2662e13f bellard
                else if (args[2] == 0xffffffff) {
1128 2662e13f bellard
                    if (args[0] != args[1])
1129 2662e13f bellard
                        tcg_out_mov (s, args[0], args[1]);
1130 2662e13f bellard
                }
1131 2662e13f bellard
                else {
1132 2662e13f bellard
                    tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1133 2662e13f bellard
                    tcg_out32 (s, AND | SAB (args[1], args[0], 0));
1134 2662e13f bellard
                }
1135 2662e13f bellard
            }
1136 2662e13f bellard
        }
1137 2662e13f bellard
        else
1138 2662e13f bellard
            tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1139 2662e13f bellard
        break;
1140 2662e13f bellard
    case INDEX_op_or_i32:
1141 2662e13f bellard
        if (const_args[2]) {
1142 2662e13f bellard
            if (args[2]) {
1143 2662e13f bellard
                if (args[2] & 0xffff) {
1144 932a6909 bellard
                    tcg_out32 (s, ORI | RS (args[1])  | RA (args[0])
1145 932a6909 bellard
                               | (args[2] & 0xffff));
1146 2662e13f bellard
                    if (args[2] >> 16)
1147 2662e13f bellard
                        tcg_out32 (s, ORIS | RS (args[0])  | RA (args[0])
1148 2662e13f bellard
                                   | ((args[2] >> 16) & 0xffff));
1149 2662e13f bellard
                }
1150 2662e13f bellard
                else {
1151 2662e13f bellard
                    tcg_out32 (s, ORIS | RS (args[1])  | RA (args[0])
1152 2662e13f bellard
                               | ((args[2] >> 16) & 0xffff));
1153 2662e13f bellard
                }
1154 2662e13f bellard
            }
1155 2662e13f bellard
            else {
1156 2662e13f bellard
                if (args[0] != args[1])
1157 2662e13f bellard
                    tcg_out_mov (s, args[0], args[1]);
1158 2662e13f bellard
            }
1159 2662e13f bellard
        }
1160 2662e13f bellard
        else
1161 2662e13f bellard
            tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1162 2662e13f bellard
        break;
1163 2662e13f bellard
    case INDEX_op_xor_i32:
1164 2662e13f bellard
        if (const_args[2]) {
1165 2662e13f bellard
            if (args[2]) {
1166 2662e13f bellard
                if ((args[2] & 0xffff) == args[2])
1167 2662e13f bellard
                    tcg_out32 (s, XORI | RS (args[1])  | RA (args[0])
1168 2662e13f bellard
                               | (args[2] & 0xffff));
1169 2662e13f bellard
                else if ((args[2] & 0xffff0000) == args[2])
1170 2662e13f bellard
                    tcg_out32 (s, XORIS | RS (args[1])  | RA (args[0])
1171 2662e13f bellard
                               | ((args[2] >> 16) & 0xffff));
1172 2662e13f bellard
                else {
1173 2662e13f bellard
                    tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1174 2662e13f bellard
                    tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
1175 2662e13f bellard
                }
1176 2662e13f bellard
            }
1177 2662e13f bellard
            else {
1178 2662e13f bellard
                if (args[0] != args[1])
1179 2662e13f bellard
                    tcg_out_mov (s, args[0], args[1]);
1180 2662e13f bellard
            }
1181 2662e13f bellard
        }
1182 2662e13f bellard
        else
1183 2662e13f bellard
            tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1184 2662e13f bellard
        break;
1185 2662e13f bellard
1186 2662e13f bellard
    case INDEX_op_mul_i32:
1187 2662e13f bellard
        if (const_args[2]) {
1188 2662e13f bellard
            if (args[2] == (int16_t) args[2])
1189 2662e13f bellard
                tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1190 2662e13f bellard
                           | (args[2] & 0xffff));
1191 2662e13f bellard
            else {
1192 2662e13f bellard
                tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1193 2662e13f bellard
                tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1194 2662e13f bellard
            }
1195 2662e13f bellard
        }
1196 2662e13f bellard
        else
1197 2662e13f bellard
            tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1198 2662e13f bellard
        break;
1199 77b73de6 malc
1200 77b73de6 malc
    case INDEX_op_div_i32:
1201 77b73de6 malc
        tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
1202 77b73de6 malc
        break;
1203 77b73de6 malc
1204 77b73de6 malc
    case INDEX_op_divu_i32:
1205 77b73de6 malc
        tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
1206 77b73de6 malc
        break;
1207 77b73de6 malc
1208 77b73de6 malc
    case INDEX_op_rem_i32:
1209 77b73de6 malc
        tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
1210 77b73de6 malc
        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1211 77b73de6 malc
        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1212 77b73de6 malc
        break;
1213 77b73de6 malc
1214 77b73de6 malc
    case INDEX_op_remu_i32:
1215 77b73de6 malc
        tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
1216 77b73de6 malc
        tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
1217 77b73de6 malc
        tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
1218 77b73de6 malc
        break;
1219 77b73de6 malc
1220 2662e13f bellard
    case INDEX_op_mulu2_i32:
1221 2662e13f bellard
        if (args[0] == args[2] || args[0] == args[3]) {
1222 2662e13f bellard
            tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
1223 2662e13f bellard
            tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1224 2662e13f bellard
            tcg_out_mov (s, args[0], 0);
1225 2662e13f bellard
        }
1226 2662e13f bellard
        else {
1227 2662e13f bellard
            tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
1228 2662e13f bellard
            tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1229 2662e13f bellard
        }
1230 2662e13f bellard
        break;
1231 2662e13f bellard
1232 2662e13f bellard
    case INDEX_op_shl_i32:
1233 2662e13f bellard
        if (const_args[2]) {
1234 2662e13f bellard
            if (args[2])
1235 2662e13f bellard
                tcg_out32 (s, (RLWINM
1236 2662e13f bellard
                               | RA (args[0])
1237 2662e13f bellard
                               | RS (args[1])
1238 2662e13f bellard
                               | SH (args[2])
1239 2662e13f bellard
                               | MB (0)
1240 2662e13f bellard
                               | ME (31 - args[2])
1241 2662e13f bellard
                               )
1242 2662e13f bellard
                    );
1243 2662e13f bellard
            else
1244 2662e13f bellard
                tcg_out_mov (s, args[0], args[1]);
1245 2662e13f bellard
        }
1246 2662e13f bellard
        else
1247 2662e13f bellard
            tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1248 2662e13f bellard
        break;
1249 2662e13f bellard
    case INDEX_op_shr_i32:
1250 2662e13f bellard
        if (const_args[2]) {
1251 2662e13f bellard
            if (args[2])
1252 2662e13f bellard
                tcg_out32 (s, (RLWINM
1253 2662e13f bellard
                               | RA (args[0])
1254 2662e13f bellard
                               | RS (args[1])
1255 2662e13f bellard
                               | SH (32 - args[2])
1256 2662e13f bellard
                               | MB (args[2])
1257 2662e13f bellard
                               | ME (31)
1258 2662e13f bellard
                               )
1259 2662e13f bellard
                    );
1260 2662e13f bellard
            else
1261 2662e13f bellard
                tcg_out_mov (s, args[0], args[1]);
1262 2662e13f bellard
        }
1263 2662e13f bellard
        else
1264 2662e13f bellard
            tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1265 2662e13f bellard
        break;
1266 2662e13f bellard
    case INDEX_op_sar_i32:
1267 2662e13f bellard
        if (const_args[2])
1268 2662e13f bellard
            tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1269 2662e13f bellard
        else
1270 2662e13f bellard
            tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1271 2662e13f bellard
        break;
1272 2662e13f bellard
1273 2662e13f bellard
    case INDEX_op_add2_i32:
1274 2662e13f bellard
        if (args[0] == args[3] || args[0] == args[5]) {
1275 2662e13f bellard
            tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
1276 2662e13f bellard
            tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1277 2662e13f bellard
            tcg_out_mov (s, args[0], 0);
1278 2662e13f bellard
        }
1279 2662e13f bellard
        else {
1280 2662e13f bellard
            tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
1281 2662e13f bellard
            tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1282 2662e13f bellard
        }
1283 2662e13f bellard
        break;
1284 2662e13f bellard
    case INDEX_op_sub2_i32:
1285 2662e13f bellard
        if (args[0] == args[3] || args[0] == args[5]) {
1286 2662e13f bellard
            tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
1287 2662e13f bellard
            tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1288 2662e13f bellard
            tcg_out_mov (s, args[0], 0);
1289 2662e13f bellard
        }
1290 2662e13f bellard
        else {
1291 2662e13f bellard
            tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
1292 2662e13f bellard
            tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1293 2662e13f bellard
        }
1294 2662e13f bellard
        break;
1295 2662e13f bellard
1296 2662e13f bellard
    case INDEX_op_brcond_i32:
1297 2662e13f bellard
        /*
1298 2662e13f bellard
          args[0] = r0
1299 2662e13f bellard
          args[1] = r1
1300 2662e13f bellard
          args[2] = cond
1301 2662e13f bellard
          args[3] = r1 is const
1302 2662e13f bellard
          args[4] = label_index
1303 2662e13f bellard
        */
1304 2662e13f bellard
        tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
1305 2662e13f bellard
        break;
1306 2662e13f bellard
    case INDEX_op_brcond2_i32:
1307 2662e13f bellard
        tcg_out_brcond2(s, args, const_args);
1308 2662e13f bellard
        break;
1309 2662e13f bellard
1310 2662e13f bellard
    case INDEX_op_neg_i32:
1311 2662e13f bellard
        tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1312 2662e13f bellard
        break;
1313 2662e13f bellard
1314 2662e13f bellard
    case INDEX_op_qemu_ld8u:
1315 2662e13f bellard
        tcg_out_qemu_ld(s, args, 0);
1316 2662e13f bellard
        break;
1317 2662e13f bellard
    case INDEX_op_qemu_ld8s:
1318 2662e13f bellard
        tcg_out_qemu_ld(s, args, 0 | 4);
1319 2662e13f bellard
        break;
1320 2662e13f bellard
    case INDEX_op_qemu_ld16u:
1321 2662e13f bellard
        tcg_out_qemu_ld(s, args, 1);
1322 2662e13f bellard
        break;
1323 2662e13f bellard
    case INDEX_op_qemu_ld16s:
1324 2662e13f bellard
        tcg_out_qemu_ld(s, args, 1 | 4);
1325 2662e13f bellard
        break;
1326 2662e13f bellard
    case INDEX_op_qemu_ld32u:
1327 2662e13f bellard
        tcg_out_qemu_ld(s, args, 2);
1328 2662e13f bellard
        break;
1329 2662e13f bellard
    case INDEX_op_qemu_ld64:
1330 2662e13f bellard
        tcg_out_qemu_ld(s, args, 3);
1331 2662e13f bellard
        break;
1332 2662e13f bellard
    case INDEX_op_qemu_st8:
1333 2662e13f bellard
        tcg_out_qemu_st(s, args, 0);
1334 2662e13f bellard
        break;
1335 2662e13f bellard
    case INDEX_op_qemu_st16:
1336 2662e13f bellard
        tcg_out_qemu_st(s, args, 1);
1337 2662e13f bellard
        break;
1338 2662e13f bellard
    case INDEX_op_qemu_st32:
1339 2662e13f bellard
        tcg_out_qemu_st(s, args, 2);
1340 2662e13f bellard
        break;
1341 2662e13f bellard
    case INDEX_op_qemu_st64:
1342 2662e13f bellard
        tcg_out_qemu_st(s, args, 3);
1343 2662e13f bellard
        break;
1344 2662e13f bellard
1345 2662e13f bellard
    default:
1346 2662e13f bellard
        tcg_dump_ops (s, stderr);
1347 2662e13f bellard
        tcg_abort ();
1348 2662e13f bellard
    }
1349 2662e13f bellard
}
1350 2662e13f bellard
1351 2662e13f bellard
static const TCGTargetOpDef ppc_op_defs[] = {
1352 2662e13f bellard
    { INDEX_op_exit_tb, { } },
1353 2662e13f bellard
    { INDEX_op_goto_tb, { } },
1354 932a6909 bellard
    { INDEX_op_call, { "ri" } },
1355 932a6909 bellard
    { INDEX_op_jmp, { "ri" } },
1356 2662e13f bellard
    { INDEX_op_br, { } },
1357 2662e13f bellard
1358 2662e13f bellard
    { INDEX_op_mov_i32, { "r", "r" } },
1359 2662e13f bellard
    { INDEX_op_movi_i32, { "r" } },
1360 2662e13f bellard
    { INDEX_op_ld8u_i32, { "r", "r" } },
1361 2662e13f bellard
    { INDEX_op_ld8s_i32, { "r", "r" } },
1362 2662e13f bellard
    { INDEX_op_ld16u_i32, { "r", "r" } },
1363 2662e13f bellard
    { INDEX_op_ld16s_i32, { "r", "r" } },
1364 2662e13f bellard
    { INDEX_op_ld_i32, { "r", "r" } },
1365 2662e13f bellard
    { INDEX_op_st8_i32, { "r", "r" } },
1366 2662e13f bellard
    { INDEX_op_st16_i32, { "r", "r" } },
1367 2662e13f bellard
    { INDEX_op_st_i32, { "r", "r" } },
1368 2662e13f bellard
1369 2662e13f bellard
    { INDEX_op_add_i32, { "r", "r", "ri" } },
1370 2662e13f bellard
    { INDEX_op_mul_i32, { "r", "r", "ri" } },
1371 77b73de6 malc
    { INDEX_op_div_i32, { "r", "r", "r" } },
1372 77b73de6 malc
    { INDEX_op_divu_i32, { "r", "r", "r" } },
1373 77b73de6 malc
    { INDEX_op_rem_i32, { "r", "r", "r" } },
1374 77b73de6 malc
    { INDEX_op_remu_i32, { "r", "r", "r" } },
1375 2662e13f bellard
    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1376 2662e13f bellard
    { INDEX_op_sub_i32, { "r", "r", "ri" } },
1377 2662e13f bellard
    { INDEX_op_and_i32, { "r", "r", "ri" } },
1378 2662e13f bellard
    { INDEX_op_or_i32, { "r", "r", "ri" } },
1379 2662e13f bellard
    { INDEX_op_xor_i32, { "r", "r", "ri" } },
1380 2662e13f bellard
1381 2662e13f bellard
    { INDEX_op_shl_i32, { "r", "r", "ri" } },
1382 2662e13f bellard
    { INDEX_op_shr_i32, { "r", "r", "ri" } },
1383 2662e13f bellard
    { INDEX_op_sar_i32, { "r", "r", "ri" } },
1384 2662e13f bellard
1385 2662e13f bellard
    { INDEX_op_brcond_i32, { "r", "ri" } },
1386 2662e13f bellard
1387 2662e13f bellard
    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1388 2662e13f bellard
    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1389 2662e13f bellard
    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1390 2662e13f bellard
1391 2662e13f bellard
    { INDEX_op_neg_i32, { "r", "r" } },
1392 2662e13f bellard
1393 2662e13f bellard
#if TARGET_LONG_BITS == 32
1394 2662e13f bellard
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1395 2662e13f bellard
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1396 2662e13f bellard
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1397 2662e13f bellard
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1398 2662e13f bellard
    { INDEX_op_qemu_ld32u, { "r", "L" } },
1399 2662e13f bellard
    { INDEX_op_qemu_ld32s, { "r", "L" } },
1400 2662e13f bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1401 2662e13f bellard
1402 2662e13f bellard
    { INDEX_op_qemu_st8, { "K", "K" } },
1403 2662e13f bellard
    { INDEX_op_qemu_st16, { "K", "K" } },
1404 2662e13f bellard
    { INDEX_op_qemu_st32, { "K", "K" } },
1405 2662e13f bellard
    { INDEX_op_qemu_st64, { "M", "M", "M" } },
1406 2662e13f bellard
#else
1407 2662e13f bellard
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1408 2662e13f bellard
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1409 2662e13f bellard
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1410 2662e13f bellard
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1411 2662e13f bellard
    { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1412 2662e13f bellard
    { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
1413 2662e13f bellard
    { INDEX_op_qemu_ld64, { "r", "L", "L", "L" } },
1414 2662e13f bellard
1415 2662e13f bellard
    { INDEX_op_qemu_st8, { "K", "K", "K" } },
1416 2662e13f bellard
    { INDEX_op_qemu_st16, { "K", "K", "K" } },
1417 2662e13f bellard
    { INDEX_op_qemu_st32, { "K", "K", "K" } },
1418 2662e13f bellard
    { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
1419 2662e13f bellard
#endif
1420 2662e13f bellard
1421 2662e13f bellard
    { -1 },
1422 2662e13f bellard
};
1423 2662e13f bellard
1424 2662e13f bellard
void tcg_target_init(TCGContext *s)
1425 2662e13f bellard
{
1426 2662e13f bellard
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1427 2662e13f bellard
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1428 2662e13f bellard
                     (1 << TCG_REG_R0) |
1429 2662e13f bellard
                     (1 << TCG_REG_R3) |
1430 2662e13f bellard
                     (1 << TCG_REG_R4) |
1431 2662e13f bellard
                     (1 << TCG_REG_R5) |
1432 2662e13f bellard
                     (1 << TCG_REG_R6) |
1433 2662e13f bellard
                     (1 << TCG_REG_R7) |
1434 2662e13f bellard
                     (1 << TCG_REG_R8) |
1435 2662e13f bellard
                     (1 << TCG_REG_R9) |
1436 2662e13f bellard
                     (1 << TCG_REG_R10) |
1437 2662e13f bellard
                     (1 << TCG_REG_R11) |
1438 2662e13f bellard
                     (1 << TCG_REG_R12)
1439 2662e13f bellard
        );
1440 2662e13f bellard
1441 2662e13f bellard
    tcg_regset_clear(s->reserved_regs);
1442 2662e13f bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
1443 2662e13f bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
1444 2662e13f bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
1445 2662e13f bellard
1446 2662e13f bellard
    tcg_add_target_add_op_defs(ppc_op_defs);
1447 2662e13f bellard
}