]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/mips/tcg-target.c
tcg/mips: implement movcond op on MIPS32R2
[mirror_qemu.git] / tcg / mips / tcg-target.c
CommitLineData
afa05235
AJ
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27#if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28# define TCG_NEED_BSWAP 0
29#else
30# define TCG_NEED_BSWAP 1
31#endif
32
33#ifndef NDEBUG
34static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35 "zero",
36 "at",
37 "v0",
38 "v1",
39 "a0",
40 "a1",
41 "a2",
42 "a3",
43 "t0",
44 "t1",
45 "t2",
46 "t3",
47 "t4",
48 "t5",
49 "t6",
50 "t7",
51 "s0",
52 "s1",
53 "s2",
54 "s3",
55 "s4",
56 "s5",
57 "s6",
58 "s7",
59 "t8",
60 "t9",
61 "k0",
62 "k1",
63 "gp",
64 "sp",
65 "fp",
66 "ra",
67};
68#endif
69
70/* check if we really need so many registers :P */
5a0eed37 71static const TCGReg tcg_target_reg_alloc_order[] = {
afa05235
AJ
72 TCG_REG_S0,
73 TCG_REG_S1,
74 TCG_REG_S2,
75 TCG_REG_S3,
76 TCG_REG_S4,
77 TCG_REG_S5,
78 TCG_REG_S6,
79 TCG_REG_S7,
80 TCG_REG_T1,
81 TCG_REG_T2,
82 TCG_REG_T3,
83 TCG_REG_T4,
84 TCG_REG_T5,
85 TCG_REG_T6,
86 TCG_REG_T7,
87 TCG_REG_T8,
88 TCG_REG_T9,
89 TCG_REG_A0,
90 TCG_REG_A1,
91 TCG_REG_A2,
92 TCG_REG_A3,
93 TCG_REG_V0,
94 TCG_REG_V1
95};
96
5a0eed37 97static const TCGReg tcg_target_call_iarg_regs[4] = {
afa05235
AJ
98 TCG_REG_A0,
99 TCG_REG_A1,
100 TCG_REG_A2,
101 TCG_REG_A3
102};
103
5a0eed37 104static const TCGReg tcg_target_call_oarg_regs[2] = {
afa05235
AJ
105 TCG_REG_V0,
106 TCG_REG_V1
107};
108
109static uint8_t *tb_ret_addr;
110
111static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
112{
113 return target & 0xffff;
114}
115
116static inline void reloc_lo16 (void *pc, tcg_target_long target)
117{
118 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
119 | reloc_lo16_val(pc, target);
120}
121
122static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
123{
124 return (target >> 16) & 0xffff;
125}
126
127static inline void reloc_hi16 (void *pc, tcg_target_long target)
128{
129 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
130 | reloc_hi16_val(pc, target);
131}
132
133static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target)
134{
135 int32_t disp;
136
137 disp = target - (tcg_target_long) pc - 4;
138 if (disp != (disp << 14) >> 14) {
139 tcg_abort ();
140 }
141
142 return (disp >> 2) & 0xffff;
143}
144
145static inline void reloc_pc16 (void *pc, tcg_target_long target)
146{
147 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
148 | reloc_pc16_val(pc, target);
149}
150
151static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
152{
153 if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
154 tcg_abort ();
155 }
156
157 return (target >> 2) & 0x3ffffff;
158}
159
160static inline void reloc_pc26 (void *pc, tcg_target_long target)
161{
162 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
163 | reloc_26_val(pc, target);
164}
165
166static void patch_reloc(uint8_t *code_ptr, int type,
167 tcg_target_long value, tcg_target_long addend)
168{
169 value += addend;
170 switch(type) {
171 case R_MIPS_LO16:
172 reloc_lo16(code_ptr, value);
173 break;
174 case R_MIPS_HI16:
175 reloc_hi16(code_ptr, value);
176 break;
177 case R_MIPS_PC16:
178 reloc_pc16(code_ptr, value);
179 break;
180 case R_MIPS_26:
181 reloc_pc26(code_ptr, value);
182 break;
183 default:
184 tcg_abort();
185 }
186}
187
188/* maximum number of register used for input function arguments */
189static inline int tcg_target_get_call_iarg_regs_count(int flags)
190{
191 return 4;
192}
193
194/* parse target specific constraints */
195static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
196{
197 const char *ct_str;
198
199 ct_str = *pct_str;
200 switch(ct_str[0]) {
201 case 'r':
202 ct->ct |= TCG_CT_REG;
203 tcg_regset_set(ct->u.regs, 0xffffffff);
204 break;
205 case 'C':
206 ct->ct |= TCG_CT_REG;
207 tcg_regset_clear(ct->u.regs);
208 tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
209 break;
210 case 'L': /* qemu_ld output arg constraint */
211 ct->ct |= TCG_CT_REG;
212 tcg_regset_set(ct->u.regs, 0xffffffff);
213 tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
214 break;
215 case 'l': /* qemu_ld input arg constraint */
216 ct->ct |= TCG_CT_REG;
217 tcg_regset_set(ct->u.regs, 0xffffffff);
218#if defined(CONFIG_SOFTMMU)
219 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
89c33337 220# if (TARGET_LONG_BITS == 64)
18fec301
AJ
221 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
222# endif
afa05235
AJ
223#endif
224 break;
225 case 'S': /* qemu_st constraint */
226 ct->ct |= TCG_CT_REG;
227 tcg_regset_set(ct->u.regs, 0xffffffff);
afa05235 228 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
cc01cc8e 229#if defined(CONFIG_SOFTMMU)
89c33337 230# if (TARGET_LONG_BITS == 32)
afa05235
AJ
231 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
232# endif
233 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
89c33337 234# if TARGET_LONG_BITS == 64
18fec301
AJ
235 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
236# endif
afa05235
AJ
237#endif
238 break;
239 case 'I':
240 ct->ct |= TCG_CT_CONST_U16;
241 break;
242 case 'J':
243 ct->ct |= TCG_CT_CONST_S16;
244 break;
245 case 'Z':
246 /* We are cheating a bit here, using the fact that the register
247 ZERO is also the register number 0. Hence there is no need
248 to check for const_args in each instruction. */
249 ct->ct |= TCG_CT_CONST_ZERO;
250 break;
251 default:
252 return -1;
253 }
254 ct_str++;
255 *pct_str = ct_str;
256 return 0;
257}
258
259/* test if a constant matches the constraint */
260static inline int tcg_target_const_match(tcg_target_long val,
261 const TCGArgConstraint *arg_ct)
262{
263 int ct;
264 ct = arg_ct->ct;
265 if (ct & TCG_CT_CONST)
266 return 1;
267 else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
268 return 1;
269 else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
270 return 1;
271 else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
272 return 1;
273 else
274 return 0;
275}
276
277/* instruction opcodes */
278enum {
afa05235
AJ
279 OPC_BEQ = 0x04 << 26,
280 OPC_BNE = 0x05 << 26,
0f46c064
AJ
281 OPC_BLEZ = 0x06 << 26,
282 OPC_BGTZ = 0x07 << 26,
afa05235 283 OPC_ADDIU = 0x09 << 26,
4cb26382
AJ
284 OPC_SLTI = 0x0A << 26,
285 OPC_SLTIU = 0x0B << 26,
afa05235
AJ
286 OPC_ANDI = 0x0C << 26,
287 OPC_ORI = 0x0D << 26,
288 OPC_XORI = 0x0E << 26,
289 OPC_LUI = 0x0F << 26,
290 OPC_LB = 0x20 << 26,
291 OPC_LH = 0x21 << 26,
292 OPC_LW = 0x23 << 26,
293 OPC_LBU = 0x24 << 26,
294 OPC_LHU = 0x25 << 26,
295 OPC_LWU = 0x27 << 26,
296 OPC_SB = 0x28 << 26,
297 OPC_SH = 0x29 << 26,
298 OPC_SW = 0x2B << 26,
116348de
AJ
299
300 OPC_SPECIAL = 0x00 << 26,
afa05235
AJ
301 OPC_SLL = OPC_SPECIAL | 0x00,
302 OPC_SRL = OPC_SPECIAL | 0x02,
9a152519 303 OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02,
afa05235
AJ
304 OPC_SRA = OPC_SPECIAL | 0x03,
305 OPC_SLLV = OPC_SPECIAL | 0x04,
306 OPC_SRLV = OPC_SPECIAL | 0x06,
9a152519 307 OPC_ROTRV = OPC_SPECIAL | (0x01 << 6) | 0x06,
afa05235
AJ
308 OPC_SRAV = OPC_SPECIAL | 0x07,
309 OPC_JR = OPC_SPECIAL | 0x08,
310 OPC_JALR = OPC_SPECIAL | 0x09,
7d7c4930
AJ
311 OPC_MOVZ = OPC_SPECIAL | 0x0A,
312 OPC_MOVN = OPC_SPECIAL | 0x0B,
afa05235
AJ
313 OPC_MFHI = OPC_SPECIAL | 0x10,
314 OPC_MFLO = OPC_SPECIAL | 0x12,
315 OPC_MULT = OPC_SPECIAL | 0x18,
316 OPC_MULTU = OPC_SPECIAL | 0x19,
317 OPC_DIV = OPC_SPECIAL | 0x1A,
318 OPC_DIVU = OPC_SPECIAL | 0x1B,
319 OPC_ADDU = OPC_SPECIAL | 0x21,
320 OPC_SUBU = OPC_SPECIAL | 0x23,
321 OPC_AND = OPC_SPECIAL | 0x24,
322 OPC_OR = OPC_SPECIAL | 0x25,
323 OPC_XOR = OPC_SPECIAL | 0x26,
324 OPC_NOR = OPC_SPECIAL | 0x27,
325 OPC_SLT = OPC_SPECIAL | 0x2A,
326 OPC_SLTU = OPC_SPECIAL | 0x2B,
116348de 327
0f46c064
AJ
328 OPC_REGIMM = 0x01 << 26,
329 OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
330 OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
331
116348de 332 OPC_SPECIAL3 = 0x1f << 26,
04f71aa3 333 OPC_INS = OPC_SPECIAL3 | 0x004,
c1cf85c9 334 OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
116348de
AJ
335 OPC_SEB = OPC_SPECIAL3 | 0x420,
336 OPC_SEH = OPC_SPECIAL3 | 0x620,
afa05235
AJ
337};
338
339/*
340 * Type reg
341 */
5a0eed37
AJ
342static inline void tcg_out_opc_reg(TCGContext *s, int opc,
343 TCGReg rd, TCGReg rs, TCGReg rt)
afa05235
AJ
344{
345 int32_t inst;
346
347 inst = opc;
348 inst |= (rs & 0x1F) << 21;
349 inst |= (rt & 0x1F) << 16;
350 inst |= (rd & 0x1F) << 11;
351 tcg_out32(s, inst);
352}
353
354/*
355 * Type immediate
356 */
5a0eed37
AJ
357static inline void tcg_out_opc_imm(TCGContext *s, int opc,
358 TCGReg rt, TCGReg rs, TCGArg imm)
afa05235
AJ
359{
360 int32_t inst;
361
362 inst = opc;
363 inst |= (rs & 0x1F) << 21;
364 inst |= (rt & 0x1F) << 16;
365 inst |= (imm & 0xffff);
366 tcg_out32(s, inst);
367}
368
6d8ff4d8
AJ
369/*
370 * Type branch
371 */
5a0eed37
AJ
372static inline void tcg_out_opc_br(TCGContext *s, int opc,
373 TCGReg rt, TCGReg rs)
6d8ff4d8 374{
56779034
AJ
375 /* We pay attention here to not modify the branch target by reading
376 the existing value and using it again. This ensure that caches and
377 memory are kept coherent during retranslation. */
d43ffce1 378 uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
6d8ff4d8
AJ
379
380 tcg_out_opc_imm(s, opc, rt, rs, offset);
381}
382
afa05235
AJ
383/*
384 * Type sa
385 */
5a0eed37
AJ
386static inline void tcg_out_opc_sa(TCGContext *s, int opc,
387 TCGReg rd, TCGReg rt, TCGArg sa)
afa05235
AJ
388{
389 int32_t inst;
390
391 inst = opc;
392 inst |= (rt & 0x1F) << 16;
393 inst |= (rd & 0x1F) << 11;
394 inst |= (sa & 0x1F) << 6;
395 tcg_out32(s, inst);
396
397}
398
399static inline void tcg_out_nop(TCGContext *s)
400{
401 tcg_out32(s, 0);
402}
403
2a534aff
RH
404static inline void tcg_out_mov(TCGContext *s, TCGType type,
405 TCGReg ret, TCGReg arg)
afa05235 406{
18fec301
AJ
407 /* Simple reg-reg move, optimising out the 'do nothing' case */
408 if (ret != arg) {
409 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
410 }
afa05235
AJ
411}
412
413static inline void tcg_out_movi(TCGContext *s, TCGType type,
2a534aff 414 TCGReg reg, tcg_target_long arg)
afa05235
AJ
415{
416 if (arg == (int16_t)arg) {
417 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
418 } else if (arg == (uint16_t)arg) {
419 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
420 } else {
421 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
422 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
423 }
424}
425
5a0eed37 426static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 427{
c1cf85c9
AJ
428#ifdef _MIPS_ARCH_MIPS32R2
429 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
430#else
afa05235
AJ
431 /* ret and arg can't be register at */
432 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
433 tcg_abort();
434 }
435
436 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
afa05235
AJ
437 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
438 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
439 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
c1cf85c9 440#endif
afa05235
AJ
441}
442
5a0eed37 443static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 444{
c1cf85c9
AJ
445#ifdef _MIPS_ARCH_MIPS32R2
446 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
447 tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
448#else
afa05235
AJ
449 /* ret and arg can't be register at */
450 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
451 tcg_abort();
452 }
453
454 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
afa05235
AJ
455 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
456 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
457 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
c1cf85c9 458#endif
afa05235
AJ
459}
460
5a0eed37 461static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
afa05235 462{
c1cf85c9
AJ
463#ifdef _MIPS_ARCH_MIPS32R2
464 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
465 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
466#else
afa05235
AJ
467 /* ret and arg must be different and can't be register at */
468 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
469 tcg_abort();
470 }
471
472 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
473
474 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
475 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
476
477 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
478 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
479 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
480
481 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
482 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
483 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
c1cf85c9 484#endif
afa05235
AJ
485}
486
5a0eed37 487static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
116348de
AJ
488{
489#ifdef _MIPS_ARCH_MIPS32R2
490 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
491#else
492 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
493 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
494#endif
495}
496
5a0eed37 497static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
116348de
AJ
498{
499#ifdef _MIPS_ARCH_MIPS32R2
500 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
501#else
502 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
503 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
504#endif
505}
506
5a0eed37
AJ
507static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg,
508 TCGReg arg1, TCGArg arg2)
afa05235
AJ
509{
510 if (arg2 == (int16_t) arg2) {
511 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
512 } else {
513 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
514 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
515 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
516 }
517}
518
2a534aff
RH
519static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
520 TCGReg arg1, tcg_target_long arg2)
afa05235
AJ
521{
522 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
523}
524
2a534aff
RH
525static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
526 TCGReg arg1, tcg_target_long arg2)
afa05235
AJ
527{
528 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
529}
530
5a0eed37 531static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
afa05235
AJ
532{
533 if (val == (int16_t)val) {
534 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
535 } else {
536 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
537 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
538 }
539}
540
18fec301
AJ
541/* Helper routines for marshalling helper function arguments into
542 * the correct registers and stack.
543 * arg_num is where we want to put this argument, and is updated to be ready
544 * for the next call. arg is the argument itself. Note that arg_num 0..3 is
545 * real registers, 4+ on stack.
546 *
547 * We provide routines for arguments which are: immediate, 32 bit
548 * value in register, 16 and 8 bit values in register (which must be zero
549 * extended before use) and 64 bit value in a lo:hi register pair.
550 */
551#define DEFINE_TCG_OUT_CALL_IARG(NAME, ARGPARAM) \
552 static inline void NAME(TCGContext *s, int *arg_num, ARGPARAM) \
553 { \
554 if (*arg_num < 4) { \
555 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(tcg_target_call_iarg_regs[*arg_num]); \
556 } else { \
557 DEFINE_TCG_OUT_CALL_IARG_GET_ARG(TCG_REG_AT); \
558 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 4 * (*arg_num)); \
559 } \
560 (*arg_num)++; \
561}
562#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
563 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xff);
564DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg8, TCGReg arg)
565#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
566#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
567 tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xffff);
568DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg)
569#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
570#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
571 tcg_out_movi(s, TCG_TYPE_I32, A, arg);
5a0eed37 572DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, TCGArg arg)
18fec301
AJ
573#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
574
575/* We don't use the macro for this one to avoid an unnecessary reg-reg
576 move when storing to the stack. */
577static inline void tcg_out_call_iarg_reg32(TCGContext *s, int *arg_num,
578 TCGReg arg)
579{
580 if (*arg_num < 4) {
581 tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[*arg_num], arg);
582 } else {
583 tcg_out_st(s, TCG_TYPE_I32, arg, TCG_REG_SP, 4 * (*arg_num));
584 }
585 (*arg_num)++;
586}
587
588static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num,
589 TCGReg arg_low, TCGReg arg_high)
590{
591 (*arg_num) = (*arg_num + 1) & ~1;
592
593#if defined(TCG_TARGET_WORDS_BIGENDIAN)
594 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
595 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
596#else
597 tcg_out_call_iarg_reg32(s, arg_num, arg_low);
598 tcg_out_call_iarg_reg32(s, arg_num, arg_high);
599#endif
600}
601
5a0eed37
AJ
602static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGArg arg1,
603 TCGArg arg2, int label_index)
afa05235
AJ
604{
605 TCGLabel *l = &s->labels[label_index];
606
607 switch (cond) {
608 case TCG_COND_EQ:
6d8ff4d8 609 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
afa05235
AJ
610 break;
611 case TCG_COND_NE:
6d8ff4d8 612 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
afa05235
AJ
613 break;
614 case TCG_COND_LT:
0f46c064
AJ
615 if (arg2 == 0) {
616 tcg_out_opc_br(s, OPC_BLTZ, 0, arg1);
617 } else {
618 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
619 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
620 }
afa05235
AJ
621 break;
622 case TCG_COND_LTU:
623 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
6d8ff4d8 624 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
625 break;
626 case TCG_COND_GE:
0f46c064
AJ
627 if (arg2 == 0) {
628 tcg_out_opc_br(s, OPC_BGEZ, 0, arg1);
629 } else {
630 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
631 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
632 }
afa05235
AJ
633 break;
634 case TCG_COND_GEU:
635 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
6d8ff4d8 636 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
637 break;
638 case TCG_COND_LE:
0f46c064
AJ
639 if (arg2 == 0) {
640 tcg_out_opc_br(s, OPC_BLEZ, 0, arg1);
641 } else {
642 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
643 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
644 }
afa05235
AJ
645 break;
646 case TCG_COND_LEU:
647 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
6d8ff4d8 648 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
649 break;
650 case TCG_COND_GT:
0f46c064
AJ
651 if (arg2 == 0) {
652 tcg_out_opc_br(s, OPC_BGTZ, 0, arg1);
653 } else {
654 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
655 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
656 }
afa05235
AJ
657 break;
658 case TCG_COND_GTU:
659 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
6d8ff4d8 660 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
afa05235
AJ
661 break;
662 default:
663 tcg_abort();
664 break;
665 }
666 if (l->has_value) {
667 reloc_pc16(s->code_ptr - 4, l->u.value);
668 } else {
669 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
670 }
671 tcg_out_nop(s);
672}
673
674/* XXX: we implement it at the target level to avoid having to
675 handle cross basic blocks temporaries */
5a0eed37
AJ
676static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGArg arg1,
677 TCGArg arg2, TCGArg arg3, TCGArg arg4,
678 int label_index)
afa05235
AJ
679{
680 void *label_ptr;
681
682 switch(cond) {
683 case TCG_COND_NE:
684 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
685 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
686 return;
687 case TCG_COND_EQ:
688 break;
689 case TCG_COND_LT:
690 case TCG_COND_LE:
691 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
692 break;
693 case TCG_COND_GT:
694 case TCG_COND_GE:
695 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
696 break;
697 case TCG_COND_LTU:
698 case TCG_COND_LEU:
699 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
700 break;
701 case TCG_COND_GTU:
702 case TCG_COND_GEU:
703 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
704 break;
705 default:
706 tcg_abort();
707 }
708
709 label_ptr = s->code_ptr;
6d8ff4d8 710 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
afa05235
AJ
711 tcg_out_nop(s);
712
713 switch(cond) {
714 case TCG_COND_EQ:
715 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
716 break;
717 case TCG_COND_LT:
718 case TCG_COND_LTU:
719 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
720 break;
721 case TCG_COND_LE:
722 case TCG_COND_LEU:
723 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
724 break;
725 case TCG_COND_GT:
726 case TCG_COND_GTU:
727 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
728 break;
729 case TCG_COND_GE:
730 case TCG_COND_GEU:
731 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
732 break;
733 default:
734 tcg_abort();
735 }
736
737 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
738}
739
7d7c4930
AJ
740static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
741 TCGArg c1, TCGArg c2, TCGArg v)
742{
743 switch (cond) {
744 case TCG_COND_EQ:
745 if (c1 == 0) {
746 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c2);
747 } else if (c2 == 0) {
748 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, c1);
749 } else {
750 tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
751 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
752 }
753 break;
754 case TCG_COND_NE:
755 if (c1 == 0) {
756 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c2);
757 } else if (c2 == 0) {
758 tcg_out_opc_reg(s, OPC_MOVN, ret, v, c1);
759 } else {
760 tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, c1, c2);
761 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
762 }
763 break;
764 case TCG_COND_LT:
765 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
766 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
767 break;
768 case TCG_COND_LTU:
769 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
770 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
771 break;
772 case TCG_COND_GE:
773 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c1, c2);
774 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
775 break;
776 case TCG_COND_GEU:
777 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c1, c2);
778 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
779 break;
780 case TCG_COND_LE:
781 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
782 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
783 break;
784 case TCG_COND_LEU:
785 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
786 tcg_out_opc_reg(s, OPC_MOVZ, ret, v, TCG_REG_AT);
787 break;
788 case TCG_COND_GT:
789 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, c2, c1);
790 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
791 break;
792 case TCG_COND_GTU:
793 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, c2, c1);
794 tcg_out_opc_reg(s, OPC_MOVN, ret, v, TCG_REG_AT);
795 break;
796 default:
797 tcg_abort();
798 break;
799 }
800}
801
5a0eed37
AJ
802static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
803 TCGArg arg1, TCGArg arg2)
4cb26382
AJ
804{
805 switch (cond) {
806 case TCG_COND_EQ:
807 if (arg1 == 0) {
808 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
809 } else if (arg2 == 0) {
810 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
811 } else {
434254aa
AJ
812 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
813 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
4cb26382
AJ
814 }
815 break;
816 case TCG_COND_NE:
817 if (arg1 == 0) {
818 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
819 } else if (arg2 == 0) {
820 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
821 } else {
434254aa
AJ
822 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
823 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
4cb26382
AJ
824 }
825 break;
826 case TCG_COND_LT:
827 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
828 break;
829 case TCG_COND_LTU:
830 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
831 break;
832 case TCG_COND_GE:
434254aa
AJ
833 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
834 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
835 break;
836 case TCG_COND_GEU:
434254aa
AJ
837 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
838 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
839 break;
840 case TCG_COND_LE:
434254aa
AJ
841 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
842 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
843 break;
844 case TCG_COND_LEU:
434254aa
AJ
845 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
846 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
4cb26382
AJ
847 break;
848 case TCG_COND_GT:
849 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
850 break;
851 case TCG_COND_GTU:
852 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
853 break;
854 default:
855 tcg_abort();
856 break;
857 }
858}
859
434254aa
AJ
860/* XXX: we implement it at the target level to avoid having to
861 handle cross basic blocks temporaries */
5a0eed37
AJ
862static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
863 TCGArg arg1, TCGArg arg2, TCGArg arg3, TCGArg arg4)
434254aa
AJ
864{
865 switch (cond) {
866 case TCG_COND_EQ:
867 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
868 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
869 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
870 return;
871 case TCG_COND_NE:
872 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
873 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
874 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
875 return;
876 case TCG_COND_LT:
877 case TCG_COND_LE:
878 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
879 break;
880 case TCG_COND_GT:
881 case TCG_COND_GE:
882 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
883 break;
884 case TCG_COND_LTU:
885 case TCG_COND_LEU:
886 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
887 break;
888 case TCG_COND_GTU:
889 case TCG_COND_GEU:
890 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
891 break;
892 default:
893 tcg_abort();
894 break;
895 }
896
897 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
898
899 switch(cond) {
900 case TCG_COND_LT:
901 case TCG_COND_LTU:
902 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
903 break;
904 case TCG_COND_LE:
905 case TCG_COND_LEU:
906 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
907 break;
908 case TCG_COND_GT:
909 case TCG_COND_GTU:
910 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
911 break;
912 case TCG_COND_GE:
913 case TCG_COND_GEU:
914 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
915 break;
916 default:
917 tcg_abort();
918 }
919
920 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
921 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
922}
923
afa05235
AJ
924#if defined(CONFIG_SOFTMMU)
925
926#include "../../softmmu_defs.h"
927
e141ab52
BS
928/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
929 int mmu_idx) */
930static const void * const qemu_ld_helpers[4] = {
931 helper_ldb_mmu,
932 helper_ldw_mmu,
933 helper_ldl_mmu,
934 helper_ldq_mmu,
935};
936
937/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
938 uintxx_t val, int mmu_idx) */
939static const void * const qemu_st_helpers[4] = {
940 helper_stb_mmu,
941 helper_stw_mmu,
942 helper_stl_mmu,
943 helper_stq_mmu,
944};
e141ab52 945#endif
afa05235
AJ
946
947static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
948 int opc)
949{
5a0eed37 950 TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
afa05235
AJ
951#if defined(CONFIG_SOFTMMU)
952 void *label1_ptr, *label2_ptr;
18fec301 953 int arg_num;
0834c9ea
AJ
954 int mem_index, s_bits;
955 int addr_meml;
956# if TARGET_LONG_BITS == 64
afa05235 957 uint8_t *label3_ptr;
5a0eed37
AJ
958 TCGReg addr_regh;
959 int addr_memh;
0834c9ea 960# endif
afa05235
AJ
961#endif
962 data_regl = *args++;
963 if (opc == 3)
964 data_regh = *args++;
965 else
966 data_regh = 0;
967 addr_regl = *args++;
0834c9ea
AJ
968#if defined(CONFIG_SOFTMMU)
969# if TARGET_LONG_BITS == 64
afa05235 970 addr_regh = *args++;
0834c9ea
AJ
971# if defined(TCG_TARGET_WORDS_BIGENDIAN)
972 addr_memh = 0;
973 addr_meml = 4;
974# else
975 addr_memh = 4;
976 addr_meml = 0;
977# endif
978# else
979 addr_meml = 0;
980# endif
afa05235
AJ
981 mem_index = *args;
982 s_bits = opc & 3;
0834c9ea 983#endif
afa05235
AJ
984
985 if (opc == 3) {
986#if defined(TCG_TARGET_WORDS_BIGENDIAN)
987 data_reg1 = data_regh;
988 data_reg2 = data_regl;
989#else
990 data_reg1 = data_regl;
991 data_reg2 = data_regh;
992#endif
993 } else {
994 data_reg1 = data_regl;
995 data_reg2 = 0;
996 }
afa05235
AJ
997#if defined(CONFIG_SOFTMMU)
998 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
999 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1000 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1001 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 1002 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
afa05235
AJ
1003 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1004 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1005
1006# if TARGET_LONG_BITS == 64
1007 label3_ptr = s->code_ptr;
6d8ff4d8 1008 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1009 tcg_out_nop(s);
1010
1011 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 1012 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
afa05235
AJ
1013
1014 label1_ptr = s->code_ptr;
6d8ff4d8 1015 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
afa05235
AJ
1016 tcg_out_nop(s);
1017
1018 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1019# else
1020 label1_ptr = s->code_ptr;
6d8ff4d8 1021 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1022 tcg_out_nop(s);
1023# endif
1024
1025 /* slow path */
18fec301 1026 arg_num = 0;
18fec301 1027 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
afa05235 1028# if TARGET_LONG_BITS == 64
18fec301
AJ
1029 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1030# else
1031 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
afa05235 1032# endif
18fec301 1033 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
afa05235
AJ
1034 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
1035 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1036 tcg_out_nop(s);
1037
1038 switch(opc) {
1039 case 0:
1040 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
1041 break;
1042 case 0 | 4:
116348de 1043 tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
afa05235
AJ
1044 break;
1045 case 1:
1046 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
1047 break;
1048 case 1 | 4:
116348de 1049 tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
afa05235
AJ
1050 break;
1051 case 2:
3b6dac34 1052 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
afa05235
AJ
1053 break;
1054 case 3:
3b6dac34
RH
1055 tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
1056 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
afa05235
AJ
1057 break;
1058 default:
1059 tcg_abort();
1060 }
1061
1062 label2_ptr = s->code_ptr;
6d8ff4d8 1063 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
afa05235
AJ
1064 tcg_out_nop(s);
1065
1066 /* label1: fast path */
1067 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1068
cca1af8c 1069 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
9349b4f9 1070 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
cca1af8c 1071 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
cc01cc8e
AJ
1072#else
1073 if (GUEST_BASE == (int16_t)GUEST_BASE) {
ba0d89bb 1074 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
cc01cc8e
AJ
1075 } else {
1076 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
ba0d89bb 1077 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
cc01cc8e 1078 }
afa05235
AJ
1079#endif
1080
1081 switch(opc) {
1082 case 0:
cc01cc8e 1083 tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1084 break;
1085 case 0 | 4:
cc01cc8e 1086 tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1087 break;
1088 case 1:
1089 if (TCG_NEED_BSWAP) {
cc01cc8e 1090 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1091 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
1092 } else {
cc01cc8e 1093 tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1094 }
1095 break;
1096 case 1 | 4:
1097 if (TCG_NEED_BSWAP) {
cc01cc8e 1098 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1099 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
1100 } else {
cc01cc8e 1101 tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1102 }
1103 break;
1104 case 2:
1105 if (TCG_NEED_BSWAP) {
cc01cc8e 1106 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1107 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1108 } else {
cc01cc8e 1109 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
afa05235
AJ
1110 }
1111 break;
1112 case 3:
afa05235 1113 if (TCG_NEED_BSWAP) {
cc01cc8e 1114 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
afa05235 1115 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
cc01cc8e 1116 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
afa05235
AJ
1117 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
1118 } else {
cc01cc8e
AJ
1119 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1120 tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
afa05235
AJ
1121 }
1122 break;
1123 default:
1124 tcg_abort();
1125 }
1126
1127#if defined(CONFIG_SOFTMMU)
1128 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1129#endif
1130}
1131
1132static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1133 int opc)
1134{
5a0eed37 1135 TCGReg addr_regl, data_regl, data_regh, data_reg1, data_reg2;
afa05235
AJ
1136#if defined(CONFIG_SOFTMMU)
1137 uint8_t *label1_ptr, *label2_ptr;
18fec301 1138 int arg_num;
0834c9ea
AJ
1139 int mem_index, s_bits;
1140 int addr_meml;
afa05235
AJ
1141#endif
1142#if TARGET_LONG_BITS == 64
1143# if defined(CONFIG_SOFTMMU)
1144 uint8_t *label3_ptr;
5a0eed37
AJ
1145 TCGReg addr_regh;
1146 int addr_memh;
0834c9ea 1147# endif
afa05235 1148#endif
afa05235
AJ
1149 data_regl = *args++;
1150 if (opc == 3) {
1151 data_regh = *args++;
afa05235 1152 } else {
afa05235
AJ
1153 data_regh = 0;
1154 }
1155 addr_regl = *args++;
0834c9ea
AJ
1156#if defined(CONFIG_SOFTMMU)
1157# if TARGET_LONG_BITS == 64
afa05235 1158 addr_regh = *args++;
0834c9ea 1159# if defined(TCG_TARGET_WORDS_BIGENDIAN)
afa05235
AJ
1160 addr_memh = 0;
1161 addr_meml = 4;
0834c9ea 1162# else
afa05235
AJ
1163 addr_memh = 4;
1164 addr_meml = 0;
0834c9ea
AJ
1165# endif
1166# else
afa05235 1167 addr_meml = 0;
0834c9ea 1168# endif
afa05235
AJ
1169 mem_index = *args;
1170 s_bits = opc;
0834c9ea
AJ
1171#endif
1172
1173 if (opc == 3) {
1174#if defined(TCG_TARGET_WORDS_BIGENDIAN)
1175 data_reg1 = data_regh;
1176 data_reg2 = data_regl;
1177#else
1178 data_reg1 = data_regl;
1179 data_reg2 = data_regh;
1180#endif
1181 } else {
1182 data_reg1 = data_regl;
1183 data_reg2 = 0;
1184 }
afa05235
AJ
1185
1186#if defined(CONFIG_SOFTMMU)
1187 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1188 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1189 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1190 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 1191 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
afa05235
AJ
1192 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1193 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1194
1195# if TARGET_LONG_BITS == 64
1196 label3_ptr = s->code_ptr;
6d8ff4d8 1197 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1198 tcg_out_nop(s);
1199
1200 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
9349b4f9 1201 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
afa05235
AJ
1202
1203 label1_ptr = s->code_ptr;
6d8ff4d8 1204 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
afa05235
AJ
1205 tcg_out_nop(s);
1206
1207 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1208# else
1209 label1_ptr = s->code_ptr;
6d8ff4d8 1210 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
afa05235
AJ
1211 tcg_out_nop(s);
1212# endif
1213
1214 /* slow path */
18fec301 1215 arg_num = 0;
18fec301 1216 tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
afa05235 1217# if TARGET_LONG_BITS == 64
18fec301
AJ
1218 tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1219# else
1220 tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
afa05235
AJ
1221# endif
1222 switch(opc) {
1223 case 0:
18fec301 1224 tcg_out_call_iarg_reg8(s, &arg_num, data_regl);
afa05235
AJ
1225 break;
1226 case 1:
18fec301 1227 tcg_out_call_iarg_reg16(s, &arg_num, data_regl);
afa05235
AJ
1228 break;
1229 case 2:
18fec301 1230 tcg_out_call_iarg_reg32(s, &arg_num, data_regl);
afa05235
AJ
1231 break;
1232 case 3:
18fec301 1233 tcg_out_call_iarg_reg64(s, &arg_num, data_regl, data_regh);
afa05235
AJ
1234 break;
1235 default:
1236 tcg_abort();
1237 }
18fec301 1238 tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
afa05235
AJ
1239 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1240 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1241 tcg_out_nop(s);
1242
1243 label2_ptr = s->code_ptr;
6d8ff4d8 1244 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
afa05235
AJ
1245 tcg_out_nop(s);
1246
1247 /* label1: fast path */
1248 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1249
1250 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
9349b4f9 1251 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
afa05235 1252 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
cc01cc8e
AJ
1253#else
1254 if (GUEST_BASE == (int16_t)GUEST_BASE) {
ba0d89bb 1255 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
cc01cc8e
AJ
1256 } else {
1257 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
ba0d89bb 1258 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
cc01cc8e 1259 }
afa05235 1260
afa05235
AJ
1261#endif
1262
1263 switch(opc) {
1264 case 0:
cc01cc8e 1265 tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
afa05235
AJ
1266 break;
1267 case 1:
1268 if (TCG_NEED_BSWAP) {
c1cf85c9
AJ
1269 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_T0, data_reg1, 0xffff);
1270 tcg_out_bswap16(s, TCG_REG_T0, TCG_REG_T0);
cc01cc8e 1271 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
afa05235 1272 } else {
cc01cc8e 1273 tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
afa05235
AJ
1274 }
1275 break;
1276 case 2:
1277 if (TCG_NEED_BSWAP) {
1278 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
cc01cc8e 1279 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
afa05235 1280 } else {
cc01cc8e 1281 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
afa05235
AJ
1282 }
1283 break;
1284 case 3:
1285 if (TCG_NEED_BSWAP) {
1286 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
cc01cc8e 1287 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
afa05235 1288 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
cc01cc8e 1289 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
afa05235 1290 } else {
cc01cc8e
AJ
1291 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1292 tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
afa05235
AJ
1293 }
1294 break;
1295 default:
1296 tcg_abort();
1297 }
1298
1299#if defined(CONFIG_SOFTMMU)
1300 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1301#endif
1302}
1303
a9751609 1304static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
afa05235
AJ
1305 const TCGArg *args, const int *const_args)
1306{
1307 switch(opc) {
1308 case INDEX_op_exit_tb:
1309 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1310 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1311 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1312 tcg_out_nop(s);
1313 break;
1314 case INDEX_op_goto_tb:
1315 if (s->tb_jmp_offset) {
1316 /* direct jump method */
1317 tcg_abort();
1318 } else {
1319 /* indirect jump method */
1320 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1321 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1322 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1323 }
1324 tcg_out_nop(s);
1325 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1326 break;
1327 case INDEX_op_call:
1328 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1329 tcg_out_nop(s);
1330 break;
1331 case INDEX_op_jmp:
1332 tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1333 tcg_out_nop(s);
1334 break;
1335 case INDEX_op_br:
1336 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1337 break;
1338
1339 case INDEX_op_mov_i32:
3b6dac34 1340 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
afa05235
AJ
1341 break;
1342 case INDEX_op_movi_i32:
1343 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1344 break;
1345
1346 case INDEX_op_ld8u_i32:
116348de 1347 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
afa05235
AJ
1348 break;
1349 case INDEX_op_ld8s_i32:
1350 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1351 break;
1352 case INDEX_op_ld16u_i32:
1353 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1354 break;
1355 case INDEX_op_ld16s_i32:
1356 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1357 break;
1358 case INDEX_op_ld_i32:
1359 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1360 break;
1361 case INDEX_op_st8_i32:
1362 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1363 break;
1364 case INDEX_op_st16_i32:
1365 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1366 break;
1367 case INDEX_op_st_i32:
1368 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1369 break;
1370
1371 case INDEX_op_add_i32:
1372 if (const_args[2]) {
1373 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1374 } else {
1375 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1376 }
1377 break;
1378 case INDEX_op_add2_i32:
1379 if (const_args[4]) {
1380 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1381 } else {
1382 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1383 }
1384 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1385 if (const_args[5]) {
1386 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1387 } else {
1388 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1389 }
1390 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
3b6dac34 1391 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
afa05235
AJ
1392 break;
1393 case INDEX_op_sub_i32:
1394 if (const_args[2]) {
1395 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1396 } else {
1397 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1398 }
1399 break;
1400 case INDEX_op_sub2_i32:
1401 if (const_args[4]) {
1402 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1403 } else {
1404 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1405 }
1406 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1407 if (const_args[5]) {
1408 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1409 } else {
1410 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1411 }
1412 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
3b6dac34 1413 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
afa05235
AJ
1414 break;
1415 case INDEX_op_mul_i32:
1416 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1417 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1418 break;
1419 case INDEX_op_mulu2_i32:
1420 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1421 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1422 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1423 break;
1424 case INDEX_op_div_i32:
1425 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1426 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1427 break;
1428 case INDEX_op_divu_i32:
1429 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1430 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1431 break;
1432 case INDEX_op_rem_i32:
1433 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1434 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1435 break;
1436 case INDEX_op_remu_i32:
1437 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1438 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1439 break;
1440
1441 case INDEX_op_and_i32:
1442 if (const_args[2]) {
1443 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1444 } else {
1445 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1446 }
1447 break;
1448 case INDEX_op_or_i32:
1449 if (const_args[2]) {
1450 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1451 } else {
1452 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1453 }
1454 break;
2b79487a
AJ
1455 case INDEX_op_nor_i32:
1456 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1457 break;
afa05235 1458 case INDEX_op_not_i32:
489722cf 1459 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
afa05235
AJ
1460 break;
1461 case INDEX_op_xor_i32:
1462 if (const_args[2]) {
1463 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1464 } else {
1465 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1466 }
1467 break;
1468
1469 case INDEX_op_sar_i32:
1470 if (const_args[2]) {
1471 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1472 } else {
1473 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1474 }
1475 break;
1476 case INDEX_op_shl_i32:
1477 if (const_args[2]) {
1478 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1479 } else {
1480 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1481 }
1482 break;
1483 case INDEX_op_shr_i32:
1484 if (const_args[2]) {
1485 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1486 } else {
1487 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1488 }
1489 break;
9a152519
AJ
1490 case INDEX_op_rotl_i32:
1491 if (const_args[2]) {
1492 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], 0x20 - args[2]);
1493 } else {
1494 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, 32);
1495 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, TCG_REG_AT, args[2]);
1496 tcg_out_opc_reg(s, OPC_ROTRV, args[0], TCG_REG_AT, args[1]);
1497 }
1498 break;
1499 case INDEX_op_rotr_i32:
1500 if (const_args[2]) {
1501 tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], args[2]);
1502 } else {
1503 tcg_out_opc_reg(s, OPC_ROTRV, args[0], args[2], args[1]);
1504 }
1505 break;
afa05235 1506
c1cf85c9
AJ
1507 /* The bswap routines do not work on non-R2 CPU. In that case
1508 we let TCG generating the corresponding code. */
1509 case INDEX_op_bswap16_i32:
1510 tcg_out_bswap16(s, args[0], args[1]);
1511 break;
1512 case INDEX_op_bswap32_i32:
1513 tcg_out_bswap32(s, args[0], args[1]);
1514 break;
1515
116348de
AJ
1516 case INDEX_op_ext8s_i32:
1517 tcg_out_ext8s(s, args[0], args[1]);
1518 break;
1519 case INDEX_op_ext16s_i32:
1520 tcg_out_ext16s(s, args[0], args[1]);
1521 break;
1522
04f71aa3
AJ
1523 case INDEX_op_deposit_i32:
1524 tcg_out_opc_imm(s, OPC_INS, args[0], args[2],
1525 ((args[3] + args[4] - 1) << 11) | (args[3] << 6));
1526 break;
1527
afa05235
AJ
1528 case INDEX_op_brcond_i32:
1529 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1530 break;
1531 case INDEX_op_brcond2_i32:
1532 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1533 break;
1534
7d7c4930
AJ
1535 case INDEX_op_movcond_i32:
1536 tcg_out_movcond(s, args[5], args[0], args[1], args[2], args[3]);
1537 break;
1538
4cb26382
AJ
1539 case INDEX_op_setcond_i32:
1540 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1541 break;
434254aa
AJ
1542 case INDEX_op_setcond2_i32:
1543 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1544 break;
4cb26382 1545
afa05235
AJ
1546 case INDEX_op_qemu_ld8u:
1547 tcg_out_qemu_ld(s, args, 0);
1548 break;
1549 case INDEX_op_qemu_ld8s:
1550 tcg_out_qemu_ld(s, args, 0 | 4);
1551 break;
1552 case INDEX_op_qemu_ld16u:
1553 tcg_out_qemu_ld(s, args, 1);
1554 break;
1555 case INDEX_op_qemu_ld16s:
1556 tcg_out_qemu_ld(s, args, 1 | 4);
1557 break;
86feb1c8 1558 case INDEX_op_qemu_ld32:
afa05235
AJ
1559 tcg_out_qemu_ld(s, args, 2);
1560 break;
1561 case INDEX_op_qemu_ld64:
1562 tcg_out_qemu_ld(s, args, 3);
1563 break;
1564 case INDEX_op_qemu_st8:
1565 tcg_out_qemu_st(s, args, 0);
1566 break;
1567 case INDEX_op_qemu_st16:
1568 tcg_out_qemu_st(s, args, 1);
1569 break;
1570 case INDEX_op_qemu_st32:
1571 tcg_out_qemu_st(s, args, 2);
1572 break;
1573 case INDEX_op_qemu_st64:
1574 tcg_out_qemu_st(s, args, 3);
1575 break;
1576
1577 default:
1578 tcg_abort();
1579 }
1580}
1581
1582static const TCGTargetOpDef mips_op_defs[] = {
1583 { INDEX_op_exit_tb, { } },
1584 { INDEX_op_goto_tb, { } },
1585 { INDEX_op_call, { "C" } },
1586 { INDEX_op_jmp, { "r" } },
1587 { INDEX_op_br, { } },
1588
1589 { INDEX_op_mov_i32, { "r", "r" } },
1590 { INDEX_op_movi_i32, { "r" } },
1591 { INDEX_op_ld8u_i32, { "r", "r" } },
1592 { INDEX_op_ld8s_i32, { "r", "r" } },
1593 { INDEX_op_ld16u_i32, { "r", "r" } },
1594 { INDEX_op_ld16s_i32, { "r", "r" } },
1595 { INDEX_op_ld_i32, { "r", "r" } },
1596 { INDEX_op_st8_i32, { "rZ", "r" } },
1597 { INDEX_op_st16_i32, { "rZ", "r" } },
1598 { INDEX_op_st_i32, { "rZ", "r" } },
1599
2ceb3a9e 1600 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
afa05235
AJ
1601 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1602 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1603 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1604 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1605 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1606 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
2ceb3a9e 1607 { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
afa05235 1608
2ceb3a9e 1609 { INDEX_op_and_i32, { "r", "rZ", "rI" } },
2b79487a 1610 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
afa05235
AJ
1611 { INDEX_op_not_i32, { "r", "rZ" } },
1612 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1613 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1614
2ceb3a9e
AJ
1615 { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1616 { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1617 { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
9a152519
AJ
1618 { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
1619 { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
afa05235 1620
c1cf85c9
AJ
1621 { INDEX_op_bswap16_i32, { "r", "r" } },
1622 { INDEX_op_bswap32_i32, { "r", "r" } },
1623
116348de
AJ
1624 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1625 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1626
04f71aa3
AJ
1627 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1628
afa05235 1629 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
7d7c4930 1630 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
4cb26382 1631 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
434254aa 1632 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
afa05235 1633
2ceb3a9e
AJ
1634 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1635 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
afa05235
AJ
1636 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1637
1638#if TARGET_LONG_BITS == 32
1639 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1640 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1641 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1642 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
86feb1c8 1643 { INDEX_op_qemu_ld32, { "L", "lZ" } },
afa05235
AJ
1644 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1645
1646 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1647 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1648 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1649 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1650#else
1651 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1652 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1653 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1654 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
86feb1c8 1655 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
afa05235
AJ
1656 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1657
1658 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1659 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1660 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1661 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1662#endif
1663 { -1 },
1664};
1665
1666static int tcg_target_callee_save_regs[] = {
cea5f9a2 1667 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
afa05235
AJ
1668 TCG_REG_S1,
1669 TCG_REG_S2,
1670 TCG_REG_S3,
1671 TCG_REG_S4,
1672 TCG_REG_S5,
1673 TCG_REG_S6,
1674 TCG_REG_S7,
60bf84cf 1675 TCG_REG_FP,
afa05235
AJ
1676 TCG_REG_RA, /* should be last for ABI compliance */
1677};
1678
1679/* Generate global QEMU prologue and epilogue code */
e4d58b41 1680static void tcg_target_qemu_prologue(TCGContext *s)
afa05235
AJ
1681{
1682 int i, frame_size;
1683
0d0b53a6 1684 /* reserve some stack space, also for TCG temps. */
afa05235 1685 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
0d0b53a6
AJ
1686 + TCG_STATIC_CALL_ARGS_SIZE
1687 + CPU_TEMP_BUF_NLONGS * sizeof(long);
afa05235
AJ
1688 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1689 ~(TCG_TARGET_STACK_ALIGN - 1);
0d0b53a6
AJ
1690 tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1691 + TCG_STATIC_CALL_ARGS_SIZE,
1692 CPU_TEMP_BUF_NLONGS * sizeof(long));
afa05235
AJ
1693
1694 /* TB prologue */
1695 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1696 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1697 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1698 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1699 }
1700
1701 /* Call generated code */
ea15fb06 1702 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
cea5f9a2 1703 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
afa05235
AJ
1704 tb_ret_addr = s->code_ptr;
1705
1706 /* TB epilogue */
1707 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1708 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1709 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1710 }
1711
1712 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1713 tcg_out_addi(s, TCG_REG_SP, frame_size);
1714}
1715
e4d58b41 1716static void tcg_target_init(TCGContext *s)
afa05235
AJ
1717{
1718 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1719 tcg_regset_set(tcg_target_call_clobber_regs,
1720 (1 << TCG_REG_V0) |
1721 (1 << TCG_REG_V1) |
1722 (1 << TCG_REG_A0) |
1723 (1 << TCG_REG_A1) |
1724 (1 << TCG_REG_A2) |
1725 (1 << TCG_REG_A3) |
1726 (1 << TCG_REG_T1) |
1727 (1 << TCG_REG_T2) |
1728 (1 << TCG_REG_T3) |
1729 (1 << TCG_REG_T4) |
1730 (1 << TCG_REG_T5) |
1731 (1 << TCG_REG_T6) |
1732 (1 << TCG_REG_T7) |
1733 (1 << TCG_REG_T8) |
1734 (1 << TCG_REG_T9));
1735
1736 tcg_regset_clear(s->reserved_regs);
1737 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1738 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1739 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1740 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1741 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1742 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1743 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
3314e008 1744 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */
afa05235
AJ
1745
1746 tcg_add_target_add_op_defs(mips_op_defs);
1747}