Statistics
| Branch: | Revision:

root / tcg / mips / tcg-target.c @ 4cb26382

History | View | Annotate | Download (41.6 kB)

1 afa05235 Aurelien Jarno
/*
2 afa05235 Aurelien Jarno
 * Tiny Code Generator for QEMU
3 afa05235 Aurelien Jarno
 *
4 afa05235 Aurelien Jarno
 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5 afa05235 Aurelien Jarno
 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6 afa05235 Aurelien Jarno
 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
7 afa05235 Aurelien Jarno
 *
8 afa05235 Aurelien Jarno
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 afa05235 Aurelien Jarno
 * of this software and associated documentation files (the "Software"), to deal
10 afa05235 Aurelien Jarno
 * in the Software without restriction, including without limitation the rights
11 afa05235 Aurelien Jarno
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 afa05235 Aurelien Jarno
 * copies of the Software, and to permit persons to whom the Software is
13 afa05235 Aurelien Jarno
 * furnished to do so, subject to the following conditions:
14 afa05235 Aurelien Jarno
 *
15 afa05235 Aurelien Jarno
 * The above copyright notice and this permission notice shall be included in
16 afa05235 Aurelien Jarno
 * all copies or substantial portions of the Software.
17 afa05235 Aurelien Jarno
 *
18 afa05235 Aurelien Jarno
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 afa05235 Aurelien Jarno
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 afa05235 Aurelien Jarno
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 afa05235 Aurelien Jarno
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 afa05235 Aurelien Jarno
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 afa05235 Aurelien Jarno
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 afa05235 Aurelien Jarno
 * THE SOFTWARE.
25 afa05235 Aurelien Jarno
 */
26 afa05235 Aurelien Jarno
27 afa05235 Aurelien Jarno
#if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28 afa05235 Aurelien Jarno
# define TCG_NEED_BSWAP 0
29 afa05235 Aurelien Jarno
#else
30 afa05235 Aurelien Jarno
# define TCG_NEED_BSWAP 1
31 afa05235 Aurelien Jarno
#endif
32 afa05235 Aurelien Jarno
33 afa05235 Aurelien Jarno
#ifndef NDEBUG
34 afa05235 Aurelien Jarno
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35 afa05235 Aurelien Jarno
    "zero",
36 afa05235 Aurelien Jarno
    "at",
37 afa05235 Aurelien Jarno
    "v0",
38 afa05235 Aurelien Jarno
    "v1",
39 afa05235 Aurelien Jarno
    "a0",
40 afa05235 Aurelien Jarno
    "a1",
41 afa05235 Aurelien Jarno
    "a2",
42 afa05235 Aurelien Jarno
    "a3",
43 afa05235 Aurelien Jarno
    "t0",
44 afa05235 Aurelien Jarno
    "t1",
45 afa05235 Aurelien Jarno
    "t2",
46 afa05235 Aurelien Jarno
    "t3",
47 afa05235 Aurelien Jarno
    "t4",
48 afa05235 Aurelien Jarno
    "t5",
49 afa05235 Aurelien Jarno
    "t6",
50 afa05235 Aurelien Jarno
    "t7",
51 afa05235 Aurelien Jarno
    "s0",
52 afa05235 Aurelien Jarno
    "s1",
53 afa05235 Aurelien Jarno
    "s2",
54 afa05235 Aurelien Jarno
    "s3",
55 afa05235 Aurelien Jarno
    "s4",
56 afa05235 Aurelien Jarno
    "s5",
57 afa05235 Aurelien Jarno
    "s6",
58 afa05235 Aurelien Jarno
    "s7",
59 afa05235 Aurelien Jarno
    "t8",
60 afa05235 Aurelien Jarno
    "t9",
61 afa05235 Aurelien Jarno
    "k0",
62 afa05235 Aurelien Jarno
    "k1",
63 afa05235 Aurelien Jarno
    "gp",
64 afa05235 Aurelien Jarno
    "sp",
65 afa05235 Aurelien Jarno
    "fp",
66 afa05235 Aurelien Jarno
    "ra",
67 afa05235 Aurelien Jarno
};
68 afa05235 Aurelien Jarno
#endif
69 afa05235 Aurelien Jarno
70 afa05235 Aurelien Jarno
/* check if we really need so many registers :P */
71 afa05235 Aurelien Jarno
static const int tcg_target_reg_alloc_order[] = {
72 afa05235 Aurelien Jarno
    TCG_REG_S0,
73 afa05235 Aurelien Jarno
    TCG_REG_S1,
74 afa05235 Aurelien Jarno
    TCG_REG_S2,
75 afa05235 Aurelien Jarno
    TCG_REG_S3,
76 afa05235 Aurelien Jarno
    TCG_REG_S4,
77 afa05235 Aurelien Jarno
    TCG_REG_S5,
78 afa05235 Aurelien Jarno
    TCG_REG_S6,
79 afa05235 Aurelien Jarno
    TCG_REG_S7,
80 afa05235 Aurelien Jarno
    TCG_REG_T1,
81 afa05235 Aurelien Jarno
    TCG_REG_T2,
82 afa05235 Aurelien Jarno
    TCG_REG_T3,
83 afa05235 Aurelien Jarno
    TCG_REG_T4,
84 afa05235 Aurelien Jarno
    TCG_REG_T5,
85 afa05235 Aurelien Jarno
    TCG_REG_T6,
86 afa05235 Aurelien Jarno
    TCG_REG_T7,
87 afa05235 Aurelien Jarno
    TCG_REG_T8,
88 afa05235 Aurelien Jarno
    TCG_REG_T9,
89 afa05235 Aurelien Jarno
    TCG_REG_A0,
90 afa05235 Aurelien Jarno
    TCG_REG_A1,
91 afa05235 Aurelien Jarno
    TCG_REG_A2,
92 afa05235 Aurelien Jarno
    TCG_REG_A3,
93 afa05235 Aurelien Jarno
    TCG_REG_V0,
94 afa05235 Aurelien Jarno
    TCG_REG_V1
95 afa05235 Aurelien Jarno
};
96 afa05235 Aurelien Jarno
97 afa05235 Aurelien Jarno
static const int tcg_target_call_iarg_regs[4] = {
98 afa05235 Aurelien Jarno
    TCG_REG_A0,
99 afa05235 Aurelien Jarno
    TCG_REG_A1,
100 afa05235 Aurelien Jarno
    TCG_REG_A2,
101 afa05235 Aurelien Jarno
    TCG_REG_A3
102 afa05235 Aurelien Jarno
};
103 afa05235 Aurelien Jarno
104 afa05235 Aurelien Jarno
static const int tcg_target_call_oarg_regs[2] = {
105 afa05235 Aurelien Jarno
    TCG_REG_V0,
106 afa05235 Aurelien Jarno
    TCG_REG_V1
107 afa05235 Aurelien Jarno
};
108 afa05235 Aurelien Jarno
109 afa05235 Aurelien Jarno
static uint8_t *tb_ret_addr;
110 afa05235 Aurelien Jarno
111 afa05235 Aurelien Jarno
static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
112 afa05235 Aurelien Jarno
{
113 afa05235 Aurelien Jarno
    return target & 0xffff;
114 afa05235 Aurelien Jarno
}
115 afa05235 Aurelien Jarno
116 afa05235 Aurelien Jarno
static inline void reloc_lo16 (void *pc, tcg_target_long target)
117 afa05235 Aurelien Jarno
{
118 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
119 afa05235 Aurelien Jarno
                       | reloc_lo16_val(pc, target);
120 afa05235 Aurelien Jarno
}
121 afa05235 Aurelien Jarno
122 afa05235 Aurelien Jarno
static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
123 afa05235 Aurelien Jarno
{
124 afa05235 Aurelien Jarno
    return (target >> 16) & 0xffff;
125 afa05235 Aurelien Jarno
}
126 afa05235 Aurelien Jarno
127 afa05235 Aurelien Jarno
static inline void reloc_hi16 (void *pc, tcg_target_long target)
128 afa05235 Aurelien Jarno
{
129 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
130 afa05235 Aurelien Jarno
                       | reloc_hi16_val(pc, target);
131 afa05235 Aurelien Jarno
}
132 afa05235 Aurelien Jarno
133 afa05235 Aurelien Jarno
static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target)
134 afa05235 Aurelien Jarno
{
135 afa05235 Aurelien Jarno
    int32_t disp;
136 afa05235 Aurelien Jarno
137 afa05235 Aurelien Jarno
    disp = target - (tcg_target_long) pc - 4;
138 afa05235 Aurelien Jarno
    if (disp != (disp << 14) >> 14) {
139 afa05235 Aurelien Jarno
        tcg_abort ();
140 afa05235 Aurelien Jarno
    }
141 afa05235 Aurelien Jarno
142 afa05235 Aurelien Jarno
    return (disp >> 2) & 0xffff;
143 afa05235 Aurelien Jarno
}
144 afa05235 Aurelien Jarno
145 afa05235 Aurelien Jarno
static inline void reloc_pc16 (void *pc, tcg_target_long target)
146 afa05235 Aurelien Jarno
{
147 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
148 afa05235 Aurelien Jarno
                       | reloc_pc16_val(pc, target);
149 afa05235 Aurelien Jarno
}
150 afa05235 Aurelien Jarno
151 afa05235 Aurelien Jarno
static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
152 afa05235 Aurelien Jarno
{
153 afa05235 Aurelien Jarno
    if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
154 afa05235 Aurelien Jarno
        tcg_abort ();
155 afa05235 Aurelien Jarno
    }
