Statistics
| Branch: | Revision:

root / tcg / ppc / tcg-target.c @ 2662e13f

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