Statistics
| Branch: | Revision:

root / tcg / ppc / tcg-target.c @ 5d794885

History | View | Annotate | Download (43 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 2662e13f bellard
    TCG_REG_R0,
71 2662e13f bellard
    TCG_REG_R1,
72 2662e13f bellard
    TCG_REG_R2,
73 2662e13f bellard
    TCG_REG_R3,
74 2662e13f bellard
    TCG_REG_R4,
75 2662e13f bellard
    TCG_REG_R5,
76 2662e13f bellard
    TCG_REG_R6,
77 2662e13f bellard
    TCG_REG_R7,
78 2662e13f bellard
    TCG_REG_R8,
79 2662e13f bellard
    TCG_REG_R9,
80 2662e13f bellard
    TCG_REG_R10,
81 2662e13f bellard
    TCG_REG_R11,
82 2662e13f bellard
    TCG_REG_R12,
83 2662e13f bellard
    TCG_REG_R13,
84 2662e13f bellard
    TCG_REG_R14,
85 2662e13f bellard
    TCG_REG_R15,
86 2662e13f bellard
    TCG_REG_R16,
87 2662e13f bellard
    TCG_REG_R17,
88 2662e13f bellard
    TCG_REG_R18,
89 2662e13f bellard
    TCG_REG_R19,
90 2662e13f bellard
    TCG_REG_R20,
91 2662e13f bellard
    TCG_REG_R21,
92 2662e13f bellard
    TCG_REG_R22,
93 2662e13f bellard
    TCG_REG_R23,
94 2662e13f bellard
    TCG_REG_R24,
95 2662e13f bellard
    TCG_REG_R25,
96 2662e13f bellard
    TCG_REG_R26,
97 2662e13f bellard
    TCG_REG_R27,
98 2662e13f bellard
    TCG_REG_R28,
99 2662e13f bellard
    TCG_REG_R29,
100 2662e13f bellard
    TCG_REG_R30,
101 2662e13f bellard
    TCG_REG_R31
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_R13,                /* sould r13 be saved? */
122 2662e13f bellard
    TCG_REG_R14,
123 2662e13f bellard
    TCG_REG_R15,
124 2662e13f bellard
    TCG_REG_R16,
125 2662e13f bellard
    TCG_REG_R17,
126 2662e13f bellard
    TCG_REG_R18,
127 2662e13f bellard
    TCG_REG_R19,
128 2662e13f bellard
    TCG_REG_R20,
129 2662e13f bellard
    TCG_REG_R21,
130 2662e13f bellard
    TCG_REG_R22,
131 2662e13f bellard
    TCG_REG_R23,
132 2662e13f bellard
    TCG_REG_R28,
133 2662e13f bellard
    TCG_REG_R29,
134 2662e13f bellard
    TCG_REG_R30,
135 2662e13f bellard
    TCG_REG_R31
136 2662e13f bellard
};
137 2662e13f bellard
138 2662e13f bellard
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
139 2662e13f bellard
{
140 932a6909 bellard
    tcg_target_long disp;
141 932a6909 bellard
142 932a6909 bellard
    disp = target - (tcg_target_long) pc;
143 932a6909 bellard
    if ((disp << 6) >> 6 != disp)
144 932a6909 bellard
        tcg_abort ();
145 932a6909 bellard
146 932a6909 bellard
    return disp & 0x3fffffc;
147 2662e13f bellard
}
148 2662e13f bellard
149 2662e13f bellard
static void reloc_pc24 (void *pc, tcg_target_long target)
150 2662e13f bellard
{
151 2662e13f bellard
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
152 2662e13f bellard
        | reloc_pc24_val (pc, target);
153 2662e13f bellard
}
154 2662e13f bellard
155 2662e13f bellard
static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
156 2662e13f bellard
{
157 932a6909 bellard
    tcg_target_long disp;
158 932a6909 bellard
159 932a6909 bellard
    disp = target - (tcg_target_long) pc;
160 932a6909 bellard
    if (disp != (int16_t) disp)
161 932a6909 bellard
        tcg_abort ();
162 932a6909 bellard
163 932a6909 bellard
    return disp & 0xfffc;
164 2662e13f bellard
}
165 2662e13f bellard
166 2662e13f bellard
static void reloc_pc14 (void *pc, tcg_target_long target)
167 2662e13f bellard
{
168 2662e13f bellard
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
169 2662e13f bellard
        | reloc_pc14_val (pc, target);
170 2662e13f bellard
}
171 2662e13f bellard
172 2662e13f bellard
static void patch_reloc(uint8_t *code_ptr, int type,
173 2662e13f bellard
                        tcg_target_long value, tcg_target_long addend)
174 2662e13f bellard
{
175 2662e13f bellard
    value += addend;
176 2662e13f bellard
    switch (type) {
177 2662e13f bellard
    case R_PPC_REL14:
178 2662e13f bellard
        reloc_pc14 (code_ptr, value);
179 2662e13f bellard
        break;
180 2662e13f bellard
    case R_PPC_REL24:
181 2662e13f bellard
        reloc_pc24 (code_ptr, value);
182 2662e13f bellard
        break;
183 2662e13f bellard
    default:
184 2662e13f bellard
        tcg_abort();
185 2662e13f bellard
    }
186 2662e13f bellard
}
187 2662e13f bellard
188 2662e13f bellard
/* maximum number of register used for input function arguments */
189 2662e13f bellard
static int tcg_target_get_call_iarg_regs_count(int flags)
190 2662e13f bellard
{
191 2662e13f bellard
    return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]);
192 2662e13f bellard
}
193 2662e13f bellard
194 2662e13f bellard
/* parse target specific constraints */
195 2662e13f bellard
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
196 2662e13f bellard
{
197 2662e13f bellard
    const char *ct_str;
198 2662e13f bellard
199 2662e13f bellard
    ct_str = *pct_str;
200 2662e13f bellard
    switch (ct_str[0]) {
201 398ce98e malc
    case 'A': case 'B': case 'C': case 'D':
202 398ce98e malc
        ct->ct |= TCG_CT_REG;
203 398ce98e malc
        tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
204 398ce98e malc
        break;
205 2662e13f bellard
    case 'r':
206 2662e13f bellard
        ct->ct |= TCG_CT_REG;
207 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
208 2662e13f bellard
        break;
209 2662e13f bellard
    case 'L':                   /* qemu_ld constraint */
210 2662e13f bellard
        ct->ct |= TCG_CT_REG;
211 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
212 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
213 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
214 2662e13f bellard
        break;
215 2662e13f bellard
    case 'K':                   /* qemu_st[8..32] constraint */
216 2662e13f bellard
        ct->ct |= TCG_CT_REG;
217 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
218 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
219 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
220 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
221 2662e13f bellard
#if TARGET_LONG_BITS == 64
222 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
223 2662e13f bellard
#endif
224 2662e13f bellard
        break;
225 2662e13f bellard
    case 'M':                   /* qemu_st64 constraint */
226 2662e13f bellard
        ct->ct |= TCG_CT_REG;
227 2662e13f bellard
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
228 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
229 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
230 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
231 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
232 2662e13f bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
233 2662e13f bellard
        break;
234 2662e13f bellard
    default:
235 2662e13f bellard
        return -1;
236 2662e13f bellard
    }
237 2662e13f bellard
    ct_str++;
238 2662e13f bellard
    *pct_str = ct_str;
239 2662e13f bellard
    return 0;
240 2662e13f bellard
}
241 2662e13f bellard
242 2662e13f bellard
/* test if a constant matches the constraint */
243 2662e13f bellard
static int tcg_target_const_match(tcg_target_long val,
244 2662e13f bellard
                                  const TCGArgConstraint *arg_ct)