156 afa05235 Aurelien Jarno
157 afa05235 Aurelien Jarno
    return (target >> 2) & 0x3ffffff;
158 afa05235 Aurelien Jarno
}
159 afa05235 Aurelien Jarno
160 afa05235 Aurelien Jarno
static inline void reloc_pc26 (void *pc, tcg_target_long target)
161 afa05235 Aurelien Jarno
{
162 afa05235 Aurelien Jarno
    *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
163 afa05235 Aurelien Jarno
                       | reloc_26_val(pc, target);
164 afa05235 Aurelien Jarno
}
165 afa05235 Aurelien Jarno
166 afa05235 Aurelien Jarno
static void patch_reloc(uint8_t *code_ptr, int type,
167 afa05235 Aurelien Jarno
                        tcg_target_long value, tcg_target_long addend)
168 afa05235 Aurelien Jarno
{
169 afa05235 Aurelien Jarno
    value += addend;
170 afa05235 Aurelien Jarno
    switch(type) {
171 afa05235 Aurelien Jarno
    case R_MIPS_LO16:
172 afa05235 Aurelien Jarno
        reloc_lo16(code_ptr, value);
173 afa05235 Aurelien Jarno
        break;
174 afa05235 Aurelien Jarno
    case R_MIPS_HI16:
175 afa05235 Aurelien Jarno
        reloc_hi16(code_ptr, value);
176 afa05235 Aurelien Jarno
        break;
177 afa05235 Aurelien Jarno
    case R_MIPS_PC16:
178 afa05235 Aurelien Jarno
        reloc_pc16(code_ptr, value);
179 afa05235 Aurelien Jarno
        break;
180 afa05235 Aurelien Jarno
    case R_MIPS_26:
181 afa05235 Aurelien Jarno
        reloc_pc26(code_ptr, value);
182 afa05235 Aurelien Jarno
        break;
183 afa05235 Aurelien Jarno
    default:
184 afa05235 Aurelien Jarno
        tcg_abort();
185 afa05235 Aurelien Jarno
    }
186 afa05235 Aurelien Jarno
}
187 afa05235 Aurelien Jarno
188 afa05235 Aurelien Jarno
/* maximum number of register used for input function arguments */
189 afa05235 Aurelien Jarno
static inline int tcg_target_get_call_iarg_regs_count(int flags)
190 afa05235 Aurelien Jarno
{
191 afa05235 Aurelien Jarno
    return 4;
192 afa05235 Aurelien Jarno
}
193 afa05235 Aurelien Jarno
194 afa05235 Aurelien Jarno
/* parse target specific constraints */
195 afa05235 Aurelien Jarno
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
196 afa05235 Aurelien Jarno
{
197 afa05235 Aurelien Jarno
    const char *ct_str;
198 afa05235 Aurelien Jarno
199 afa05235 Aurelien Jarno
    ct_str = *pct_str;
200 afa05235 Aurelien Jarno
    switch(ct_str[0]) {
201 afa05235 Aurelien Jarno
    case 'r':
202 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
203 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
204 afa05235 Aurelien Jarno
        break;
205 afa05235 Aurelien Jarno
    case 'C':
206 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
207 afa05235 Aurelien Jarno
        tcg_regset_clear(ct->u.regs);
208 afa05235 Aurelien Jarno
        tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
209 afa05235 Aurelien Jarno
        break;
210 afa05235 Aurelien Jarno
    case 'L': /* qemu_ld output arg constraint */
211 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
212 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
213 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
214 afa05235 Aurelien Jarno
        break;
215 afa05235 Aurelien Jarno
    case 'l': /* qemu_ld input arg constraint */
216 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
217 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
218 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
219 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
220 afa05235 Aurelien Jarno
#endif
221 afa05235 Aurelien Jarno
        break;
222 afa05235 Aurelien Jarno
    case 'S': /* qemu_st constraint */
223 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_REG;
224 afa05235 Aurelien Jarno
        tcg_regset_set(ct->u.regs, 0xffffffff);
225 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
226 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
227 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
228 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
229 afa05235 Aurelien Jarno
# endif
230 afa05235 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
231 afa05235 Aurelien Jarno
#endif
232 afa05235 Aurelien Jarno
        break;
233 afa05235 Aurelien Jarno
    case 'I':
234 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_CONST_U16;
235 afa05235 Aurelien Jarno
        break;
236 afa05235 Aurelien Jarno
    case 'J':
237 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_CONST_S16;
238 afa05235 Aurelien Jarno
        break;
239 afa05235 Aurelien Jarno
    case 'Z':
240 afa05235 Aurelien Jarno
        /* We are cheating a bit here, using the fact that the register
241 afa05235 Aurelien Jarno
           ZERO is also the register number 0. Hence there is no need
242 afa05235 Aurelien Jarno
           to check for const_args in each instruction. */
243 afa05235 Aurelien Jarno
        ct->ct |= TCG_CT_CONST_ZERO;
244 afa05235 Aurelien Jarno
        break;
245 afa05235 Aurelien Jarno
    default:
246 afa05235 Aurelien Jarno
        return -1;
247 afa05235 Aurelien Jarno
    }
248 afa05235 Aurelien Jarno
    ct_str++;
249 afa05235 Aurelien Jarno
    *pct_str = ct_str;
250 afa05235 Aurelien Jarno
    return 0;
251 afa05235 Aurelien Jarno
}
252 afa05235 Aurelien Jarno
253 afa05235 Aurelien Jarno
/* test if a constant matches the constraint */
254 afa05235 Aurelien Jarno
static inline int tcg_target_const_match(tcg_target_long val,
255 afa05235 Aurelien Jarno
                                         const TCGArgConstraint *arg_ct)
256 afa05235 Aurelien Jarno
{
257 afa05235 Aurelien Jarno
    int ct;
258 afa05235 Aurelien Jarno
    ct = arg_ct->ct;
259 afa05235 Aurelien Jarno
    if (ct & TCG_CT_CONST)
260 afa05235 Aurelien Jarno
        return 1;
261 afa05235 Aurelien Jarno
    else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
262 afa05235 Aurelien Jarno
        return 1;
263 afa05235 Aurelien Jarno
    else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
264 afa05235 Aurelien Jarno
        return 1;
265 afa05235 Aurelien Jarno
    else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
266 afa05235 Aurelien Jarno
        return 1;
267 afa05235 Aurelien Jarno
    else
268 afa05235 Aurelien Jarno
        return 0;
269 afa05235 Aurelien Jarno
}
270 afa05235 Aurelien Jarno
271 afa05235 Aurelien Jarno
/* instruction opcodes */
272 afa05235 Aurelien Jarno
enum {
273 afa05235 Aurelien Jarno
    OPC_SPECIAL  = 0x00 << 26,
274 afa05235 Aurelien Jarno
    OPC_BEQ      = 0x04 << 26,
275 afa05235 Aurelien Jarno
    OPC_BNE      = 0x05 << 26,
276 afa05235 Aurelien Jarno
    OPC_ADDIU    = 0x09 << 26,
277 4cb26382 Aurelien Jarno
    OPC_SLTI     = 0x0A << 26,
278 4cb26382 Aurelien Jarno
    OPC_SLTIU    = 0x0B << 26,
279 afa05235 Aurelien Jarno
    OPC_ANDI     = 0x0C << 26,
280 afa05235 Aurelien Jarno
    OPC_ORI      = 0x0D << 26,
281 afa05235 Aurelien Jarno
    OPC_XORI     = 0x0E << 26,
282 afa05235 Aurelien Jarno
    OPC_LUI      = 0x0F << 26,
283 afa05235 Aurelien Jarno
    OPC_LB       = 0x20 << 26,
284 afa05235 Aurelien Jarno
    OPC_LH       = 0x21 << 26,
285 afa05235 Aurelien Jarno
    OPC_LW       = 0x23 << 26,
286 afa05235 Aurelien Jarno
    OPC_LBU      = 0x24 << 26,
287 afa05235 Aurelien Jarno
    OPC_LHU      = 0x25 << 26,
288 afa05235 Aurelien Jarno
    OPC_LWU      = 0x27 << 26,
289 afa05235 Aurelien Jarno
    OPC_SB       = 0x28 << 26,
290 afa05235 Aurelien Jarno
    OPC_SH       = 0x29 << 26,
291 afa05235 Aurelien Jarno
    OPC_SW       = 0x2B << 26,
292 afa05235 Aurelien Jarno
    OPC_SLL      = OPC_SPECIAL | 0x00,
293 afa05235 Aurelien Jarno
    OPC_SRL      = OPC_SPECIAL | 0x02,
294 afa05235 Aurelien Jarno
    OPC_SRA      = OPC_SPECIAL | 0x03,
295 afa05235 Aurelien Jarno
    OPC_SLLV     = OPC_SPECIAL | 0x04,
296 afa05235 Aurelien Jarno
    OPC_SRLV     = OPC_SPECIAL | 0x06,
297 afa05235 Aurelien Jarno
    OPC_SRAV     = OPC_SPECIAL | 0x07,
298 afa05235 Aurelien Jarno
    OPC_JR       = OPC_SPECIAL | 0x08,
299 afa05235 Aurelien Jarno
    OPC_JALR     = OPC_SPECIAL | 0x09,
300 afa05235 Aurelien Jarno
    OPC_MFHI     = OPC_SPECIAL | 0x10,
301 afa05235 Aurelien Jarno
    OPC_MFLO     = OPC_SPECIAL | 0x12,
302 afa05235 Aurelien Jarno
    OPC_MULT     = OPC_SPECIAL | 0x18,
303 afa05235 Aurelien Jarno
    OPC_MULTU    = OPC_SPECIAL | 0x19,
304 afa05235 Aurelien Jarno
    OPC_DIV      = OPC_SPECIAL | 0x1A,
305 afa05235 Aurelien Jarno
    OPC_DIVU     = OPC_SPECIAL | 0x1B,
306 afa05235 Aurelien Jarno
    OPC_ADDU     = OPC_SPECIAL | 0x21,
307 afa05235 Aurelien Jarno
    OPC_SUBU     = OPC_SPECIAL | 0x23,
308 afa05235 Aurelien Jarno
    OPC_AND      = OPC_SPECIAL | 0x24,
309 afa05235 Aurelien Jarno
    OPC_OR       = OPC_SPECIAL | 0x25,
310 afa05235 Aurelien Jarno
    OPC_XOR      = OPC_SPECIAL | 0x26,
311 afa05235 Aurelien Jarno
    OPC_NOR      = OPC_SPECIAL | 0x27,
312 afa05235 Aurelien Jarno
    OPC_SLT      = OPC_SPECIAL | 0x2A,
313 afa05235 Aurelien Jarno
    OPC_SLTU     = OPC_SPECIAL | 0x2B,
314 afa05235 Aurelien Jarno
};
315 afa05235 Aurelien Jarno
316 afa05235 Aurelien Jarno
/*
317 afa05235 Aurelien Jarno
 * Type reg
318 afa05235 Aurelien Jarno
 */
