|
|
1.1 root 1: /*
2: * Alpha emulation cpu translation for qemu.
3: *
4: * Copyright (c) 2007 Jocelyn Mayer
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20:
21: #include <stdint.h>
22: #include <stdlib.h>
23: #include <stdio.h>
24:
25: #include "cpu.h"
26: #include "exec-all.h"
27: #include "disas.h"
28:
29: #define DO_SINGLE_STEP
30: #define GENERATE_NOP
31: #define ALPHA_DEBUG_DISAS
32: #define DO_TB_FLUSH
33:
34: typedef struct DisasContext DisasContext;
35: struct DisasContext {
36: uint64_t pc;
37: int mem_idx;
38: #if !defined (CONFIG_USER_ONLY)
39: int pal_mode;
40: #endif
41: uint32_t amask;
42: };
43:
44: #ifdef USE_DIRECT_JUMP
45: #define TBPARAM(x)
46: #else
47: #define TBPARAM(x) (long)(x)
48: #endif
49:
50: enum {
51: #define DEF(s, n, copy_size) INDEX_op_ ## s,
52: #include "opc.h"
53: #undef DEF
54: NB_OPS,
55: };
56:
57: static uint16_t *gen_opc_ptr;
58: static uint32_t *gen_opparam_ptr;
59:
60: #include "gen-op.h"
61:
62: static always_inline void gen_op_nop (void)
63: {
64: #if defined(GENERATE_NOP)
65: gen_op_no_op();
66: #endif
67: }
68:
69: #define GEN32(func, NAME) \
70: static GenOpFunc *NAME ## _table [32] = { \
71: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
72: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
73: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
74: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
75: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
76: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
77: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
78: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
79: }; \
80: static always_inline void func (int n) \
81: { \
82: NAME ## _table[n](); \
83: }
84:
85: /* IR moves */
86: /* Special hacks for ir31 */
87: #define gen_op_load_T0_ir31 gen_op_reset_T0
88: #define gen_op_load_T1_ir31 gen_op_reset_T1
89: #define gen_op_load_T2_ir31 gen_op_reset_T2
90: #define gen_op_store_T0_ir31 gen_op_nop
91: #define gen_op_store_T1_ir31 gen_op_nop
92: #define gen_op_store_T2_ir31 gen_op_nop
93: #define gen_op_cmov_ir31 gen_op_nop
94: GEN32(gen_op_load_T0_ir, gen_op_load_T0_ir);
95: GEN32(gen_op_load_T1_ir, gen_op_load_T1_ir);
96: GEN32(gen_op_load_T2_ir, gen_op_load_T2_ir);
97: GEN32(gen_op_store_T0_ir, gen_op_store_T0_ir);
98: GEN32(gen_op_store_T1_ir, gen_op_store_T1_ir);
99: GEN32(gen_op_store_T2_ir, gen_op_store_T2_ir);
100: GEN32(gen_op_cmov_ir, gen_op_cmov_ir);
101:
102: static always_inline void gen_load_ir (DisasContext *ctx, int irn, int Tn)
103: {
104: switch (Tn) {
105: case 0:
106: gen_op_load_T0_ir(irn);
107: break;
108: case 1:
109: gen_op_load_T1_ir(irn);
110: break;
111: case 2:
112: gen_op_load_T2_ir(irn);
113: break;
114: }
115: }
116:
117: static always_inline void gen_store_ir (DisasContext *ctx, int irn, int Tn)
118: {
119: switch (Tn) {
120: case 0:
121: gen_op_store_T0_ir(irn);
122: break;
123: case 1:
124: gen_op_store_T1_ir(irn);
125: break;
126: case 2:
127: gen_op_store_T2_ir(irn);
128: break;
129: }
130: }
131:
132: /* FIR moves */
133: /* Special hacks for fir31 */
134: #define gen_op_load_FT0_fir31 gen_op_reset_FT0
135: #define gen_op_load_FT1_fir31 gen_op_reset_FT1
136: #define gen_op_load_FT2_fir31 gen_op_reset_FT2
137: #define gen_op_store_FT0_fir31 gen_op_nop
138: #define gen_op_store_FT1_fir31 gen_op_nop
139: #define gen_op_store_FT2_fir31 gen_op_nop
140: #define gen_op_cmov_fir31 gen_op_nop
141: GEN32(gen_op_load_FT0_fir, gen_op_load_FT0_fir);
142: GEN32(gen_op_load_FT1_fir, gen_op_load_FT1_fir);
143: GEN32(gen_op_load_FT2_fir, gen_op_load_FT2_fir);
144: GEN32(gen_op_store_FT0_fir, gen_op_store_FT0_fir);
145: GEN32(gen_op_store_FT1_fir, gen_op_store_FT1_fir);
146: GEN32(gen_op_store_FT2_fir, gen_op_store_FT2_fir);
147: GEN32(gen_op_cmov_fir, gen_op_cmov_fir);
148:
149: static always_inline void gen_load_fir (DisasContext *ctx, int firn, int Tn)
150: {
151: switch (Tn) {
152: case 0:
153: gen_op_load_FT0_fir(firn);
154: break;
155: case 1:
156: gen_op_load_FT1_fir(firn);
157: break;
158: case 2:
159: gen_op_load_FT2_fir(firn);
160: break;
161: }
162: }
163:
164: static always_inline void gen_store_fir (DisasContext *ctx, int firn, int Tn)
165: {
166: switch (Tn) {
167: case 0:
168: gen_op_store_FT0_fir(firn);
169: break;
170: case 1:
171: gen_op_store_FT1_fir(firn);
172: break;
173: case 2:
174: gen_op_store_FT2_fir(firn);
175: break;
176: }
177: }
178:
179: /* Memory moves */
180: #if defined(CONFIG_USER_ONLY)
181: #define OP_LD_TABLE(width) \
182: static GenOpFunc *gen_op_ld##width[] = { \
183: &gen_op_ld##width##_raw, \
184: }
185: #define OP_ST_TABLE(width) \
186: static GenOpFunc *gen_op_st##width[] = { \
187: &gen_op_st##width##_raw, \
188: }
189: #else
190: #define OP_LD_TABLE(width) \
191: static GenOpFunc *gen_op_ld##width[] = { \
192: &gen_op_ld##width##_kernel, \
193: &gen_op_ld##width##_executive, \
194: &gen_op_ld##width##_supervisor, \
195: &gen_op_ld##width##_user, \
196: }
197: #define OP_ST_TABLE(width) \
198: static GenOpFunc *gen_op_st##width[] = { \
199: &gen_op_st##width##_kernel, \
200: &gen_op_st##width##_executive, \
201: &gen_op_st##width##_supervisor, \
202: &gen_op_st##width##_user, \
203: }
204: #endif
205:
206: #define GEN_LD(width) \
207: OP_LD_TABLE(width); \
208: static always_inline void gen_ld##width (DisasContext *ctx) \
209: { \
210: (*gen_op_ld##width[ctx->mem_idx])(); \
211: }
212:
213: #define GEN_ST(width) \
214: OP_ST_TABLE(width); \
215: static always_inline void gen_st##width (DisasContext *ctx) \
216: { \
217: (*gen_op_st##width[ctx->mem_idx])(); \
218: }
219:
220: GEN_LD(bu);
221: GEN_ST(b);
222: GEN_LD(wu);
223: GEN_ST(w);
224: GEN_LD(l);
225: GEN_ST(l);
226: GEN_LD(q);
227: GEN_ST(q);
228: GEN_LD(q_u);
229: GEN_ST(q_u);
230: GEN_LD(l_l);
231: GEN_ST(l_c);
232: GEN_LD(q_l);
233: GEN_ST(q_c);
234:
235: #if 0 /* currently unused */
236: GEN_LD(f);
237: GEN_ST(f);
238: GEN_LD(g);
239: GEN_ST(g);
240: #endif /* 0 */
241: GEN_LD(s);
242: GEN_ST(s);
243: GEN_LD(t);
244: GEN_ST(t);
245:
246: #if defined(__i386__) || defined(__x86_64__)
247: static always_inline void gen_op_set_s16_T0 (int16_t imm)
248: {
249: gen_op_set_s32_T0((int32_t)imm);
250: }
251:
252: static always_inline void gen_op_set_s16_T1 (int16_t imm)
253: {
254: gen_op_set_s32_T1((int32_t)imm);
255: }
256:
257: static always_inline void gen_op_set_u16_T0 (uint16_t imm)
258: {
259: gen_op_set_s32_T0((uint32_t)imm);
260: }
261:
262: static always_inline void gen_op_set_u16_T1 (uint16_t imm)
263: {
264: gen_op_set_s32_T1((uint32_t)imm);
265: }
266: #endif
267:
268: static always_inline void gen_set_sT0 (DisasContext *ctx, int64_t imm)
269: {
270: int32_t imm32;
271: int16_t imm16;
272:
273: imm32 = imm;
274: if (imm32 == imm) {
275: imm16 = imm;
276: if (imm16 == imm) {
277: if (imm == 0) {
278: gen_op_reset_T0();
279: } else {
280: gen_op_set_s16_T0(imm16);
281: }
282: } else {
283: gen_op_set_s32_T0(imm32);
284: }
285: } else {
286: #if 0 // Qemu does not know how to do this...
287: gen_op_set_64_T0(imm);
288: #else
289: gen_op_set_64_T0(imm >> 32, imm);
290: #endif
291: }
292: }
293:
294: static always_inline void gen_set_sT1 (DisasContext *ctx, int64_t imm)
295: {
296: int32_t imm32;
297: int16_t imm16;
298:
299: imm32 = imm;
300: if (imm32 == imm) {
301: imm16 = imm;
302: if (imm16 == imm) {
303: if (imm == 0) {
304: gen_op_reset_T1();
305: } else {
306: gen_op_set_s16_T1(imm16);
307: }
308: } else {
309: gen_op_set_s32_T1(imm32);
310: }
311: } else {
312: #if 0 // Qemu does not know how to do this...
313: gen_op_set_64_T1(imm);
314: #else
315: gen_op_set_64_T1(imm >> 32, imm);
316: #endif
317: }
318: }
319:
320: static always_inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm)
321: {
322: if (!(imm >> 32)) {
323: if ((!imm >> 16)) {
324: if (imm == 0)
325: gen_op_reset_T0();
326: else
327: gen_op_set_u16_T0(imm);
328: } else {
329: gen_op_set_u32_T0(imm);
330: }
331: } else {
332: #if 0 // Qemu does not know how to do this...
333: gen_op_set_64_T0(imm);
334: #else
335: gen_op_set_64_T0(imm >> 32, imm);
336: #endif
337: }
338: }
339:
340: static always_inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm)
341: {
342: if (!(imm >> 32)) {
343: if ((!imm >> 16)) {
344: if (imm == 0)
345: gen_op_reset_T1();
346: else
347: gen_op_set_u16_T1(imm);
348: } else {
349: gen_op_set_u32_T1(imm);
350: }
351: } else {
352: #if 0 // Qemu does not know how to do this...
353: gen_op_set_64_T1(imm);
354: #else
355: gen_op_set_64_T1(imm >> 32, imm);
356: #endif
357: }
358: }
359:
360: static always_inline void gen_update_pc (DisasContext *ctx)
361: {
362: if (!(ctx->pc >> 32)) {
363: gen_op_update_pc32(ctx->pc);
364: } else {
365: #if 0 // Qemu does not know how to do this...
366: gen_op_update_pc(ctx->pc);
367: #else
368: gen_op_update_pc(ctx->pc >> 32, ctx->pc);
369: #endif
370: }
371: }
372:
373: static always_inline void _gen_op_bcond (DisasContext *ctx)
374: {
375: #if 0 // Qemu does not know how to do this...
376: gen_op_bcond(ctx->pc);
377: #else
378: gen_op_bcond(ctx->pc >> 32, ctx->pc);
379: #endif
380: }
381:
382: static always_inline void gen_excp (DisasContext *ctx,
383: int exception, int error_code)
384: {
385: gen_update_pc(ctx);
386: gen_op_excp(exception, error_code);
387: }
388:
389: static always_inline void gen_invalid (DisasContext *ctx)
390: {
391: gen_excp(ctx, EXCP_OPCDEC, 0);
392: }
393:
394: static always_inline void gen_load_mem (DisasContext *ctx,
395: void (*gen_load_op)(DisasContext *ctx),
396: int ra, int rb, int32_t disp16,
397: int clear)
398: {
399: if (ra == 31 && disp16 == 0) {
400: /* UNOP */
401: gen_op_nop();
402: } else {
403: gen_load_ir(ctx, rb, 0);
404: if (disp16 != 0) {
405: gen_set_sT1(ctx, disp16);
406: gen_op_addq();
407: }
408: if (clear)
409: gen_op_n7();
410: (*gen_load_op)(ctx);
411: gen_store_ir(ctx, ra, 1);
412: }
413: }
414:
415: static always_inline void gen_store_mem (DisasContext *ctx,
416: void (*gen_store_op)(DisasContext *ctx),
417: int ra, int rb, int32_t disp16,
418: int clear)
419: {
420: gen_load_ir(ctx, rb, 0);
421: if (disp16 != 0) {
422: gen_set_sT1(ctx, disp16);
423: gen_op_addq();
424: }
425: if (clear)
426: gen_op_n7();
427: gen_load_ir(ctx, ra, 1);
428: (*gen_store_op)(ctx);
429: }
430:
431: static always_inline void gen_load_fmem (DisasContext *ctx,
432: void (*gen_load_fop)(DisasContext *ctx),
433: int ra, int rb, int32_t disp16)
434: {
435: gen_load_ir(ctx, rb, 0);
436: if (disp16 != 0) {
437: gen_set_sT1(ctx, disp16);
438: gen_op_addq();
439: }
440: (*gen_load_fop)(ctx);
441: gen_store_fir(ctx, ra, 1);
442: }
443:
444: static always_inline void gen_store_fmem (DisasContext *ctx,
445: void (*gen_store_fop)(DisasContext *ctx),
446: int ra, int rb, int32_t disp16)
447: {
448: gen_load_ir(ctx, rb, 0);
449: if (disp16 != 0) {
450: gen_set_sT1(ctx, disp16);
451: gen_op_addq();
452: }
453: gen_load_fir(ctx, ra, 1);
454: (*gen_store_fop)(ctx);
455: }
456:
457: static always_inline void gen_bcond (DisasContext *ctx,
458: void (*gen_test_op)(void),
459: int ra, int32_t disp16)
460: {
461: if (disp16 != 0) {
462: gen_set_uT0(ctx, ctx->pc);
463: gen_set_sT1(ctx, disp16 << 2);
464: gen_op_addq1();
465: } else {
466: gen_set_uT1(ctx, ctx->pc);
467: }
468: gen_load_ir(ctx, ra, 0);
469: (*gen_test_op)();
470: _gen_op_bcond(ctx);
471: }
472:
473: static always_inline void gen_fbcond (DisasContext *ctx,
474: void (*gen_test_op)(void),
475: int ra, int32_t disp16)
476: {
477: if (disp16 != 0) {
478: gen_set_uT0(ctx, ctx->pc);
479: gen_set_sT1(ctx, disp16 << 2);
480: gen_op_addq1();
481: } else {
482: gen_set_uT1(ctx, ctx->pc);
483: }
484: gen_load_fir(ctx, ra, 0);
485: (*gen_test_op)();
486: _gen_op_bcond(ctx);
487: }
488:
489: static always_inline void gen_arith2 (DisasContext *ctx,
490: void (*gen_arith_op)(void),
491: int rb, int rc, int islit, int8_t lit)
492: {
493: if (islit)
494: gen_set_sT0(ctx, lit);
495: else
496: gen_load_ir(ctx, rb, 0);
497: (*gen_arith_op)();
498: gen_store_ir(ctx, rc, 0);
499: }
500:
501: static always_inline void gen_arith3 (DisasContext *ctx,
502: void (*gen_arith_op)(void),
503: int ra, int rb, int rc,
504: int islit, int8_t lit)
505: {
506: gen_load_ir(ctx, ra, 0);
507: if (islit)
508: gen_set_sT1(ctx, lit);
509: else
510: gen_load_ir(ctx, rb, 1);
511: (*gen_arith_op)();
512: gen_store_ir(ctx, rc, 0);
513: }
514:
515: static always_inline void gen_cmov (DisasContext *ctx,
516: void (*gen_test_op)(void),
517: int ra, int rb, int rc,
518: int islit, int8_t lit)
519: {
520: gen_load_ir(ctx, ra, 1);
521: if (islit)
522: gen_set_sT0(ctx, lit);
523: else
524: gen_load_ir(ctx, rb, 0);
525: (*gen_test_op)();
526: gen_op_cmov_ir(rc);
527: }
528:
529: static always_inline void gen_farith2 (DisasContext *ctx,
530: void (*gen_arith_fop)(void),
531: int rb, int rc)
532: {
533: gen_load_fir(ctx, rb, 0);
534: (*gen_arith_fop)();
535: gen_store_fir(ctx, rc, 0);
536: }
537:
538: static always_inline void gen_farith3 (DisasContext *ctx,
539: void (*gen_arith_fop)(void),
540: int ra, int rb, int rc)
541: {
542: gen_load_fir(ctx, ra, 0);
543: gen_load_fir(ctx, rb, 1);
544: (*gen_arith_fop)();
545: gen_store_fir(ctx, rc, 0);
546: }
547:
548: static always_inline void gen_fcmov (DisasContext *ctx,
549: void (*gen_test_fop)(void),
550: int ra, int rb, int rc)
551: {
552: gen_load_fir(ctx, ra, 0);
553: gen_load_fir(ctx, rb, 1);
554: (*gen_test_fop)();
555: gen_op_cmov_fir(rc);
556: }
557:
558: static always_inline void gen_fti (DisasContext *ctx,
559: void (*gen_move_fop)(void),
560: int ra, int rc)
561: {
562: gen_load_fir(ctx, rc, 0);
563: (*gen_move_fop)();
564: gen_store_ir(ctx, ra, 0);
565: }
566:
567: static always_inline void gen_itf (DisasContext *ctx,
568: void (*gen_move_fop)(void),
569: int ra, int rc)
570: {
571: gen_load_ir(ctx, ra, 0);
572: (*gen_move_fop)();
573: gen_store_fir(ctx, rc, 0);
574: }
575:
576: static always_inline void gen_s4addl (void)
577: {
578: gen_op_s4();
579: gen_op_addl();
580: }
581:
582: static always_inline void gen_s4subl (void)
583: {
584: gen_op_s4();
585: gen_op_subl();
586: }
587:
588: static always_inline void gen_s8addl (void)
589: {
590: gen_op_s8();
591: gen_op_addl();
592: }
593:
594: static always_inline void gen_s8subl (void)
595: {
596: gen_op_s8();
597: gen_op_subl();
598: }
599:
600: static always_inline void gen_s4addq (void)
601: {
602: gen_op_s4();
603: gen_op_addq();
604: }
605:
606: static always_inline void gen_s4subq (void)
607: {
608: gen_op_s4();
609: gen_op_subq();
610: }
611:
612: static always_inline void gen_s8addq (void)
613: {
614: gen_op_s8();
615: gen_op_addq();
616: }
617:
618: static always_inline void gen_s8subq (void)
619: {
620: gen_op_s8();
621: gen_op_subq();
622: }
623:
624: static always_inline void gen_amask (void)
625: {
626: gen_op_load_amask();
627: gen_op_bic();
628: }
629:
630: static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
631: {
632: uint32_t palcode;
633: int32_t disp21, disp16, disp12;
634: uint16_t fn11, fn16;
635: uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit;
636: int8_t lit;
637: int ret;
638:
639: /* Decode all instruction fields */
640: opc = insn >> 26;
641: ra = (insn >> 21) & 0x1F;
642: rb = (insn >> 16) & 0x1F;
643: rc = insn & 0x1F;
644: sbz = (insn >> 13) & 0x07;
645: islit = (insn >> 12) & 1;
646: lit = (insn >> 13) & 0xFF;
647: palcode = insn & 0x03FFFFFF;
648: disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
649: disp16 = (int16_t)(insn & 0x0000FFFF);
650: disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
651: fn16 = insn & 0x0000FFFF;
652: fn11 = (insn >> 5) & 0x000007FF;
653: fpfn = fn11 & 0x3F;
654: fn7 = (insn >> 5) & 0x0000007F;
655: fn2 = (insn >> 5) & 0x00000003;
656: ret = 0;
657: #if defined ALPHA_DEBUG_DISAS
658: if (logfile != NULL) {
659: fprintf(logfile, "opc %02x ra %d rb %d rc %d disp16 %04x\n",
660: opc, ra, rb, rc, disp16);
661: }
662: #endif
663: switch (opc) {
664: case 0x00:
665: /* CALL_PAL */
666: if (palcode >= 0x80 && palcode < 0xC0) {
667: /* Unprivileged PAL call */
668: gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0);
669: #if !defined (CONFIG_USER_ONLY)
670: } else if (palcode < 0x40) {
671: /* Privileged PAL code */
672: if (ctx->mem_idx & 1)
673: goto invalid_opc;
674: else
675: gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x1F) << 6), 0);
676: #endif
677: } else {
678: /* Invalid PAL call */
679: goto invalid_opc;
680: }
681: ret = 3;
682: break;
683: case 0x01:
684: /* OPC01 */
685: goto invalid_opc;
686: case 0x02:
687: /* OPC02 */
688: goto invalid_opc;
689: case 0x03:
690: /* OPC03 */
691: goto invalid_opc;
692: case 0x04:
693: /* OPC04 */
694: goto invalid_opc;
695: case 0x05:
696: /* OPC05 */
697: goto invalid_opc;
698: case 0x06:
699: /* OPC06 */
700: goto invalid_opc;
701: case 0x07:
702: /* OPC07 */
703: goto invalid_opc;
704: case 0x08:
705: /* LDA */
706: gen_load_ir(ctx, rb, 0);
707: gen_set_sT1(ctx, disp16);
708: gen_op_addq();
709: gen_store_ir(ctx, ra, 0);
710: break;
711: case 0x09:
712: /* LDAH */
713: gen_load_ir(ctx, rb, 0);
714: gen_set_sT1(ctx, disp16 << 16);
715: gen_op_addq();
716: gen_store_ir(ctx, ra, 0);
717: break;
718: case 0x0A:
719: /* LDBU */
720: if (!(ctx->amask & AMASK_BWX))
721: goto invalid_opc;
722: gen_load_mem(ctx, &gen_ldbu, ra, rb, disp16, 0);
723: break;
724: case 0x0B:
725: /* LDQ_U */
726: gen_load_mem(ctx, &gen_ldq_u, ra, rb, disp16, 1);
727: break;
728: case 0x0C:
729: /* LDWU */
730: if (!(ctx->amask & AMASK_BWX))
731: goto invalid_opc;
732: gen_load_mem(ctx, &gen_ldwu, ra, rb, disp16, 0);
733: break;
734: case 0x0D:
735: /* STW */
736: if (!(ctx->amask & AMASK_BWX))
737: goto invalid_opc;
738: gen_store_mem(ctx, &gen_stw, ra, rb, disp16, 0);
739: break;
740: case 0x0E:
741: /* STB */
742: if (!(ctx->amask & AMASK_BWX))
743: goto invalid_opc;
744: gen_store_mem(ctx, &gen_stb, ra, rb, disp16, 0);
745: break;
746: case 0x0F:
747: /* STQ_U */
748: gen_store_mem(ctx, &gen_stq_u, ra, rb, disp16, 1);
749: break;
750: case 0x10:
751: switch (fn7) {
752: case 0x00:
753: /* ADDL */
754: gen_arith3(ctx, &gen_op_addl, ra, rb, rc, islit, lit);
755: break;
756: case 0x02:
757: /* S4ADDL */
758: gen_arith3(ctx, &gen_s4addl, ra, rb, rc, islit, lit);
759: break;
760: case 0x09:
761: /* SUBL */
762: gen_arith3(ctx, &gen_op_subl, ra, rb, rc, islit, lit);
763: break;
764: case 0x0B:
765: /* S4SUBL */
766: gen_arith3(ctx, &gen_s4subl, ra, rb, rc, islit, lit);
767: break;
768: case 0x0F:
769: /* CMPBGE */
770: gen_arith3(ctx, &gen_op_cmpbge, ra, rb, rc, islit, lit);
771: break;
772: case 0x12:
773: /* S8ADDL */
774: gen_arith3(ctx, &gen_s8addl, ra, rb, rc, islit, lit);
775: break;
776: case 0x1B:
777: /* S8SUBL */
778: gen_arith3(ctx, &gen_s8subl, ra, rb, rc, islit, lit);
779: break;
780: case 0x1D:
781: /* CMPULT */
782: gen_arith3(ctx, &gen_op_cmpult, ra, rb, rc, islit, lit);
783: break;
784: case 0x20:
785: /* ADDQ */
786: gen_arith3(ctx, &gen_op_addq, ra, rb, rc, islit, lit);
787: break;
788: case 0x22:
789: /* S4ADDQ */
790: gen_arith3(ctx, &gen_s4addq, ra, rb, rc, islit, lit);
791: break;
792: case 0x29:
793: /* SUBQ */
794: gen_arith3(ctx, &gen_op_subq, ra, rb, rc, islit, lit);
795: break;
796: case 0x2B:
797: /* S4SUBQ */
798: gen_arith3(ctx, &gen_s4subq, ra, rb, rc, islit, lit);
799: break;
800: case 0x2D:
801: /* CMPEQ */
802: gen_arith3(ctx, &gen_op_cmpeq, ra, rb, rc, islit, lit);
803: break;
804: case 0x32:
805: /* S8ADDQ */
806: gen_arith3(ctx, &gen_s8addq, ra, rb, rc, islit, lit);
807: break;
808: case 0x3B:
809: /* S8SUBQ */
810: gen_arith3(ctx, &gen_s8subq, ra, rb, rc, islit, lit);
811: break;
812: case 0x3D:
813: /* CMPULE */
814: gen_arith3(ctx, &gen_op_cmpule, ra, rb, rc, islit, lit);
815: break;
816: case 0x40:
817: /* ADDL/V */
818: gen_arith3(ctx, &gen_op_addlv, ra, rb, rc, islit, lit);
819: break;
820: case 0x49:
821: /* SUBL/V */
822: gen_arith3(ctx, &gen_op_sublv, ra, rb, rc, islit, lit);
823: break;
824: case 0x4D:
825: /* CMPLT */
826: gen_arith3(ctx, &gen_op_cmplt, ra, rb, rc, islit, lit);
827: break;
828: case 0x60:
829: /* ADDQ/V */
830: gen_arith3(ctx, &gen_op_addqv, ra, rb, rc, islit, lit);
831: break;
832: case 0x69:
833: /* SUBQ/V */
834: gen_arith3(ctx, &gen_op_subqv, ra, rb, rc, islit, lit);
835: break;
836: case 0x6D:
837: /* CMPLE */
838: gen_arith3(ctx, &gen_op_cmple, ra, rb, rc, islit, lit);
839: break;
840: default:
841: goto invalid_opc;
842: }
843: break;
844: case 0x11:
845: switch (fn7) {
846: case 0x00:
847: /* AND */
848: gen_arith3(ctx, &gen_op_and, ra, rb, rc, islit, lit);
849: break;
850: case 0x08:
851: /* BIC */
852: gen_arith3(ctx, &gen_op_bic, ra, rb, rc, islit, lit);
853: break;
854: case 0x14:
855: /* CMOVLBS */
856: gen_cmov(ctx, &gen_op_cmplbs, ra, rb, rc, islit, lit);
857: break;
858: case 0x16:
859: /* CMOVLBC */
860: gen_cmov(ctx, &gen_op_cmplbc, ra, rb, rc, islit, lit);
861: break;
862: case 0x20:
863: /* BIS */
864: if (ra == rb || ra == 31 || rb == 31) {
865: if (ra == 31 && rc == 31) {
866: /* NOP */
867: gen_op_nop();
868: } else {
869: /* MOV */
870: gen_load_ir(ctx, rb, 0);
871: gen_store_ir(ctx, rc, 0);
872: }
873: } else {
874: gen_arith3(ctx, &gen_op_bis, ra, rb, rc, islit, lit);
875: }
876: break;
877: case 0x24:
878: /* CMOVEQ */
879: gen_cmov(ctx, &gen_op_cmpeqz, ra, rb, rc, islit, lit);
880: break;
881: case 0x26:
882: /* CMOVNE */
883: gen_cmov(ctx, &gen_op_cmpnez, ra, rb, rc, islit, lit);
884: break;
885: case 0x28:
886: /* ORNOT */
887: gen_arith3(ctx, &gen_op_ornot, ra, rb, rc, islit, lit);
888: break;
889: case 0x40:
890: /* XOR */
891: gen_arith3(ctx, &gen_op_xor, ra, rb, rc, islit, lit);
892: break;
893: case 0x44:
894: /* CMOVLT */
895: gen_cmov(ctx, &gen_op_cmpltz, ra, rb, rc, islit, lit);
896: break;
897: case 0x46:
898: /* CMOVGE */
899: gen_cmov(ctx, &gen_op_cmpgez, ra, rb, rc, islit, lit);
900: break;
901: case 0x48:
902: /* EQV */
903: gen_arith3(ctx, &gen_op_eqv, ra, rb, rc, islit, lit);
904: break;
905: case 0x61:
906: /* AMASK */
907: gen_arith2(ctx, &gen_amask, rb, rc, islit, lit);
908: break;
909: case 0x64:
910: /* CMOVLE */
911: gen_cmov(ctx, &gen_op_cmplez, ra, rb, rc, islit, lit);
912: break;
913: case 0x66:
914: /* CMOVGT */
915: gen_cmov(ctx, &gen_op_cmpgtz, ra, rb, rc, islit, lit);
916: break;
917: case 0x6C:
918: /* IMPLVER */
919: gen_op_load_implver();
920: gen_store_ir(ctx, rc, 0);
921: break;
922: default:
923: goto invalid_opc;
924: }
925: break;
926: case 0x12:
927: switch (fn7) {
928: case 0x02:
929: /* MSKBL */
930: gen_arith3(ctx, &gen_op_mskbl, ra, rb, rc, islit, lit);
931: break;
932: case 0x06:
933: /* EXTBL */
934: gen_arith3(ctx, &gen_op_extbl, ra, rb, rc, islit, lit);
935: break;
936: case 0x0B:
937: /* INSBL */
938: gen_arith3(ctx, &gen_op_insbl, ra, rb, rc, islit, lit);
939: break;
940: case 0x12:
941: /* MSKWL */
942: gen_arith3(ctx, &gen_op_mskwl, ra, rb, rc, islit, lit);
943: break;
944: case 0x16:
945: /* EXTWL */
946: gen_arith3(ctx, &gen_op_extwl, ra, rb, rc, islit, lit);
947: break;
948: case 0x1B:
949: /* INSWL */
950: gen_arith3(ctx, &gen_op_inswl, ra, rb, rc, islit, lit);
951: break;
952: case 0x22:
953: /* MSKLL */
954: gen_arith3(ctx, &gen_op_mskll, ra, rb, rc, islit, lit);
955: break;
956: case 0x26:
957: /* EXTLL */
958: gen_arith3(ctx, &gen_op_extll, ra, rb, rc, islit, lit);
959: break;
960: case 0x2B:
961: /* INSLL */
962: gen_arith3(ctx, &gen_op_insll, ra, rb, rc, islit, lit);
963: break;
964: case 0x30:
965: /* ZAP */
966: gen_arith3(ctx, &gen_op_zap, ra, rb, rc, islit, lit);
967: break;
968: case 0x31:
969: /* ZAPNOT */
970: gen_arith3(ctx, &gen_op_zapnot, ra, rb, rc, islit, lit);
971: break;
972: case 0x32:
973: /* MSKQL */
974: gen_arith3(ctx, &gen_op_mskql, ra, rb, rc, islit, lit);
975: break;
976: case 0x34:
977: /* SRL */
978: gen_arith3(ctx, &gen_op_srl, ra, rb, rc, islit, lit);
979: break;
980: case 0x36:
981: /* EXTQL */
982: gen_arith3(ctx, &gen_op_extql, ra, rb, rc, islit, lit);
983: break;
984: case 0x39:
985: /* SLL */
986: gen_arith3(ctx, &gen_op_sll, ra, rb, rc, islit, lit);
987: break;
988: case 0x3B:
989: /* INSQL */
990: gen_arith3(ctx, &gen_op_insql, ra, rb, rc, islit, lit);
991: break;
992: case 0x3C:
993: /* SRA */
994: gen_arith3(ctx, &gen_op_sra, ra, rb, rc, islit, lit);
995: break;
996: case 0x52:
997: /* MSKWH */
998: gen_arith3(ctx, &gen_op_mskwh, ra, rb, rc, islit, lit);
999: break;
1000: case 0x57:
1001: /* INSWH */
1002: gen_arith3(ctx, &gen_op_inswh, ra, rb, rc, islit, lit);
1003: break;
1004: case 0x5A:
1005: /* EXTWH */
1006: gen_arith3(ctx, &gen_op_extwh, ra, rb, rc, islit, lit);
1007: break;
1008: case 0x62:
1009: /* MSKLH */
1010: gen_arith3(ctx, &gen_op_msklh, ra, rb, rc, islit, lit);
1011: break;
1012: case 0x67:
1013: /* INSLH */
1014: gen_arith3(ctx, &gen_op_inslh, ra, rb, rc, islit, lit);
1015: break;
1016: case 0x6A:
1017: /* EXTLH */
1018: gen_arith3(ctx, &gen_op_extlh, ra, rb, rc, islit, lit);
1019: break;
1020: case 0x72:
1021: /* MSKQH */
1022: gen_arith3(ctx, &gen_op_mskqh, ra, rb, rc, islit, lit);
1023: break;
1024: case 0x77:
1025: /* INSQH */
1026: gen_arith3(ctx, &gen_op_insqh, ra, rb, rc, islit, lit);
1027: break;
1028: case 0x7A:
1029: /* EXTQH */
1030: gen_arith3(ctx, &gen_op_extqh, ra, rb, rc, islit, lit);
1031: break;
1032: default:
1033: goto invalid_opc;
1034: }
1035: break;
1036: case 0x13:
1037: switch (fn7) {
1038: case 0x00:
1039: /* MULL */
1040: gen_arith3(ctx, &gen_op_mull, ra, rb, rc, islit, lit);
1041: break;
1042: case 0x20:
1043: /* MULQ */
1044: gen_arith3(ctx, &gen_op_mulq, ra, rb, rc, islit, lit);
1045: break;
1046: case 0x30:
1047: /* UMULH */
1048: gen_arith3(ctx, &gen_op_umulh, ra, rb, rc, islit, lit);
1049: break;
1050: case 0x40:
1051: /* MULL/V */
1052: gen_arith3(ctx, &gen_op_mullv, ra, rb, rc, islit, lit);
1053: break;
1054: case 0x60:
1055: /* MULQ/V */
1056: gen_arith3(ctx, &gen_op_mulqv, ra, rb, rc, islit, lit);
1057: break;
1058: default:
1059: goto invalid_opc;
1060: }
1061: break;
1062: case 0x14:
1063: switch (fpfn) { /* f11 & 0x3F */
1064: case 0x04:
1065: /* ITOFS */
1066: if (!(ctx->amask & AMASK_FIX))
1067: goto invalid_opc;
1068: gen_itf(ctx, &gen_op_itofs, ra, rc);
1069: break;
1070: case 0x0A:
1071: /* SQRTF */
1072: if (!(ctx->amask & AMASK_FIX))
1073: goto invalid_opc;
1074: gen_farith2(ctx, &gen_op_sqrtf, rb, rc);
1075: break;
1076: case 0x0B:
1077: /* SQRTS */
1078: if (!(ctx->amask & AMASK_FIX))
1079: goto invalid_opc;
1080: gen_farith2(ctx, &gen_op_sqrts, rb, rc);
1081: break;
1082: case 0x14:
1083: /* ITOFF */
1084: if (!(ctx->amask & AMASK_FIX))
1085: goto invalid_opc;
1086: #if 0 // TODO
1087: gen_itf(ctx, &gen_op_itoff, ra, rc);
1088: #else
1089: goto invalid_opc;
1090: #endif
1091: break;
1092: case 0x24:
1093: /* ITOFT */
1094: if (!(ctx->amask & AMASK_FIX))
1095: goto invalid_opc;
1096: gen_itf(ctx, &gen_op_itoft, ra, rc);
1097: break;
1098: case 0x2A:
1099: /* SQRTG */
1100: if (!(ctx->amask & AMASK_FIX))
1101: goto invalid_opc;
1102: gen_farith2(ctx, &gen_op_sqrtg, rb, rc);
1103: break;
1104: case 0x02B:
1105: /* SQRTT */
1106: if (!(ctx->amask & AMASK_FIX))
1107: goto invalid_opc;
1108: gen_farith2(ctx, &gen_op_sqrtt, rb, rc);
1109: break;
1110: default:
1111: goto invalid_opc;
1112: }
1113: break;
1114: case 0x15:
1115: /* VAX floating point */
1116: /* XXX: rounding mode and trap are ignored (!) */
1117: switch (fpfn) { /* f11 & 0x3F */
1118: case 0x00:
1119: /* ADDF */
1120: gen_farith3(ctx, &gen_op_addf, ra, rb, rc);
1121: break;
1122: case 0x01:
1123: /* SUBF */
1124: gen_farith3(ctx, &gen_op_subf, ra, rb, rc);
1125: break;
1126: case 0x02:
1127: /* MULF */
1128: gen_farith3(ctx, &gen_op_mulf, ra, rb, rc);
1129: break;
1130: case 0x03:
1131: /* DIVF */
1132: gen_farith3(ctx, &gen_op_divf, ra, rb, rc);
1133: break;
1134: case 0x1E:
1135: /* CVTDG */
1136: #if 0 // TODO
1137: gen_farith2(ctx, &gen_op_cvtdg, rb, rc);
1138: #else
1139: goto invalid_opc;
1140: #endif
1141: break;
1142: case 0x20:
1143: /* ADDG */
1144: gen_farith3(ctx, &gen_op_addg, ra, rb, rc);
1145: break;
1146: case 0x21:
1147: /* SUBG */
1148: gen_farith3(ctx, &gen_op_subg, ra, rb, rc);
1149: break;
1150: case 0x22:
1151: /* MULG */
1152: gen_farith3(ctx, &gen_op_mulg, ra, rb, rc);
1153: break;
1154: case 0x23:
1155: /* DIVG */
1156: gen_farith3(ctx, &gen_op_divg, ra, rb, rc);
1157: break;
1158: case 0x25:
1159: /* CMPGEQ */
1160: gen_farith3(ctx, &gen_op_cmpgeq, ra, rb, rc);
1161: break;
1162: case 0x26:
1163: /* CMPGLT */
1164: gen_farith3(ctx, &gen_op_cmpglt, ra, rb, rc);
1165: break;
1166: case 0x27:
1167: /* CMPGLE */
1168: gen_farith3(ctx, &gen_op_cmpgle, ra, rb, rc);
1169: break;
1170: case 0x2C:
1171: /* CVTGF */
1172: gen_farith2(ctx, &gen_op_cvtgf, rb, rc);
1173: break;
1174: case 0x2D:
1175: /* CVTGD */
1176: #if 0 // TODO
1177: gen_farith2(ctx, &gen_op_cvtgd, rb, rc);
1178: #else
1179: goto invalid_opc;
1180: #endif
1181: break;
1182: case 0x2F:
1183: /* CVTGQ */
1184: gen_farith2(ctx, &gen_op_cvtgq, rb, rc);
1185: break;
1186: case 0x3C:
1187: /* CVTQF */
1188: gen_farith2(ctx, &gen_op_cvtqf, rb, rc);
1189: break;
1190: case 0x3E:
1191: /* CVTQG */
1192: gen_farith2(ctx, &gen_op_cvtqg, rb, rc);
1193: break;
1194: default:
1195: goto invalid_opc;
1196: }
1197: break;
1198: case 0x16:
1199: /* IEEE floating-point */
1200: /* XXX: rounding mode and traps are ignored (!) */
1201: switch (fpfn) { /* f11 & 0x3F */
1202: case 0x00:
1203: /* ADDS */
1204: gen_farith3(ctx, &gen_op_adds, ra, rb, rc);
1205: break;
1206: case 0x01:
1207: /* SUBS */
1208: gen_farith3(ctx, &gen_op_subs, ra, rb, rc);
1209: break;
1210: case 0x02:
1211: /* MULS */
1212: gen_farith3(ctx, &gen_op_muls, ra, rb, rc);
1213: break;
1214: case 0x03:
1215: /* DIVS */
1216: gen_farith3(ctx, &gen_op_divs, ra, rb, rc);
1217: break;
1218: case 0x20:
1219: /* ADDT */
1220: gen_farith3(ctx, &gen_op_addt, ra, rb, rc);
1221: break;
1222: case 0x21:
1223: /* SUBT */
1224: gen_farith3(ctx, &gen_op_subt, ra, rb, rc);
1225: break;
1226: case 0x22:
1227: /* MULT */
1228: gen_farith3(ctx, &gen_op_mult, ra, rb, rc);
1229: break;
1230: case 0x23:
1231: /* DIVT */
1232: gen_farith3(ctx, &gen_op_divt, ra, rb, rc);
1233: break;
1234: case 0x24:
1235: /* CMPTUN */
1236: gen_farith3(ctx, &gen_op_cmptun, ra, rb, rc);
1237: break;
1238: case 0x25:
1239: /* CMPTEQ */
1240: gen_farith3(ctx, &gen_op_cmpteq, ra, rb, rc);
1241: break;
1242: case 0x26:
1243: /* CMPTLT */
1244: gen_farith3(ctx, &gen_op_cmptlt, ra, rb, rc);
1245: break;
1246: case 0x27:
1247: /* CMPTLE */
1248: gen_farith3(ctx, &gen_op_cmptle, ra, rb, rc);
1249: break;
1250: case 0x2C:
1251: /* XXX: incorrect */
1252: if (fn11 == 0x2AC) {
1253: /* CVTST */
1254: gen_farith2(ctx, &gen_op_cvtst, rb, rc);
1255: } else {
1256: /* CVTTS */
1257: gen_farith2(ctx, &gen_op_cvtts, rb, rc);
1258: }
1259: break;
1260: case 0x2F:
1261: /* CVTTQ */
1262: gen_farith2(ctx, &gen_op_cvttq, rb, rc);
1263: break;
1264: case 0x3C:
1265: /* CVTQS */
1266: gen_farith2(ctx, &gen_op_cvtqs, rb, rc);
1267: break;
1268: case 0x3E:
1269: /* CVTQT */
1270: gen_farith2(ctx, &gen_op_cvtqt, rb, rc);
1271: break;
1272: default:
1273: goto invalid_opc;
1274: }
1275: break;
1276: case 0x17:
1277: switch (fn11) {
1278: case 0x010:
1279: /* CVTLQ */
1280: gen_farith2(ctx, &gen_op_cvtlq, rb, rc);
1281: break;
1282: case 0x020:
1283: /* CPYS */
1284: if (ra == rb) {
1285: if (ra == 31 && rc == 31) {
1286: /* FNOP */
1287: gen_op_nop();
1288: } else {
1289: /* FMOV */
1290: gen_load_fir(ctx, rb, 0);
1291: gen_store_fir(ctx, rc, 0);
1292: }
1293: } else {
1294: gen_farith3(ctx, &gen_op_cpys, ra, rb, rc);
1295: }
1296: break;
1297: case 0x021:
1298: /* CPYSN */
1299: gen_farith2(ctx, &gen_op_cpysn, rb, rc);
1300: break;
1301: case 0x022:
1302: /* CPYSE */
1303: gen_farith2(ctx, &gen_op_cpyse, rb, rc);
1304: break;
1305: case 0x024:
1306: /* MT_FPCR */
1307: gen_load_fir(ctx, ra, 0);
1308: gen_op_store_fpcr();
1309: break;
1310: case 0x025:
1311: /* MF_FPCR */
1312: gen_op_load_fpcr();
1313: gen_store_fir(ctx, ra, 0);
1314: break;
1315: case 0x02A:
1316: /* FCMOVEQ */
1317: gen_fcmov(ctx, &gen_op_cmpfeq, ra, rb, rc);
1318: break;
1319: case 0x02B:
1320: /* FCMOVNE */
1321: gen_fcmov(ctx, &gen_op_cmpfne, ra, rb, rc);
1322: break;
1323: case 0x02C:
1324: /* FCMOVLT */
1325: gen_fcmov(ctx, &gen_op_cmpflt, ra, rb, rc);
1326: break;
1327: case 0x02D:
1328: /* FCMOVGE */
1329: gen_fcmov(ctx, &gen_op_cmpfge, ra, rb, rc);
1330: break;
1331: case 0x02E:
1332: /* FCMOVLE */
1333: gen_fcmov(ctx, &gen_op_cmpfle, ra, rb, rc);
1334: break;
1335: case 0x02F:
1336: /* FCMOVGT */
1337: gen_fcmov(ctx, &gen_op_cmpfgt, ra, rb, rc);
1338: break;
1339: case 0x030:
1340: /* CVTQL */
1341: gen_farith2(ctx, &gen_op_cvtql, rb, rc);
1342: break;
1343: case 0x130:
1344: /* CVTQL/V */
1345: gen_farith2(ctx, &gen_op_cvtqlv, rb, rc);
1346: break;
1347: case 0x530:
1348: /* CVTQL/SV */
1349: gen_farith2(ctx, &gen_op_cvtqlsv, rb, rc);
1350: break;
1351: default:
1352: goto invalid_opc;
1353: }
1354: break;
1355: case 0x18:
1356: switch ((uint16_t)disp16) {
1357: case 0x0000:
1358: /* TRAPB */
1359: /* No-op. Just exit from the current tb */
1360: ret = 2;
1361: break;
1362: case 0x0400:
1363: /* EXCB */
1364: /* No-op. Just exit from the current tb */
1365: ret = 2;
1366: break;
1367: case 0x4000:
1368: /* MB */
1369: /* No-op */
1370: break;
1371: case 0x4400:
1372: /* WMB */
1373: /* No-op */
1374: break;
1375: case 0x8000:
1376: /* FETCH */
1377: /* No-op */
1378: break;
1379: case 0xA000:
1380: /* FETCH_M */
1381: /* No-op */
1382: break;
1383: case 0xC000:
1384: /* RPCC */
1385: gen_op_load_pcc();
1386: gen_store_ir(ctx, ra, 0);
1387: break;
1388: case 0xE000:
1389: /* RC */
1390: gen_op_load_irf();
1391: gen_store_ir(ctx, ra, 0);
1392: gen_op_clear_irf();
1393: break;
1394: case 0xE800:
1395: /* ECB */
1396: /* XXX: TODO: evict tb cache at address rb */
1397: #if 0
1398: ret = 2;
1399: #else
1400: goto invalid_opc;
1401: #endif
1402: break;
1403: case 0xF000:
1404: /* RS */
1405: gen_op_load_irf();
1406: gen_store_ir(ctx, ra, 0);
1407: gen_op_set_irf();
1408: break;
1409: case 0xF800:
1410: /* WH64 */
1411: /* No-op */
1412: break;
1413: default:
1414: goto invalid_opc;
1415: }
1416: break;
1417: case 0x19:
1418: /* HW_MFPR (PALcode) */
1419: #if defined (CONFIG_USER_ONLY)
1420: goto invalid_opc;
1421: #else
1422: if (!ctx->pal_mode)
1423: goto invalid_opc;
1424: gen_op_mfpr(insn & 0xFF);
1425: gen_store_ir(ctx, ra, 0);
1426: break;
1427: #endif
1428: case 0x1A:
1429: gen_load_ir(ctx, rb, 0);
1430: if (ra != 31) {
1431: gen_set_uT1(ctx, ctx->pc);
1432: gen_store_ir(ctx, ra, 1);
1433: }
1434: gen_op_branch();
1435: /* Those four jumps only differ by the branch prediction hint */
1436: switch (fn2) {
1437: case 0x0:
1438: /* JMP */
1439: break;
1440: case 0x1:
1441: /* JSR */
1442: break;
1443: case 0x2:
1444: /* RET */
1445: break;
1446: case 0x3:
1447: /* JSR_COROUTINE */
1448: break;
1449: }
1450: ret = 1;
1451: break;
1452: case 0x1B:
1453: /* HW_LD (PALcode) */
1454: #if defined (CONFIG_USER_ONLY)
1455: goto invalid_opc;
1456: #else
1457: if (!ctx->pal_mode)
1458: goto invalid_opc;
1459: gen_load_ir(ctx, rb, 0);
1460: gen_set_sT1(ctx, disp12);
1461: gen_op_addq();
1462: switch ((insn >> 12) & 0xF) {
1463: case 0x0:
1464: /* Longword physical access */
1465: gen_op_ldl_raw();
1466: break;
1467: case 0x1:
1468: /* Quadword physical access */
1469: gen_op_ldq_raw();
1470: break;
1471: case 0x2:
1472: /* Longword physical access with lock */
1473: gen_op_ldl_l_raw();
1474: break;
1475: case 0x3:
1476: /* Quadword physical access with lock */
1477: gen_op_ldq_l_raw();
1478: break;
1479: case 0x4:
1480: /* Longword virtual PTE fetch */
1481: gen_op_ldl_kernel();
1482: break;
1483: case 0x5:
1484: /* Quadword virtual PTE fetch */
1485: gen_op_ldq_kernel();
1486: break;
1487: case 0x6:
1488: /* Invalid */
1489: goto invalid_opc;
1490: case 0x7:
1491: /* Invalid */
1492: goto invalid_opc;
1493: case 0x8:
1494: /* Longword virtual access */
1495: gen_op_ld_phys_to_virt();
1496: gen_op_ldl_raw();
1497: break;
1498: case 0x9:
1499: /* Quadword virtual access */
1500: gen_op_ld_phys_to_virt();
1501: gen_op_ldq_raw();
1502: break;
1503: case 0xA:
1504: /* Longword virtual access with protection check */
1505: gen_ldl(ctx);
1506: break;
1507: case 0xB:
1508: /* Quadword virtual access with protection check */
1509: gen_ldq(ctx);
1510: break;
1511: case 0xC:
1512: /* Longword virtual access with altenate access mode */
1513: gen_op_set_alt_mode();
1514: gen_op_ld_phys_to_virt();
1515: gen_op_ldl_raw();
1516: gen_op_restore_mode();
1517: break;
1518: case 0xD:
1519: /* Quadword virtual access with altenate access mode */
1520: gen_op_set_alt_mode();
1521: gen_op_ld_phys_to_virt();
1522: gen_op_ldq_raw();
1523: gen_op_restore_mode();
1524: break;
1525: case 0xE:
1526: /* Longword virtual access with alternate access mode and
1527: * protection checks
1528: */
1529: gen_op_set_alt_mode();
1530: gen_op_ldl_data();
1531: gen_op_restore_mode();
1532: break;
1533: case 0xF:
1534: /* Quadword virtual access with alternate access mode and
1535: * protection checks
1536: */
1537: gen_op_set_alt_mode();
1538: gen_op_ldq_data();
1539: gen_op_restore_mode();
1540: break;
1541: }
1542: gen_store_ir(ctx, ra, 1);
1543: break;
1544: #endif
1545: case 0x1C:
1546: switch (fn7) {
1547: case 0x00:
1548: /* SEXTB */
1549: if (!(ctx->amask & AMASK_BWX))
1550: goto invalid_opc;
1551: gen_arith2(ctx, &gen_op_sextb, rb, rc, islit, lit);
1552: break;
1553: case 0x01:
1554: /* SEXTW */
1555: if (!(ctx->amask & AMASK_BWX))
1556: goto invalid_opc;
1557: gen_arith2(ctx, &gen_op_sextw, rb, rc, islit, lit);
1558: break;
1559: case 0x30:
1560: /* CTPOP */
1561: if (!(ctx->amask & AMASK_CIX))
1562: goto invalid_opc;
1563: gen_arith2(ctx, &gen_op_ctpop, rb, rc, 0, 0);
1564: break;
1565: case 0x31:
1566: /* PERR */
1567: if (!(ctx->amask & AMASK_MVI))
1568: goto invalid_opc;
1569: /* XXX: TODO */
1570: goto invalid_opc;
1571: break;
1572: case 0x32:
1573: /* CTLZ */
1574: if (!(ctx->amask & AMASK_CIX))
1575: goto invalid_opc;
1576: gen_arith2(ctx, &gen_op_ctlz, rb, rc, 0, 0);
1577: break;
1578: case 0x33:
1579: /* CTTZ */
1580: if (!(ctx->amask & AMASK_CIX))
1581: goto invalid_opc;
1582: gen_arith2(ctx, &gen_op_cttz, rb, rc, 0, 0);
1583: break;
1584: case 0x34:
1585: /* UNPKBW */
1586: if (!(ctx->amask & AMASK_MVI))
1587: goto invalid_opc;
1588: /* XXX: TODO */
1589: goto invalid_opc;
1590: break;
1591: case 0x35:
1592: /* UNPKWL */
1593: if (!(ctx->amask & AMASK_MVI))
1594: goto invalid_opc;
1595: /* XXX: TODO */
1596: goto invalid_opc;
1597: break;
1598: case 0x36:
1599: /* PKWB */
1600: if (!(ctx->amask & AMASK_MVI))
1601: goto invalid_opc;
1602: /* XXX: TODO */
1603: goto invalid_opc;
1604: break;
1605: case 0x37:
1606: /* PKLB */
1607: if (!(ctx->amask & AMASK_MVI))
1608: goto invalid_opc;
1609: /* XXX: TODO */
1610: goto invalid_opc;
1611: break;
1612: case 0x38:
1613: /* MINSB8 */
1614: if (!(ctx->amask & AMASK_MVI))
1615: goto invalid_opc;
1616: /* XXX: TODO */
1617: goto invalid_opc;
1618: break;
1619: case 0x39:
1620: /* MINSW4 */
1621: if (!(ctx->amask & AMASK_MVI))
1622: goto invalid_opc;
1623: /* XXX: TODO */
1624: goto invalid_opc;
1625: break;
1626: case 0x3A:
1627: /* MINUB8 */
1628: if (!(ctx->amask & AMASK_MVI))
1629: goto invalid_opc;
1630: /* XXX: TODO */
1631: goto invalid_opc;
1632: break;
1633: case 0x3B:
1634: /* MINUW4 */
1635: if (!(ctx->amask & AMASK_MVI))
1636: goto invalid_opc;
1637: /* XXX: TODO */
1638: goto invalid_opc;
1639: break;
1640: case 0x3C:
1641: /* MAXUB8 */
1642: if (!(ctx->amask & AMASK_MVI))
1643: goto invalid_opc;
1644: /* XXX: TODO */
1645: goto invalid_opc;
1646: break;
1647: case 0x3D:
1648: /* MAXUW4 */
1649: if (!(ctx->amask & AMASK_MVI))
1650: goto invalid_opc;
1651: /* XXX: TODO */
1652: goto invalid_opc;
1653: break;
1654: case 0x3E:
1655: /* MAXSB8 */
1656: if (!(ctx->amask & AMASK_MVI))
1657: goto invalid_opc;
1658: /* XXX: TODO */
1659: goto invalid_opc;
1660: break;
1661: case 0x3F:
1662: /* MAXSW4 */
1663: if (!(ctx->amask & AMASK_MVI))
1664: goto invalid_opc;
1665: /* XXX: TODO */
1666: goto invalid_opc;
1667: break;
1668: case 0x70:
1669: /* FTOIT */
1670: if (!(ctx->amask & AMASK_FIX))
1671: goto invalid_opc;
1672: gen_fti(ctx, &gen_op_ftoit, ra, rb);
1673: break;
1674: case 0x78:
1675: /* FTOIS */
1676: if (!(ctx->amask & AMASK_FIX))
1677: goto invalid_opc;
1678: gen_fti(ctx, &gen_op_ftois, ra, rb);
1679: break;
1680: default:
1681: goto invalid_opc;
1682: }
1683: break;
1684: case 0x1D:
1685: /* HW_MTPR (PALcode) */
1686: #if defined (CONFIG_USER_ONLY)
1687: goto invalid_opc;
1688: #else
1689: if (!ctx->pal_mode)
1690: goto invalid_opc;
1691: gen_load_ir(ctx, ra, 0);
1692: gen_op_mtpr(insn & 0xFF);
1693: ret = 2;
1694: break;
1695: #endif
1696: case 0x1E:
1697: /* HW_REI (PALcode) */
1698: #if defined (CONFIG_USER_ONLY)
1699: goto invalid_opc;
1700: #else
1701: if (!ctx->pal_mode)
1702: goto invalid_opc;
1703: if (rb == 31) {
1704: /* "Old" alpha */
1705: gen_op_hw_rei();
1706: } else {
1707: gen_load_ir(ctx, rb, 0);
1708: gen_set_uT1(ctx, (((int64_t)insn << 51) >> 51));
1709: gen_op_addq();
1710: gen_op_hw_ret();
1711: }
1712: ret = 2;
1713: break;
1714: #endif
1715: case 0x1F:
1716: /* HW_ST (PALcode) */
1717: #if defined (CONFIG_USER_ONLY)
1718: goto invalid_opc;
1719: #else
1720: if (!ctx->pal_mode)
1721: goto invalid_opc;
1722: gen_load_ir(ctx, rb, 0);
1723: gen_set_sT1(ctx, disp12);
1724: gen_op_addq();
1725: gen_load_ir(ctx, ra, 1);
1726: switch ((insn >> 12) & 0xF) {
1727: case 0x0:
1728: /* Longword physical access */
1729: gen_op_stl_raw();
1730: break;
1731: case 0x1:
1732: /* Quadword physical access */
1733: gen_op_stq_raw();
1734: break;
1735: case 0x2:
1736: /* Longword physical access with lock */
1737: gen_op_stl_c_raw();
1738: break;
1739: case 0x3:
1740: /* Quadword physical access with lock */
1741: gen_op_stq_c_raw();
1742: break;
1743: case 0x4:
1744: /* Longword virtual access */
1745: gen_op_st_phys_to_virt();
1746: gen_op_stl_raw();
1747: break;
1748: case 0x5:
1749: /* Quadword virtual access */
1750: gen_op_st_phys_to_virt();
1751: gen_op_stq_raw();
1752: break;
1753: case 0x6:
1754: /* Invalid */
1755: goto invalid_opc;
1756: case 0x7:
1757: /* Invalid */
1758: goto invalid_opc;
1759: case 0x8:
1760: /* Invalid */
1761: goto invalid_opc;
1762: case 0x9:
1763: /* Invalid */
1764: goto invalid_opc;
1765: case 0xA:
1766: /* Invalid */
1767: goto invalid_opc;
1768: case 0xB:
1769: /* Invalid */
1770: goto invalid_opc;
1771: case 0xC:
1772: /* Longword virtual access with alternate access mode */
1773: gen_op_set_alt_mode();
1774: gen_op_st_phys_to_virt();
1775: gen_op_ldl_raw();
1776: gen_op_restore_mode();
1777: break;
1778: case 0xD:
1779: /* Quadword virtual access with alternate access mode */
1780: gen_op_set_alt_mode();
1781: gen_op_st_phys_to_virt();
1782: gen_op_ldq_raw();
1783: gen_op_restore_mode();
1784: break;
1785: case 0xE:
1786: /* Invalid */
1787: goto invalid_opc;
1788: case 0xF:
1789: /* Invalid */
1790: goto invalid_opc;
1791: }
1792: ret = 2;
1793: break;
1794: #endif
1795: case 0x20:
1796: /* LDF */
1797: #if 0 // TODO
1798: gen_load_fmem(ctx, &gen_ldf, ra, rb, disp16);
1799: #else
1800: goto invalid_opc;
1801: #endif
1802: break;
1803: case 0x21:
1804: /* LDG */
1805: #if 0 // TODO
1806: gen_load_fmem(ctx, &gen_ldg, ra, rb, disp16);
1807: #else
1808: goto invalid_opc;
1809: #endif
1810: break;
1811: case 0x22:
1812: /* LDS */
1813: gen_load_fmem(ctx, &gen_lds, ra, rb, disp16);
1814: break;
1815: case 0x23:
1816: /* LDT */
1817: gen_load_fmem(ctx, &gen_ldt, ra, rb, disp16);
1818: break;
1819: case 0x24:
1820: /* STF */
1821: #if 0 // TODO
1822: gen_store_fmem(ctx, &gen_stf, ra, rb, disp16);
1823: #else
1824: goto invalid_opc;
1825: #endif
1826: break;
1827: case 0x25:
1828: /* STG */
1829: #if 0 // TODO
1830: gen_store_fmem(ctx, &gen_stg, ra, rb, disp16);
1831: #else
1832: goto invalid_opc;
1833: #endif
1834: break;
1835: case 0x26:
1836: /* STS */
1837: gen_store_fmem(ctx, &gen_sts, ra, rb, disp16);
1838: break;
1839: case 0x27:
1840: /* STT */
1841: gen_store_fmem(ctx, &gen_stt, ra, rb, disp16);
1842: break;
1843: case 0x28:
1844: /* LDL */
1845: gen_load_mem(ctx, &gen_ldl, ra, rb, disp16, 0);
1846: break;
1847: case 0x29:
1848: /* LDQ */
1849: gen_load_mem(ctx, &gen_ldq, ra, rb, disp16, 0);
1850: break;
1851: case 0x2A:
1852: /* LDL_L */
1853: gen_load_mem(ctx, &gen_ldl_l, ra, rb, disp16, 0);
1854: break;
1855: case 0x2B:
1856: /* LDQ_L */
1857: gen_load_mem(ctx, &gen_ldq_l, ra, rb, disp16, 0);
1858: break;
1859: case 0x2C:
1860: /* STL */
1861: gen_store_mem(ctx, &gen_stl, ra, rb, disp16, 0);
1862: break;
1863: case 0x2D:
1864: /* STQ */
1865: gen_store_mem(ctx, &gen_stq, ra, rb, disp16, 0);
1866: break;
1867: case 0x2E:
1868: /* STL_C */
1869: gen_store_mem(ctx, &gen_stl_c, ra, rb, disp16, 0);
1870: break;
1871: case 0x2F:
1872: /* STQ_C */
1873: gen_store_mem(ctx, &gen_stq_c, ra, rb, disp16, 0);
1874: break;
1875: case 0x30:
1876: /* BR */
1877: gen_set_uT0(ctx, ctx->pc);
1878: gen_store_ir(ctx, ra, 0);
1879: if (disp21 != 0) {
1880: gen_set_sT1(ctx, disp21 << 2);
1881: gen_op_addq();
1882: }
1883: gen_op_branch();
1884: ret = 1;
1885: break;
1886: case 0x31:
1887: /* FBEQ */
1888: gen_fbcond(ctx, &gen_op_cmpfeq, ra, disp16);
1889: ret = 1;
1890: break;
1891: case 0x32:
1892: /* FBLT */
1893: gen_fbcond(ctx, &gen_op_cmpflt, ra, disp16);
1894: ret = 1;
1895: break;
1896: case 0x33:
1897: /* FBLE */
1898: gen_fbcond(ctx, &gen_op_cmpfle, ra, disp16);
1899: ret = 1;
1900: break;
1901: case 0x34:
1902: /* BSR */
1903: gen_set_uT0(ctx, ctx->pc);
1904: gen_store_ir(ctx, ra, 0);
1905: if (disp21 != 0) {
1906: gen_set_sT1(ctx, disp21 << 2);
1907: gen_op_addq();
1908: }
1909: gen_op_branch();
1910: ret = 1;
1911: break;
1912: case 0x35:
1913: /* FBNE */
1914: gen_fbcond(ctx, &gen_op_cmpfne, ra, disp16);
1915: ret = 1;
1916: break;
1917: case 0x36:
1918: /* FBGE */
1919: gen_fbcond(ctx, &gen_op_cmpfge, ra, disp16);
1920: ret = 1;
1921: break;
1922: case 0x37:
1923: /* FBGT */
1924: gen_fbcond(ctx, &gen_op_cmpfgt, ra, disp16);
1925: ret = 1;
1926: break;
1927: case 0x38:
1928: /* BLBC */
1929: gen_bcond(ctx, &gen_op_cmplbc, ra, disp16);
1930: ret = 1;
1931: break;
1932: case 0x39:
1933: /* BEQ */
1934: gen_bcond(ctx, &gen_op_cmpeqz, ra, disp16);
1935: ret = 1;
1936: break;
1937: case 0x3A:
1938: /* BLT */
1939: gen_bcond(ctx, &gen_op_cmpltz, ra, disp16);
1940: ret = 1;
1941: break;
1942: case 0x3B:
1943: /* BLE */
1944: gen_bcond(ctx, &gen_op_cmplez, ra, disp16);
1945: ret = 1;
1946: break;
1947: case 0x3C:
1948: /* BLBS */
1949: gen_bcond(ctx, &gen_op_cmplbs, ra, disp16);
1950: ret = 1;
1951: break;
1952: case 0x3D:
1953: /* BNE */
1954: gen_bcond(ctx, &gen_op_cmpnez, ra, disp16);
1955: ret = 1;
1956: break;
1957: case 0x3E:
1958: /* BGE */
1959: gen_bcond(ctx, &gen_op_cmpgez, ra, disp16);
1960: ret = 1;
1961: break;
1962: case 0x3F:
1963: /* BGT */
1964: gen_bcond(ctx, &gen_op_cmpgtz, ra, disp16);
1965: ret = 1;
1966: break;
1967: invalid_opc:
1968: gen_invalid(ctx);
1969: ret = 3;
1970: break;
1971: }
1972:
1973: return ret;
1974: }
1975:
1976: static always_inline int gen_intermediate_code_internal (CPUState *env,
1977: TranslationBlock *tb,
1978: int search_pc)
1979: {
1980: #if defined ALPHA_DEBUG_DISAS
1981: static int insn_count;
1982: #endif
1983: DisasContext ctx, *ctxp = &ctx;
1984: target_ulong pc_start;
1985: uint32_t insn;
1986: uint16_t *gen_opc_end;
1987: int j, lj = -1;
1988: int ret;
1989:
1990: pc_start = tb->pc;
1991: gen_opc_ptr = gen_opc_buf;
1992: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1993: gen_opparam_ptr = gen_opparam_buf;
1994: nb_gen_labels = 0;
1995: ctx.pc = pc_start;
1996: ctx.amask = env->amask;
1997: #if defined (CONFIG_USER_ONLY)
1998: ctx.mem_idx = 0;
1999: #else
2000: ctx.mem_idx = ((env->ps >> 3) & 3);
2001: ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
2002: #endif
2003: for (ret = 0; ret == 0;) {
2004: if (env->nb_breakpoints > 0) {
2005: for(j = 0; j < env->nb_breakpoints; j++) {
2006: if (env->breakpoints[j] == ctx.pc) {
2007: gen_excp(&ctx, EXCP_DEBUG, 0);
2008: break;
2009: }
2010: }
2011: }
2012: if (search_pc) {
2013: j = gen_opc_ptr - gen_opc_buf;
2014: if (lj < j) {
2015: lj++;
2016: while (lj < j)
2017: gen_opc_instr_start[lj++] = 0;
2018: gen_opc_pc[lj] = ctx.pc;
2019: gen_opc_instr_start[lj] = 1;
2020: }
2021: }
2022: #if defined ALPHA_DEBUG_DISAS
2023: insn_count++;
2024: if (logfile != NULL) {
2025: fprintf(logfile, "pc " TARGET_FMT_lx " mem_idx %d\n",
2026: ctx.pc, ctx.mem_idx);
2027: }
2028: #endif
2029: insn = ldl_code(ctx.pc);
2030: #if defined ALPHA_DEBUG_DISAS
2031: insn_count++;
2032: if (logfile != NULL) {
2033: fprintf(logfile, "opcode %08x %d\n", insn, insn_count);
2034: }
2035: #endif
2036: ctx.pc += 4;
2037: ret = translate_one(ctxp, insn);
2038: if (ret != 0)
2039: break;
2040: /* if we reach a page boundary or are single stepping, stop
2041: * generation
2042: */
2043: if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
2044: (env->singlestep_enabled)) {
2045: break;
2046: }
2047: #if defined (DO_SINGLE_STEP)
2048: break;
2049: #endif
2050: }
2051: if (ret != 1 && ret != 3) {
2052: gen_update_pc(&ctx);
2053: }
2054: gen_op_reset_T0();
2055: #if defined (DO_TB_FLUSH)
2056: gen_op_tb_flush();
2057: #endif
2058: /* Generate the return instruction */
2059: gen_op_exit_tb();
2060: *gen_opc_ptr = INDEX_op_end;
2061: if (search_pc) {
2062: j = gen_opc_ptr - gen_opc_buf;
2063: lj++;
2064: while (lj <= j)
2065: gen_opc_instr_start[lj++] = 0;
2066: } else {
2067: tb->size = ctx.pc - pc_start;
2068: }
2069: #if defined ALPHA_DEBUG_DISAS
2070: if (loglevel & CPU_LOG_TB_CPU) {
2071: cpu_dump_state(env, logfile, fprintf, 0);
2072: }
2073: if (loglevel & CPU_LOG_TB_IN_ASM) {
2074: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2075: target_disas(logfile, pc_start, ctx.pc - pc_start, 1);
2076: fprintf(logfile, "\n");
2077: }
2078: if (loglevel & CPU_LOG_TB_OP) {
2079: fprintf(logfile, "OP:\n");
2080: dump_ops(gen_opc_buf, gen_opparam_buf);
2081: fprintf(logfile, "\n");
2082: }
2083: #endif
2084:
2085: return 0;
2086: }
2087:
2088: int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2089: {
2090: return gen_intermediate_code_internal(env, tb, 0);
2091: }
2092:
2093: int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2094: {
2095: return gen_intermediate_code_internal(env, tb, 1);
2096: }
2097:
2098: CPUAlphaState * cpu_alpha_init (const char *cpu_model)
2099: {
2100: CPUAlphaState *env;
2101: uint64_t hwpcb;
2102:
2103: env = qemu_mallocz(sizeof(CPUAlphaState));
2104: if (!env)
2105: return NULL;
2106: cpu_exec_init(env);
2107: tlb_flush(env, 1);
2108: /* XXX: should not be hardcoded */
2109: env->implver = IMPLVER_2106x;
2110: env->ps = 0x1F00;
2111: #if defined (CONFIG_USER_ONLY)
2112: env->ps |= 1 << 3;
2113: #endif
2114: pal_init(env);
2115: /* Initialize IPR */
2116: hwpcb = env->ipr[IPR_PCBB];
2117: env->ipr[IPR_ASN] = 0;
2118: env->ipr[IPR_ASTEN] = 0;
2119: env->ipr[IPR_ASTSR] = 0;
2120: env->ipr[IPR_DATFX] = 0;
2121: /* XXX: fix this */
2122: // env->ipr[IPR_ESP] = ldq_raw(hwpcb + 8);
2123: // env->ipr[IPR_KSP] = ldq_raw(hwpcb + 0);
2124: // env->ipr[IPR_SSP] = ldq_raw(hwpcb + 16);
2125: // env->ipr[IPR_USP] = ldq_raw(hwpcb + 24);
2126: env->ipr[IPR_FEN] = 0;
2127: env->ipr[IPR_IPL] = 31;
2128: env->ipr[IPR_MCES] = 0;
2129: env->ipr[IPR_PERFMON] = 0; /* Implementation specific */
2130: // env->ipr[IPR_PTBR] = ldq_raw(hwpcb + 32);
2131: env->ipr[IPR_SISR] = 0;
2132: env->ipr[IPR_VIRBND] = -1ULL;
2133:
2134: return env;
2135: }
2136:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.