245 2662e13f bellard
{
246 2662e13f bellard
    int ct;
247 2662e13f bellard
248 2662e13f bellard
    ct = arg_ct->ct;
249 2662e13f bellard
    if (ct & TCG_CT_CONST)
250 2662e13f bellard
        return 1;
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 0a878c47 malc
            tcg_out32 (s, ORI | RS (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 932a6909 bellard
static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
411 932a6909 bellard
{
412 932a6909 bellard
    tcg_target_long disp;
413 932a6909 bellard
414 932a6909 bellard
    disp = target - (tcg_target_long) s->code_ptr;
415 932a6909 bellard
    if ((disp << 6) >> 6 == disp)
416 932a6909 bellard
        tcg_out32 (s, B | disp | mask);
417 932a6909 bellard
    else {
418 932a6909 bellard
        tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target);
419 932a6909 bellard
        tcg_out32 (s, MTSPR | RS (0) | CTR);
420 932a6909 bellard
        tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
421 932a6909 bellard
    }
422 932a6909 bellard
}
423 932a6909 bellard
424 2662e13f bellard
#if defined(CONFIG_SOFTMMU)
425 2662e13f bellard
extern void __ldb_mmu(void);
426 2662e13f bellard
extern void __ldw_mmu(void);
427 2662e13f bellard
extern void __ldl_mmu(void);
428 2662e13f bellard
extern void __ldq_mmu(void);
429 2662e13f bellard
430 2662e13f bellard
extern void __stb_mmu(void);
431 2662e13f bellard
extern void __stw_mmu(void);
432 2662e13f bellard
extern void __stl_mmu(void);
433 2662e13f bellard
extern void __stq_mmu(void);
434 2662e13f bellard
435 2662e13f bellard
static void *qemu_ld_helpers[4] = {
436 2662e13f bellard
    __ldb_mmu,
437 2662e13f bellard
    __ldw_mmu,
438 2662e13f bellard
    __ldl_mmu,
439 2662e13f bellard
    __ldq_mmu,
440 2662e13f bellard
};
441 2662e13f bellard
442 2662e13f bellard
static void *qemu_st_helpers[4] = {
443 2662e13f bellard
    __stb_mmu,
444 2662e13f bellard
    __stw_mmu,
445 2662e13f bellard
    __stl_mmu,
446 2662e13f bellard
    __stq_mmu,
447 2662e13f bellard
};
448 2662e13f bellard
#endif
449 2662e13f bellard
450 2662e13f bellard
static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
451 2662e13f bellard
{
452 2662e13f bellard
    int addr_reg, data_reg, data_reg2, r0, mem_index, s_bits, bswap;
453 2662e13f bellard
#ifdef CONFIG_SOFTMMU
454 2662e13f bellard
    int r1, r2;
455 2662e13f bellard
    void *label1_ptr, *label2_ptr;
456 2662e13f bellard
#endif
457 2662e13f bellard
#if TARGET_LONG_BITS == 64
458 2662e13f bellard
    int addr_reg2;
459 2662e13f bellard
#endif
460 2662e13f bellard
461 2662e13f bellard
    data_reg = *args++;
462 2662e13f bellard
    if (opc == 3)
463 2662e13f bellard
        data_reg2 = *args++;
464 2662e13f bellard
    else
465 2662e13f bellard
        data_reg2 = 0;
466 2662e13f bellard
    addr_reg = *args++;
467 2662e13f bellard
#if TARGET_LONG_BITS == 64
468 2662e13f bellard
    addr_reg2 = *args++;
469 2662e13f bellard
#endif
470 2662e13f bellard
    mem_index = *args;
471 2662e13f bellard
    s_bits = opc & 3;
472 2662e13f bellard
473 2662e13f bellard
#ifdef CONFIG_SOFTMMU
474 2662e13f bellard
    r0 = 3;
475 2662e13f bellard
    r1 = 4;
476 2662e13f bellard
    r2 = 0;
477 2662e13f bellard
478 2662e13f bellard
    tcg_out32 (s, (RLWINM
479 2662e13f bellard
                   | RA (r0)
480 2662e13f bellard
                   | RS (addr_reg)
481 2662e13f bellard
                   | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
482 2662e13f bellard
                   | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
483 2662e13f bellard
                   | ME (31 - CPU_TLB_ENTRY_BITS)
484 2662e13f bellard
                   )
485 2662e13f bellard
        );
486 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
487 2662e13f bellard
    tcg_out32 (s, (LWZU
488 2662e13f bellard
                   | RT (r1)
489 2662e13f bellard
                   | RA (r0)
490 2662e13f bellard
                   | offsetof (CPUState, tlb_table[mem_index][0].addr_read)
491 2662e13f bellard
                   )
492 2662e13f bellard
        );
493 2662e13f bellard
    tcg_out32 (s, (RLWINM
494 2662e13f bellard
                   | RA (r2)
495 2662e13f bellard
                   | RS (addr_reg)
496 2662e13f bellard
                   | SH (0)
497 2662e13f bellard
                   | MB ((32 - s_bits) & 31)
498 2662e13f bellard
                   | ME (31 - TARGET_PAGE_BITS)
499 2662e13f bellard
                   )
500 2662e13f bellard
        );
501 2662e13f bellard
502 2662e13f bellard
    tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
503 2662e13f bellard
#if TARGET_LONG_BITS == 64
504 2662e13f bellard
    tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
505 2662e13f bellard
    tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
506 2662e13f bellard
    tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
507 2662e13f bellard
#endif
508 2662e13f bellard
509 2662e13f bellard
    label1_ptr = s->code_ptr;
510 2662e13f bellard
#ifdef FAST_PATH
511 2662e13f bellard
    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
512 2662e13f bellard
#endif
513 2662e13f bellard
514 2662e13f bellard
    /* slow path */
515 2662e13f bellard
#if TARGET_LONG_BITS == 32
516 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg);
517 2662e13f bellard
    tcg_out_movi (s, TCG_TYPE_I32, 4, mem_index);
518 2662e13f bellard
#else
519 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg2);
520 2662e13f bellard
    tcg_out_mov (s, 4, addr_reg);
521 2662e13f bellard
    tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
522 2662e13f bellard
#endif
523 2662e13f bellard
524 932a6909 bellard
    tcg_out_b (s, LK, (tcg_target_long) qemu_ld_helpers[s_bits]);
525 2662e13f bellard
    switch (opc) {
526 2662e13f bellard
    case 0|4:
527 2662e13f bellard
        tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
528 2662e13f bellard
        break;
529 2662e13f bellard
    case 1|4:
530 2662e13f bellard
        tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
531 2662e13f bellard
        break;
532 2662e13f bellard
    case 0:
533 2662e13f bellard
    case 1:
534 2662e13f bellard
    case 2:
535 2662e13f bellard
        if (data_reg != 3)
536 2662e13f bellard
            tcg_out_mov (s, data_reg, 3);
537 2662e13f bellard
        break;
538 2662e13f bellard
    case 3:
539 2662e13f bellard
        if (data_reg == 3) {
540 2662e13f bellard
            if (data_reg2 == 4) {
541 2662e13f bellard
                tcg_out_mov (s, 0, 4);
542 2662e13f bellard
                tcg_out_mov (s, 4, 3);
543 2662e13f bellard
                tcg_out_mov (s, 3, 0);
544 2662e13f bellard
            }
545 2662e13f bellard
            else {
546 2662e13f bellard
                tcg_out_mov (s, data_reg2, 3);
547 2662e13f bellard
                tcg_out_mov (s, 3, 4);
548 2662e13f bellard
            }
549 2662e13f bellard
        }
550 2662e13f bellard
        else {
551 2662e13f bellard
            if (data_reg != 4) tcg_out_mov (s, data_reg, 4);
552 2662e13f bellard
            if (data_reg2 != 3) tcg_out_mov (s, data_reg2, 3);
553 2662e13f bellard
        }
554 2662e13f bellard
        break;
555 2662e13f bellard
    }
556 2662e13f bellard
    label2_ptr = s->code_ptr;
557 2662e13f bellard
    tcg_out32 (s, B);
558 2662e13f bellard
559 2662e13f bellard
    /* label1: fast path */
560 2662e13f bellard
#ifdef FAST_PATH
561 2662e13f bellard
    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
562 2662e13f bellard
#endif
563 2662e13f bellard
564 2662e13f bellard
    /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
565 2662e13f bellard
    tcg_out32 (s, (LWZ
566 2662e13f bellard
                   | RT (r0)
567 2662e13f bellard
                   | RA (r0)
568 2662e13f bellard
                   | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
569 2662e13f bellard
                      - offsetof (CPUTLBEntry, addr_read))
570 2662e13f bellard
                   ));