319 afa05235 Aurelien Jarno
static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
320 afa05235 Aurelien Jarno
{
321 afa05235 Aurelien Jarno
    int32_t inst;
322 afa05235 Aurelien Jarno
323 afa05235 Aurelien Jarno
    inst = opc;
324 afa05235 Aurelien Jarno
    inst |= (rs & 0x1F) << 21;
325 afa05235 Aurelien Jarno
    inst |= (rt & 0x1F) << 16;
326 afa05235 Aurelien Jarno
    inst |= (rd & 0x1F) << 11;
327 afa05235 Aurelien Jarno
    tcg_out32(s, inst);
328 afa05235 Aurelien Jarno
}
329 afa05235 Aurelien Jarno
330 afa05235 Aurelien Jarno
/*
331 afa05235 Aurelien Jarno
 * Type immediate
332 afa05235 Aurelien Jarno
 */
333 afa05235 Aurelien Jarno
static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
334 afa05235 Aurelien Jarno
{
335 afa05235 Aurelien Jarno
    int32_t inst;
336 afa05235 Aurelien Jarno
337 afa05235 Aurelien Jarno
    inst = opc;
338 afa05235 Aurelien Jarno
    inst |= (rs & 0x1F) << 21;
339 afa05235 Aurelien Jarno
    inst |= (rt & 0x1F) << 16;
340 afa05235 Aurelien Jarno
    inst |= (imm & 0xffff);
341 afa05235 Aurelien Jarno
    tcg_out32(s, inst);
342 afa05235 Aurelien Jarno
}
343 afa05235 Aurelien Jarno
344 afa05235 Aurelien Jarno
/*
345 afa05235 Aurelien Jarno
 * Type sa
346 afa05235 Aurelien Jarno
 */
347 afa05235 Aurelien Jarno
static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
348 afa05235 Aurelien Jarno
{
349 afa05235 Aurelien Jarno
    int32_t inst;
350 afa05235 Aurelien Jarno
351 afa05235 Aurelien Jarno
    inst = opc;
352 afa05235 Aurelien Jarno
    inst |= (rt & 0x1F) << 16;
353 afa05235 Aurelien Jarno
    inst |= (rd & 0x1F) << 11;
354 afa05235 Aurelien Jarno
    inst |= (sa & 0x1F) <<  6;
355 afa05235 Aurelien Jarno
    tcg_out32(s, inst);
356 afa05235 Aurelien Jarno
357 afa05235 Aurelien Jarno
}
358 afa05235 Aurelien Jarno
359 afa05235 Aurelien Jarno
static inline void tcg_out_nop(TCGContext *s)
360 afa05235 Aurelien Jarno
{
361 afa05235 Aurelien Jarno
    tcg_out32(s, 0);
362 afa05235 Aurelien Jarno
}
363 afa05235 Aurelien Jarno
364 afa05235 Aurelien Jarno
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
365 afa05235 Aurelien Jarno
{
366 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
367 afa05235 Aurelien Jarno
}
368 afa05235 Aurelien Jarno
369 afa05235 Aurelien Jarno
static inline void tcg_out_movi(TCGContext *s, TCGType type,
370 afa05235 Aurelien Jarno
                                int reg, int32_t arg)
371 afa05235 Aurelien Jarno
{
372 afa05235 Aurelien Jarno
    if (arg == (int16_t)arg) {
373 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
374 afa05235 Aurelien Jarno
    } else if (arg == (uint16_t)arg) {
375 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
376 afa05235 Aurelien Jarno
    } else {
377 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
378 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
379 afa05235 Aurelien Jarno
    }
380 afa05235 Aurelien Jarno
}
381 afa05235 Aurelien Jarno
382 afa05235 Aurelien Jarno
static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
383 afa05235 Aurelien Jarno
{
384 afa05235 Aurelien Jarno
    /* ret and arg can't be register at */
385 afa05235 Aurelien Jarno
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
386 afa05235 Aurelien Jarno
        tcg_abort();
387 afa05235 Aurelien Jarno
    }
388 afa05235 Aurelien Jarno
389 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
390 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
391 afa05235 Aurelien Jarno
392 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
393 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
394 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
395 afa05235 Aurelien Jarno
}
396 afa05235 Aurelien Jarno
397 afa05235 Aurelien Jarno
static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
398 afa05235 Aurelien Jarno
{
399 afa05235 Aurelien Jarno
    /* ret and arg can't be register at */
400 afa05235 Aurelien Jarno
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
401 afa05235 Aurelien Jarno
        tcg_abort();
402 afa05235 Aurelien Jarno
    }
403 afa05235 Aurelien Jarno
404 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
405 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
406 afa05235 Aurelien Jarno
407 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
408 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
409 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
410 afa05235 Aurelien Jarno
}
411 afa05235 Aurelien Jarno
412 afa05235 Aurelien Jarno
static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
413 afa05235 Aurelien Jarno
{
414 afa05235 Aurelien Jarno
    /* ret and arg must be different and can't be register at */
415 afa05235 Aurelien Jarno
    if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
416 afa05235 Aurelien Jarno
        tcg_abort();
417 afa05235 Aurelien Jarno
    }
418 afa05235 Aurelien Jarno
419 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
420 afa05235 Aurelien Jarno
421 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
422 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
423 afa05235 Aurelien Jarno
424 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
425 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
426 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
427 afa05235 Aurelien Jarno
428 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
429 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
430 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
431 afa05235 Aurelien Jarno
}
432 afa05235 Aurelien Jarno
433 afa05235 Aurelien Jarno
static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
434 afa05235 Aurelien Jarno
                              int arg1, tcg_target_long arg2)
435 afa05235 Aurelien Jarno
{
436 afa05235 Aurelien Jarno
    if (arg2 == (int16_t) arg2) {
437 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, opc, arg, arg1, arg2);
438 afa05235 Aurelien Jarno
    } else {
439 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
440 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
441 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
442 afa05235 Aurelien Jarno
    }
443 afa05235 Aurelien Jarno
}
444 afa05235 Aurelien Jarno
445 afa05235 Aurelien Jarno
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
446 afa05235 Aurelien Jarno
                              int arg1, tcg_target_long arg2)
447 afa05235 Aurelien Jarno
{
448 afa05235 Aurelien Jarno
    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
449 afa05235 Aurelien Jarno
}
450 afa05235 Aurelien Jarno
451 afa05235 Aurelien Jarno
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
452 afa05235 Aurelien Jarno
                              int arg1, tcg_target_long arg2)
453 afa05235 Aurelien Jarno
{
454 afa05235 Aurelien Jarno
    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
455 afa05235 Aurelien Jarno
}
456 afa05235 Aurelien Jarno
457 afa05235 Aurelien Jarno
static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
458 afa05235 Aurelien Jarno
{
459 afa05235 Aurelien Jarno
    if (val == (int16_t)val) {
460 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
461 afa05235 Aurelien Jarno
    } else {
462 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
463 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
464 afa05235 Aurelien Jarno
    }
465 afa05235 Aurelien Jarno
}
466 afa05235 Aurelien Jarno
467 afa05235 Aurelien Jarno
static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
468 afa05235 Aurelien Jarno
                           int arg2, int label_index)
