|
|
1.1 root 1: /*
2: * Tiny Code Generator for QEMU
3: *
4: * Copyright (c) 2008-2009 Arnaud Patard <[email protected]>
5: * Copyright (c) 2009 Aurelien Jarno <[email protected]>
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);
1.1.1.4 root 226: #if defined(CONFIG_SOFTMMU)
1.1 root 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,
1.1.1.4 root 276: OPC_SLTI = 0x0A << 26,
277: OPC_SLTIU = 0x0B << 26,
1.1 root 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,
1.1.1.4 root 291:
292: OPC_SPECIAL = 0x00 << 26,
1.1 root 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,
1.1.1.4 root 315:
316: OPC_SPECIAL3 = 0x1f << 26,
317: OPC_SEB = OPC_SPECIAL3 | 0x420,
318: OPC_SEH = OPC_SPECIAL3 | 0x620,
1.1 root 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: /*
1.1.1.3 root 350: * Type branch
351: */
352: static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
353: {
1.1.1.5 root 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);
1.1.1.3 root 358:
359: tcg_out_opc_imm(s, opc, rt, rs, offset);
360: }
361:
362: /*
1.1 root 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:
1.1.1.4 root 382: static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
1.1 root 383: {
384: tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
385: }
386:
387: static inline void tcg_out_movi(TCGContext *s, TCGType type,
388: int reg, int32_t arg)
389: {
390: if (arg == (int16_t)arg) {
391: tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
392: } else if (arg == (uint16_t)arg) {
393: tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
394: } else {
395: tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
396: tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
397: }
398: }
399:
400: static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
401: {
402: /* ret and arg can't be register at */
403: if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
404: tcg_abort();
405: }
406:
407: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
408: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
409:
410: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
411: tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
412: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
413: }
414:
415: static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
416: {
417: /* ret and arg can't be register at */
418: if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
419: tcg_abort();
420: }
421:
422: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
423: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
424:
425: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
426: tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
427: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
428: }
429:
430: static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
431: {
432: /* ret and arg must be different and can't be register at */
433: if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
434: tcg_abort();
435: }
436:
437: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
438:
439: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
440: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
441:
442: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
443: tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
444: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
445:
446: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
447: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
448: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
449: }
450:
1.1.1.4 root 451: static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
452: {
453: #ifdef _MIPS_ARCH_MIPS32R2
454: tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
455: #else
456: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
457: tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
458: #endif
459: }
460:
461: static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
462: {
463: #ifdef _MIPS_ARCH_MIPS32R2
464: tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
465: #else
466: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
467: tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
468: #endif
469: }
470:
1.1 root 471: static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
472: int arg1, tcg_target_long arg2)
473: {
474: if (arg2 == (int16_t) arg2) {
475: tcg_out_opc_imm(s, opc, arg, arg1, arg2);
476: } else {
477: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
478: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
479: tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
480: }
481: }
482:
483: static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
484: int arg1, tcg_target_long arg2)
485: {
486: tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
487: }
488:
489: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
490: int arg1, tcg_target_long arg2)
491: {
492: tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
493: }
494:
495: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
496: {
497: if (val == (int16_t)val) {
498: tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
499: } else {
500: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
501: tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
502: }
503: }
504:
1.1.1.4 root 505: static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
1.1 root 506: int arg2, int label_index)
507: {
508: TCGLabel *l = &s->labels[label_index];
509:
510: switch (cond) {
511: case TCG_COND_EQ:
1.1.1.3 root 512: tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
1.1 root 513: break;
514: case TCG_COND_NE:
1.1.1.3 root 515: tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
1.1 root 516: break;
517: case TCG_COND_LT:
518: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 519: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 520: break;
521: case TCG_COND_LTU:
522: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 523: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 524: break;
525: case TCG_COND_GE:
526: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 527: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 528: break;
529: case TCG_COND_GEU:
530: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 531: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 532: break;
533: case TCG_COND_LE:
534: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 535: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 536: break;
537: case TCG_COND_LEU:
538: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 539: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 540: break;
541: case TCG_COND_GT:
542: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 543: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 544: break;
545: case TCG_COND_GTU:
546: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 547: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 548: break;
549: default:
550: tcg_abort();
551: break;
552: }
553: if (l->has_value) {
554: reloc_pc16(s->code_ptr - 4, l->u.value);
555: } else {
556: tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
557: }
558: tcg_out_nop(s);
559: }
560:
561: /* XXX: we implement it at the target level to avoid having to
562: handle cross basic blocks temporaries */
1.1.1.4 root 563: static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
1.1 root 564: int arg2, int arg3, int arg4, int label_index)
565: {
566: void *label_ptr;
567:
568: switch(cond) {
569: case TCG_COND_NE:
570: tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
571: tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
572: return;
573: case TCG_COND_EQ:
574: break;
575: case TCG_COND_LT:
576: case TCG_COND_LE:
577: tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
578: break;
579: case TCG_COND_GT:
580: case TCG_COND_GE:
581: tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
582: break;
583: case TCG_COND_LTU:
584: case TCG_COND_LEU:
585: tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
586: break;
587: case TCG_COND_GTU:
588: case TCG_COND_GEU:
589: tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
590: break;
591: default:
592: tcg_abort();
593: }
594:
595: label_ptr = s->code_ptr;
1.1.1.3 root 596: tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
1.1 root 597: tcg_out_nop(s);
598:
599: switch(cond) {
600: case TCG_COND_EQ:
601: tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
602: break;
603: case TCG_COND_LT:
604: case TCG_COND_LTU:
605: tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
606: break;
607: case TCG_COND_LE:
608: case TCG_COND_LEU:
609: tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
610: break;
611: case TCG_COND_GT:
612: case TCG_COND_GTU:
613: tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
614: break;
615: case TCG_COND_GE:
616: case TCG_COND_GEU:
617: tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
618: break;
619: default:
620: tcg_abort();
621: }
622:
623: reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
624: }
625:
1.1.1.4 root 626: static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
627: int arg1, int arg2)
628: {
629: switch (cond) {
630: case TCG_COND_EQ:
631: if (arg1 == 0) {
632: tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
633: } else if (arg2 == 0) {
634: tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
635: } else {
636: tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
637: tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
638: }
639: break;
640: case TCG_COND_NE:
641: if (arg1 == 0) {
642: tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
643: } else if (arg2 == 0) {
644: tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
645: } else {
646: tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
647: tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
648: }
649: break;
650: case TCG_COND_LT:
651: tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
652: break;
653: case TCG_COND_LTU:
654: tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
655: break;
656: case TCG_COND_GE:
657: tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
658: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
659: break;
660: case TCG_COND_GEU:
661: tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
662: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
663: break;
664: case TCG_COND_LE:
665: tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
666: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
667: break;
668: case TCG_COND_LEU:
669: tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
670: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
671: break;
672: case TCG_COND_GT:
673: tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
674: break;
675: case TCG_COND_GTU:
676: tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
677: break;
678: default:
679: tcg_abort();
680: break;
681: }
682: }
683:
684: /* XXX: we implement it at the target level to avoid having to
685: handle cross basic blocks temporaries */
686: static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
687: int arg1, int arg2, int arg3, int arg4)
688: {
689: switch (cond) {
690: case TCG_COND_EQ:
691: tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
692: tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
693: tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
694: return;
695: case TCG_COND_NE:
696: tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
697: tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
698: tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
699: return;
700: case TCG_COND_LT:
701: case TCG_COND_LE:
702: tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
703: break;
704: case TCG_COND_GT:
705: case TCG_COND_GE:
706: tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
707: break;
708: case TCG_COND_LTU:
709: case TCG_COND_LEU:
710: tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
711: break;
712: case TCG_COND_GTU:
713: case TCG_COND_GEU:
714: tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
715: break;
716: default:
717: tcg_abort();
718: break;
719: }
720:
721: tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
722:
723: switch(cond) {
724: case TCG_COND_LT:
725: case TCG_COND_LTU:
726: tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
727: break;
728: case TCG_COND_LE:
729: case TCG_COND_LEU:
730: tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
731: break;
732: case TCG_COND_GT:
733: case TCG_COND_GTU:
734: tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
735: break;
736: case TCG_COND_GE:
737: case TCG_COND_GEU:
738: tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
739: break;
740: default:
741: tcg_abort();
742: }
743:
744: tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
745: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
746: }
747:
1.1 root 748: #if defined(CONFIG_SOFTMMU)
749:
750: #include "../../softmmu_defs.h"
751:
752: static void *qemu_ld_helpers[4] = {
753: __ldb_mmu,
754: __ldw_mmu,
755: __ldl_mmu,
756: __ldq_mmu,
757: };
758:
759: static void *qemu_st_helpers[4] = {
760: __stb_mmu,
761: __stw_mmu,
762: __stl_mmu,
763: __stq_mmu,
764: };
765: #endif
766:
767: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
768: int opc)
769: {
770: int addr_regl, addr_reg1, addr_meml;
771: int data_regl, data_regh, data_reg1, data_reg2;
772: int mem_index, s_bits;
773: #if defined(CONFIG_SOFTMMU)
774: void *label1_ptr, *label2_ptr;
775: int sp_args;
776: #endif
777: #if TARGET_LONG_BITS == 64
778: # if defined(CONFIG_SOFTMMU)
779: uint8_t *label3_ptr;
780: # endif
781: int addr_regh, addr_reg2, addr_memh;
782: #endif
783: data_regl = *args++;
784: if (opc == 3)
785: data_regh = *args++;
786: else
787: data_regh = 0;
788: addr_regl = *args++;
789: #if TARGET_LONG_BITS == 64
790: addr_regh = *args++;
791: #endif
792: mem_index = *args;
793: s_bits = opc & 3;
794:
795: if (opc == 3) {
796: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
797: data_reg1 = data_regh;
798: data_reg2 = data_regl;
799: #else
800: data_reg1 = data_regl;
801: data_reg2 = data_regh;
802: #endif
803: } else {
804: data_reg1 = data_regl;
805: data_reg2 = 0;
806: }
807: #if TARGET_LONG_BITS == 64
808: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
809: addr_reg1 = addr_regh;
810: addr_reg2 = addr_regl;
811: addr_memh = 0;
812: addr_meml = 4;
813: # else
814: addr_reg1 = addr_regl;
815: addr_reg2 = addr_regh;
816: addr_memh = 4;
817: addr_meml = 0;
818: # endif
819: #else
820: addr_reg1 = addr_regl;
821: addr_meml = 0;
822: #endif
823:
824: #if defined(CONFIG_SOFTMMU)
825: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
826: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
827: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
828: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
829: offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
830: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
831: tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
832:
833: # if TARGET_LONG_BITS == 64
834: label3_ptr = s->code_ptr;
1.1.1.3 root 835: tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1 root 836: tcg_out_nop(s);
837:
838: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
839: offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
840:
841: label1_ptr = s->code_ptr;
1.1.1.3 root 842: tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1 root 843: tcg_out_nop(s);
844:
845: reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
846: # else
847: label1_ptr = s->code_ptr;
1.1.1.3 root 848: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1 root 849: tcg_out_nop(s);
850: # endif
851:
852: /* slow path */
853: sp_args = TCG_REG_A0;
1.1.1.4 root 854: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1 root 855: # if TARGET_LONG_BITS == 64
1.1.1.4 root 856: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1 root 857: # endif
858: tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
859: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
860: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
861: tcg_out_nop(s);
862:
863: switch(opc) {
864: case 0:
865: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
866: break;
867: case 0 | 4:
1.1.1.4 root 868: tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
1.1 root 869: break;
870: case 1:
871: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
872: break;
873: case 1 | 4:
1.1.1.4 root 874: tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
1.1 root 875: break;
876: case 2:
1.1.1.4 root 877: tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1 root 878: break;
879: case 3:
1.1.1.4 root 880: tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
881: tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1 root 882: break;
883: default:
884: tcg_abort();
885: }
886:
887: label2_ptr = s->code_ptr;
1.1.1.3 root 888: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1 root 889: tcg_out_nop(s);
890:
891: /* label1: fast path */
892: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
893:
1.1.1.2 root 894: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.4 root 895: offsetof(CPUState, tlb_table[mem_index][0].addend));
1.1.1.2 root 896: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
1.1.1.4 root 897: #else
898: if (GUEST_BASE == (int16_t)GUEST_BASE) {
899: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
900: } else {
901: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
902: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
903: }
1.1 root 904: #endif
905:
906: switch(opc) {
907: case 0:
1.1.1.4 root 908: tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
1.1 root 909: break;
910: case 0 | 4:
1.1.1.4 root 911: tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
1.1 root 912: break;
913: case 1:
914: if (TCG_NEED_BSWAP) {
1.1.1.4 root 915: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 916: tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
917: } else {
1.1.1.4 root 918: tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
1.1 root 919: }
920: break;
921: case 1 | 4:
922: if (TCG_NEED_BSWAP) {
1.1.1.4 root 923: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 924: tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
925: } else {
1.1.1.4 root 926: tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
1.1 root 927: }
928: break;
929: case 2:
930: if (TCG_NEED_BSWAP) {
1.1.1.4 root 931: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 932: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
933: } else {
1.1.1.4 root 934: tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1.1 root 935: }
936: break;
937: case 3:
938: if (TCG_NEED_BSWAP) {
1.1.1.4 root 939: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
1.1 root 940: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1.1.1.4 root 941: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 942: tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
943: } else {
1.1.1.4 root 944: tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
945: tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
1.1 root 946: }
947: break;
948: default:
949: tcg_abort();
950: }
951:
952: #if defined(CONFIG_SOFTMMU)
953: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
954: #endif
955: }
956:
957: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
958: int opc)
959: {
960: int addr_regl, addr_reg1, addr_meml;
961: int data_regl, data_regh, data_reg1, data_reg2;
962: int mem_index, s_bits;
963: #if defined(CONFIG_SOFTMMU)
964: uint8_t *label1_ptr, *label2_ptr;
965: int sp_args;
966: #endif
967: #if TARGET_LONG_BITS == 64
968: # if defined(CONFIG_SOFTMMU)
969: uint8_t *label3_ptr;
970: # endif
971: int addr_regh, addr_reg2, addr_memh;
972: #endif
973:
974: data_regl = *args++;
975: if (opc == 3) {
976: data_regh = *args++;
977: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
978: data_reg1 = data_regh;
979: data_reg2 = data_regl;
980: #else
981: data_reg1 = data_regl;
982: data_reg2 = data_regh;
983: #endif
984: } else {
985: data_reg1 = data_regl;
986: data_reg2 = 0;
987: data_regh = 0;
988: }
989: addr_regl = *args++;
990: #if TARGET_LONG_BITS == 64
991: addr_regh = *args++;
992: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
993: addr_reg1 = addr_regh;
994: addr_reg2 = addr_regl;
995: addr_memh = 0;
996: addr_meml = 4;
997: # else
998: addr_reg1 = addr_regl;
999: addr_reg2 = addr_regh;
1000: addr_memh = 4;
1001: addr_meml = 0;
1002: # endif
1003: #else
1004: addr_reg1 = addr_regl;
1005: addr_meml = 0;
1006: #endif
1007: mem_index = *args;
1008: s_bits = opc;
1009:
1010: #if defined(CONFIG_SOFTMMU)
1011: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1012: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1013: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1014: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1015: offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
1016: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1017: tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1018:
1019: # if TARGET_LONG_BITS == 64
1020: label3_ptr = s->code_ptr;
1.1.1.3 root 1021: tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1 root 1022: tcg_out_nop(s);
1023:
1024: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1025: offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
1026:
1027: label1_ptr = s->code_ptr;
1.1.1.3 root 1028: tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1 root 1029: tcg_out_nop(s);
1030:
1031: reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1032: # else
1033: label1_ptr = s->code_ptr;
1.1.1.3 root 1034: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1 root 1035: tcg_out_nop(s);
1036: # endif
1037:
1038: /* slow path */
1039: sp_args = TCG_REG_A0;
1.1.1.4 root 1040: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1 root 1041: # if TARGET_LONG_BITS == 64
1.1.1.4 root 1042: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1 root 1043: # endif
1044: switch(opc) {
1045: case 0:
1046: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1047: break;
1048: case 1:
1049: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1050: break;
1051: case 2:
1.1.1.4 root 1052: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1.1 root 1053: break;
1054: case 3:
1055: sp_args = (sp_args + 1) & ~1;
1.1.1.4 root 1056: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1057: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
1.1 root 1058: break;
1059: default:
1060: tcg_abort();
1061: }
1062: if (sp_args > TCG_REG_A3) {
1063: /* Push mem_index on the stack */
1064: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1065: tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1066: } else {
1067: tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1068: }
1069:
1070: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1071: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1072: tcg_out_nop(s);
1073:
1074: label2_ptr = s->code_ptr;
1.1.1.3 root 1075: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1 root 1076: tcg_out_nop(s);
1077:
1078: /* label1: fast path */
1079: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1080:
1081: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.4 root 1082: offsetof(CPUState, tlb_table[mem_index][0].addend));
1.1 root 1083: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1.1.1.4 root 1084: #else
1085: if (GUEST_BASE == (int16_t)GUEST_BASE) {
1086: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1087: } else {
1088: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1089: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1090: }
1.1 root 1091:
1092: #endif
1093:
1094: switch(opc) {
1095: case 0:
1.1.1.4 root 1096: tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1.1 root 1097: break;
1098: case 1:
1099: if (TCG_NEED_BSWAP) {
1100: tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1101: tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1102: } else {
1.1.1.4 root 1103: tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1.1 root 1104: }
1105: break;
1106: case 2:
1107: if (TCG_NEED_BSWAP) {
1108: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1109: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1110: } else {
1.1.1.4 root 1111: tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1.1 root 1112: }
1113: break;
1114: case 3:
1115: if (TCG_NEED_BSWAP) {
1116: tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1.1.1.4 root 1117: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1118: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1119: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1.1 root 1120: } else {
1.1.1.4 root 1121: tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1122: tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1.1 root 1123: }
1124: break;
1125: default:
1126: tcg_abort();
1127: }
1128:
1129: #if defined(CONFIG_SOFTMMU)
1130: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1131: #endif
1132: }
1133:
1.1.1.4 root 1134: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1 root 1135: const TCGArg *args, const int *const_args)
1136: {
1137: switch(opc) {
1138: case INDEX_op_exit_tb:
1139: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1140: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1141: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1142: tcg_out_nop(s);
1143: break;
1144: case INDEX_op_goto_tb:
1145: if (s->tb_jmp_offset) {
1146: /* direct jump method */
1147: tcg_abort();
1148: } else {
1149: /* indirect jump method */
1150: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1151: tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1152: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1153: }
1154: tcg_out_nop(s);
1155: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1156: break;
1157: case INDEX_op_call:
1158: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1159: tcg_out_nop(s);
1160: break;
1161: case INDEX_op_jmp:
1162: tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1163: tcg_out_nop(s);
1164: break;
1165: case INDEX_op_br:
1166: tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1167: break;
1168:
1169: case INDEX_op_mov_i32:
1.1.1.4 root 1170: tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1.1 root 1171: break;
1172: case INDEX_op_movi_i32:
1173: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1174: break;
1175:
1176: case INDEX_op_ld8u_i32:
1.1.1.4 root 1177: tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1.1 root 1178: break;
1179: case INDEX_op_ld8s_i32:
1180: tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1181: break;
1182: case INDEX_op_ld16u_i32:
1183: tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1184: break;
1185: case INDEX_op_ld16s_i32:
1186: tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1187: break;
1188: case INDEX_op_ld_i32:
1189: tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1190: break;
1191: case INDEX_op_st8_i32:
1192: tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1193: break;
1194: case INDEX_op_st16_i32:
1195: tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1196: break;
1197: case INDEX_op_st_i32:
1198: tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1199: break;
1200:
1201: case INDEX_op_add_i32:
1202: if (const_args[2]) {
1203: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1204: } else {
1205: tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1206: }
1207: break;
1208: case INDEX_op_add2_i32:
1209: if (const_args[4]) {
1210: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1211: } else {
1212: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1213: }
1214: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1215: if (const_args[5]) {
1216: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1217: } else {
1218: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1219: }
1220: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1.1.1.4 root 1221: tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1 root 1222: break;
1223: case INDEX_op_sub_i32:
1224: if (const_args[2]) {
1225: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1226: } else {
1227: tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1228: }
1229: break;
1230: case INDEX_op_sub2_i32:
1231: if (const_args[4]) {
1232: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1233: } else {
1234: tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1235: }
1236: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1237: if (const_args[5]) {
1238: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1239: } else {
1240: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1241: }
1242: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1.1.1.4 root 1243: tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1 root 1244: break;
1245: case INDEX_op_mul_i32:
1246: tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1247: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1248: break;
1249: case INDEX_op_mulu2_i32:
1250: tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1251: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1252: tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1253: break;
1254: case INDEX_op_div_i32:
1255: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1256: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1257: break;
1258: case INDEX_op_divu_i32:
1259: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1260: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1261: break;
1262: case INDEX_op_rem_i32:
1263: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1264: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1265: break;
1266: case INDEX_op_remu_i32:
1267: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1268: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1269: break;
1270:
1271: case INDEX_op_and_i32:
1272: if (const_args[2]) {
1273: tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1274: } else {
1275: tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1276: }
1277: break;
1278: case INDEX_op_or_i32:
1279: if (const_args[2]) {
1280: tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1281: } else {
1282: tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1283: }
1284: break;
1.1.1.4 root 1285: case INDEX_op_nor_i32:
1286: tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1287: break;
1.1 root 1288: case INDEX_op_not_i32:
1.1.1.4 root 1289: tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1.1 root 1290: break;
1291: case INDEX_op_xor_i32:
1292: if (const_args[2]) {
1293: tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1294: } else {
1295: tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1296: }
1297: break;
1298:
1299: case INDEX_op_sar_i32:
1300: if (const_args[2]) {
1301: tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1302: } else {
1303: tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1304: }
1305: break;
1306: case INDEX_op_shl_i32:
1307: if (const_args[2]) {
1308: tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1309: } else {
1310: tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1311: }
1312: break;
1313: case INDEX_op_shr_i32:
1314: if (const_args[2]) {
1315: tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1316: } else {
1317: tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1318: }
1319: break;
1320:
1.1.1.4 root 1321: case INDEX_op_ext8s_i32:
1322: tcg_out_ext8s(s, args[0], args[1]);
1323: break;
1324: case INDEX_op_ext16s_i32:
1325: tcg_out_ext16s(s, args[0], args[1]);
1326: break;
1327:
1.1 root 1328: case INDEX_op_brcond_i32:
1329: tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1330: break;
1331: case INDEX_op_brcond2_i32:
1332: tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1333: break;
1334:
1.1.1.4 root 1335: case INDEX_op_setcond_i32:
1336: tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1337: break;
1338: case INDEX_op_setcond2_i32:
1339: tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1340: break;
1341:
1.1 root 1342: case INDEX_op_qemu_ld8u:
1343: tcg_out_qemu_ld(s, args, 0);
1344: break;
1345: case INDEX_op_qemu_ld8s:
1346: tcg_out_qemu_ld(s, args, 0 | 4);
1347: break;
1348: case INDEX_op_qemu_ld16u:
1349: tcg_out_qemu_ld(s, args, 1);
1350: break;
1351: case INDEX_op_qemu_ld16s:
1352: tcg_out_qemu_ld(s, args, 1 | 4);
1353: break;
1.1.1.4 root 1354: case INDEX_op_qemu_ld32:
1.1 root 1355: tcg_out_qemu_ld(s, args, 2);
1356: break;
1357: case INDEX_op_qemu_ld64:
1358: tcg_out_qemu_ld(s, args, 3);
1359: break;
1360: case INDEX_op_qemu_st8:
1361: tcg_out_qemu_st(s, args, 0);
1362: break;
1363: case INDEX_op_qemu_st16:
1364: tcg_out_qemu_st(s, args, 1);
1365: break;
1366: case INDEX_op_qemu_st32:
1367: tcg_out_qemu_st(s, args, 2);
1368: break;
1369: case INDEX_op_qemu_st64:
1370: tcg_out_qemu_st(s, args, 3);
1371: break;
1372:
1373: default:
1374: tcg_abort();
1375: }
1376: }
1377:
1378: static const TCGTargetOpDef mips_op_defs[] = {
1379: { INDEX_op_exit_tb, { } },
1380: { INDEX_op_goto_tb, { } },
1381: { INDEX_op_call, { "C" } },
1382: { INDEX_op_jmp, { "r" } },
1383: { INDEX_op_br, { } },
1384:
1385: { INDEX_op_mov_i32, { "r", "r" } },
1386: { INDEX_op_movi_i32, { "r" } },
1387: { INDEX_op_ld8u_i32, { "r", "r" } },
1388: { INDEX_op_ld8s_i32, { "r", "r" } },
1389: { INDEX_op_ld16u_i32, { "r", "r" } },
1390: { INDEX_op_ld16s_i32, { "r", "r" } },
1391: { INDEX_op_ld_i32, { "r", "r" } },
1392: { INDEX_op_st8_i32, { "rZ", "r" } },
1393: { INDEX_op_st16_i32, { "rZ", "r" } },
1394: { INDEX_op_st_i32, { "rZ", "r" } },
1395:
1396: { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1397: { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1398: { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1399: { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1400: { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1401: { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1402: { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1403: { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1404:
1405: { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1.1.1.4 root 1406: { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1.1 root 1407: { INDEX_op_not_i32, { "r", "rZ" } },
1408: { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1409: { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1410:
1411: { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1412: { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1413: { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1414:
1.1.1.4 root 1415: { INDEX_op_ext8s_i32, { "r", "rZ" } },
1416: { INDEX_op_ext16s_i32, { "r", "rZ" } },
1417:
1.1 root 1418: { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1.1.1.4 root 1419: { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1420: { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1.1 root 1421:
1422: { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1423: { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1424: { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1425:
1426: #if TARGET_LONG_BITS == 32
1427: { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1428: { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1429: { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1430: { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1.1.1.4 root 1431: { INDEX_op_qemu_ld32, { "L", "lZ" } },
1.1 root 1432: { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1433:
1434: { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1435: { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1436: { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1437: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1438: #else
1439: { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1440: { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1441: { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1442: { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1.1.1.4 root 1443: { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1.1 root 1444: { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1445:
1446: { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1447: { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1448: { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1449: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1450: #endif
1451: { -1 },
1452: };
1453:
1454: static int tcg_target_callee_save_regs[] = {
1.1.1.6 ! root 1455: TCG_REG_S0, /* used for the global env (TCG_AREG0) */
1.1 root 1456: TCG_REG_S1,
1457: TCG_REG_S2,
1458: TCG_REG_S3,
1459: TCG_REG_S4,
1460: TCG_REG_S5,
1461: TCG_REG_S6,
1462: TCG_REG_S7,
1463: TCG_REG_GP,
1.1.1.3 root 1464: TCG_REG_FP,
1.1 root 1465: TCG_REG_RA, /* should be last for ABI compliance */
1466: };
1467:
1468: /* Generate global QEMU prologue and epilogue code */
1.1.1.4 root 1469: static void tcg_target_qemu_prologue(TCGContext *s)
1.1 root 1470: {
1471: int i, frame_size;
1472:
1473: /* reserve some stack space */
1474: frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1475: + TCG_STATIC_CALL_ARGS_SIZE;
1476: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1477: ~(TCG_TARGET_STACK_ALIGN - 1);
1478:
1479: /* TB prologue */
1480: tcg_out_addi(s, TCG_REG_SP, -frame_size);
1481: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1482: tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1483: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1484: }
1485:
1486: /* Call generated code */
1.1.1.6 ! root 1487: tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
! 1488: tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1.1 root 1489: tb_ret_addr = s->code_ptr;
1490:
1491: /* TB epilogue */
1492: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1493: tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1494: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1495: }
1496:
1497: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1498: tcg_out_addi(s, TCG_REG_SP, frame_size);
1499: }
1500:
1.1.1.4 root 1501: static void tcg_target_init(TCGContext *s)
1.1 root 1502: {
1503: tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1504: tcg_regset_set(tcg_target_call_clobber_regs,
1505: (1 << TCG_REG_V0) |
1506: (1 << TCG_REG_V1) |
1507: (1 << TCG_REG_A0) |
1508: (1 << TCG_REG_A1) |
1509: (1 << TCG_REG_A2) |
1510: (1 << TCG_REG_A3) |
1511: (1 << TCG_REG_T1) |
1512: (1 << TCG_REG_T2) |
1513: (1 << TCG_REG_T3) |
1514: (1 << TCG_REG_T4) |
1515: (1 << TCG_REG_T5) |
1516: (1 << TCG_REG_T6) |
1517: (1 << TCG_REG_T7) |
1518: (1 << TCG_REG_T8) |
1519: (1 << TCG_REG_T9));
1520:
1521: tcg_regset_clear(s->reserved_regs);
1522: tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1523: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1524: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1525: tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1526: tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1527: tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1528: tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1529:
1530: tcg_add_target_add_op_defs(mips_op_defs);
1.1.1.6 ! root 1531: tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
! 1532: CPU_TEMP_BUF_NLONGS * sizeof(long));
1.1 root 1533: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.