571 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend */
572 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
573 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend + addr */
574 2662e13f bellard
575 2662e13f bellard
#else  /* !CONFIG_SOFTMMU */
576 2662e13f bellard
    r0 = addr_reg;
577 2662e13f bellard
#endif
578 2662e13f bellard
579 2662e13f bellard
#ifdef TARGET_WORDS_BIGENDIAN
580 2662e13f bellard
    bswap = 0;
581 2662e13f bellard
#else
582 2662e13f bellard
    bswap = 1;
583 2662e13f bellard
#endif
584 2662e13f bellard
    switch (opc) {
585 2662e13f bellard
    default:
586 2662e13f bellard
    case 0:
587 2662e13f bellard
        tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
588 2662e13f bellard
        break;
589 2662e13f bellard
    case 0|4:
590 2662e13f bellard
        tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
591 2662e13f bellard
        tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
592 2662e13f bellard
        break;
593 2662e13f bellard
    case 1:
594 2662e13f bellard
        if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
595 2662e13f bellard
        else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0));
596 2662e13f bellard
        break;
597 2662e13f bellard
    case 1|4:
598 2662e13f bellard
        if (bswap) {
599 2662e13f bellard
            tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
600 2662e13f bellard
            tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
601 2662e13f bellard
        }
602 2662e13f bellard
        else tcg_out32 (s, LHA | RT (data_reg) | RA (r0));
603 2662e13f bellard
        break;
604 2662e13f bellard
    case 2:
605 2662e13f bellard
        if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
606 2662e13f bellard
        else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0));
607 2662e13f bellard
        break;
608 2662e13f bellard
    case 3:
609 2662e13f bellard
        if (bswap) {
610 2662e13f bellard
            if (r0 == data_reg) {
611 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (0) | RB (r0));
612 2662e13f bellard
                tcg_out32 (s, ADDI | RT (r0) | RA (r0) |  4);
613 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
614 2662e13f bellard
                tcg_out_mov (s, data_reg, 0);
615 2662e13f bellard
            }
616 2662e13f bellard
            else {
617 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
618 2662e13f bellard
                tcg_out32 (s, ADDI | RT (r0) | RA (r0) |  4);
619 2662e13f bellard
                tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
620 2662e13f bellard
            }
621 2662e13f bellard
        }
622 2662e13f bellard
        else {
623 2662e13f bellard
            if (r0 == data_reg2) {
624 2662e13f bellard
                tcg_out32 (s, LWZ | RT (0) | RA (r0));
625 2662e13f bellard
                tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
626 2662e13f bellard
                tcg_out_mov (s, data_reg2, 0);
627 2662e13f bellard
            }
628 2662e13f bellard
            else {
629 2662e13f bellard
                tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
630 2662e13f bellard
                tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
631 2662e13f bellard
            }
632 2662e13f bellard
        }
633 2662e13f bellard
        break;
634 2662e13f bellard
    }
635 2662e13f bellard
636 2662e13f bellard
#ifdef CONFIG_SOFTMMU
637 2662e13f bellard
    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
638 2662e13f bellard
#endif
639 2662e13f bellard
}
640 2662e13f bellard
641 2662e13f bellard
static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
642 2662e13f bellard
{
643 2662e13f bellard
    int addr_reg, r0, r1, data_reg, data_reg2, mem_index, bswap;
644 2662e13f bellard
#ifdef CONFIG_SOFTMMU
645 2662e13f bellard
    int r2, ir;
646 2662e13f bellard
    void *label1_ptr, *label2_ptr;
647 2662e13f bellard
#endif
648 2662e13f bellard
#if TARGET_LONG_BITS == 64
649 2662e13f bellard
    int addr_reg2;
650 2662e13f bellard
#endif
651 2662e13f bellard
652 2662e13f bellard
    data_reg = *args++;
653 2662e13f bellard
    if (opc == 3)
654 2662e13f bellard
        data_reg2 = *args++;
655 2662e13f bellard
    else
656 2662e13f bellard
        data_reg2 = 0;
657 2662e13f bellard
    addr_reg = *args++;
658 2662e13f bellard
#if TARGET_LONG_BITS == 64
659 2662e13f bellard
    addr_reg2 = *args++;
660 2662e13f bellard
#endif
661 2662e13f bellard
    mem_index = *args;
662 2662e13f bellard
663 2662e13f bellard
#ifdef CONFIG_SOFTMMU
664 2662e13f bellard
    r0 = 3;
665 2662e13f bellard
    r1 = 4;
666 2662e13f bellard
    r2 = 0;
667 2662e13f bellard
668 2662e13f bellard
    tcg_out32 (s, (RLWINM
669 2662e13f bellard
                   | RA (r0)
670 2662e13f bellard
                   | RS (addr_reg)
671 2662e13f bellard
                   | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
672 2662e13f bellard
                   | MB (32 - (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS))
673 2662e13f bellard
                   | ME (31 - CPU_TLB_ENTRY_BITS)
674 2662e13f bellard
                   )
675 2662e13f bellard
        );
676 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
677 2662e13f bellard
    tcg_out32 (s, (LWZU
678 2662e13f bellard
                   | RT (r1)
679 2662e13f bellard
                   | RA (r0)
680 2662e13f bellard
                   | offsetof (CPUState, tlb_table[mem_index][0].addr_write)
681 2662e13f bellard
                   )
682 2662e13f bellard
        );
683 2662e13f bellard
    tcg_out32 (s, (RLWINM
684 2662e13f bellard
                   | RA (r2)
685 2662e13f bellard
                   | RS (addr_reg)
686 2662e13f bellard
                   | SH (0)
687 2662e13f bellard
                   | MB ((32 - opc) & 31)
688 2662e13f bellard
                   | ME (31 - TARGET_PAGE_BITS)
689 2662e13f bellard
                   )
690 2662e13f bellard
        );
691 2662e13f bellard
692 2662e13f bellard
    tcg_out32 (s, CMP | (7 << 23) | RA (r2) | RB (r1));
693 2662e13f bellard
#if TARGET_LONG_BITS == 64
694 2662e13f bellard
    tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
695 2662e13f bellard
    tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
696 2662e13f bellard
    tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
697 2662e13f bellard
#endif
698 2662e13f bellard
699 2662e13f bellard
    label1_ptr = s->code_ptr;
700 2662e13f bellard
#ifdef FAST_PATH
701 2662e13f bellard
    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
702 2662e13f bellard
#endif
703 2662e13f bellard
704 2662e13f bellard
    /* slow path */
705 2662e13f bellard
#if TARGET_LONG_BITS == 32
706 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg);
707 2662e13f bellard
    ir = 4;
708 2662e13f bellard
#else
709 2662e13f bellard
    tcg_out_mov (s, 3, addr_reg2);