469 afa05235 Aurelien Jarno
{
470 afa05235 Aurelien Jarno
    TCGLabel *l = &s->labels[label_index];
471 afa05235 Aurelien Jarno
472 afa05235 Aurelien Jarno
    switch (cond) {
473 afa05235 Aurelien Jarno
    case TCG_COND_EQ:
474 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
475 afa05235 Aurelien Jarno
        break;
476 afa05235 Aurelien Jarno
    case TCG_COND_NE:
477 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
478 afa05235 Aurelien Jarno
        break;
479 afa05235 Aurelien Jarno
    case TCG_COND_LT:
480 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
481 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
482 afa05235 Aurelien Jarno
        break;
483 afa05235 Aurelien Jarno
    case TCG_COND_LTU:
484 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
485 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
486 afa05235 Aurelien Jarno
        break;
487 afa05235 Aurelien Jarno
    case TCG_COND_GE:
488 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
489 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
490 afa05235 Aurelien Jarno
        break;
491 afa05235 Aurelien Jarno
    case TCG_COND_GEU:
492 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
493 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
494 afa05235 Aurelien Jarno
        break;
495 afa05235 Aurelien Jarno
    case TCG_COND_LE:
496 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
497 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
498 afa05235 Aurelien Jarno
        break;
499 afa05235 Aurelien Jarno
    case TCG_COND_LEU:
500 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
501 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
502 afa05235 Aurelien Jarno
        break;
503 afa05235 Aurelien Jarno
    case TCG_COND_GT:
504 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
505 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
506 afa05235 Aurelien Jarno
        break;
507 afa05235 Aurelien Jarno
    case TCG_COND_GTU:
508 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
509 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
510 afa05235 Aurelien Jarno
        break;
511 afa05235 Aurelien Jarno
    default:
512 afa05235 Aurelien Jarno
        tcg_abort();
513 afa05235 Aurelien Jarno
        break;
514 afa05235 Aurelien Jarno
    }
515 afa05235 Aurelien Jarno
    if (l->has_value) {
516 afa05235 Aurelien Jarno
        reloc_pc16(s->code_ptr - 4, l->u.value);
517 afa05235 Aurelien Jarno
    } else {
518 afa05235 Aurelien Jarno
        tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
519 afa05235 Aurelien Jarno
    }
520 afa05235 Aurelien Jarno
    tcg_out_nop(s);
521 afa05235 Aurelien Jarno
}
522 afa05235 Aurelien Jarno
523 afa05235 Aurelien Jarno
/* XXX: we implement it at the target level to avoid having to
524 afa05235 Aurelien Jarno
   handle cross basic blocks temporaries */
525 afa05235 Aurelien Jarno
static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
526 afa05235 Aurelien Jarno
                            int arg2, int arg3, int arg4, int label_index)
527 afa05235 Aurelien Jarno
{
528 afa05235 Aurelien Jarno
    void *label_ptr;
529 afa05235 Aurelien Jarno
530 afa05235 Aurelien Jarno
    switch(cond) {
531 afa05235 Aurelien Jarno
    case TCG_COND_NE:
532 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
533 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
534 afa05235 Aurelien Jarno
        return;
535 afa05235 Aurelien Jarno
    case TCG_COND_EQ:
536 afa05235 Aurelien Jarno
        break;
537 afa05235 Aurelien Jarno
    case TCG_COND_LT:
538 afa05235 Aurelien Jarno
    case TCG_COND_LE:
539 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
540 afa05235 Aurelien Jarno
        break;
541 afa05235 Aurelien Jarno
    case TCG_COND_GT:
542 afa05235 Aurelien Jarno
    case TCG_COND_GE:
543 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
544 afa05235 Aurelien Jarno
        break;
545 afa05235 Aurelien Jarno
    case TCG_COND_LTU:
546 afa05235 Aurelien Jarno
    case TCG_COND_LEU:
547 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
548 afa05235 Aurelien Jarno
        break;
549 afa05235 Aurelien Jarno
    case TCG_COND_GTU:
550 afa05235 Aurelien Jarno
    case TCG_COND_GEU:
551 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
552 afa05235 Aurelien Jarno
        break;
553 afa05235 Aurelien Jarno
    default:
554 afa05235 Aurelien Jarno
        tcg_abort();
555 afa05235 Aurelien Jarno
    }
556 afa05235 Aurelien Jarno
557 afa05235 Aurelien Jarno
    label_ptr = s->code_ptr;
558 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
559 afa05235 Aurelien Jarno
    tcg_out_nop(s);
560 afa05235 Aurelien Jarno
561 afa05235 Aurelien Jarno
    switch(cond) {
562 afa05235 Aurelien Jarno
    case TCG_COND_EQ:
563 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
564 afa05235 Aurelien Jarno
        break;
565 afa05235 Aurelien Jarno
    case TCG_COND_LT:
566 afa05235 Aurelien Jarno
    case TCG_COND_LTU:
567 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
568 afa05235 Aurelien Jarno
        break;
569 afa05235 Aurelien Jarno
    case TCG_COND_LE:
570 afa05235 Aurelien Jarno
    case TCG_COND_LEU:
571 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
572 afa05235 Aurelien Jarno
        break;
573 afa05235 Aurelien Jarno
    case TCG_COND_GT:
574 afa05235 Aurelien Jarno
    case TCG_COND_GTU:
575 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
576 afa05235 Aurelien Jarno
        break;
577 afa05235 Aurelien Jarno
    case TCG_COND_GE:
578 afa05235 Aurelien Jarno
    case TCG_COND_GEU:
579 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
580 afa05235 Aurelien Jarno
        break;
581 afa05235 Aurelien Jarno
    default:
582 afa05235 Aurelien Jarno
        tcg_abort();
583 afa05235 Aurelien Jarno
    }
584 afa05235 Aurelien Jarno
585 afa05235 Aurelien Jarno
    reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
586 afa05235 Aurelien Jarno
}
587 afa05235 Aurelien Jarno
588 4cb26382 Aurelien Jarno
static void tcg_out_setcond(TCGContext *s, int cond, int ret,
589 4cb26382 Aurelien Jarno
                            int arg1, int arg2)
590 4cb26382 Aurelien Jarno
{
591 4cb26382 Aurelien Jarno
    switch (cond) {
592 4cb26382 Aurelien Jarno
    case TCG_COND_EQ:
593 4cb26382 Aurelien Jarno
        if (arg1 == 0) {
594 4cb26382 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
595 4cb26382 Aurelien Jarno
        } else if (arg2 == 0) {
596 4cb26382 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
597 4cb26382 Aurelien Jarno
        } else {
598 4cb26382 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, arg1, arg2);
599 4cb26382 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SLTIU, ret, TCG_REG_AT, 1);
600 4cb26382 Aurelien Jarno
        }
601 4cb26382 Aurelien Jarno
        break;
602 4cb26382 Aurelien Jarno
    case TCG_COND_NE:
603 4cb26382 Aurelien Jarno
        if (arg1 == 0) {
604 4cb26382 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
605 4cb26382 Aurelien Jarno
        } else if (arg2 == 0) {
606 4cb26382 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
607 4cb26382 Aurelien Jarno
        } else {
608 4cb26382 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, arg1, arg2);
609 4cb26382 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, TCG_REG_AT);
610 4cb26382 Aurelien Jarno
        }
611 4cb26382 Aurelien Jarno
        break;
612 4cb26382 Aurelien Jarno
    case TCG_COND_LT:
613 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
614 4cb26382 Aurelien Jarno
        break;
615 4cb26382 Aurelien Jarno
    case TCG_COND_LTU:
616 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
617 4cb26382 Aurelien Jarno
        break;
618 4cb26382 Aurelien Jarno
    case TCG_COND_GE:
619 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
620 4cb26382 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
621 4cb26382 Aurelien Jarno
        break;
622 4cb26382 Aurelien Jarno
    case TCG_COND_GEU:
623 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
624 4cb26382 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
625 4cb26382 Aurelien Jarno
        break;
626 4cb26382 Aurelien Jarno
    case TCG_COND_LE:
627 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
628 4cb26382 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
629 4cb26382 Aurelien Jarno
        break;
630 4cb26382 Aurelien Jarno
    case TCG_COND_LEU:
631 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
632 4cb26382 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
633 4cb26382 Aurelien Jarno
        break;
634 4cb26382 Aurelien Jarno
    case TCG_COND_GT:
635 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
636 4cb26382 Aurelien Jarno
        break;
637 4cb26382 Aurelien Jarno
    case TCG_COND_GTU:
638 4cb26382 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
639 4cb26382 Aurelien Jarno
        break;
640 4cb26382 Aurelien Jarno
    default:
641 4cb26382 Aurelien Jarno
        tcg_abort();
642 4cb26382 Aurelien Jarno
        break;
643 4cb26382 Aurelien Jarno
    }
644 4cb26382 Aurelien Jarno
}
645 4cb26382 Aurelien Jarno
646 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
647 afa05235 Aurelien Jarno
648 afa05235 Aurelien Jarno
#include "../../softmmu_defs.h"
649 afa05235 Aurelien Jarno
650 afa05235 Aurelien Jarno
static void *qemu_ld_helpers[4] = {
651 afa05235 Aurelien Jarno
    __ldb_mmu,
652 afa05235 Aurelien Jarno
    __ldw_mmu,
653 afa05235 Aurelien Jarno
    __ldl_mmu,
654 afa05235 Aurelien Jarno
    __ldq_mmu,
655 afa05235 Aurelien Jarno
};
656 afa05235 Aurelien Jarno
657 afa05235 Aurelien Jarno
static void *qemu_st_helpers[4] = {
658 afa05235 Aurelien Jarno
    __stb_mmu,
659 afa05235 Aurelien Jarno
    __stw_mmu,
660 afa05235 Aurelien Jarno
    __stl_mmu,
661 afa05235 Aurelien Jarno
    __stq_mmu,
662 afa05235 Aurelien Jarno
};
663 afa05235 Aurelien Jarno
#endif
664 afa05235 Aurelien Jarno
665 afa05235 Aurelien Jarno
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
666 afa05235 Aurelien Jarno
                            int opc)
