|
|
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: #if defined(CONFIG_SOFTMMU)
226: tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
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_SPECIAL = 0x00 << 26,
274: OPC_BEQ = 0x04 << 26,
275: OPC_BNE = 0x05 << 26,
276: OPC_ADDIU = 0x09 << 26,
277: OPC_ANDI = 0x0C << 26,
278: OPC_ORI = 0x0D << 26,
279: OPC_XORI = 0x0E << 26,
280: OPC_LUI = 0x0F << 26,
281: OPC_LB = 0x20 << 26,
282: OPC_LH = 0x21 << 26,
283: OPC_LW = 0x23 << 26,
284: OPC_LBU = 0x24 << 26,
285: OPC_LHU = 0x25 << 26,
286: OPC_LWU = 0x27 << 26,
287: OPC_SB = 0x28 << 26,
288: OPC_SH = 0x29 << 26,
289: OPC_SW = 0x2B << 26,
290: OPC_SLL = OPC_SPECIAL | 0x00,
291: OPC_SRL = OPC_SPECIAL | 0x02,
292: OPC_SRA = OPC_SPECIAL | 0x03,
293: OPC_SLLV = OPC_SPECIAL | 0x04,
294: OPC_SRLV = OPC_SPECIAL | 0x06,
295: OPC_SRAV = OPC_SPECIAL | 0x07,
296: OPC_JR = OPC_SPECIAL | 0x08,
297: OPC_JALR = OPC_SPECIAL | 0x09,
298: OPC_MFHI = OPC_SPECIAL | 0x10,
299: OPC_MFLO = OPC_SPECIAL | 0x12,
300: OPC_MULT = OPC_SPECIAL | 0x18,
301: OPC_MULTU = OPC_SPECIAL | 0x19,
302: OPC_DIV = OPC_SPECIAL | 0x1A,
303: OPC_DIVU = OPC_SPECIAL | 0x1B,
304: OPC_ADDU = OPC_SPECIAL | 0x21,
305: OPC_SUBU = OPC_SPECIAL | 0x23,
306: OPC_AND = OPC_SPECIAL | 0x24,
307: OPC_OR = OPC_SPECIAL | 0x25,
308: OPC_XOR = OPC_SPECIAL | 0x26,
309: OPC_NOR = OPC_SPECIAL | 0x27,
310: OPC_SLT = OPC_SPECIAL | 0x2A,
311: OPC_SLTU = OPC_SPECIAL | 0x2B,
312: };
313:
314: /*
315: * Type reg
316: */
317: static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
318: {
319: int32_t inst;
320:
321: inst = opc;
322: inst |= (rs & 0x1F) << 21;
323: inst |= (rt & 0x1F) << 16;
324: inst |= (rd & 0x1F) << 11;
325: tcg_out32(s, inst);
326: }
327:
328: /*
329: * Type immediate
330: */
331: static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
332: {
333: int32_t inst;
334:
335: inst = opc;
336: inst |= (rs & 0x1F) << 21;
337: inst |= (rt & 0x1F) << 16;
338: inst |= (imm & 0xffff);
339: tcg_out32(s, inst);
340: }
341:
342: /*
343: * Type sa
344: */
345: static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
346: {
347: int32_t inst;
348:
349: inst = opc;
350: inst |= (rt & 0x1F) << 16;
351: inst |= (rd & 0x1F) << 11;
352: inst |= (sa & 0x1F) << 6;
353: tcg_out32(s, inst);
354:
355: }
356:
357: static inline void tcg_out_nop(TCGContext *s)
358: {
359: tcg_out32(s, 0);
360: }
361:
362: static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
363: {
364: tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
365: }
366:
367: static inline void tcg_out_movi(TCGContext *s, TCGType type,
368: int reg, int32_t arg)
369: {
370: if (arg == (int16_t)arg) {
371: tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
372: } else if (arg == (uint16_t)arg) {
373: tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
374: } else {
375: tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
376: tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
377: }
378: }
379:
380: static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
381: {
382: /* ret and arg can't be register at */
383: if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
384: tcg_abort();
385: }
386:
387: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
388: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
389:
390: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
391: tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
392: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
393: }
394:
395: static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
396: {
397: /* ret and arg can't be register at */
398: if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
399: tcg_abort();
400: }
401:
402: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
403: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
404:
405: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
406: tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
407: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
408: }
409:
410: static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
411: {
412: /* ret and arg must be different and can't be register at */
413: if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
414: tcg_abort();
415: }
416:
417: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
418:
419: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
420: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
421:
422: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
423: tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
424: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
425:
426: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
427: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
428: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
429: }
430:
431: static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
432: int arg1, tcg_target_long arg2)
433: {
434: if (arg2 == (int16_t) arg2) {
435: tcg_out_opc_imm(s, opc, arg, arg1, arg2);
436: } else {
437: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
438: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
439: tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
440: }
441: }
442:
443: static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
444: int arg1, tcg_target_long arg2)
445: {
446: tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
447: }
448:
449: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
450: int arg1, tcg_target_long arg2)
451: {
452: tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
453: }
454:
455: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
456: {
457: if (val == (int16_t)val) {
458: tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
459: } else {
460: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
461: tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
462: }
463: }
464:
465: static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
466: int arg2, int label_index)
467: {
468: TCGLabel *l = &s->labels[label_index];
469:
470: switch (cond) {
471: case TCG_COND_EQ:
472: tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
473: break;
474: case TCG_COND_NE:
475: tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
476: break;
477: case TCG_COND_LT:
478: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
479: tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
480: break;
481: case TCG_COND_LTU:
482: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
483: tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
484: break;
485: case TCG_COND_GE:
486: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
487: tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
488: break;
489: case TCG_COND_GEU:
490: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
491: tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
492: break;
493: case TCG_COND_LE:
494: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
495: tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
496: break;
497: case TCG_COND_LEU:
498: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
499: tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
500: break;
501: case TCG_COND_GT:
502: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
503: tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
504: break;
505: case TCG_COND_GTU:
506: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
507: tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
508: break;
509: default:
510: tcg_abort();
511: break;
512: }
513: if (l->has_value) {
514: reloc_pc16(s->code_ptr - 4, l->u.value);
515: } else {
516: tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
517: }
518: tcg_out_nop(s);
519: }
520:
521: /* XXX: we implement it at the target level to avoid having to
522: handle cross basic blocks temporaries */
523: static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
524: int arg2, int arg3, int arg4, int label_index)
525: {
526: void *label_ptr;
527:
528: switch(cond) {
529: case TCG_COND_NE:
530: tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
531: tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
532: return;
533: case TCG_COND_EQ:
534: break;
535: case TCG_COND_LT:
536: case TCG_COND_LE:
537: tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
538: break;
539: case TCG_COND_GT:
540: case TCG_COND_GE:
541: tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
542: break;
543: case TCG_COND_LTU:
544: case TCG_COND_LEU:
545: tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
546: break;
547: case TCG_COND_GTU:
548: case TCG_COND_GEU:
549: tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
550: break;
551: default:
552: tcg_abort();
553: }
554:
555: label_ptr = s->code_ptr;
556: tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
557: tcg_out_nop(s);
558:
559: switch(cond) {
560: case TCG_COND_EQ:
561: tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
562: break;
563: case TCG_COND_LT:
564: case TCG_COND_LTU:
565: tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
566: break;
567: case TCG_COND_LE:
568: case TCG_COND_LEU:
569: tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
570: break;
571: case TCG_COND_GT:
572: case TCG_COND_GTU:
573: tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
574: break;
575: case TCG_COND_GE:
576: case TCG_COND_GEU:
577: tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
578: break;
579: default:
580: tcg_abort();
581: }
582:
583: reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
584: }
585:
586: #if defined(CONFIG_SOFTMMU)
587:
588: #include "../../softmmu_defs.h"
589:
590: static void *qemu_ld_helpers[4] = {
591: __ldb_mmu,
592: __ldw_mmu,
593: __ldl_mmu,
594: __ldq_mmu,
595: };
596:
597: static void *qemu_st_helpers[4] = {
598: __stb_mmu,
599: __stw_mmu,
600: __stl_mmu,
601: __stq_mmu,
602: };
603: #endif
604:
605: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
606: int opc)
607: {
608: int addr_regl, addr_reg1, addr_meml;
609: int data_regl, data_regh, data_reg1, data_reg2;
610: int mem_index, s_bits;
611: #if defined(CONFIG_SOFTMMU)
612: void *label1_ptr, *label2_ptr;
613: int sp_args;
614: #endif
615: #if TARGET_LONG_BITS == 64
616: # if defined(CONFIG_SOFTMMU)
617: uint8_t *label3_ptr;
618: # endif
619: int addr_regh, addr_reg2, addr_memh;
620: #endif
621: data_regl = *args++;
622: if (opc == 3)
623: data_regh = *args++;
624: else
625: data_regh = 0;
626: addr_regl = *args++;
627: #if TARGET_LONG_BITS == 64
628: addr_regh = *args++;
629: #endif
630: mem_index = *args;
631: s_bits = opc & 3;
632:
633: if (opc == 3) {
634: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
635: data_reg1 = data_regh;
636: data_reg2 = data_regl;
637: #else
638: data_reg1 = data_regl;
639: data_reg2 = data_regh;
640: #endif
641: } else {
642: data_reg1 = data_regl;
643: data_reg2 = 0;
644: }
645: #if TARGET_LONG_BITS == 64
646: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
647: addr_reg1 = addr_regh;
648: addr_reg2 = addr_regl;
649: addr_memh = 0;
650: addr_meml = 4;
651: # else
652: addr_reg1 = addr_regl;
653: addr_reg2 = addr_regh;
654: addr_memh = 4;
655: addr_meml = 0;
656: # endif
657: #else
658: addr_reg1 = addr_regl;
659: addr_meml = 0;
660: #endif
661:
662: #if defined(CONFIG_SOFTMMU)
663: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
664: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
665: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
666: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
667: offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
668: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
669: tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
670:
671: # if TARGET_LONG_BITS == 64
672: label3_ptr = s->code_ptr;
673: tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
674: tcg_out_nop(s);
675:
676: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
677: offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
678:
679: label1_ptr = s->code_ptr;
680: tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
681: tcg_out_nop(s);
682:
683: reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
684: # else
685: label1_ptr = s->code_ptr;
686: tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
687: tcg_out_nop(s);
688: # endif
689:
690: /* slow path */
691: sp_args = TCG_REG_A0;
692: tcg_out_mov(s, sp_args++, addr_reg1);
693: # if TARGET_LONG_BITS == 64
694: tcg_out_mov(s, sp_args++, addr_reg2);
695: # endif
696: tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
697: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
698: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
699: tcg_out_nop(s);
700:
701: switch(opc) {
702: case 0:
703: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
704: break;
705: case 0 | 4:
706: tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
707: tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
708: break;
709: case 1:
710: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
711: break;
712: case 1 | 4:
713: tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
714: tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
715: break;
716: case 2:
717: tcg_out_mov(s, data_reg1, TCG_REG_V0);
718: break;
719: case 3:
720: tcg_out_mov(s, data_reg2, TCG_REG_V1);
721: tcg_out_mov(s, data_reg1, TCG_REG_V0);
722: break;
723: default:
724: tcg_abort();
725: }
726:
727: label2_ptr = s->code_ptr;
728: tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
729: tcg_out_nop(s);
730:
731: /* label1: fast path */
732: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
733:
1.1.1.2 ! root 734: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1 root 735: offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
1.1.1.2 ! root 736: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
1.1 root 737:
738: addr_reg1 = TCG_REG_V0;
739: #endif
740:
741: switch(opc) {
742: case 0:
743: tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
744: break;
745: case 0 | 4:
746: tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
747: break;
748: case 1:
749: if (TCG_NEED_BSWAP) {
750: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
751: tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
752: } else {
753: tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
754: }
755: break;
756: case 1 | 4:
757: if (TCG_NEED_BSWAP) {
758: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
759: tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
760: } else {
761: tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
762: }
763: break;
764: case 2:
765: if (TCG_NEED_BSWAP) {
766: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
767: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
768: } else {
769: tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
770: }
771: break;
772: case 3:
773: #if !defined(CONFIG_SOFTMMU)
774: tcg_out_mov(s, TCG_REG_V0, addr_reg1);
775: addr_reg1 = TCG_REG_V0;
776: #endif
777: if (TCG_NEED_BSWAP) {
778: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
779: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
780: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
781: tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
782: } else {
783: tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
784: tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
785: }
786: break;
787: default:
788: tcg_abort();
789: }
790:
791: #if defined(CONFIG_SOFTMMU)
792: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
793: #endif
794: }
795:
796: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
797: int opc)
798: {
799: int addr_regl, addr_reg1, addr_meml;
800: int data_regl, data_regh, data_reg1, data_reg2;
801: int mem_index, s_bits;
802: #if defined(CONFIG_SOFTMMU)
803: uint8_t *label1_ptr, *label2_ptr;
804: int sp_args;
805: #endif
806: #if TARGET_LONG_BITS == 64
807: # if defined(CONFIG_SOFTMMU)
808: uint8_t *label3_ptr;
809: # endif
810: int addr_regh, addr_reg2, addr_memh;
811: #endif
812:
813: data_regl = *args++;
814: if (opc == 3) {
815: data_regh = *args++;
816: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
817: data_reg1 = data_regh;
818: data_reg2 = data_regl;
819: #else
820: data_reg1 = data_regl;
821: data_reg2 = data_regh;
822: #endif
823: } else {
824: data_reg1 = data_regl;
825: data_reg2 = 0;
826: data_regh = 0;
827: }
828: addr_regl = *args++;
829: #if TARGET_LONG_BITS == 64
830: addr_regh = *args++;
831: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
832: addr_reg1 = addr_regh;
833: addr_reg2 = addr_regl;
834: addr_memh = 0;
835: addr_meml = 4;
836: # else
837: addr_reg1 = addr_regl;
838: addr_reg2 = addr_regh;
839: addr_memh = 4;
840: addr_meml = 0;
841: # endif
842: #else
843: addr_reg1 = addr_regl;
844: addr_meml = 0;
845: #endif
846: mem_index = *args;
847: s_bits = opc;
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(CPUState, tlb_table[mem_index][0].addr_write) + 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_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
861: tcg_out_nop(s);
862:
863: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
864: offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
865:
866: label1_ptr = s->code_ptr;
867: tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
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_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
874: tcg_out_nop(s);
875: # endif
876:
877: /* slow path */
878: sp_args = TCG_REG_A0;
879: tcg_out_mov(s, sp_args++, addr_reg1);
880: # if TARGET_LONG_BITS == 64
881: tcg_out_mov(s, sp_args++, addr_reg2);
882: # endif
883: switch(opc) {
884: case 0:
885: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
886: break;
887: case 1:
888: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
889: break;
890: case 2:
891: tcg_out_mov(s, sp_args++, data_reg1);
892: break;
893: case 3:
894: sp_args = (sp_args + 1) & ~1;
895: tcg_out_mov(s, sp_args++, data_reg1);
896: tcg_out_mov(s, sp_args++, data_reg2);
897: break;
898: default:
899: tcg_abort();
900: }
901: if (sp_args > TCG_REG_A3) {
902: /* Push mem_index on the stack */
903: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
904: tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
905: } else {
906: tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
907: }
908:
909: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
910: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
911: tcg_out_nop(s);
912:
913: label2_ptr = s->code_ptr;
914: tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
915: tcg_out_nop(s);
916:
917: /* label1: fast path */
918: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
919:
920: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
921: offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
922: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
923:
924: addr_reg1 = TCG_REG_A0;
925: #endif
926:
927: switch(opc) {
928: case 0:
929: tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
930: break;
931: case 1:
932: if (TCG_NEED_BSWAP) {
933: tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
934: tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
935: } else {
936: tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
937: }
938: break;
939: case 2:
940: if (TCG_NEED_BSWAP) {
941: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
942: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
943: } else {
944: tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
945: }
946: break;
947: case 3:
948: if (TCG_NEED_BSWAP) {
949: tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
950: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
951: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
952: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
953: } else {
954: tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
955: tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
956: }
957: break;
958: default:
959: tcg_abort();
960: }
961:
962: #if defined(CONFIG_SOFTMMU)
963: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
964: #endif
965: }
966:
967: static inline void tcg_out_op(TCGContext *s, int opc,
968: const TCGArg *args, const int *const_args)
969: {
970: switch(opc) {
971: case INDEX_op_exit_tb:
972: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
973: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
974: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
975: tcg_out_nop(s);
976: break;
977: case INDEX_op_goto_tb:
978: if (s->tb_jmp_offset) {
979: /* direct jump method */
980: tcg_abort();
981: } else {
982: /* indirect jump method */
983: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
984: tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
985: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
986: }
987: tcg_out_nop(s);
988: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
989: break;
990: case INDEX_op_call:
991: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
992: tcg_out_nop(s);
993: break;
994: case INDEX_op_jmp:
995: tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
996: tcg_out_nop(s);
997: break;
998: case INDEX_op_br:
999: tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1000: break;
1001:
1002: case INDEX_op_mov_i32:
1003: tcg_out_mov(s, args[0], args[1]);
1004: break;
1005: case INDEX_op_movi_i32:
1006: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1007: break;
1008:
1009: case INDEX_op_ld8u_i32:
1010: tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1011: break;
1012: case INDEX_op_ld8s_i32:
1013: tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1014: break;
1015: case INDEX_op_ld16u_i32:
1016: tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1017: break;
1018: case INDEX_op_ld16s_i32:
1019: tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1020: break;
1021: case INDEX_op_ld_i32:
1022: tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1023: break;
1024: case INDEX_op_st8_i32:
1025: tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1026: break;
1027: case INDEX_op_st16_i32:
1028: tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1029: break;
1030: case INDEX_op_st_i32:
1031: tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1032: break;
1033:
1034: case INDEX_op_add_i32:
1035: if (const_args[2]) {
1036: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1037: } else {
1038: tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1039: }
1040: break;
1041: case INDEX_op_add2_i32:
1042: if (const_args[4]) {
1043: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1044: } else {
1045: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1046: }
1047: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1048: if (const_args[5]) {
1049: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1050: } else {
1051: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1052: }
1053: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1054: tcg_out_mov(s, args[0], TCG_REG_AT);
1055: break;
1056: case INDEX_op_sub_i32:
1057: if (const_args[2]) {
1058: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1059: } else {
1060: tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1061: }
1062: break;
1063: case INDEX_op_sub2_i32:
1064: if (const_args[4]) {
1065: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1066: } else {
1067: tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1068: }
1069: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1070: if (const_args[5]) {
1071: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1072: } else {
1073: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1074: }
1075: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1076: tcg_out_mov(s, args[0], TCG_REG_AT);
1077: break;
1078: case INDEX_op_mul_i32:
1079: tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1080: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1081: break;
1082: case INDEX_op_mulu2_i32:
1083: tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1084: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1085: tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1086: break;
1087: case INDEX_op_div_i32:
1088: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1089: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1090: break;
1091: case INDEX_op_divu_i32:
1092: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1093: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1094: break;
1095: case INDEX_op_rem_i32:
1096: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1097: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1098: break;
1099: case INDEX_op_remu_i32:
1100: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1101: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1102: break;
1103:
1104: case INDEX_op_and_i32:
1105: if (const_args[2]) {
1106: tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1107: } else {
1108: tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1109: }
1110: break;
1111: case INDEX_op_or_i32:
1112: if (const_args[2]) {
1113: tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1114: } else {
1115: tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1116: }
1117: break;
1118: case INDEX_op_not_i32:
1119: tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[1]);
1120: break;
1121: case INDEX_op_xor_i32:
1122: if (const_args[2]) {
1123: tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1124: } else {
1125: tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1126: }
1127: break;
1128:
1129: case INDEX_op_sar_i32:
1130: if (const_args[2]) {
1131: tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1132: } else {
1133: tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1134: }
1135: break;
1136: case INDEX_op_shl_i32:
1137: if (const_args[2]) {
1138: tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1139: } else {
1140: tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1141: }
1142: break;
1143: case INDEX_op_shr_i32:
1144: if (const_args[2]) {
1145: tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1146: } else {
1147: tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1148: }
1149: break;
1150:
1151: case INDEX_op_brcond_i32:
1152: tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1153: break;
1154: case INDEX_op_brcond2_i32:
1155: tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1156: break;
1157:
1158: case INDEX_op_qemu_ld8u:
1159: tcg_out_qemu_ld(s, args, 0);
1160: break;
1161: case INDEX_op_qemu_ld8s:
1162: tcg_out_qemu_ld(s, args, 0 | 4);
1163: break;
1164: case INDEX_op_qemu_ld16u:
1165: tcg_out_qemu_ld(s, args, 1);
1166: break;
1167: case INDEX_op_qemu_ld16s:
1168: tcg_out_qemu_ld(s, args, 1 | 4);
1169: break;
1170: case INDEX_op_qemu_ld32u:
1171: tcg_out_qemu_ld(s, args, 2);
1172: break;
1173: case INDEX_op_qemu_ld64:
1174: tcg_out_qemu_ld(s, args, 3);
1175: break;
1176: case INDEX_op_qemu_st8:
1177: tcg_out_qemu_st(s, args, 0);
1178: break;
1179: case INDEX_op_qemu_st16:
1180: tcg_out_qemu_st(s, args, 1);
1181: break;
1182: case INDEX_op_qemu_st32:
1183: tcg_out_qemu_st(s, args, 2);
1184: break;
1185: case INDEX_op_qemu_st64:
1186: tcg_out_qemu_st(s, args, 3);
1187: break;
1188:
1189: default:
1190: tcg_abort();
1191: }
1192: }
1193:
1194: static const TCGTargetOpDef mips_op_defs[] = {
1195: { INDEX_op_exit_tb, { } },
1196: { INDEX_op_goto_tb, { } },
1197: { INDEX_op_call, { "C" } },
1198: { INDEX_op_jmp, { "r" } },
1199: { INDEX_op_br, { } },
1200:
1201: { INDEX_op_mov_i32, { "r", "r" } },
1202: { INDEX_op_movi_i32, { "r" } },
1203: { INDEX_op_ld8u_i32, { "r", "r" } },
1204: { INDEX_op_ld8s_i32, { "r", "r" } },
1205: { INDEX_op_ld16u_i32, { "r", "r" } },
1206: { INDEX_op_ld16s_i32, { "r", "r" } },
1207: { INDEX_op_ld_i32, { "r", "r" } },
1208: { INDEX_op_st8_i32, { "rZ", "r" } },
1209: { INDEX_op_st16_i32, { "rZ", "r" } },
1210: { INDEX_op_st_i32, { "rZ", "r" } },
1211:
1212: { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1213: { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1214: { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1215: { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1216: { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1217: { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1218: { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1219: { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1220:
1221: { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1222: { INDEX_op_not_i32, { "r", "rZ" } },
1223: { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1224: { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1225:
1226: { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1227: { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1228: { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1229:
1230: { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1231:
1232: { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1233: { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1234: { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1235:
1236: #if TARGET_LONG_BITS == 32
1237: { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1238: { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1239: { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1240: { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1241: { INDEX_op_qemu_ld32u, { "L", "lZ" } },
1242: { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1243:
1244: { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1245: { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1246: { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1247: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1248: #else
1249: { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1250: { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1251: { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1252: { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1253: { INDEX_op_qemu_ld32u, { "L", "lZ", "lZ" } },
1254: { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1255:
1256: { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1257: { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1258: { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1259: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1260: #endif
1261: { -1 },
1262: };
1263:
1264: static int tcg_target_callee_save_regs[] = {
1265: TCG_REG_S0,
1266: TCG_REG_S1,
1267: TCG_REG_S2,
1268: TCG_REG_S3,
1269: TCG_REG_S4,
1270: TCG_REG_S5,
1271: TCG_REG_S6,
1272: TCG_REG_S7,
1273: TCG_REG_GP,
1274: /* TCG_REG_FP, */ /* currently used for the global env, so np
1275: need to save */
1276: TCG_REG_RA, /* should be last for ABI compliance */
1277: };
1278:
1279: /* Generate global QEMU prologue and epilogue code */
1280: void tcg_target_qemu_prologue(TCGContext *s)
1281: {
1282: int i, frame_size;
1283:
1284: /* reserve some stack space */
1285: frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1286: + TCG_STATIC_CALL_ARGS_SIZE;
1287: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1288: ~(TCG_TARGET_STACK_ALIGN - 1);
1289:
1290: /* TB prologue */
1291: tcg_out_addi(s, TCG_REG_SP, -frame_size);
1292: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1293: tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1294: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1295: }
1296:
1297: /* Call generated code */
1298: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1299: tcg_out_nop(s);
1300: tb_ret_addr = s->code_ptr;
1301:
1302: /* TB epilogue */
1303: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1304: tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1305: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1306: }
1307:
1308: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1309: tcg_out_addi(s, TCG_REG_SP, frame_size);
1310: }
1311:
1312: void tcg_target_init(TCGContext *s)
1313: {
1314: tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1315: tcg_regset_set(tcg_target_call_clobber_regs,
1316: (1 << TCG_REG_V0) |
1317: (1 << TCG_REG_V1) |
1318: (1 << TCG_REG_A0) |
1319: (1 << TCG_REG_A1) |
1320: (1 << TCG_REG_A2) |
1321: (1 << TCG_REG_A3) |
1322: (1 << TCG_REG_T1) |
1323: (1 << TCG_REG_T2) |
1324: (1 << TCG_REG_T3) |
1325: (1 << TCG_REG_T4) |
1326: (1 << TCG_REG_T5) |
1327: (1 << TCG_REG_T6) |
1328: (1 << TCG_REG_T7) |
1329: (1 << TCG_REG_T8) |
1330: (1 << TCG_REG_T9));
1331:
1332: tcg_regset_clear(s->reserved_regs);
1333: tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1334: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1335: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1336: tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1337: tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1338: tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1339: tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1340:
1341: tcg_add_target_add_op_defs(mips_op_defs);
1342: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.