710 2662e13f bellard
    tcg_out_mov (s, 4, addr_reg);
711 2662e13f bellard
    ir = 5;
712 2662e13f bellard
#endif
713 2662e13f bellard
714 2662e13f bellard
    switch (opc) {
715 2662e13f bellard
    case 0:
716 2662e13f bellard
        tcg_out32 (s, (RLWINM
717 2662e13f bellard
                       | RA (ir)
718 2662e13f bellard
                       | RS (data_reg)
719 2662e13f bellard
                       | SH (0)
720 2662e13f bellard
                       | MB (24)
721 2662e13f bellard
                       | ME (31)));
722 2662e13f bellard
        break;
723 2662e13f bellard
    case 1:
724 2662e13f bellard
        tcg_out32 (s, (RLWINM
725 2662e13f bellard
                       | RA (ir)
726 2662e13f bellard
                       | RS (data_reg)
727 2662e13f bellard
                       | SH (0)
728 2662e13f bellard
                       | MB (16)
729 2662e13f bellard
                       | ME (31)));
730 2662e13f bellard
        break;
731 2662e13f bellard
    case 2:
732 2662e13f bellard
        tcg_out_mov (s, ir, data_reg);
733 2662e13f bellard
        break;
734 2662e13f bellard
    case 3:
735 2662e13f bellard
        tcg_out_mov (s, 5, data_reg2);
736 2662e13f bellard
        tcg_out_mov (s, 6, data_reg);
737 2662e13f bellard
        ir = 6;
738 2662e13f bellard
        break;
739 2662e13f bellard
    }
740 2662e13f bellard
    ir++;
741 2662e13f bellard
742 2662e13f bellard
    tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
743 932a6909 bellard
    tcg_out_b (s, LK, (tcg_target_long) qemu_st_helpers[opc]);
744 2662e13f bellard
    label2_ptr = s->code_ptr;
745 2662e13f bellard
    tcg_out32 (s, B);
746 2662e13f bellard
747 2662e13f bellard
    /* label1: fast path */
748 2662e13f bellard
#ifdef FAST_PATH
749 2662e13f bellard
    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
750 2662e13f bellard
#endif
751 2662e13f bellard
752 2662e13f bellard
    tcg_out32 (s, (LWZ
753 2662e13f bellard
                   | RT (r0)
754 2662e13f bellard
                   | RA (r0)
755 2662e13f bellard
                   | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
756 2662e13f bellard
                      - offsetof (CPUTLBEntry, addr_write))
757 2662e13f bellard
                   ));
758 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend */
759 2662e13f bellard
    tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
760 2662e13f bellard
    /* r0 = env->tlb_table[mem_index][index].addend + addr */
761 2662e13f bellard
762 2662e13f bellard
#else  /* !CONFIG_SOFTMMU */
763 2662e13f bellard
    r1 = 4;
764 2662e13f bellard
    r0 = addr_reg;
765 2662e13f bellard
#endif
766 2662e13f bellard
767 2662e13f bellard
#ifdef TARGET_WORDS_BIGENDIAN
768 2662e13f bellard
    bswap = 0;
769 2662e13f bellard
#else
770 2662e13f bellard
    bswap = 1;
771 2662e13f bellard
#endif
772 2662e13f bellard
    switch (opc) {
773 2662e13f bellard
    case 0:
774 2662e13f bellard
        tcg_out32 (s, STB | RS (data_reg) | RA (r0));
775 2662e13f bellard
        break;
776 2662e13f bellard
    case 1:
777 2662e13f bellard
        if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0));
778 2662e13f bellard
        else tcg_out32 (s, STH | RS (data_reg) | RA (r0));
779 2662e13f bellard
        break;
780 2662e13f bellard
    case 2:
781 2662e13f bellard
        if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
782 2662e13f bellard
        else tcg_out32 (s, STW | RS (data_reg) | RA (r0));
783 2662e13f bellard
        break;
784 2662e13f bellard
    case 3:
785 2662e13f bellard
        if (bswap) {
786 2662e13f bellard
            tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
787 2662e13f bellard
            tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
788 2662e13f bellard
            tcg_out32 (s, STWBRX | RS (data_reg2) | RA (0) | RB (r1));
789 2662e13f bellard
        }
790 2662e13f bellard
        else {
791 2662e13f bellard
            tcg_out32 (s, STW | RS (data_reg2) | RA (r0));
792 2662e13f bellard
            tcg_out32 (s, STW | RS (data_reg) | RA (r0) | 4);
793 2662e13f bellard
        }
794 2662e13f bellard
        break;
795 2662e13f bellard
    }
796 2662e13f bellard
797 2662e13f bellard
#ifdef CONFIG_SOFTMMU
798 2662e13f bellard
    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
799 2662e13f bellard
#endif
800 2662e13f bellard
}
801 2662e13f bellard
802 2662e13f bellard
void tcg_target_qemu_prologue (TCGContext *s)
803 2662e13f bellard
{
804 2662e13f bellard
    int i, frame_size;
805 2662e13f bellard
806 2662e13f bellard
    frame_size = 0
807 2662e13f bellard
        + 4                     /* back chain */
808 2662e13f bellard
        + 4                     /* LR */
809 2662e13f bellard
        + TCG_STATIC_CALL_ARGS_SIZE
810 2662e13f bellard
        + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
811 2662e13f bellard
        ;
812 2662e13f bellard
    frame_size = (frame_size + 15) & ~15;
813 2662e13f bellard
814 2662e13f bellard
    tcg_out32 (s, MFSPR | RT (0) | LR);
815 2662e13f bellard
    tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
816 2662e13f bellard
    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
817 2662e13f bellard
        tcg_out32 (s, (STW
818 2662e13f bellard
                       | RS (tcg_target_callee_save_regs[i])
819 2662e13f bellard
                       | RA (1)
820 2662e13f bellard
                       | (i * 4 + 8 + TCG_STATIC_CALL_ARGS_SIZE)
821 2662e13f bellard
                       )
822 2662e13f bellard
            );
823 2662e13f bellard
    tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size - 4));
824 2662e13f bellard
825 2662e13f bellard
    tcg_out32 (s, MTSPR | RS (3) | CTR);
826 2662e13f bellard
    tcg_out32 (s, BCCTR | BO_ALWAYS);
827 2662e13f bellard
    tb_ret_addr = s->code_ptr;
828 2662e13f bellard
829 2662e13f bellard
    for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
830 2662e13f bellard
        tcg_out32 (s, (LWZ
831 2662e13f bellard
                       | RT (tcg_target_callee_save_regs[i])
832 2662e13f bellard
                       | RA (1)
833 2662e13f bellard
                       | (i * 4 + 8 + TCG_STATIC_CALL_ARGS_SIZE)
834 2662e13f bellard
                       )
835 2662e13f bellard
            );
836 2662e13f bellard
    tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size - 4));
837 2662e13f bellard
    tcg_out32 (s, MTSPR | RS (0) | LR);
838 2662e13f bellard
    tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
839 2662e13f bellard
    tcg_out32 (s, BCLR | BO_ALWAYS);
840 2662e13f bellard
}
841 2662e13f bellard
842 2662e13f bellard
static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
843 2662e13f bellard
                        tcg_target_long arg2)
844 2662e13f bellard
{
845 2662e13f bellard
    tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
846 2662e13f bellard
}
847 2662e13f bellard
848 2662e13f bellard
static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
849 2662e13f bellard
                        tcg_target_long arg2)