667 afa05235 Aurelien Jarno
{
668 afa05235 Aurelien Jarno
    int addr_regl, addr_reg1, addr_meml;
669 afa05235 Aurelien Jarno
    int data_regl, data_regh, data_reg1, data_reg2;
670 afa05235 Aurelien Jarno
    int mem_index, s_bits;
671 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
672 afa05235 Aurelien Jarno
    void *label1_ptr, *label2_ptr;
673 afa05235 Aurelien Jarno
    int sp_args;
674 afa05235 Aurelien Jarno
#endif
675 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
676 afa05235 Aurelien Jarno
# if defined(CONFIG_SOFTMMU)
677 afa05235 Aurelien Jarno
    uint8_t *label3_ptr;
678 afa05235 Aurelien Jarno
# endif
679 afa05235 Aurelien Jarno
    int addr_regh, addr_reg2, addr_memh;
680 afa05235 Aurelien Jarno
#endif
681 afa05235 Aurelien Jarno
    data_regl = *args++;
682 afa05235 Aurelien Jarno
    if (opc == 3)
683 afa05235 Aurelien Jarno
        data_regh = *args++;
684 afa05235 Aurelien Jarno
    else
685 afa05235 Aurelien Jarno
        data_regh = 0;
686 afa05235 Aurelien Jarno
    addr_regl = *args++;
687 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
688 afa05235 Aurelien Jarno
    addr_regh = *args++;
689 afa05235 Aurelien Jarno
#endif
690 afa05235 Aurelien Jarno
    mem_index = *args;
691 afa05235 Aurelien Jarno
    s_bits = opc & 3;
692 afa05235 Aurelien Jarno
693 afa05235 Aurelien Jarno
    if (opc == 3) {
694 afa05235 Aurelien Jarno
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
695 afa05235 Aurelien Jarno
        data_reg1 = data_regh;
696 afa05235 Aurelien Jarno
        data_reg2 = data_regl;
697 afa05235 Aurelien Jarno
#else
698 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
699 afa05235 Aurelien Jarno
        data_reg2 = data_regh;
700 afa05235 Aurelien Jarno
#endif
701 afa05235 Aurelien Jarno
    } else {
702 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
703 afa05235 Aurelien Jarno
        data_reg2 = 0;
704 afa05235 Aurelien Jarno
    }
705 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
706 afa05235 Aurelien Jarno
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
707 afa05235 Aurelien Jarno
    addr_reg1 = addr_regh;
708 afa05235 Aurelien Jarno
    addr_reg2 = addr_regl;
709 afa05235 Aurelien Jarno
    addr_memh = 0;
710 afa05235 Aurelien Jarno
    addr_meml = 4;
711 afa05235 Aurelien Jarno
# else
712 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
713 afa05235 Aurelien Jarno
    addr_reg2 = addr_regh;
714 afa05235 Aurelien Jarno
    addr_memh = 4;
715 afa05235 Aurelien Jarno
    addr_meml = 0;
716 afa05235 Aurelien Jarno
# endif
717 afa05235 Aurelien Jarno
#else
718 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
719 afa05235 Aurelien Jarno
    addr_meml = 0;
720 afa05235 Aurelien Jarno
#endif
721 afa05235 Aurelien Jarno
722 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
723 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
724 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
725 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
726 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
727 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
728 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
729 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
730 afa05235 Aurelien Jarno
731 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
732 afa05235 Aurelien Jarno
    label3_ptr = s->code_ptr;
733 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
734 afa05235 Aurelien Jarno
    tcg_out_nop(s);
735 afa05235 Aurelien Jarno
736 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
737 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
738 afa05235 Aurelien Jarno
739 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
740 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
741 afa05235 Aurelien Jarno
    tcg_out_nop(s);
742 afa05235 Aurelien Jarno
743 afa05235 Aurelien Jarno
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
744 afa05235 Aurelien Jarno
# else
745 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
746 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
747 afa05235 Aurelien Jarno
    tcg_out_nop(s);
748 afa05235 Aurelien Jarno
# endif
749 afa05235 Aurelien Jarno
750 afa05235 Aurelien Jarno
    /* slow path */
751 afa05235 Aurelien Jarno
    sp_args = TCG_REG_A0;
752 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg1);
753 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
754 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg2);
755 afa05235 Aurelien Jarno
# endif
756 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
757 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
758 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
759 afa05235 Aurelien Jarno
    tcg_out_nop(s);
760 afa05235 Aurelien Jarno
761 afa05235 Aurelien Jarno
    switch(opc) {
762 afa05235 Aurelien Jarno
    case 0:
763 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
764 afa05235 Aurelien Jarno
        break;
765 afa05235 Aurelien Jarno
    case 0 | 4:
766 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
767 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
768 afa05235 Aurelien Jarno
        break;
769 afa05235 Aurelien Jarno
    case 1:
770 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
771 afa05235 Aurelien Jarno
        break;
772 afa05235 Aurelien Jarno
    case 1 | 4:
773 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
774 afa05235 Aurelien Jarno
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
775 afa05235 Aurelien Jarno
        break;
776 afa05235 Aurelien Jarno
    case 2:
777 afa05235 Aurelien Jarno
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
778 afa05235 Aurelien Jarno
        break;
779 afa05235 Aurelien Jarno
    case 3:
780 afa05235 Aurelien Jarno
        tcg_out_mov(s, data_reg2, TCG_REG_V1);
781 afa05235 Aurelien Jarno
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
782 afa05235 Aurelien Jarno
        break;
783 afa05235 Aurelien Jarno
    default:
784 afa05235 Aurelien Jarno
        tcg_abort();
785 afa05235 Aurelien Jarno
    }
786 afa05235 Aurelien Jarno
787 afa05235 Aurelien Jarno
    label2_ptr = s->code_ptr;
788 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
789 afa05235 Aurelien Jarno
    tcg_out_nop(s);
790 afa05235 Aurelien Jarno
791 afa05235 Aurelien Jarno
    /* label1: fast path */
792 afa05235 Aurelien Jarno
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
793 afa05235 Aurelien Jarno
794 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_V0, TCG_REG_A0,
795 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
796 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
797 afa05235 Aurelien Jarno
798 afa05235 Aurelien Jarno
    addr_reg1 = TCG_REG_V0;
799 afa05235 Aurelien Jarno
#endif
800 afa05235 Aurelien Jarno
801 afa05235 Aurelien Jarno
    switch(opc) {
802 afa05235 Aurelien Jarno
    case 0:
803 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
804 afa05235 Aurelien Jarno
        break;
805 afa05235 Aurelien Jarno
    case 0 | 4:
806 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
807 afa05235 Aurelien Jarno
        break;
808 afa05235 Aurelien Jarno
    case 1:
809 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
810 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
811 afa05235 Aurelien Jarno
            tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
812 afa05235 Aurelien Jarno
        } else {
813 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
814 afa05235 Aurelien Jarno
        }
815 afa05235 Aurelien Jarno
        break;
816 afa05235 Aurelien Jarno
    case 1 | 4:
817 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
818 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
819 afa05235 Aurelien Jarno
            tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
820 afa05235 Aurelien Jarno
        } else {
821 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
822 afa05235 Aurelien Jarno
        }
823 afa05235 Aurelien Jarno
        break;
824 afa05235 Aurelien Jarno
    case 2:
825 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
826 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
827 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
828 afa05235 Aurelien Jarno
        } else {
829 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
830 afa05235 Aurelien Jarno
        }
831 afa05235 Aurelien Jarno
        break;
832 afa05235 Aurelien Jarno
    case 3:
833 afa05235 Aurelien Jarno
#if !defined(CONFIG_SOFTMMU)
834 afa05235 Aurelien Jarno
        tcg_out_mov(s, TCG_REG_V0, addr_reg1);
835 afa05235 Aurelien Jarno
        addr_reg1 = TCG_REG_V0;
836 afa05235 Aurelien Jarno
#endif
837 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
838 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
839 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
840 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
841 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
842 afa05235 Aurelien Jarno
        } else {
843 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
844 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
845 afa05235 Aurelien Jarno
        }
846 afa05235 Aurelien Jarno
        break;
847 afa05235 Aurelien Jarno
    default:
848 afa05235 Aurelien Jarno
        tcg_abort();
849 afa05235 Aurelien Jarno
    }
850 afa05235 Aurelien Jarno
851 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
852 afa05235 Aurelien Jarno
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
853 afa05235 Aurelien Jarno
#endif
854 afa05235 Aurelien Jarno
}
855 afa05235 Aurelien Jarno
856 afa05235 Aurelien Jarno
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
857 afa05235 Aurelien Jarno
                            int opc)
