]> git.proxmox.com Git - mirror_qemu.git/blob - tcg/mips/tcg-target.c
softmmu templates: optionally pass CPUState to memory access functions
[mirror_qemu.git] / tcg / mips / tcg-target.c
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
34 static 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 */
71 static const int tcg_target_reg_alloc_order[] = {
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
97 static const int tcg_target_call_iarg_regs[4] = {
98 TCG_REG_A0,
99 TCG_REG_A1,
100 TCG_REG_A2,
101 TCG_REG_A3
102 };
103
104 static const int tcg_target_call_oarg_regs[2] = {
105 TCG_REG_V0,
106 TCG_REG_V1
107 };
108
109 static uint8_t *tb_ret_addr;
110
111 static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
112 {
113 return target & 0xffff;
114 }
115
116 static 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
122 static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
123 {
124 return (target >> 16) & 0xffff;
125 }
126
127 static 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
133 static 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
145 static 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
151 static 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
160 static 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
166 static 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 */
189 static inline int tcg_target_get_call_iarg_regs_count(int flags)
190 {
191 return 4;
192 }
193
194 /* parse target specific constraints */
195 static 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);
220 #endif
221 break;
222 case 'S': /* qemu_st constraint */
223 ct->ct |= TCG_CT_REG;
224 tcg_regset_set(ct->u.regs, 0xffffffff);
225 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
226 #if defined(CONFIG_SOFTMMU)
227 # if TARGET_LONG_BITS == 64
228 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
229 # endif
230 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
231 #endif
232 break;
233 case 'I':
234 ct->ct |= TCG_CT_CONST_U16;
235 break;
236 case 'J':
237 ct->ct |= TCG_CT_CONST_S16;
238 break;
239 case 'Z':
240 /* We are cheating a bit here, using the fact that the register
241 ZERO is also the register number 0. Hence there is no need
242 to check for const_args in each instruction. */
243 ct->ct |= TCG_CT_CONST_ZERO;
244 break;
245 default:
246 return -1;
247 }
248 ct_str++;
249 *pct_str = ct_str;
250 return 0;
251 }
252
253 /* test if a constant matches the constraint */
254 static inline int tcg_target_const_match(tcg_target_long val,
255 const TCGArgConstraint *arg_ct)
256 {
257 int ct;
258 ct = arg_ct->ct;
259 if (ct & TCG_CT_CONST)
260 return 1;
261 else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
262 return 1;
263 else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
264 return 1;
265 else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
266 return 1;
267 else
268 return 0;
269 }
270
271 /* instruction opcodes */
272 enum {
273 OPC_BEQ = 0x04 << 26,
274 OPC_BNE = 0x05 << 26,
275 OPC_ADDIU = 0x09 << 26,
276 OPC_SLTI = 0x0A << 26,
277 OPC_SLTIU = 0x0B << 26,
278 OPC_ANDI = 0x0C << 26,
279 OPC_ORI = 0x0D << 26,
280 OPC_XORI = 0x0E << 26,
281 OPC_LUI = 0x0F << 26,
282 OPC_LB = 0x20 << 26,
283 OPC_LH = 0x21 << 26,
284 OPC_LW = 0x23 << 26,
285 OPC_LBU = 0x24 << 26,
286 OPC_LHU = 0x25 << 26,
287 OPC_LWU = 0x27 << 26,
288 OPC_SB = 0x28 << 26,
289 OPC_SH = 0x29 << 26,
290 OPC_SW = 0x2B << 26,
291
292 OPC_SPECIAL = 0x00 << 26,
293 OPC_SLL = OPC_SPECIAL | 0x00,
294 OPC_SRL = OPC_SPECIAL | 0x02,
295 OPC_SRA = OPC_SPECIAL | 0x03,
296 OPC_SLLV = OPC_SPECIAL | 0x04,
297 OPC_SRLV = OPC_SPECIAL | 0x06,
298 OPC_SRAV = OPC_SPECIAL | 0x07,
299 OPC_JR = OPC_SPECIAL | 0x08,
300 OPC_JALR = OPC_SPECIAL | 0x09,
301 OPC_MFHI = OPC_SPECIAL | 0x10,
302 OPC_MFLO = OPC_SPECIAL | 0x12,
303 OPC_MULT = OPC_SPECIAL | 0x18,
304 OPC_MULTU = OPC_SPECIAL | 0x19,
305 OPC_DIV = OPC_SPECIAL | 0x1A,
306 OPC_DIVU = OPC_SPECIAL | 0x1B,
307 OPC_ADDU = OPC_SPECIAL | 0x21,
308 OPC_SUBU = OPC_SPECIAL | 0x23,
309 OPC_AND = OPC_SPECIAL | 0x24,
310 OPC_OR = OPC_SPECIAL | 0x25,
311 OPC_XOR = OPC_SPECIAL | 0x26,
312 OPC_NOR = OPC_SPECIAL | 0x27,
313 OPC_SLT = OPC_SPECIAL | 0x2A,
314 OPC_SLTU = OPC_SPECIAL | 0x2B,
315
316 OPC_SPECIAL3 = 0x1f << 26,
317 OPC_SEB = OPC_SPECIAL3 | 0x420,
318 OPC_SEH = OPC_SPECIAL3 | 0x620,
319 };
320
321 /*
322 * Type reg
323 */
324 static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
325 {
326 int32_t inst;
327
328 inst = opc;
329 inst |= (rs & 0x1F) << 21;
330 inst |= (rt & 0x1F) << 16;
331 inst |= (rd & 0x1F) << 11;
332 tcg_out32(s, inst);
333 }
334
335 /*
336 * Type immediate
337 */
338 static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
339 {
340 int32_t inst;
341
342 inst = opc;
343 inst |= (rs & 0x1F) << 21;
344 inst |= (rt & 0x1F) << 16;
345 inst |= (imm & 0xffff);
346 tcg_out32(s, inst);
347 }
348
349 /*
350 * Type branch
351 */
352 static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
353 {
354 /* We pay attention here to not modify the branch target by reading
355 the existing value and using it again. This ensure that caches and
356 memory are kept coherent during retranslation. */
357 uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
358
359 tcg_out_opc_imm(s, opc, rt, rs, offset);
360 }
361
362 /*
363 * Type sa
364 */
365 static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
366 {
367 int32_t inst;
368
369 inst = opc;
370 inst |= (rt & 0x1F) << 16;
371 inst |= (rd & 0x1F) << 11;
372 inst |= (sa & 0x1F) << 6;
373 tcg_out32(s, inst);
374
375 }
376
377 static inline void tcg_out_nop(TCGContext *s)
378 {
379 tcg_out32(s, 0);
380 }
381
382 static inline void tcg_out_mov(TCGContext *s, TCGType type,
383 TCGReg ret, TCGReg arg)
384 {
385 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
386 }
387
388 static inline void tcg_out_movi(TCGContext *s, TCGType type,
389 TCGReg reg, tcg_target_long arg)
390 {
391 if (arg == (int16_t)arg) {
392 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
393 } else if (arg == (uint16_t)arg) {
394 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
395 } else {
396 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
397 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
398 }
399 }
400
401 static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
402 {
403 /* ret and arg can't be register at */
404 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
405 tcg_abort();
406 }
407
408 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
409 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
410
411 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
412 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
413 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
414 }
415
416 static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
417 {
418 /* ret and arg can't be register at */
419 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
420 tcg_abort();
421 }
422
423 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
424 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
425
426 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
427 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
428 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
429 }
430
431 static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
432 {
433 /* ret and arg must be different and can't be register at */
434 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
435 tcg_abort();
436 }
437
438 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
439
440 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
441 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
442
443 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
444 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
445 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
446
447 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
448 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
449 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
450 }
451
452 static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
453 {
454 #ifdef _MIPS_ARCH_MIPS32R2
455 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
456 #else
457 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
458 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
459 #endif
460 }
461
462 static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
463 {
464 #ifdef _MIPS_ARCH_MIPS32R2
465 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
466 #else
467 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
468 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
469 #endif
470 }
471
472 static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
473 int arg1, tcg_target_long arg2)
474 {
475 if (arg2 == (int16_t) arg2) {
476 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
477 } else {
478 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
479 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
480 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
481 }
482 }
483
484 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
485 TCGReg arg1, tcg_target_long arg2)
486 {
487 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
488 }
489
490 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
491 TCGReg arg1, tcg_target_long arg2)
492 {
493 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
494 }
495
496 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
497 {
498 if (val == (int16_t)val) {
499 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
500 } else {
501 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
502 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
503 }
504 }
505
506 static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
507 int arg2, int label_index)
508 {
509 TCGLabel *l = &s->labels[label_index];
510
511 switch (cond) {
512 case TCG_COND_EQ:
513 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
514 break;
515 case TCG_COND_NE:
516 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
517 break;
518 case TCG_COND_LT:
519 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
520 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
521 break;
522 case TCG_COND_LTU:
523 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
524 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
525 break;
526 case TCG_COND_GE:
527 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
528 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
529 break;
530 case TCG_COND_GEU:
531 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
532 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
533 break;
534 case TCG_COND_LE:
535 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
536 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
537 break;
538 case TCG_COND_LEU:
539 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
540 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
541 break;
542 case TCG_COND_GT:
543 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
544 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
545 break;
546 case TCG_COND_GTU:
547 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
548 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
549 break;
550 default:
551 tcg_abort();
552 break;
553 }
554 if (l->has_value) {
555 reloc_pc16(s->code_ptr - 4, l->u.value);
556 } else {
557 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
558 }
559 tcg_out_nop(s);
560 }
561
562 /* XXX: we implement it at the target level to avoid having to
563 handle cross basic blocks temporaries */
564 static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
565 int arg2, int arg3, int arg4, int label_index)
566 {
567 void *label_ptr;
568
569 switch(cond) {
570 case TCG_COND_NE:
571 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
572 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
573 return;
574 case TCG_COND_EQ:
575 break;
576 case TCG_COND_LT:
577 case TCG_COND_LE:
578 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
579 break;
580 case TCG_COND_GT:
581 case TCG_COND_GE:
582 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
583 break;
584 case TCG_COND_LTU:
585 case TCG_COND_LEU:
586 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
587 break;
588 case TCG_COND_GTU:
589 case TCG_COND_GEU:
590 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
591 break;
592 default:
593 tcg_abort();
594 }
595
596 label_ptr = s->code_ptr;
597 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
598 tcg_out_nop(s);
599
600 switch(cond) {
601 case TCG_COND_EQ:
602 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
603 break;
604 case TCG_COND_LT:
605 case TCG_COND_LTU:
606 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
607 break;
608 case TCG_COND_LE:
609 case TCG_COND_LEU:
610 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
611 break;
612 case TCG_COND_GT:
613 case TCG_COND_GTU:
614 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
615 break;
616 case TCG_COND_GE:
617 case TCG_COND_GEU:
618 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
619 break;
620 default:
621 tcg_abort();
622 }
623
624 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
625 }
626
627 static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
628 int arg1, int arg2)
629 {
630 switch (cond) {
631 case TCG_COND_EQ:
632 if (arg1 == 0) {
633 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
634 } else if (arg2 == 0) {
635 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
636 } else {
637 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
638 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
639 }
640 break;
641 case TCG_COND_NE:
642 if (arg1 == 0) {
643 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
644 } else if (arg2 == 0) {
645 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
646 } else {
647 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
648 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
649 }
650 break;
651 case TCG_COND_LT:
652 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
653 break;
654 case TCG_COND_LTU:
655 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
656 break;
657 case TCG_COND_GE:
658 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
659 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
660 break;
661 case TCG_COND_GEU:
662 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
663 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
664 break;
665 case TCG_COND_LE:
666 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
667 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
668 break;
669 case TCG_COND_LEU:
670 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
671 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
672 break;
673 case TCG_COND_GT:
674 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
675 break;
676 case TCG_COND_GTU:
677 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
678 break;
679 default:
680 tcg_abort();
681 break;
682 }
683 }
684
685 /* XXX: we implement it at the target level to avoid having to
686 handle cross basic blocks temporaries */
687 static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
688 int arg1, int arg2, int arg3, int arg4)
689 {
690 switch (cond) {
691 case TCG_COND_EQ:
692 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
693 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
694 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
695 return;
696 case TCG_COND_NE:
697 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
698 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
699 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
700 return;
701 case TCG_COND_LT:
702 case TCG_COND_LE:
703 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
704 break;
705 case TCG_COND_GT:
706 case TCG_COND_GE:
707 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
708 break;
709 case TCG_COND_LTU:
710 case TCG_COND_LEU:
711 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
712 break;
713 case TCG_COND_GTU:
714 case TCG_COND_GEU:
715 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
716 break;
717 default:
718 tcg_abort();
719 break;
720 }
721
722 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
723
724 switch(cond) {
725 case TCG_COND_LT:
726 case TCG_COND_LTU:
727 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
728 break;
729 case TCG_COND_LE:
730 case TCG_COND_LEU:
731 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
732 break;
733 case TCG_COND_GT:
734 case TCG_COND_GTU:
735 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
736 break;
737 case TCG_COND_GE:
738 case TCG_COND_GEU:
739 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
740 break;
741 default:
742 tcg_abort();
743 }
744
745 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
746 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
747 }
748
749 #if defined(CONFIG_SOFTMMU)
750
751 #include "../../softmmu_defs.h"
752
753 #ifdef CONFIG_TCG_PASS_AREG0
754 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
755 int mmu_idx) */
756 static const void * const qemu_ld_helpers[4] = {
757 helper_ldb_mmu,
758 helper_ldw_mmu,
759 helper_ldl_mmu,
760 helper_ldq_mmu,
761 };
762
763 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
764 uintxx_t val, int mmu_idx) */
765 static const void * const qemu_st_helpers[4] = {
766 helper_stb_mmu,
767 helper_stw_mmu,
768 helper_stl_mmu,
769 helper_stq_mmu,
770 };
771 #else
772 /* legacy helper signature: __ld_mmu(target_ulong addr, int
773 mmu_idx) */
774 static void *qemu_ld_helpers[4] = {
775 __ldb_mmu,
776 __ldw_mmu,
777 __ldl_mmu,
778 __ldq_mmu,
779 };
780
781 /* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
782 int mmu_idx) */
783 static void *qemu_st_helpers[4] = {
784 __stb_mmu,
785 __stw_mmu,
786 __stl_mmu,
787 __stq_mmu,
788 };
789 #endif
790 #endif
791
792 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
793 int opc)
794 {
795 int addr_regl, addr_reg1, addr_meml;
796 int data_regl, data_regh, data_reg1, data_reg2;
797 int mem_index, s_bits;
798 #if defined(CONFIG_SOFTMMU)
799 void *label1_ptr, *label2_ptr;
800 int sp_args;
801 #endif
802 #if TARGET_LONG_BITS == 64
803 # if defined(CONFIG_SOFTMMU)
804 uint8_t *label3_ptr;
805 # endif
806 int addr_regh, addr_reg2, addr_memh;
807 #endif
808 data_regl = *args++;
809 if (opc == 3)
810 data_regh = *args++;
811 else
812 data_regh = 0;
813 addr_regl = *args++;
814 #if TARGET_LONG_BITS == 64
815 addr_regh = *args++;
816 #endif
817 mem_index = *args;
818 s_bits = opc & 3;
819
820 if (opc == 3) {
821 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
822 data_reg1 = data_regh;
823 data_reg2 = data_regl;
824 #else
825 data_reg1 = data_regl;
826 data_reg2 = data_regh;
827 #endif
828 } else {
829 data_reg1 = data_regl;
830 data_reg2 = 0;
831 }
832 #if TARGET_LONG_BITS == 64
833 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
834 addr_reg1 = addr_regh;
835 addr_reg2 = addr_regl;
836 addr_memh = 0;
837 addr_meml = 4;
838 # else
839 addr_reg1 = addr_regl;
840 addr_reg2 = addr_regh;
841 addr_memh = 4;
842 addr_meml = 0;
843 # endif
844 #else
845 addr_reg1 = addr_regl;
846 addr_meml = 0;
847 #endif
848
849 #if defined(CONFIG_SOFTMMU)
850 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
851 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
852 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
853 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
854 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
855 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
856 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
857
858 # if TARGET_LONG_BITS == 64
859 label3_ptr = s->code_ptr;
860 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
861 tcg_out_nop(s);
862
863 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
864 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
865
866 label1_ptr = s->code_ptr;
867 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
868 tcg_out_nop(s);
869
870 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
871 # else
872 label1_ptr = s->code_ptr;
873 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
874 tcg_out_nop(s);
875 # endif
876
877 /* slow path */
878 sp_args = TCG_REG_A0;
879 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
880 # if TARGET_LONG_BITS == 64
881 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
882 # endif
883 tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
884 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
885 #ifdef CONFIG_TCG_PASS_AREG0
886 /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
887 tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
888 tcg_target_call_iarg_regs[1]);
889 tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
890 tcg_target_call_iarg_regs[0]);
891 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
892 TCG_AREG0);
893 #endif
894 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
895 tcg_out_nop(s);
896
897 switch(opc) {
898 case 0:
899 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
900 break;
901 case 0 | 4:
902 tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
903 break;
904 case 1:
905 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
906 break;
907 case 1 | 4:
908 tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
909 break;
910 case 2:
911 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
912 break;
913 case 3:
914 tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
915 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
916 break;
917 default:
918 tcg_abort();
919 }
920
921 label2_ptr = s->code_ptr;
922 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
923 tcg_out_nop(s);
924
925 /* label1: fast path */
926 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
927
928 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
929 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
930 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
931 #else
932 if (GUEST_BASE == (int16_t)GUEST_BASE) {
933 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
934 } else {
935 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
936 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
937 }
938 #endif
939
940 switch(opc) {
941 case 0:
942 tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
943 break;
944 case 0 | 4:
945 tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
946 break;
947 case 1:
948 if (TCG_NEED_BSWAP) {
949 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
950 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
951 } else {
952 tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
953 }
954 break;
955 case 1 | 4:
956 if (TCG_NEED_BSWAP) {
957 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
958 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
959 } else {
960 tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
961 }
962 break;
963 case 2:
964 if (TCG_NEED_BSWAP) {
965 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
966 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
967 } else {
968 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
969 }
970 break;
971 case 3:
972 if (TCG_NEED_BSWAP) {
973 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
974 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
975 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
976 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
977 } else {
978 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
979 tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
980 }
981 break;
982 default:
983 tcg_abort();
984 }
985
986 #if defined(CONFIG_SOFTMMU)
987 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
988 #endif
989 }
990
991 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
992 int opc)
993 {
994 int addr_regl, addr_reg1, addr_meml;
995 int data_regl, data_regh, data_reg1, data_reg2;
996 int mem_index, s_bits;
997 #if defined(CONFIG_SOFTMMU)
998 uint8_t *label1_ptr, *label2_ptr;
999 int sp_args;
1000 #endif
1001 #if TARGET_LONG_BITS == 64
1002 # if defined(CONFIG_SOFTMMU)
1003 uint8_t *label3_ptr;
1004 # endif
1005 int addr_regh, addr_reg2, addr_memh;
1006 #endif
1007
1008 data_regl = *args++;
1009 if (opc == 3) {
1010 data_regh = *args++;
1011 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
1012 data_reg1 = data_regh;
1013 data_reg2 = data_regl;
1014 #else
1015 data_reg1 = data_regl;
1016 data_reg2 = data_regh;
1017 #endif
1018 } else {
1019 data_reg1 = data_regl;
1020 data_reg2 = 0;
1021 data_regh = 0;
1022 }
1023 addr_regl = *args++;
1024 #if TARGET_LONG_BITS == 64
1025 addr_regh = *args++;
1026 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
1027 addr_reg1 = addr_regh;
1028 addr_reg2 = addr_regl;
1029 addr_memh = 0;
1030 addr_meml = 4;
1031 # else
1032 addr_reg1 = addr_regl;
1033 addr_reg2 = addr_regh;
1034 addr_memh = 4;
1035 addr_meml = 0;
1036 # endif
1037 #else
1038 addr_reg1 = addr_regl;
1039 addr_meml = 0;
1040 #endif
1041 mem_index = *args;
1042 s_bits = opc;
1043
1044 #if defined(CONFIG_SOFTMMU)
1045 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1046 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1047 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1048 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1049 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
1050 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1051 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1052
1053 # if TARGET_LONG_BITS == 64
1054 label3_ptr = s->code_ptr;
1055 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1056 tcg_out_nop(s);
1057
1058 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1059 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
1060
1061 label1_ptr = s->code_ptr;
1062 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1063 tcg_out_nop(s);
1064
1065 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1066 # else
1067 label1_ptr = s->code_ptr;
1068 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1069 tcg_out_nop(s);
1070 # endif
1071
1072 /* slow path */
1073 sp_args = TCG_REG_A0;
1074 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1075 # if TARGET_LONG_BITS == 64
1076 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1077 # endif
1078 switch(opc) {
1079 case 0:
1080 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1081 break;
1082 case 1:
1083 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1084 break;
1085 case 2:
1086 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1087 break;
1088 case 3:
1089 sp_args = (sp_args + 1) & ~1;
1090 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1091 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
1092 break;
1093 default:
1094 tcg_abort();
1095 }
1096 if (sp_args > TCG_REG_A3) {
1097 /* Push mem_index on the stack */
1098 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1099 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1100 } else {
1101 tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1102 }
1103
1104 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1105 #ifdef CONFIG_TCG_PASS_AREG0
1106 /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
1107 tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
1108 tcg_target_call_iarg_regs[2]);
1109 tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
1110 tcg_target_call_iarg_regs[1]);
1111 tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
1112 tcg_target_call_iarg_regs[0]);
1113 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
1114 TCG_AREG0);
1115 #endif
1116 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1117 tcg_out_nop(s);
1118
1119 label2_ptr = s->code_ptr;
1120 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1121 tcg_out_nop(s);
1122
1123 /* label1: fast path */
1124 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1125
1126 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1127 offsetof(CPUArchState, tlb_table[mem_index][0].addend));
1128 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1129 #else
1130 if (GUEST_BASE == (int16_t)GUEST_BASE) {
1131 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1132 } else {
1133 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1134 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1135 }
1136
1137 #endif
1138
1139 switch(opc) {
1140 case 0:
1141 tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1142 break;
1143 case 1:
1144 if (TCG_NEED_BSWAP) {
1145 tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1146 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1147 } else {
1148 tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1149 }
1150 break;
1151 case 2:
1152 if (TCG_NEED_BSWAP) {
1153 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1154 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1155 } else {
1156 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1157 }
1158 break;
1159 case 3:
1160 if (TCG_NEED_BSWAP) {
1161 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1162 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1163 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1164 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1165 } else {
1166 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1167 tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1168 }
1169 break;
1170 default:
1171 tcg_abort();
1172 }
1173
1174 #if defined(CONFIG_SOFTMMU)
1175 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1176 #endif
1177 }
1178
1179 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1180 const TCGArg *args, const int *const_args)
1181 {
1182 switch(opc) {
1183 case INDEX_op_exit_tb:
1184 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1185 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1186 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1187 tcg_out_nop(s);
1188 break;
1189 case INDEX_op_goto_tb:
1190 if (s->tb_jmp_offset) {
1191 /* direct jump method */
1192 tcg_abort();
1193 } else {
1194 /* indirect jump method */
1195 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1196 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1197 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1198 }
1199 tcg_out_nop(s);
1200 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1201 break;
1202 case INDEX_op_call:
1203 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1204 tcg_out_nop(s);
1205 break;
1206 case INDEX_op_jmp:
1207 tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1208 tcg_out_nop(s);
1209 break;
1210 case INDEX_op_br:
1211 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1212 break;
1213
1214 case INDEX_op_mov_i32:
1215 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1216 break;
1217 case INDEX_op_movi_i32:
1218 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1219 break;
1220
1221 case INDEX_op_ld8u_i32:
1222 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1223 break;
1224 case INDEX_op_ld8s_i32:
1225 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1226 break;
1227 case INDEX_op_ld16u_i32:
1228 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1229 break;
1230 case INDEX_op_ld16s_i32:
1231 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1232 break;
1233 case INDEX_op_ld_i32:
1234 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1235 break;
1236 case INDEX_op_st8_i32:
1237 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1238 break;
1239 case INDEX_op_st16_i32:
1240 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1241 break;
1242 case INDEX_op_st_i32:
1243 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1244 break;
1245
1246 case INDEX_op_add_i32:
1247 if (const_args[2]) {
1248 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1249 } else {
1250 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1251 }
1252 break;
1253 case INDEX_op_add2_i32:
1254 if (const_args[4]) {
1255 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1256 } else {
1257 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1258 }
1259 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1260 if (const_args[5]) {
1261 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1262 } else {
1263 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1264 }
1265 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1266 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1267 break;
1268 case INDEX_op_sub_i32:
1269 if (const_args[2]) {
1270 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1271 } else {
1272 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1273 }
1274 break;
1275 case INDEX_op_sub2_i32:
1276 if (const_args[4]) {
1277 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1278 } else {
1279 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1280 }
1281 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1282 if (const_args[5]) {
1283 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1284 } else {
1285 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1286 }
1287 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1288 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1289 break;
1290 case INDEX_op_mul_i32:
1291 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1292 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1293 break;
1294 case INDEX_op_mulu2_i32:
1295 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1296 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1297 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1298 break;
1299 case INDEX_op_div_i32:
1300 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1301 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1302 break;
1303 case INDEX_op_divu_i32:
1304 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1305 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1306 break;
1307 case INDEX_op_rem_i32:
1308 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1309 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1310 break;
1311 case INDEX_op_remu_i32:
1312 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1313 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1314 break;
1315
1316 case INDEX_op_and_i32:
1317 if (const_args[2]) {
1318 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1319 } else {
1320 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1321 }
1322 break;
1323 case INDEX_op_or_i32:
1324 if (const_args[2]) {
1325 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1326 } else {
1327 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1328 }
1329 break;
1330 case INDEX_op_nor_i32:
1331 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1332 break;
1333 case INDEX_op_not_i32:
1334 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1335 break;
1336 case INDEX_op_xor_i32:
1337 if (const_args[2]) {
1338 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1339 } else {
1340 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1341 }
1342 break;
1343
1344 case INDEX_op_sar_i32:
1345 if (const_args[2]) {
1346 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1347 } else {
1348 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1349 }
1350 break;
1351 case INDEX_op_shl_i32:
1352 if (const_args[2]) {
1353 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1354 } else {
1355 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1356 }
1357 break;
1358 case INDEX_op_shr_i32:
1359 if (const_args[2]) {
1360 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1361 } else {
1362 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1363 }
1364 break;
1365
1366 case INDEX_op_ext8s_i32:
1367 tcg_out_ext8s(s, args[0], args[1]);
1368 break;
1369 case INDEX_op_ext16s_i32:
1370 tcg_out_ext16s(s, args[0], args[1]);
1371 break;
1372
1373 case INDEX_op_brcond_i32:
1374 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1375 break;
1376 case INDEX_op_brcond2_i32:
1377 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1378 break;
1379
1380 case INDEX_op_setcond_i32:
1381 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1382 break;
1383 case INDEX_op_setcond2_i32:
1384 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1385 break;
1386
1387 case INDEX_op_qemu_ld8u:
1388 tcg_out_qemu_ld(s, args, 0);
1389 break;
1390 case INDEX_op_qemu_ld8s:
1391 tcg_out_qemu_ld(s, args, 0 | 4);
1392 break;
1393 case INDEX_op_qemu_ld16u:
1394 tcg_out_qemu_ld(s, args, 1);
1395 break;
1396 case INDEX_op_qemu_ld16s:
1397 tcg_out_qemu_ld(s, args, 1 | 4);
1398 break;
1399 case INDEX_op_qemu_ld32:
1400 tcg_out_qemu_ld(s, args, 2);
1401 break;
1402 case INDEX_op_qemu_ld64:
1403 tcg_out_qemu_ld(s, args, 3);
1404 break;
1405 case INDEX_op_qemu_st8:
1406 tcg_out_qemu_st(s, args, 0);
1407 break;
1408 case INDEX_op_qemu_st16:
1409 tcg_out_qemu_st(s, args, 1);
1410 break;
1411 case INDEX_op_qemu_st32:
1412 tcg_out_qemu_st(s, args, 2);
1413 break;
1414 case INDEX_op_qemu_st64:
1415 tcg_out_qemu_st(s, args, 3);
1416 break;
1417
1418 default:
1419 tcg_abort();
1420 }
1421 }
1422
1423 static const TCGTargetOpDef mips_op_defs[] = {
1424 { INDEX_op_exit_tb, { } },
1425 { INDEX_op_goto_tb, { } },
1426 { INDEX_op_call, { "C" } },
1427 { INDEX_op_jmp, { "r" } },
1428 { INDEX_op_br, { } },
1429
1430 { INDEX_op_mov_i32, { "r", "r" } },
1431 { INDEX_op_movi_i32, { "r" } },
1432 { INDEX_op_ld8u_i32, { "r", "r" } },
1433 { INDEX_op_ld8s_i32, { "r", "r" } },
1434 { INDEX_op_ld16u_i32, { "r", "r" } },
1435 { INDEX_op_ld16s_i32, { "r", "r" } },
1436 { INDEX_op_ld_i32, { "r", "r" } },
1437 { INDEX_op_st8_i32, { "rZ", "r" } },
1438 { INDEX_op_st16_i32, { "rZ", "r" } },
1439 { INDEX_op_st_i32, { "rZ", "r" } },
1440
1441 { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1442 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1443 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1444 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1445 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1446 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1447 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1448 { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1449
1450 { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1451 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1452 { INDEX_op_not_i32, { "r", "rZ" } },
1453 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1454 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1455
1456 { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1457 { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1458 { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1459
1460 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1461 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1462
1463 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1464 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1465 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1466
1467 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1468 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1469 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1470
1471 #if TARGET_LONG_BITS == 32
1472 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1473 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1474 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1475 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1476 { INDEX_op_qemu_ld32, { "L", "lZ" } },
1477 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1478
1479 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1480 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1481 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1482 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1483 #else
1484 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1485 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1486 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1487 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1488 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1489 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1490
1491 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1492 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1493 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1494 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1495 #endif
1496 { -1 },
1497 };
1498
1499 static int tcg_target_callee_save_regs[] = {
1500 TCG_REG_S0, /* used for the global env (TCG_AREG0) */
1501 TCG_REG_S1,
1502 TCG_REG_S2,
1503 TCG_REG_S3,
1504 TCG_REG_S4,
1505 TCG_REG_S5,
1506 TCG_REG_S6,
1507 TCG_REG_S7,
1508 TCG_REG_GP,
1509 TCG_REG_FP,
1510 TCG_REG_RA, /* should be last for ABI compliance */
1511 };
1512
1513 /* Generate global QEMU prologue and epilogue code */
1514 static void tcg_target_qemu_prologue(TCGContext *s)
1515 {
1516 int i, frame_size;
1517
1518 /* reserve some stack space */
1519 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1520 + TCG_STATIC_CALL_ARGS_SIZE;
1521 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1522 ~(TCG_TARGET_STACK_ALIGN - 1);
1523
1524 /* TB prologue */
1525 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1526 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1527 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1528 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1529 }
1530
1531 /* Call generated code */
1532 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1533 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1534 tb_ret_addr = s->code_ptr;
1535
1536 /* TB epilogue */
1537 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1538 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1539 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1540 }
1541
1542 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1543 tcg_out_addi(s, TCG_REG_SP, frame_size);
1544 }
1545
1546 static void tcg_target_init(TCGContext *s)
1547 {
1548 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1549 tcg_regset_set(tcg_target_call_clobber_regs,
1550 (1 << TCG_REG_V0) |
1551 (1 << TCG_REG_V1) |
1552 (1 << TCG_REG_A0) |
1553 (1 << TCG_REG_A1) |
1554 (1 << TCG_REG_A2) |
1555 (1 << TCG_REG_A3) |
1556 (1 << TCG_REG_T1) |
1557 (1 << TCG_REG_T2) |
1558 (1 << TCG_REG_T3) |
1559 (1 << TCG_REG_T4) |
1560 (1 << TCG_REG_T5) |
1561 (1 << TCG_REG_T6) |
1562 (1 << TCG_REG_T7) |
1563 (1 << TCG_REG_T8) |
1564 (1 << TCG_REG_T9));
1565
1566 tcg_regset_clear(s->reserved_regs);
1567 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1568 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1569 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1570 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1571 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1572 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1573 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1574
1575 tcg_add_target_add_op_defs(mips_op_defs);
1576 tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
1577 CPU_TEMP_BUF_NLONGS * sizeof(long));
1578 }