850 2662e13f bellard
{
851 2662e13f bellard
    tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
852 2662e13f bellard
}
853 2662e13f bellard
854 2662e13f bellard
static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
855 2662e13f bellard
{
856 2662e13f bellard
    if (!si && rt == ra)
857 2662e13f bellard
        return;
858 2662e13f bellard
859 2662e13f bellard
    if (si == (int16_t) si)
860 2662e13f bellard
        tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
861 2662e13f bellard
    else {
862 2662e13f bellard
        uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
863 2662e13f bellard
        tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
864 2662e13f bellard
        tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
865 2662e13f bellard
    }
866 2662e13f bellard
}
867 2662e13f bellard
868 2662e13f bellard
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
869 2662e13f bellard
{
870 2662e13f bellard
    ppc_addi (s, reg, reg, val);
871 2662e13f bellard
}
872 2662e13f bellard
873 2662e13f bellard
static void tcg_out_brcond(TCGContext *s, int cond,
874 2662e13f bellard
                           TCGArg arg1, TCGArg arg2, int const_arg2,
875 2662e13f bellard
                           int label_index)
876 2662e13f bellard
{
877 2662e13f bellard
    TCGLabel *l = &s->labels[label_index];
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 2662e13f bellard
    op |= BF (7);
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 0a878c47 malc
    if (l->has_value)
947 2662e13f bellard
        tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr,
948 2662e13f bellard
                                                        l->u.value));
949 2662e13f bellard
    else {
950 0a878c47 malc
        uint16_t val = *(uint16_t *) &s->code_ptr[2];
951 0a878c47 malc
952 0a878c47 malc
        /* Thanks to Andrzej Zaborowski */
953 0a878c47 malc
        tcg_out32 (s, tcg_to_bc[cond] | (val & 0xfffc));
954 2662e13f bellard
        tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
955 2662e13f bellard
    }
956 2662e13f bellard
}
957 2662e13f bellard
958 2662e13f bellard
/* brcond2 is taken verbatim from i386 tcg-target */
959 2662e13f bellard
/* XXX: we implement it at the target level to avoid having to
960 2662e13f bellard
   handle cross basic blocks temporaries */
961 2662e13f bellard
static void tcg_out_brcond2(TCGContext *s,
962 2662e13f bellard
                            const TCGArg *args, const int *const_args)
963 2662e13f bellard
{
964 2662e13f bellard
    int label_next;
965 2662e13f bellard
    label_next = gen_new_label();
966 2662e13f bellard
    switch(args[4]) {
967 2662e13f bellard
    case TCG_COND_EQ:
968 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], label_next);
969 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3], args[5]);
970 2662e13f bellard
        break;
971 2662e13f bellard
    case TCG_COND_NE:
972 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], args[5]);
973 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], args[5]);
974 2662e13f bellard
        break;
975 2662e13f bellard
    case TCG_COND_LT:
976 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
977 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
978 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LT, args[0], args[2], const_args[2], args[5]);
979 2662e13f bellard
        break;
980 2662e13f bellard
    case TCG_COND_LE:
981 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
982 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
983 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LE, args[0], args[2], const_args[2], args[5]);
984 2662e13f bellard
        break;
985 2662e13f bellard
    case TCG_COND_GT:
986 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
987 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
988 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GT, args[0], args[2], const_args[2], args[5]);
989 2662e13f bellard
        break;
990 2662e13f bellard
    case TCG_COND_GE:
991 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
992 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
993 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GE, args[0], args[2], const_args[2], args[5]);
994 2662e13f bellard
        break;
995 2662e13f bellard
    case TCG_COND_LTU:
996 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
997 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
998 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
999 2662e13f bellard
        break;
1000 2662e13f bellard
    case TCG_COND_LEU:
1001 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
1002 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
1003 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
1004 2662e13f bellard
        break;
1005 2662e13f bellard
    case TCG_COND_GTU:
1006 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
1007 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
1008 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
1009 2662e13f bellard
        break;
1010 2662e13f bellard
    case TCG_COND_GEU:
1011 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
1012 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
1013 2662e13f bellard
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
1014 2662e13f bellard
        break;
1015 2662e13f bellard
    default:
1016 2662e13f bellard
        tcg_abort();
1017 2662e13f bellard
    }
1018 2662e13f bellard
    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
1019 2662e13f bellard
}
1020 2662e13f bellard
1021 398ce98e malc
static uint64_t __attribute ((used)) ppc_udiv_helper (uint64_t a, uint32_t b)
1022 398ce98e malc
{
1023 398ce98e malc
    uint64_t rem, quo;
1024 398ce98e malc
    quo = a / b;
1025 398ce98e malc
    rem = a % b;
1026 398ce98e malc
    return (rem << 32) | (uint32_t) quo;
1027 398ce98e malc
}
1028 398ce98e malc
1029 398ce98e malc
static uint64_t __attribute ((used)) ppc_div_helper (int64_t a, int32_t b)
1030 398ce98e malc
{
1031 398ce98e malc
    int64_t rem, quo;
1032 398ce98e malc
    quo = a / b;
1033 398ce98e malc
    rem = a % b;
1034 398ce98e malc
    return (rem << 32) | (uint32_t) quo;
1035 398ce98e malc
}
1036 398ce98e malc
1037 398ce98e malc
#define MAKE_TRAMPOLINE(name)                   \
1038 398ce98e malc
extern void name##_trampoline (void);           \
1039 398ce98e malc
asm (#name "_trampoline:\n"                     \
1040 398ce98e malc
     " mflr 0\n"                                \
1041 398ce98e malc
     " addi 1,1,-112\n"                         \
1042 398ce98e malc
     " mr   4,6\n"                              \
1043 398ce98e malc
     " stmw 7,0(1)\n"                           \
1044 398ce98e malc
     " stw  0,108(0)\n"                         \
1045 398ce98e malc
     " bl   ppc_" #name "_helper\n"             \
1046 398ce98e malc
     " lmw  7,0(1)\n"                           \
1047 398ce98e malc
     " lwz  0,108(0)\n"                         \
1048 398ce98e malc
     " addi 1,1,112\n"                          \
1049 398ce98e malc
     " mtlr 0\n"                                \
1050 398ce98e malc
     " blr\n"                                   \
1051 398ce98e malc
    )
1052 398ce98e malc
1053 398ce98e malc
MAKE_TRAMPOLINE (div);
1054 398ce98e malc
MAKE_TRAMPOLINE (udiv);
1055 398ce98e malc
1056 398ce98e malc
static void tcg_out_div2 (TCGContext *s, int uns)
1057 398ce98e malc
{
1058 398ce98e malc
    void *label1_ptr, *label2_ptr;
1059 398ce98e malc
1060 5d794885 malc
    if (uns)
1061 5d794885 malc
        tcg_out32 (s, CMPLI | BF (7) | RA (3));
1062 5d794885 malc
    else {
1063 5d794885 malc
        tcg_out32 (s, SRAWI | RS (4) | RA (0) | 31);
1064 5d794885 malc
        tcg_out32 (s, CMPL | BF (7) | RA (3) | RB (4));
1065 5d794885 malc
    }
1066 5d794885 malc
1067 398ce98e malc
    label1_ptr = s->code_ptr;
1068 398ce98e malc
    tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
1069 398ce98e malc
1070 398ce98e malc
    tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_trampoline : div_trampoline));
1071 398ce98e malc
1072 398ce98e malc
    label2_ptr = s->code_ptr;
1073 398ce98e malc
    tcg_out32 (s, B);
1074 398ce98e malc
1075 398ce98e malc
    reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
1076 398ce98e malc
1077 398ce98e malc
    tcg_out32 (s, (uns ? DIVWU : DIVW) | TAB (6, 4, 5));
1078 398ce98e malc
    tcg_out32 (s, MULLW | TAB (0, 6, 5));
1079 398ce98e malc
    tcg_out32 (s, SUBF | TAB (3, 0, 4));
1080 398ce98e malc
1081 398ce98e malc
    reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