858 afa05235 Aurelien Jarno
{
859 afa05235 Aurelien Jarno
    int addr_regl, addr_reg1, addr_meml;
860 afa05235 Aurelien Jarno
    int data_regl, data_regh, data_reg1, data_reg2;
861 afa05235 Aurelien Jarno
    int mem_index, s_bits;
862 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
863 afa05235 Aurelien Jarno
    uint8_t *label1_ptr, *label2_ptr;
864 afa05235 Aurelien Jarno
    int sp_args;
865 afa05235 Aurelien Jarno
#endif
866 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
867 afa05235 Aurelien Jarno
# if defined(CONFIG_SOFTMMU)
868 afa05235 Aurelien Jarno
    uint8_t *label3_ptr;
869 afa05235 Aurelien Jarno
# endif
870 afa05235 Aurelien Jarno
    int addr_regh, addr_reg2, addr_memh;
871 afa05235 Aurelien Jarno
#endif
872 afa05235 Aurelien Jarno
873 afa05235 Aurelien Jarno
    data_regl = *args++;
874 afa05235 Aurelien Jarno
    if (opc == 3) {
875 afa05235 Aurelien Jarno
        data_regh = *args++;
876 afa05235 Aurelien Jarno
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
877 afa05235 Aurelien Jarno
        data_reg1 = data_regh;
878 afa05235 Aurelien Jarno
        data_reg2 = data_regl;
879 afa05235 Aurelien Jarno
#else
880 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
881 afa05235 Aurelien Jarno
        data_reg2 = data_regh;
882 afa05235 Aurelien Jarno
#endif
883 afa05235 Aurelien Jarno
    } else {
884 afa05235 Aurelien Jarno
        data_reg1 = data_regl;
885 afa05235 Aurelien Jarno
        data_reg2 = 0;
886 afa05235 Aurelien Jarno
        data_regh = 0;
887 afa05235 Aurelien Jarno
    }
888 afa05235 Aurelien Jarno
    addr_regl = *args++;
889 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 64
890 afa05235 Aurelien Jarno
    addr_regh = *args++;
891 afa05235 Aurelien Jarno
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
892 afa05235 Aurelien Jarno
    addr_reg1 = addr_regh;
893 afa05235 Aurelien Jarno
    addr_reg2 = addr_regl;
894 afa05235 Aurelien Jarno
    addr_memh = 0;
895 afa05235 Aurelien Jarno
    addr_meml = 4;
896 afa05235 Aurelien Jarno
# else
897 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
898 afa05235 Aurelien Jarno
    addr_reg2 = addr_regh;
899 afa05235 Aurelien Jarno
    addr_memh = 4;
900 afa05235 Aurelien Jarno
    addr_meml = 0;
901 afa05235 Aurelien Jarno
# endif
902 afa05235 Aurelien Jarno
#else
903 afa05235 Aurelien Jarno
    addr_reg1 = addr_regl;
904 afa05235 Aurelien Jarno
    addr_meml = 0;
905 afa05235 Aurelien Jarno
#endif
906 afa05235 Aurelien Jarno
    mem_index = *args;
907 afa05235 Aurelien Jarno
    s_bits = opc;
908 afa05235 Aurelien Jarno
909 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
910 afa05235 Aurelien Jarno
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
911 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
912 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
913 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
914 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
915 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
916 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
917 afa05235 Aurelien Jarno
918 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
919 afa05235 Aurelien Jarno
    label3_ptr = s->code_ptr;
920 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
921 afa05235 Aurelien Jarno
    tcg_out_nop(s);
922 afa05235 Aurelien Jarno
923 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
924 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
925 afa05235 Aurelien Jarno
926 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
927 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
928 afa05235 Aurelien Jarno
    tcg_out_nop(s);
929 afa05235 Aurelien Jarno
930 afa05235 Aurelien Jarno
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
931 afa05235 Aurelien Jarno
# else
932 afa05235 Aurelien Jarno
    label1_ptr = s->code_ptr;
933 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
934 afa05235 Aurelien Jarno
    tcg_out_nop(s);
935 afa05235 Aurelien Jarno
# endif
936 afa05235 Aurelien Jarno
937 afa05235 Aurelien Jarno
    /* slow path */
938 afa05235 Aurelien Jarno
    sp_args = TCG_REG_A0;
939 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg1);
940 afa05235 Aurelien Jarno
# if TARGET_LONG_BITS == 64
941 afa05235 Aurelien Jarno
    tcg_out_mov(s, sp_args++, addr_reg2);
942 afa05235 Aurelien Jarno
# endif
943 afa05235 Aurelien Jarno
    switch(opc) {
944 afa05235 Aurelien Jarno
    case 0:
945 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
946 afa05235 Aurelien Jarno
        break;
947 afa05235 Aurelien Jarno
    case 1:
948 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
949 afa05235 Aurelien Jarno
        break;
950 afa05235 Aurelien Jarno
    case 2:
951 afa05235 Aurelien Jarno
        tcg_out_mov(s, sp_args++, data_reg1);
952 afa05235 Aurelien Jarno
        break;
953 afa05235 Aurelien Jarno
    case 3:
954 afa05235 Aurelien Jarno
        sp_args = (sp_args + 1) & ~1;
955 afa05235 Aurelien Jarno
        tcg_out_mov(s, sp_args++, data_reg1);
956 afa05235 Aurelien Jarno
        tcg_out_mov(s, sp_args++, data_reg2);
957 afa05235 Aurelien Jarno
        break;
958 afa05235 Aurelien Jarno
    default:
959 afa05235 Aurelien Jarno
        tcg_abort();
960 afa05235 Aurelien Jarno
    }
961 afa05235 Aurelien Jarno
    if (sp_args > TCG_REG_A3) {
962 afa05235 Aurelien Jarno
        /* Push mem_index on the stack */
963 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
964 afa05235 Aurelien Jarno
        tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
965 afa05235 Aurelien Jarno
    } else {
966 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
967 afa05235 Aurelien Jarno
    }
968 afa05235 Aurelien Jarno
969 afa05235 Aurelien Jarno
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
970 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
971 afa05235 Aurelien Jarno
    tcg_out_nop(s);
972 afa05235 Aurelien Jarno
973 afa05235 Aurelien Jarno
    label2_ptr = s->code_ptr;
974 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
975 afa05235 Aurelien Jarno
    tcg_out_nop(s);
976 afa05235 Aurelien Jarno
977 afa05235 Aurelien Jarno
    /* label1: fast path */
978 afa05235 Aurelien Jarno
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
979 afa05235 Aurelien Jarno
980 afa05235 Aurelien Jarno
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
981 afa05235 Aurelien Jarno
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
982 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
983 afa05235 Aurelien Jarno
984 afa05235 Aurelien Jarno
    addr_reg1 = TCG_REG_A0;
985 afa05235 Aurelien Jarno
#endif
986 afa05235 Aurelien Jarno
987 afa05235 Aurelien Jarno
    switch(opc) {
988 afa05235 Aurelien Jarno
    case 0:
989 afa05235 Aurelien Jarno
        tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
990 afa05235 Aurelien Jarno
        break;
991 afa05235 Aurelien Jarno
    case 1:
992 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
993 afa05235 Aurelien Jarno
            tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
994 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
995 afa05235 Aurelien Jarno
        } else {
996 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
997 afa05235 Aurelien Jarno
        }
998 afa05235 Aurelien Jarno
        break;
999 afa05235 Aurelien Jarno
    case 2:
1000 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
1001 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1002 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1003 afa05235 Aurelien Jarno
        } else {
1004 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1005 afa05235 Aurelien Jarno
        }
1006 afa05235 Aurelien Jarno
        break;
1007 afa05235 Aurelien Jarno
    case 3:
1008 afa05235 Aurelien Jarno
        if (TCG_NEED_BSWAP) {
1009 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1010 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1011 afa05235 Aurelien Jarno
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1012 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
1013 afa05235 Aurelien Jarno
        } else {
1014 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1015 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
1016 afa05235 Aurelien Jarno
        }
1017 afa05235 Aurelien Jarno
        break;
1018 afa05235 Aurelien Jarno
    default:
1019 afa05235 Aurelien Jarno
        tcg_abort();
1020 afa05235 Aurelien Jarno
    }
1021 afa05235 Aurelien Jarno
1022 afa05235 Aurelien Jarno
#if defined(CONFIG_SOFTMMU)
1023 afa05235 Aurelien Jarno
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1024 afa05235 Aurelien Jarno
#endif
1025 afa05235 Aurelien Jarno
}
1026 afa05235 Aurelien Jarno
1027 afa05235 Aurelien Jarno
static inline void tcg_out_op(TCGContext *s, int opc,
1028 afa05235 Aurelien Jarno
                              const TCGArg *args, const int *const_args)
1029 afa05235 Aurelien Jarno
{
1030 afa05235 Aurelien Jarno
    switch(opc) {
1031 afa05235 Aurelien Jarno
    case INDEX_op_exit_tb:
1032 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1033 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1034 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1035 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1036 afa05235 Aurelien Jarno
        break;
1037 afa05235 Aurelien Jarno
    case INDEX_op_goto_tb:
1038 afa05235 Aurelien Jarno
        if (s->tb_jmp_offset) {
1039 afa05235 Aurelien Jarno
            /* direct jump method */
1040 afa05235 Aurelien Jarno
            tcg_abort();
1041 afa05235 Aurelien Jarno
        } else {
1042 afa05235 Aurelien Jarno
            /* indirect jump method */
1043 afa05235 Aurelien Jarno
            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1044 afa05235 Aurelien Jarno
            tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1045 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1046 afa05235 Aurelien Jarno
        }
1047 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1048 afa05235 Aurelien Jarno
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1049 afa05235 Aurelien Jarno
        break;
1050 afa05235 Aurelien Jarno
    case INDEX_op_call:
1051 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1052 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1053 afa05235 Aurelien Jarno
        break;
1054 afa05235 Aurelien Jarno
    case INDEX_op_jmp:
1055 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1056 afa05235 Aurelien Jarno
        tcg_out_nop(s);
1057 afa05235 Aurelien Jarno
        break;
1058 afa05235 Aurelien Jarno
    case INDEX_op_br:
1059 afa05235 Aurelien Jarno
        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1060 afa05235 Aurelien Jarno
        break;
1061 afa05235 Aurelien Jarno
1062 afa05235 Aurelien Jarno
    case INDEX_op_mov_i32:
1063 afa05235 Aurelien Jarno
        tcg_out_mov(s, args[0], args[1]);
1064 afa05235 Aurelien Jarno
        break;
1065 afa05235 Aurelien Jarno
    case INDEX_op_movi_i32:
1066 afa05235 Aurelien Jarno
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1067 afa05235 Aurelien Jarno
        break;
1068 afa05235 Aurelien Jarno
1069 afa05235 Aurelien Jarno
    case INDEX_op_ld8u_i32:
1070 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1071 afa05235 Aurelien Jarno
        break;
1072 afa05235 Aurelien Jarno
    case INDEX_op_ld8s_i32:
1073 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1074 afa05235 Aurelien Jarno
        break;
1075 afa05235 Aurelien Jarno
    case INDEX_op_ld16u_i32:
1076 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1077 afa05235 Aurelien Jarno
        break;
1078 afa05235 Aurelien Jarno
    case INDEX_op_ld16s_i32:
1079 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1080 afa05235 Aurelien Jarno
        break;
1081 afa05235 Aurelien Jarno
    case INDEX_op_ld_i32:
1082 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1083 afa05235 Aurelien Jarno
        break;
1084 afa05235 Aurelien Jarno
    case INDEX_op_st8_i32:
1085 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1086 afa05235 Aurelien Jarno
        break;
1087 afa05235 Aurelien Jarno
    case INDEX_op_st16_i32:
1088 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1089 afa05235 Aurelien Jarno
        break;
1090 afa05235 Aurelien Jarno
    case INDEX_op_st_i32:
1091 afa05235 Aurelien Jarno
        tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1092 afa05235 Aurelien Jarno
        break;
1093 afa05235 Aurelien Jarno
1094 afa05235 Aurelien Jarno
    case INDEX_op_add_i32:
1095 afa05235 Aurelien Jarno
        if (const_args[2]) {
1096 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1097 afa05235 Aurelien Jarno
        } else {
1098 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1099 afa05235 Aurelien Jarno
        }
1100 afa05235 Aurelien Jarno
        break;
1101 afa05235 Aurelien Jarno
    case INDEX_op_add2_i32:
1102 afa05235 Aurelien Jarno
        if (const_args[4]) {
1103 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1104 afa05235 Aurelien Jarno
        } else {
1105 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1106 afa05235 Aurelien Jarno
        }
1107 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1108 afa05235 Aurelien Jarno
        if (const_args[5]) {
1109 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1110 afa05235 Aurelien Jarno
        } else {
1111 afa05235 Aurelien Jarno
             tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1112 afa05235 Aurelien Jarno
        }
1113 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1114 afa05235 Aurelien Jarno
        tcg_out_mov(s, args[0], TCG_REG_AT);
1115 afa05235 Aurelien Jarno
        break;
1116 afa05235 Aurelien Jarno
    case INDEX_op_sub_i32:
1117 afa05235 Aurelien Jarno
        if (const_args[2]) {
1118 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1119 afa05235 Aurelien Jarno
        } else {
1120 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1121 afa05235 Aurelien Jarno
        }
1122 afa05235 Aurelien Jarno
        break;
1123 afa05235 Aurelien Jarno
    case INDEX_op_sub2_i32:
1124 afa05235 Aurelien Jarno
        if (const_args[4]) {
1125 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1126 afa05235 Aurelien Jarno
        } else {
1127 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1128 afa05235 Aurelien Jarno
        }
1129 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1130 afa05235 Aurelien Jarno
        if (const_args[5]) {
1131 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1132 afa05235 Aurelien Jarno
        } else {
1133 afa05235 Aurelien Jarno
             tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1134 afa05235 Aurelien Jarno
        }
1135 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1136 afa05235 Aurelien Jarno
        tcg_out_mov(s, args[0], TCG_REG_AT);
1137 afa05235 Aurelien Jarno
        break;
1138 afa05235 Aurelien Jarno
    case INDEX_op_mul_i32:
1139 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1140 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1141 afa05235 Aurelien Jarno
        break;
1142 afa05235 Aurelien Jarno
    case INDEX_op_mulu2_i32:
1143 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1144 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1145 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1146 afa05235 Aurelien Jarno
        break;
1147 afa05235 Aurelien Jarno
    case INDEX_op_div_i32:
1148 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1149 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1150 afa05235 Aurelien Jarno
        break;
1151 afa05235 Aurelien Jarno
    case INDEX_op_divu_i32:
1152 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1153 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1154 afa05235 Aurelien Jarno
        break;
1155 afa05235 Aurelien Jarno
    case INDEX_op_rem_i32:
1156 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1157 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1158 afa05235 Aurelien Jarno
        break;
1159 afa05235 Aurelien Jarno
    case INDEX_op_remu_i32:
1160 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1161 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1162 afa05235 Aurelien Jarno
        break;
1163 afa05235 Aurelien Jarno
1164 afa05235 Aurelien Jarno
    case INDEX_op_and_i32:
1165 afa05235 Aurelien Jarno
        if (const_args[2]) {
1166 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1167 afa05235 Aurelien Jarno
        } else {
1168 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1169 afa05235 Aurelien Jarno
        }
1170 afa05235 Aurelien Jarno
        break;
1171 afa05235 Aurelien Jarno
    case INDEX_op_or_i32:
1172 afa05235 Aurelien Jarno
        if (const_args[2]) {
1173 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1174 afa05235 Aurelien Jarno
        } else {
1175 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1176 afa05235 Aurelien Jarno
        }
1177 afa05235 Aurelien Jarno
        break;
1178 afa05235 Aurelien Jarno
    case INDEX_op_not_i32:
1179 afa05235 Aurelien Jarno
        tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[1]);
1180 afa05235 Aurelien Jarno
        break;
1181 afa05235 Aurelien Jarno
    case INDEX_op_xor_i32:
1182 afa05235 Aurelien Jarno
        if (const_args[2]) {
1183 afa05235 Aurelien Jarno
            tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1184 afa05235 Aurelien Jarno
        } else {
1185 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1186 afa05235 Aurelien Jarno
        }
1187 afa05235 Aurelien Jarno
        break;
1188 afa05235 Aurelien Jarno
1189 afa05235 Aurelien Jarno
    case INDEX_op_sar_i32:
1190 afa05235 Aurelien Jarno
        if (const_args[2]) {
1191 afa05235 Aurelien Jarno
            tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1192 afa05235 Aurelien Jarno
        } else {
1193 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1194 afa05235 Aurelien Jarno
        }
1195 afa05235 Aurelien Jarno
        break;
1196 afa05235 Aurelien Jarno
    case INDEX_op_shl_i32:
1197 afa05235 Aurelien Jarno
        if (const_args[2]) {
1198 afa05235 Aurelien Jarno
            tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1199 afa05235 Aurelien Jarno
        } else {
1200 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1201 afa05235 Aurelien Jarno
        }
1202 afa05235 Aurelien Jarno
        break;
1203 afa05235 Aurelien Jarno
    case INDEX_op_shr_i32:
1204 afa05235 Aurelien Jarno
        if (const_args[2]) {
1205 afa05235 Aurelien Jarno
            tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1206 afa05235 Aurelien Jarno
        } else {
1207 afa05235 Aurelien Jarno
            tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1208 afa05235 Aurelien Jarno
        }
1209 afa05235 Aurelien Jarno
        break;
1210 afa05235 Aurelien Jarno
1211 afa05235 Aurelien Jarno
    case INDEX_op_brcond_i32:
1212 afa05235 Aurelien Jarno
        tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1213 afa05235 Aurelien Jarno
        break;
1214 afa05235 Aurelien Jarno
    case INDEX_op_brcond2_i32:
1215 afa05235 Aurelien Jarno
        tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1216 afa05235 Aurelien Jarno
        break;
1217 afa05235 Aurelien Jarno
1218 4cb26382 Aurelien Jarno
    case INDEX_op_setcond_i32:
1219 4cb26382 Aurelien Jarno
        tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1220 4cb26382 Aurelien Jarno
        break;
1221 4cb26382 Aurelien Jarno
1222 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld8u:
1223 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 0);
1224 afa05235 Aurelien Jarno
        break;
1225 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld8s:
1226 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 0 | 4);
1227 afa05235 Aurelien Jarno
        break;
1228 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld16u:
1229 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 1);
1230 afa05235 Aurelien Jarno
        break;
1231 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld16s:
1232 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 1 | 4);
1233 afa05235 Aurelien Jarno
        break;
1234 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld32u:
1235 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 2);
1236 afa05235 Aurelien Jarno
        break;