1082 398ce98e malc
}
1083 398ce98e malc
1084 2662e13f bellard
static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
1085 2662e13f bellard
                       const int *const_args)
1086 2662e13f bellard
{
1087 2662e13f bellard
    switch (opc) {
1088 2662e13f bellard
    case INDEX_op_exit_tb:
1089 2662e13f bellard
        tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
1090 932a6909 bellard
        tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
1091 2662e13f bellard
        break;
1092 2662e13f bellard
    case INDEX_op_goto_tb:
1093 2662e13f bellard
        if (s->tb_jmp_offset) {
1094 2662e13f bellard
            /* direct jump method */
1095 932a6909 bellard
1096 2662e13f bellard
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1097 0a878c47 malc
            s->code_ptr += 16;
1098 932a6909 bellard
        }
1099 932a6909 bellard
        else {
1100 2662e13f bellard
            tcg_abort ();
1101 2662e13f bellard
        }
1102 2662e13f bellard
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1103 2662e13f bellard
        break;
1104 2662e13f bellard
    case INDEX_op_br:
1105 2662e13f bellard
        {
1106 2662e13f bellard
            TCGLabel *l = &s->labels[args[0]];
1107 2662e13f bellard
1108 2662e13f bellard
            if (l->has_value) {
1109 932a6909 bellard
                tcg_out_b (s, 0, l->u.value);
1110 2662e13f bellard
            }
1111 2662e13f bellard
            else {
1112 0a878c47 malc
                uint32_t val = *(uint32_t *) s->code_ptr;
1113 0a878c47 malc
1114 0a878c47 malc
                /* Thanks to Andrzej Zaborowski */
1115 0a878c47 malc
                tcg_out32 (s, B | (val & 0x3fffffc));
1116 2662e13f bellard
                tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
1117 2662e13f bellard
            }
1118 2662e13f bellard
        }
1119 2662e13f bellard
        break;
1120 2662e13f bellard
    case INDEX_op_call:
1121 2662e13f bellard
        if (const_args[0]) {
1122 932a6909 bellard
            tcg_out_b (s, LK, args[0]);
1123 2662e13f bellard
        }
1124 2662e13f bellard
        else {
1125 2662e13f bellard
            tcg_out32 (s, MTSPR | RS (args[0]) | LR);
1126 2662e13f bellard
            tcg_out32 (s, BCLR | BO_ALWAYS | LK);
1127 2662e13f bellard
        }
1128 2662e13f bellard
        break;
1129 2662e13f bellard
    case INDEX_op_jmp:
1130 2662e13f bellard
        if (const_args[0]) {
1131 932a6909 bellard
            tcg_out_b (s, 0, args[0]);
1132 2662e13f bellard
        }
1133 2662e13f bellard
        else {
1134 2662e13f bellard
            tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
1135 2662e13f bellard
            tcg_out32 (s, BCCTR | BO_ALWAYS);
1136 2662e13f bellard
        }
1137 2662e13f bellard
        break;
1138 2662e13f bellard
    case INDEX_op_movi_i32:
1139 2662e13f bellard
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1140 2662e13f bellard
        break;
1141 2662e13f bellard
    case INDEX_op_ld8u_i32:
1142 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1143 2662e13f bellard
        break;
1144 2662e13f bellard
    case INDEX_op_ld8s_i32:
1145 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
1146 2662e13f bellard
        tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
1147 2662e13f bellard
        break;
1148 2662e13f bellard
    case INDEX_op_ld16u_i32:
1149 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
1150 2662e13f bellard
        break;
1151 2662e13f bellard
    case INDEX_op_ld16s_i32:
1152 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
1153 2662e13f bellard
        break;
1154 2662e13f bellard
    case INDEX_op_ld_i32:
1155 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
1156 2662e13f bellard
        break;
1157 2662e13f bellard
    case INDEX_op_st8_i32:
1158 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
1159 2662e13f bellard
        break;
1160 2662e13f bellard
    case INDEX_op_st16_i32:
1161 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
1162 2662e13f bellard
        break;
1163 2662e13f bellard
    case INDEX_op_st_i32:
1164 2662e13f bellard
        tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
1165 2662e13f bellard
        break;
1166 2662e13f bellard
1167 2662e13f bellard
    case INDEX_op_add_i32:
1168 2662e13f bellard
        if (const_args[2])
1169 2662e13f bellard
            ppc_addi (s, args[0], args[1], args[2]);
1170 2662e13f bellard
        else
1171 2662e13f bellard
            tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
1172 2662e13f bellard
        break;
1173 2662e13f bellard
    case INDEX_op_sub_i32:
1174 2662e13f bellard
        if (const_args[2])
1175 2662e13f bellard
            ppc_addi (s, args[0], args[1], -args[2]);
1176 2662e13f bellard
        else
1177 2662e13f bellard
            tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
1178 2662e13f bellard
        break;
1179 2662e13f bellard
1180 2662e13f bellard
    case INDEX_op_and_i32:
1181 2662e13f bellard
        if (const_args[2]) {
1182 2662e13f bellard
            if (!args[2])
1183 2662e13f bellard
                tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
1184 2662e13f bellard
            else {
1185 2662e13f bellard
                if ((args[2] & 0xffff) == args[2])
1186 2662e13f bellard
                    tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
1187 2662e13f bellard
                else if ((args[2] & 0xffff0000) == args[2])
1188 2662e13f bellard
                    tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
1189 2662e13f bellard
                               | ((args[2] >> 16) & 0xffff));
1190 2662e13f bellard
                else if (args[2] == 0xffffffff) {
1191 2662e13f bellard
                    if (args[0] != args[1])
1192 2662e13f bellard
                        tcg_out_mov (s, args[0], args[1]);
1193 2662e13f bellard
                }
1194 2662e13f bellard
                else {
1195 2662e13f bellard
                    tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1196 2662e13f bellard
                    tcg_out32 (s, AND | SAB (args[1], args[0], 0));
1197 2662e13f bellard
                }
1198 2662e13f bellard
            }
1199 2662e13f bellard
        }
1200 2662e13f bellard
        else
1201 2662e13f bellard
            tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
1202 2662e13f bellard
        break;
1203 2662e13f bellard
    case INDEX_op_or_i32:
1204 2662e13f bellard
        if (const_args[2]) {
1205 2662e13f bellard
            if (args[2]) {
1206 2662e13f bellard
                if (args[2] & 0xffff) {
1207 932a6909 bellard
                    tcg_out32 (s, ORI | RS (args[1])  | RA (args[0])
1208 932a6909 bellard
                               | (args[2] & 0xffff));
1209 2662e13f bellard
                    if (args[2] >> 16)
1210 2662e13f bellard
                        tcg_out32 (s, ORIS | RS (args[0])  | RA (args[0])
1211 2662e13f bellard
                                   | ((args[2] >> 16) & 0xffff));
1212 2662e13f bellard
                }
1213 2662e13f bellard
                else {
1214 2662e13f bellard
                    tcg_out32 (s, ORIS | RS (args[1])  | RA (args[0])
1215 2662e13f bellard
                               | ((args[2] >> 16) & 0xffff));
1216 2662e13f bellard
                }
1217 2662e13f bellard
            }
1218 2662e13f bellard
            else {
1219 2662e13f bellard
                if (args[0] != args[1])
1220 2662e13f bellard
                    tcg_out_mov (s, args[0], args[1]);
1221 2662e13f bellard
            }
1222 2662e13f bellard
        }
1223 2662e13f bellard
        else
1224 2662e13f bellard
            tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
1225 2662e13f bellard
        break;
1226 2662e13f bellard
    case INDEX_op_xor_i32:
1227 2662e13f bellard
        if (const_args[2]) {
1228 2662e13f bellard
            if (args[2]) {
1229 2662e13f bellard
                if ((args[2] & 0xffff) == args[2])
1230 2662e13f bellard
                    tcg_out32 (s, XORI | RS (args[1])  | RA (args[0])
1231 2662e13f bellard
                               | (args[2] & 0xffff));
1232 2662e13f bellard
                else if ((args[2] & 0xffff0000) == args[2])
1233 2662e13f bellard
                    tcg_out32 (s, XORIS | RS (args[1])  | RA (args[0])
1234 2662e13f bellard
                               | ((args[2] >> 16) & 0xffff));
1235 2662e13f bellard
                else {
1236 2662e13f bellard
                    tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1237 2662e13f bellard
                    tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
1238 2662e13f bellard
                }
1239 2662e13f bellard
            }
1240 2662e13f bellard
            else {
1241 2662e13f bellard
                if (args[0] != args[1])
1242 2662e13f bellard
                    tcg_out_mov (s, args[0], args[1]);
1243 2662e13f bellard
            }
1244 2662e13f bellard
        }
1245 2662e13f bellard
        else
1246 2662e13f bellard
            tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
1247 2662e13f bellard
        break;
1248 2662e13f bellard
1249 2662e13f bellard
    case INDEX_op_mul_i32:
1250 2662e13f bellard
        if (const_args[2]) {
1251 2662e13f bellard
            if (args[2] == (int16_t) args[2])
1252 2662e13f bellard
                tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
1253 2662e13f bellard
                           | (args[2] & 0xffff));
1254 2662e13f bellard
            else {
1255 2662e13f bellard
                tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
1256 2662e13f bellard
                tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
1257 2662e13f bellard
            }
1258 2662e13f bellard
        }