1237 afa05235 Aurelien Jarno
    case INDEX_op_qemu_ld64:
1238 afa05235 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 3);
1239 afa05235 Aurelien Jarno
        break;
1240 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st8:
1241 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 0);
1242 afa05235 Aurelien Jarno
        break;
1243 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st16:
1244 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 1);
1245 afa05235 Aurelien Jarno
        break;
1246 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st32:
1247 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 2);
1248 afa05235 Aurelien Jarno
        break;
1249 afa05235 Aurelien Jarno
    case INDEX_op_qemu_st64:
1250 afa05235 Aurelien Jarno
        tcg_out_qemu_st(s, args, 3);
1251 afa05235 Aurelien Jarno
        break;
1252 afa05235 Aurelien Jarno
1253 afa05235 Aurelien Jarno
    default:
1254 afa05235 Aurelien Jarno
        tcg_abort();
1255 afa05235 Aurelien Jarno
    }
1256 afa05235 Aurelien Jarno
}
1257 afa05235 Aurelien Jarno
1258 afa05235 Aurelien Jarno
static const TCGTargetOpDef mips_op_defs[] = {
1259 afa05235 Aurelien Jarno
    { INDEX_op_exit_tb, { } },
1260 afa05235 Aurelien Jarno
    { INDEX_op_goto_tb, { } },
1261 afa05235 Aurelien Jarno
    { INDEX_op_call, { "C" } },
1262 afa05235 Aurelien Jarno
    { INDEX_op_jmp, { "r" } },
1263 afa05235 Aurelien Jarno
    { INDEX_op_br, { } },
1264 afa05235 Aurelien Jarno
1265 afa05235 Aurelien Jarno
    { INDEX_op_mov_i32, { "r", "r" } },
1266 afa05235 Aurelien Jarno
    { INDEX_op_movi_i32, { "r" } },
1267 afa05235 Aurelien Jarno
    { INDEX_op_ld8u_i32, { "r", "r" } },
1268 afa05235 Aurelien Jarno
    { INDEX_op_ld8s_i32, { "r", "r" } },
1269 afa05235 Aurelien Jarno
    { INDEX_op_ld16u_i32, { "r", "r" } },
1270 afa05235 Aurelien Jarno
    { INDEX_op_ld16s_i32, { "r", "r" } },
1271 afa05235 Aurelien Jarno
    { INDEX_op_ld_i32, { "r", "r" } },
1272 afa05235 Aurelien Jarno
    { INDEX_op_st8_i32, { "rZ", "r" } },
1273 afa05235 Aurelien Jarno
    { INDEX_op_st16_i32, { "rZ", "r" } },
1274 afa05235 Aurelien Jarno
    { INDEX_op_st_i32, { "rZ", "r" } },
1275 afa05235 Aurelien Jarno
1276 afa05235 Aurelien Jarno
    { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1277 afa05235 Aurelien Jarno
    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1278 afa05235 Aurelien Jarno
    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1279 afa05235 Aurelien Jarno
    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1280 afa05235 Aurelien Jarno
    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1281 afa05235 Aurelien Jarno
    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1282 afa05235 Aurelien Jarno
    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1283 afa05235 Aurelien Jarno
    { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1284 afa05235 Aurelien Jarno
1285 afa05235 Aurelien Jarno
    { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1286 afa05235 Aurelien Jarno
    { INDEX_op_not_i32, { "r", "rZ" } },
1287 afa05235 Aurelien Jarno
    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1288 afa05235 Aurelien Jarno
    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1289 afa05235 Aurelien Jarno
1290 afa05235 Aurelien Jarno
    { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1291 afa05235 Aurelien Jarno
    { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1292 afa05235 Aurelien Jarno
    { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1293 afa05235 Aurelien Jarno
1294 afa05235 Aurelien Jarno
    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1295 4cb26382 Aurelien Jarno
    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1296 afa05235 Aurelien Jarno
1297 afa05235 Aurelien Jarno
    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1298 afa05235 Aurelien Jarno
    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1299 afa05235 Aurelien Jarno
    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1300 afa05235 Aurelien Jarno
1301 afa05235 Aurelien Jarno
#if TARGET_LONG_BITS == 32
1302 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1303 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1304 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1305 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1306 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld32u, { "L", "lZ" } },
1307 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1308 afa05235 Aurelien Jarno
1309 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1310 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1311 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1312 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1313 afa05235 Aurelien Jarno
#else
1314 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1315 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1316 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1317 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1318 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld32u, { "L", "lZ", "lZ" } },
1319 afa05235 Aurelien Jarno
    { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1320 afa05235 Aurelien Jarno
1321 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1322 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1323 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1324 afa05235 Aurelien Jarno
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1325 afa05235 Aurelien Jarno
#endif
1326 afa05235 Aurelien Jarno
    { -1 },
1327 afa05235 Aurelien Jarno
};
1328 afa05235 Aurelien Jarno
1329 afa05235 Aurelien Jarno
static int tcg_target_callee_save_regs[] = {
1330 afa05235 Aurelien Jarno
    TCG_REG_S0,
1331 afa05235 Aurelien Jarno
    TCG_REG_S1,
1332 afa05235 Aurelien Jarno
    TCG_REG_S2,
1333 afa05235 Aurelien Jarno
    TCG_REG_S3,
1334 afa05235 Aurelien Jarno
    TCG_REG_S4,
1335 afa05235 Aurelien Jarno
    TCG_REG_S5,
1336 afa05235 Aurelien Jarno
    TCG_REG_S6,
1337 afa05235 Aurelien Jarno
    TCG_REG_S7,
1338 afa05235 Aurelien Jarno
    TCG_REG_GP,
1339 afa05235 Aurelien Jarno
    /* TCG_REG_FP, */ /* currently used for the global env, so np
1340 afa05235 Aurelien Jarno
                         need to save */
1341 afa05235 Aurelien Jarno
    TCG_REG_RA,       /* should be last for ABI compliance */
1342 afa05235 Aurelien Jarno
};
1343 afa05235 Aurelien Jarno
1344 afa05235 Aurelien Jarno
/* Generate global QEMU prologue and epilogue code */
1345 afa05235 Aurelien Jarno
void tcg_target_qemu_prologue(TCGContext *s)
1346 afa05235 Aurelien Jarno
{
1347 afa05235 Aurelien Jarno
    int i, frame_size;
1348 afa05235 Aurelien Jarno
1349 afa05235 Aurelien Jarno
    /* reserve some stack space */
1350 afa05235 Aurelien Jarno
    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1351 afa05235 Aurelien Jarno
                 + TCG_STATIC_CALL_ARGS_SIZE;
1352 afa05235 Aurelien Jarno
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1353 afa05235 Aurelien Jarno
                 ~(TCG_TARGET_STACK_ALIGN - 1);
1354 afa05235 Aurelien Jarno
1355 afa05235 Aurelien Jarno
    /* TB prologue */
1356 afa05235 Aurelien Jarno
    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1357 afa05235 Aurelien Jarno
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1358 afa05235 Aurelien Jarno
        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1359 afa05235 Aurelien Jarno
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1360 afa05235 Aurelien Jarno
    }
1361 afa05235 Aurelien Jarno
1362 afa05235 Aurelien Jarno
    /* Call generated code */
1363 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1364 afa05235 Aurelien Jarno
    tcg_out_nop(s);
1365 afa05235 Aurelien Jarno
    tb_ret_addr = s->code_ptr;
1366 afa05235 Aurelien Jarno
1367 afa05235 Aurelien Jarno
    /* TB epilogue */
1368 afa05235 Aurelien Jarno
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1369 afa05235 Aurelien Jarno
        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1370 afa05235 Aurelien Jarno
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1371 afa05235 Aurelien Jarno
    }
1372 afa05235 Aurelien Jarno
1373 afa05235 Aurelien Jarno
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1374 afa05235 Aurelien Jarno
    tcg_out_addi(s, TCG_REG_SP, frame_size);
1375 afa05235 Aurelien Jarno
}
1376 afa05235 Aurelien Jarno
1377 afa05235 Aurelien Jarno
void tcg_target_init(TCGContext *s)
1378 afa05235 Aurelien Jarno
{
1379 afa05235 Aurelien Jarno
    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1380 afa05235 Aurelien Jarno
    tcg_regset_set(tcg_target_call_clobber_regs,
1381 afa05235 Aurelien Jarno
                   (1 << TCG_REG_V0) |
1382 afa05235 Aurelien Jarno
                   (1 << TCG_REG_V1) |
1383 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A0) |
1384 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A1) |
1385 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A2) |
1386 afa05235 Aurelien Jarno
                   (1 << TCG_REG_A3) |
1387 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T1) |
1388 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T2) |
1389 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T3) |
1390 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T4) |
1391 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T5) |
1392 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T6) |
1393 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T7) |
1394 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T8) |
1395 afa05235 Aurelien Jarno
                   (1 << TCG_REG_T9));
1396 afa05235 Aurelien Jarno
1397 afa05235 Aurelien Jarno
    tcg_regset_clear(s->reserved_regs);
1398 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1399 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1400 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1401 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
1402 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
1403 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1404 afa05235 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1405 afa05235 Aurelien Jarno
1406 afa05235 Aurelien Jarno
    tcg_add_target_add_op_defs(mips_op_defs);
1407 afa05235 Aurelien Jarno
}