1259 2662e13f bellard
        else
1260 2662e13f bellard
            tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
1261 2662e13f bellard
        break;
1262 2662e13f bellard
    case INDEX_op_mulu2_i32:
1263 2662e13f bellard
        if (args[0] == args[2] || args[0] == args[3]) {
1264 2662e13f bellard
            tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
1265 2662e13f bellard
            tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1266 2662e13f bellard
            tcg_out_mov (s, args[0], 0);
1267 2662e13f bellard
        }
1268 2662e13f bellard
        else {
1269 2662e13f bellard
            tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
1270 2662e13f bellard
            tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
1271 2662e13f bellard
        }
1272 2662e13f bellard
        break;
1273 2662e13f bellard
    case INDEX_op_div2_i32:
1274 398ce98e malc
        tcg_out_div2 (s, 0);
1275 2662e13f bellard
        break;
1276 2662e13f bellard
    case INDEX_op_divu2_i32:
1277 398ce98e malc
        tcg_out_div2 (s, 1);
1278 2662e13f bellard
        break;
1279 2662e13f bellard
1280 2662e13f bellard
    case INDEX_op_shl_i32:
1281 2662e13f bellard
        if (const_args[2]) {
1282 2662e13f bellard
            if (args[2])
1283 2662e13f bellard
                tcg_out32 (s, (RLWINM
1284 2662e13f bellard
                               | RA (args[0])
1285 2662e13f bellard
                               | RS (args[1])
1286 2662e13f bellard
                               | SH (args[2])
1287 2662e13f bellard
                               | MB (0)
1288 2662e13f bellard
                               | ME (31 - args[2])
1289 2662e13f bellard
                               )
1290 2662e13f bellard
                    );
1291 2662e13f bellard
            else
1292 2662e13f bellard
                tcg_out_mov (s, args[0], args[1]);
1293 2662e13f bellard
        }
1294 2662e13f bellard
        else
1295 2662e13f bellard
            tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
1296 2662e13f bellard
        break;
1297 2662e13f bellard
    case INDEX_op_shr_i32:
1298 2662e13f bellard
        if (const_args[2]) {
1299 2662e13f bellard
            if (args[2])
1300 2662e13f bellard
                tcg_out32 (s, (RLWINM
1301 2662e13f bellard
                               | RA (args[0])
1302 2662e13f bellard
                               | RS (args[1])
1303 2662e13f bellard
                               | SH (32 - args[2])
1304 2662e13f bellard
                               | MB (args[2])
1305 2662e13f bellard
                               | ME (31)
1306 2662e13f bellard
                               )
1307 2662e13f bellard
                    );
1308 2662e13f bellard
            else
1309 2662e13f bellard
                tcg_out_mov (s, args[0], args[1]);
1310 2662e13f bellard
        }
1311 2662e13f bellard
        else
1312 2662e13f bellard
            tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
1313 2662e13f bellard
        break;
1314 2662e13f bellard
    case INDEX_op_sar_i32:
1315 2662e13f bellard
        if (const_args[2])
1316 2662e13f bellard
            tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
1317 2662e13f bellard
        else
1318 2662e13f bellard
            tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
1319 2662e13f bellard
        break;
1320 2662e13f bellard
1321 2662e13f bellard
    case INDEX_op_add2_i32:
1322 2662e13f bellard
        if (args[0] == args[3] || args[0] == args[5]) {
1323 2662e13f bellard
            tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
1324 2662e13f bellard
            tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1325 2662e13f bellard
            tcg_out_mov (s, args[0], 0);
1326 2662e13f bellard
        }
1327 2662e13f bellard
        else {
1328 2662e13f bellard
            tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
1329 2662e13f bellard
            tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
1330 2662e13f bellard
        }
1331 2662e13f bellard
        break;
1332 2662e13f bellard
    case INDEX_op_sub2_i32:
1333 2662e13f bellard
        if (args[0] == args[3] || args[0] == args[5]) {
1334 2662e13f bellard
            tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
1335 2662e13f bellard
            tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1336 2662e13f bellard
            tcg_out_mov (s, args[0], 0);
1337 2662e13f bellard
        }
1338 2662e13f bellard
        else {
1339 2662e13f bellard
            tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
1340 2662e13f bellard
            tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
1341 2662e13f bellard
        }
1342 2662e13f bellard
        break;
1343 2662e13f bellard
1344 2662e13f bellard
    case INDEX_op_brcond_i32:
1345 2662e13f bellard
        /*
1346 2662e13f bellard
          args[0] = r0
1347 2662e13f bellard
          args[1] = r1
1348 2662e13f bellard
          args[2] = cond
1349 2662e13f bellard
          args[3] = r1 is const
1350 2662e13f bellard
          args[4] = label_index
1351 2662e13f bellard
        */
1352 2662e13f bellard
        tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
1353 2662e13f bellard
        break;
1354 2662e13f bellard
    case INDEX_op_brcond2_i32:
1355 2662e13f bellard
        tcg_out_brcond2(s, args, const_args);
1356 2662e13f bellard
        break;
1357 2662e13f bellard
1358 2662e13f bellard
    case INDEX_op_neg_i32:
1359 2662e13f bellard
        tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
1360 2662e13f bellard
        break;
1361 2662e13f bellard
1362 2662e13f bellard
    case INDEX_op_qemu_ld8u:
1363 2662e13f bellard
        tcg_out_qemu_ld(s, args, 0);
1364 2662e13f bellard
        break;
1365 2662e13f bellard
    case INDEX_op_qemu_ld8s:
1366 2662e13f bellard
        tcg_out_qemu_ld(s, args, 0 | 4);
1367 2662e13f bellard
        break;
1368 2662e13f bellard
    case INDEX_op_qemu_ld16u:
1369 2662e13f bellard
        tcg_out_qemu_ld(s, args, 1);
1370 2662e13f bellard
        break;
1371 2662e13f bellard
    case INDEX_op_qemu_ld16s:
1372 2662e13f bellard
        tcg_out_qemu_ld(s, args, 1 | 4);
1373 2662e13f bellard
        break;
1374 2662e13f bellard
    case INDEX_op_qemu_ld32u:
1375 2662e13f bellard
        tcg_out_qemu_ld(s, args, 2);
1376 2662e13f bellard
        break;
1377 2662e13f bellard
    case INDEX_op_qemu_ld64:
1378 2662e13f bellard
        tcg_out_qemu_ld(s, args, 3);
1379 2662e13f bellard
        break;
1380 2662e13f bellard
    case INDEX_op_qemu_st8:
1381 2662e13f bellard
        tcg_out_qemu_st(s, args, 0);
1382 2662e13f bellard
        break;
1383 2662e13f bellard
    case INDEX_op_qemu_st16:
1384 2662e13f bellard
        tcg_out_qemu_st(s, args, 1);
1385 2662e13f bellard
        break;
1386 2662e13f bellard
    case INDEX_op_qemu_st32:
1387 2662e13f bellard
        tcg_out_qemu_st(s, args, 2);
1388 2662e13f bellard
        break;
1389 2662e13f bellard
    case INDEX_op_qemu_st64:
1390 2662e13f bellard
        tcg_out_qemu_st(s, args, 3);
1391 2662e13f bellard
        break;
1392 2662e13f bellard
1393 2662e13f bellard
    default:
1394 2662e13f bellard
        tcg_dump_ops (s, stderr);
1395 2662e13f bellard
        tcg_abort ();
1396 2662e13f bellard
    }
1397 2662e13f bellard
}
1398 2662e13f bellard
1399 2662e13f bellard
static const TCGTargetOpDef ppc_op_defs[] = {
1400 2662e13f bellard
    { INDEX_op_exit_tb, { } },
1401 2662e13f bellard
    { INDEX_op_goto_tb, { } },
1402 932a6909 bellard
    { INDEX_op_call, { "ri" } },
1403 932a6909 bellard
    { INDEX_op_jmp, { "ri" } },
1404 2662e13f bellard
    { INDEX_op_br, { } },
1405 2662e13f bellard
1406 2662e13f bellard
    { INDEX_op_mov_i32, { "r", "r" } },
1407 2662e13f bellard
    { INDEX_op_movi_i32, { "r" } },
1408 2662e13f bellard
    { INDEX_op_ld8u_i32, { "r", "r" } },
1409 2662e13f bellard
    { INDEX_op_ld8s_i32, { "r", "r" } },
1410 2662e13f bellard
    { INDEX_op_ld16u_i32, { "r", "r" } },
1411 2662e13f bellard
    { INDEX_op_ld16s_i32, { "r", "r" } },
1412 2662e13f bellard
    { INDEX_op_ld_i32, { "r", "r" } },
1413 2662e13f bellard
    { INDEX_op_st8_i32, { "r", "r" } },
1414 2662e13f bellard
    { INDEX_op_st16_i32, { "r", "r" } },
1415 2662e13f bellard
    { INDEX_op_st_i32, { "r", "r" } },
1416 2662e13f bellard
1417 2662e13f bellard
    { INDEX_op_add_i32, { "r", "r", "ri" } },
1418 2662e13f bellard
    { INDEX_op_mul_i32, { "r", "r", "ri" } },
1419 2662e13f bellard
    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1420 398ce98e malc
    { INDEX_op_div2_i32, { "D", "A", "B", "1", "C" } },
1421 398ce98e malc
    { INDEX_op_divu2_i32, { "D", "A", "B", "1", "C" } },
1422 2662e13f bellard
    { INDEX_op_sub_i32, { "r", "r", "ri" } },
1423 2662e13f bellard
    { INDEX_op_and_i32, { "r", "r", "ri" } },
1424 2662e13f bellard
    { INDEX_op_or_i32, { "r", "r", "ri" } },
1425 2662e13f bellard
    { INDEX_op_xor_i32, { "r", "r", "ri" } },
1426 2662e13f bellard
1427 2662e13f bellard
    { INDEX_op_shl_i32, { "r", "r", "ri" } },
1428 2662e13f bellard
    { INDEX_op_shr_i32, { "r", "r", "ri" } },
1429 2662e13f bellard
    { INDEX_op_sar_i32, { "r", "r", "ri" } },
1430 2662e13f bellard
1431 2662e13f bellard
    { INDEX_op_brcond_i32, { "r", "ri" } },
1432 2662e13f bellard
1433 2662e13f bellard
    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1434 2662e13f bellard
    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1435 2662e13f bellard
    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1436 2662e13f bellard
1437 2662e13f bellard
    { INDEX_op_neg_i32, { "r", "r" } },
1438 2662e13f bellard
1439 2662e13f bellard
#if TARGET_LONG_BITS == 32
1440 2662e13f bellard
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1441 2662e13f bellard
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1442 2662e13f bellard
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1443 2662e13f bellard
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1444 2662e13f bellard
    { INDEX_op_qemu_ld32u, { "r", "L" } },
1445 2662e13f bellard
    { INDEX_op_qemu_ld32s, { "r", "L" } },
1446 2662e13f bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1447 2662e13f bellard
1448 2662e13f bellard
    { INDEX_op_qemu_st8, { "K", "K" } },
1449 2662e13f bellard
    { INDEX_op_qemu_st16, { "K", "K" } },
1450 2662e13f bellard
    { INDEX_op_qemu_st32, { "K", "K" } },
1451 2662e13f bellard
    { INDEX_op_qemu_st64, { "M", "M", "M" } },
1452 2662e13f bellard
#else
1453 2662e13f bellard
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1454 2662e13f bellard
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1455 2662e13f bellard
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1456 2662e13f bellard
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1457 2662e13f bellard
    { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1458 2662e13f bellard
    { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
1459 2662e13f bellard
    { INDEX_op_qemu_ld64, { "r", "L", "L", "L" } },
1460 2662e13f bellard
1461 2662e13f bellard
    { INDEX_op_qemu_st8, { "K", "K", "K" } },
1462 2662e13f bellard
    { INDEX_op_qemu_st16, { "K", "K", "K" } },
1463 2662e13f bellard
    { INDEX_op_qemu_st32, { "K", "K", "K" } },
1464 2662e13f bellard
    { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
1465 2662e13f bellard
#endif
1466 2662e13f bellard
1467 2662e13f bellard
    { -1 },
1468 2662e13f bellard
};
1469 2662e13f bellard
1470 2662e13f bellard
void tcg_target_init(TCGContext *s)
1471 2662e13f bellard
{
1472 2662e13f bellard
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1473 2662e13f bellard
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1474 2662e13f bellard
                     (1 << TCG_REG_R0) |
1475 2662e13f bellard
                     (1 << TCG_REG_R3) |
1476 2662e13f bellard
                     (1 << TCG_REG_R4) |
1477 2662e13f bellard
                     (1 << TCG_REG_R5) |
1478 2662e13f bellard
                     (1 << TCG_REG_R6) |
1479 2662e13f bellard
                     (1 << TCG_REG_R7) |
1480 2662e13f bellard
                     (1 << TCG_REG_R8) |
1481 2662e13f bellard
                     (1 << TCG_REG_R9) |
1482 2662e13f bellard
                     (1 << TCG_REG_R10) |
1483 2662e13f bellard
                     (1 << TCG_REG_R11) |
1484 2662e13f bellard
                     (1 << TCG_REG_R12)
1485 2662e13f bellard
        );
1486 2662e13f bellard
1487 2662e13f bellard
    tcg_regset_clear(s->reserved_regs);
1488 2662e13f bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
1489 2662e13f bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
1490 2662e13f bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
1491 2662e13f bellard
1492 2662e13f bellard
    tcg_add_target_add_op_defs(ppc_op_defs);
1493 2662e13f bellard
}