|
|
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
1.1.1.3 root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
19:
20: #include <stdint.h>
21: #include <stdlib.h>
22: #include <stdio.h>
23:
24: #include "cpu.h"
25: #include "disas.h"
1.1.1.2 root 26: #include "host-utils.h"
27: #include "tcg-op.h"
28: #include "qemu-common.h"
29:
30: #include "helper.h"
31: #define GEN_HELPER 1
32: #include "helper.h"
1.1 root 33:
1.1.1.5 root 34: #undef ALPHA_DEBUG_DISAS
35: #define CONFIG_SOFTFLOAT_INLINE
1.1.1.2 root 36:
37: #ifdef ALPHA_DEBUG_DISAS
1.1.1.5 root 38: # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
1.1.1.2 root 39: #else
40: # define LOG_DISAS(...) do { } while (0)
41: #endif
1.1 root 42:
43: typedef struct DisasContext DisasContext;
44: struct DisasContext {
1.1.1.5 root 45: struct TranslationBlock *tb;
46: CPUAlphaState *env;
1.1 root 47: uint64_t pc;
48: int mem_idx;
1.1.1.5 root 49:
50: /* Current rounding mode for this TB. */
51: int tb_rm;
52: /* Current flush-to-zero setting for this TB. */
53: int tb_ftz;
1.1 root 54: };
55:
1.1.1.5 root 56: /* Return values from translate_one, indicating the state of the TB.
57: Note that zero indicates that we are not exiting the TB. */
58:
59: typedef enum {
60: NO_EXIT,
61:
62: /* We have emitted one or more goto_tb. No fixup required. */
63: EXIT_GOTO_TB,
64:
65: /* We are not using a goto_tb (for whatever reason), but have updated
66: the PC (for whatever reason), so there's no need to do it again on
67: exiting the TB. */
68: EXIT_PC_UPDATED,
69:
70: /* We are exiting the TB, but have neither emitted a goto_tb, nor
71: updated the PC for the next instruction to be executed. */
72: EXIT_PC_STALE,
73:
74: /* We are ending the TB with a noreturn function call, e.g. longjmp.
75: No following code will be executed. */
76: EXIT_NORETURN,
77: } ExitStatus;
78:
1.1.1.2 root 79: /* global register indexes */
80: static TCGv_ptr cpu_env;
81: static TCGv cpu_ir[31];
82: static TCGv cpu_fir[31];
83: static TCGv cpu_pc;
1.1.1.5 root 84: static TCGv cpu_lock_addr;
85: static TCGv cpu_lock_st_addr;
86: static TCGv cpu_lock_value;
1.1.1.6 ! root 87: static TCGv cpu_unique;
! 88: #ifndef CONFIG_USER_ONLY
! 89: static TCGv cpu_sysval;
! 90: static TCGv cpu_usp;
1.1.1.5 root 91: #endif
1.1 root 92:
1.1.1.2 root 93: /* register names */
94: static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
1.1 root 95:
1.1.1.2 root 96: #include "gen-icount.h"
1.1 root 97:
1.1.1.2 root 98: static void alpha_translate_init(void)
1.1 root 99: {
1.1.1.2 root 100: int i;
101: char *p;
102: static int done_init = 0;
1.1 root 103:
1.1.1.2 root 104: if (done_init)
105: return;
1.1 root 106:
1.1.1.2 root 107: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1 root 108:
1.1.1.2 root 109: p = cpu_reg_names;
110: for (i = 0; i < 31; i++) {
111: sprintf(p, "ir%d", i);
112: cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
113: offsetof(CPUState, ir[i]), p);
114: p += (i < 10) ? 4 : 5;
1.1 root 115:
1.1.1.2 root 116: sprintf(p, "fir%d", i);
117: cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
118: offsetof(CPUState, fir[i]), p);
119: p += (i < 10) ? 5 : 6;
1.1 root 120: }
121:
1.1.1.2 root 122: cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
123: offsetof(CPUState, pc), "pc");
1.1 root 124:
1.1.1.5 root 125: cpu_lock_addr = tcg_global_mem_new_i64(TCG_AREG0,
126: offsetof(CPUState, lock_addr),
127: "lock_addr");
128: cpu_lock_st_addr = tcg_global_mem_new_i64(TCG_AREG0,
129: offsetof(CPUState, lock_st_addr),
130: "lock_st_addr");
131: cpu_lock_value = tcg_global_mem_new_i64(TCG_AREG0,
132: offsetof(CPUState, lock_value),
133: "lock_value");
134:
1.1.1.6 ! root 135: cpu_unique = tcg_global_mem_new_i64(TCG_AREG0,
! 136: offsetof(CPUState, unique), "unique");
! 137: #ifndef CONFIG_USER_ONLY
! 138: cpu_sysval = tcg_global_mem_new_i64(TCG_AREG0,
! 139: offsetof(CPUState, sysval), "sysval");
! 140: cpu_usp = tcg_global_mem_new_i64(TCG_AREG0,
! 141: offsetof(CPUState, usp), "usp");
1.1.1.5 root 142: #endif
1.1 root 143:
1.1.1.2 root 144: /* register helpers */
145: #define GEN_HELPER 2
146: #include "helper.h"
1.1 root 147:
1.1.1.2 root 148: done_init = 1;
149: }
1.1 root 150:
1.1.1.6 ! root 151: static void gen_excp_1(int exception, int error_code)
1.1 root 152: {
1.1.1.2 root 153: TCGv_i32 tmp1, tmp2;
154:
155: tmp1 = tcg_const_i32(exception);
156: tmp2 = tcg_const_i32(error_code);
157: gen_helper_excp(tmp1, tmp2);
158: tcg_temp_free_i32(tmp2);
159: tcg_temp_free_i32(tmp1);
1.1.1.6 ! root 160: }
1.1.1.5 root 161:
1.1.1.6 ! root 162: static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
! 163: {
! 164: tcg_gen_movi_i64(cpu_pc, ctx->pc);
! 165: gen_excp_1(exception, error_code);
1.1.1.5 root 166: return EXIT_NORETURN;
1.1 root 167: }
168:
1.1.1.5 root 169: static inline ExitStatus gen_invalid(DisasContext *ctx)
1.1 root 170: {
1.1.1.5 root 171: return gen_excp(ctx, EXCP_OPCDEC, 0);
1.1 root 172: }
173:
1.1.1.4 root 174: static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
1.1 root 175: {
1.1.1.2 root 176: TCGv tmp = tcg_temp_new();
177: TCGv_i32 tmp32 = tcg_temp_new_i32();
178: tcg_gen_qemu_ld32u(tmp, t1, flags);
179: tcg_gen_trunc_i64_i32(tmp32, tmp);
180: gen_helper_memory_to_f(t0, tmp32);
181: tcg_temp_free_i32(tmp32);
182: tcg_temp_free(tmp);
1.1 root 183: }
184:
1.1.1.4 root 185: static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
1.1 root 186: {
1.1.1.2 root 187: TCGv tmp = tcg_temp_new();
188: tcg_gen_qemu_ld64(tmp, t1, flags);
189: gen_helper_memory_to_g(t0, tmp);
190: tcg_temp_free(tmp);
1.1 root 191: }
192:
1.1.1.4 root 193: static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
1.1 root 194: {
1.1.1.2 root 195: TCGv tmp = tcg_temp_new();
196: TCGv_i32 tmp32 = tcg_temp_new_i32();
197: tcg_gen_qemu_ld32u(tmp, t1, flags);
198: tcg_gen_trunc_i64_i32(tmp32, tmp);
199: gen_helper_memory_to_s(t0, tmp32);
200: tcg_temp_free_i32(tmp32);
201: tcg_temp_free(tmp);
1.1 root 202: }
203:
1.1.1.4 root 204: static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
1.1 root 205: {
1.1.1.2 root 206: tcg_gen_qemu_ld32s(t0, t1, flags);
1.1.1.5 root 207: tcg_gen_mov_i64(cpu_lock_addr, t1);
208: tcg_gen_mov_i64(cpu_lock_value, t0);
1.1 root 209: }
210:
1.1.1.4 root 211: static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
1.1 root 212: {
1.1.1.2 root 213: tcg_gen_qemu_ld64(t0, t1, flags);
1.1.1.5 root 214: tcg_gen_mov_i64(cpu_lock_addr, t1);
215: tcg_gen_mov_i64(cpu_lock_value, t0);
1.1 root 216: }
217:
1.1.1.4 root 218: static inline void gen_load_mem(DisasContext *ctx,
219: void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
220: int flags),
221: int ra, int rb, int32_t disp16, int fp,
222: int clear)
1.1 root 223: {
1.1.1.5 root 224: TCGv addr, va;
1.1.1.2 root 225:
1.1.1.5 root 226: /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
227: prefetches, which we can treat as nops. No worries about
228: missed exceptions here. */
229: if (unlikely(ra == 31)) {
1.1.1.2 root 230: return;
1.1.1.5 root 231: }
1.1.1.2 root 232:
233: addr = tcg_temp_new();
234: if (rb != 31) {
235: tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
1.1.1.5 root 236: if (clear) {
1.1.1.2 root 237: tcg_gen_andi_i64(addr, addr, ~0x7);
1.1.1.5 root 238: }
1.1 root 239: } else {
1.1.1.5 root 240: if (clear) {
1.1.1.2 root 241: disp16 &= ~0x7;
1.1.1.5 root 242: }
1.1.1.2 root 243: tcg_gen_movi_i64(addr, disp16);
1.1 root 244: }
1.1.1.5 root 245:
246: va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
247: tcg_gen_qemu_load(va, addr, ctx->mem_idx);
248:
1.1.1.2 root 249: tcg_temp_free(addr);
1.1 root 250: }
251:
1.1.1.4 root 252: static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
1.1 root 253: {
1.1.1.2 root 254: TCGv_i32 tmp32 = tcg_temp_new_i32();
255: TCGv tmp = tcg_temp_new();
256: gen_helper_f_to_memory(tmp32, t0);
257: tcg_gen_extu_i32_i64(tmp, tmp32);
258: tcg_gen_qemu_st32(tmp, t1, flags);
259: tcg_temp_free(tmp);
260: tcg_temp_free_i32(tmp32);
1.1 root 261: }
262:
1.1.1.4 root 263: static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
1.1 root 264: {
1.1.1.2 root 265: TCGv tmp = tcg_temp_new();
266: gen_helper_g_to_memory(tmp, t0);
267: tcg_gen_qemu_st64(tmp, t1, flags);
268: tcg_temp_free(tmp);
1.1 root 269: }
270:
1.1.1.4 root 271: static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
1.1 root 272: {
1.1.1.2 root 273: TCGv_i32 tmp32 = tcg_temp_new_i32();
274: TCGv tmp = tcg_temp_new();
275: gen_helper_s_to_memory(tmp32, t0);
276: tcg_gen_extu_i32_i64(tmp, tmp32);
277: tcg_gen_qemu_st32(tmp, t1, flags);
278: tcg_temp_free(tmp);
279: tcg_temp_free_i32(tmp32);
1.1 root 280: }
281:
1.1.1.4 root 282: static inline void gen_store_mem(DisasContext *ctx,
283: void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
284: int flags),
285: int ra, int rb, int32_t disp16, int fp,
1.1.1.5 root 286: int clear)
1.1 root 287: {
1.1.1.5 root 288: TCGv addr, va;
289:
290: addr = tcg_temp_new();
1.1.1.2 root 291: if (rb != 31) {
292: tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
1.1.1.5 root 293: if (clear) {
1.1.1.2 root 294: tcg_gen_andi_i64(addr, addr, ~0x7);
1.1.1.5 root 295: }
1.1.1.2 root 296: } else {
1.1.1.5 root 297: if (clear) {
1.1.1.2 root 298: disp16 &= ~0x7;
1.1.1.5 root 299: }
1.1.1.2 root 300: tcg_gen_movi_i64(addr, disp16);
1.1 root 301: }
1.1.1.5 root 302:
303: if (ra == 31) {
304: va = tcg_const_i64(0);
305: } else {
306: va = (fp ? cpu_fir[ra] : cpu_ir[ra]);
1.1 root 307: }
1.1.1.5 root 308: tcg_gen_qemu_store(va, addr, ctx->mem_idx);
309:
1.1.1.2 root 310: tcg_temp_free(addr);
1.1.1.5 root 311: if (ra == 31) {
312: tcg_temp_free(va);
313: }
1.1 root 314: }
315:
1.1.1.5 root 316: static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
317: int32_t disp16, int quad)
1.1 root 318: {
1.1.1.5 root 319: TCGv addr;
1.1.1.2 root 320:
1.1.1.5 root 321: if (ra == 31) {
322: /* ??? Don't bother storing anything. The user can't tell
323: the difference, since the zero register always reads zero. */
324: return NO_EXIT;
325: }
326:
327: #if defined(CONFIG_USER_ONLY)
328: addr = cpu_lock_st_addr;
329: #else
1.1.1.6 ! root 330: addr = tcg_temp_local_new();
1.1.1.5 root 331: #endif
332:
333: if (rb != 31) {
334: tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
1.1 root 335: } else {
1.1.1.5 root 336: tcg_gen_movi_i64(addr, disp16);
1.1.1.2 root 337: }
1.1.1.5 root 338:
339: #if defined(CONFIG_USER_ONLY)
340: /* ??? This is handled via a complicated version of compare-and-swap
341: in the cpu_loop. Hopefully one day we'll have a real CAS opcode
342: in TCG so that this isn't necessary. */
343: return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
344: #else
345: /* ??? In system mode we are never multi-threaded, so CAS can be
346: implemented via a non-atomic load-compare-store sequence. */
347: {
348: int lab_fail, lab_done;
349: TCGv val;
350:
351: lab_fail = gen_new_label();
352: lab_done = gen_new_label();
1.1.1.6 ! root 353: tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
1.1.1.5 root 354:
355: val = tcg_temp_new();
356: if (quad) {
357: tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
358: } else {
359: tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
360: }
1.1.1.6 ! root 361: tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
1.1.1.5 root 362:
363: if (quad) {
364: tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
365: } else {
366: tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
367: }
368: tcg_gen_movi_i64(cpu_ir[ra], 1);
369: tcg_gen_br(lab_done);
370:
371: gen_set_label(lab_fail);
372: tcg_gen_movi_i64(cpu_ir[ra], 0);
373:
374: gen_set_label(lab_done);
375: tcg_gen_movi_i64(cpu_lock_addr, -1);
376:
377: tcg_temp_free(addr);
378: return NO_EXIT;
379: }
380: #endif
381: }
382:
383: static int use_goto_tb(DisasContext *ctx, uint64_t dest)
384: {
385: /* Check for the dest on the same page as the start of the TB. We
386: also want to suppress goto_tb in the case of single-steping and IO. */
387: return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
388: && !ctx->env->singlestep_enabled
389: && !(ctx->tb->cflags & CF_LAST_IO));
1.1 root 390: }
391:
1.1.1.5 root 392: static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
1.1 root 393: {
1.1.1.5 root 394: uint64_t dest = ctx->pc + (disp << 2);
1.1.1.2 root 395:
396: if (ra != 31) {
1.1.1.5 root 397: tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
1.1 root 398: }
1.1.1.5 root 399:
400: /* Notice branch-to-next; used to initialize RA with the PC. */
401: if (disp == 0) {
402: return 0;
403: } else if (use_goto_tb(ctx, dest)) {
404: tcg_gen_goto_tb(0);
405: tcg_gen_movi_i64(cpu_pc, dest);
1.1.1.6 ! root 406: tcg_gen_exit_tb((tcg_target_long)ctx->tb);
1.1.1.5 root 407: return EXIT_GOTO_TB;
408: } else {
409: tcg_gen_movi_i64(cpu_pc, dest);
410: return EXIT_PC_UPDATED;
411: }
412: }
413:
414: static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond,
415: TCGv cmp, int32_t disp)
416: {
417: uint64_t dest = ctx->pc + (disp << 2);
418: int lab_true = gen_new_label();
419:
420: if (use_goto_tb(ctx, dest)) {
421: tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
422:
423: tcg_gen_goto_tb(0);
424: tcg_gen_movi_i64(cpu_pc, ctx->pc);
1.1.1.6 ! root 425: tcg_gen_exit_tb((tcg_target_long)ctx->tb);
1.1.1.5 root 426:
427: gen_set_label(lab_true);
428: tcg_gen_goto_tb(1);
429: tcg_gen_movi_i64(cpu_pc, dest);
1.1.1.6 ! root 430: tcg_gen_exit_tb((tcg_target_long)ctx->tb + 1);
1.1.1.5 root 431:
432: return EXIT_GOTO_TB;
433: } else {
434: int lab_over = gen_new_label();
435:
436: /* ??? Consider using either
437: movi pc, next
438: addi tmp, pc, disp
439: movcond pc, cond, 0, tmp, pc
440: or
441: setcond tmp, cond, 0
442: movi pc, next
443: neg tmp, tmp
444: andi tmp, tmp, disp
445: add pc, pc, tmp
446: The current diamond subgraph surely isn't efficient. */
447:
448: tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
449: tcg_gen_movi_i64(cpu_pc, ctx->pc);
450: tcg_gen_br(lab_over);
451: gen_set_label(lab_true);
452: tcg_gen_movi_i64(cpu_pc, dest);
453: gen_set_label(lab_over);
454:
455: return EXIT_PC_UPDATED;
456: }
457: }
458:
459: static ExitStatus gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
460: int32_t disp, int mask)
461: {
462: TCGv cmp_tmp;
463:
464: if (unlikely(ra == 31)) {
465: cmp_tmp = tcg_const_i64(0);
466: } else {
467: cmp_tmp = tcg_temp_new();
468: if (mask) {
469: tcg_gen_andi_i64(cmp_tmp, cpu_ir[ra], 1);
470: } else {
471: tcg_gen_mov_i64(cmp_tmp, cpu_ir[ra]);
472: }
473: }
474:
475: return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
476: }
477:
478: /* Fold -0.0 for comparison with COND. */
479:
480: static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
481: {
482: uint64_t mzero = 1ull << 63;
483:
484: switch (cond) {
485: case TCG_COND_LE:
486: case TCG_COND_GT:
487: /* For <= or >, the -0.0 value directly compares the way we want. */
488: tcg_gen_mov_i64(dest, src);
1.1.1.2 root 489: break;
1.1.1.5 root 490:
491: case TCG_COND_EQ:
492: case TCG_COND_NE:
493: /* For == or !=, we can simply mask off the sign bit and compare. */
494: tcg_gen_andi_i64(dest, src, mzero - 1);
1.1.1.2 root 495: break;
1.1.1.5 root 496:
497: case TCG_COND_GE:
498: case TCG_COND_LT:
499: /* For >= or <, map -0.0 to +0.0 via comparison and mask. */
500: tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero);
501: tcg_gen_neg_i64(dest, dest);
502: tcg_gen_and_i64(dest, dest, src);
1.1.1.2 root 503: break;
1.1.1.5 root 504:
1.1.1.2 root 505: default:
506: abort();
507: }
1.1 root 508: }
509:
1.1.1.5 root 510: static ExitStatus gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
511: int32_t disp)
1.1 root 512: {
1.1.1.5 root 513: TCGv cmp_tmp;
514:
515: if (unlikely(ra == 31)) {
516: /* Very uncommon case, but easier to optimize it to an integer
517: comparison than continuing with the floating point comparison. */
518: return gen_bcond(ctx, cond, ra, disp, 0);
519: }
520:
521: cmp_tmp = tcg_temp_new();
522: gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
523: return gen_bcond_internal(ctx, cond, cmp_tmp, disp);
524: }
525:
526: static void gen_cmov(TCGCond cond, int ra, int rb, int rc,
527: int islit, uint8_t lit, int mask)
528: {
529: TCGCond inv_cond = tcg_invert_cond(cond);
1.1.1.2 root 530: int l1;
1.1 root 531:
1.1.1.2 root 532: if (unlikely(rc == 31))
533: return;
1.1 root 534:
1.1.1.2 root 535: l1 = gen_new_label();
1.1 root 536:
1.1.1.2 root 537: if (ra != 31) {
538: if (mask) {
539: TCGv tmp = tcg_temp_new();
540: tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
541: tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
542: tcg_temp_free(tmp);
543: } else
544: tcg_gen_brcondi_i64(inv_cond, cpu_ir[ra], 0, l1);
545: } else {
546: /* Very uncommon case - Do not bother to optimize. */
547: TCGv tmp = tcg_const_i64(0);
548: tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
549: tcg_temp_free(tmp);
550: }
1.1 root 551:
1.1.1.2 root 552: if (islit)
553: tcg_gen_movi_i64(cpu_ir[rc], lit);
554: else
555: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
556: gen_set_label(l1);
1.1 root 557: }
558:
1.1.1.5 root 559: static void gen_fcmov(TCGCond cond, int ra, int rb, int rc)
560: {
561: TCGv cmp_tmp;
562: int l1;
563:
564: if (unlikely(rc == 31)) {
565: return;
566: }
567:
568: cmp_tmp = tcg_temp_new();
569: if (unlikely(ra == 31)) {
570: tcg_gen_movi_i64(cmp_tmp, 0);
571: } else {
572: gen_fold_mzero(cond, cmp_tmp, cpu_fir[ra]);
573: }
574:
575: l1 = gen_new_label();
576: tcg_gen_brcondi_i64(tcg_invert_cond(cond), cmp_tmp, 0, l1);
577: tcg_temp_free(cmp_tmp);
578:
579: if (rb != 31)
580: tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[rb]);
581: else
582: tcg_gen_movi_i64(cpu_fir[rc], 0);
583: gen_set_label(l1);
1.1.1.2 root 584: }
1.1.1.5 root 585:
586: #define QUAL_RM_N 0x080 /* Round mode nearest even */
587: #define QUAL_RM_C 0x000 /* Round mode chopped */
588: #define QUAL_RM_M 0x040 /* Round mode minus infinity */
589: #define QUAL_RM_D 0x0c0 /* Round mode dynamic */
590: #define QUAL_RM_MASK 0x0c0
591:
592: #define QUAL_U 0x100 /* Underflow enable (fp output) */
593: #define QUAL_V 0x100 /* Overflow enable (int output) */
594: #define QUAL_S 0x400 /* Software completion enable */
595: #define QUAL_I 0x200 /* Inexact detection enable */
596:
597: static void gen_qual_roundmode(DisasContext *ctx, int fn11)
598: {
599: TCGv_i32 tmp;
600:
601: fn11 &= QUAL_RM_MASK;
602: if (fn11 == ctx->tb_rm) {
603: return;
604: }
605: ctx->tb_rm = fn11;
606:
607: tmp = tcg_temp_new_i32();
608: switch (fn11) {
609: case QUAL_RM_N:
610: tcg_gen_movi_i32(tmp, float_round_nearest_even);
611: break;
612: case QUAL_RM_C:
613: tcg_gen_movi_i32(tmp, float_round_to_zero);
614: break;
615: case QUAL_RM_M:
616: tcg_gen_movi_i32(tmp, float_round_down);
617: break;
618: case QUAL_RM_D:
619: tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_dyn_round));
620: break;
621: }
622:
623: #if defined(CONFIG_SOFTFLOAT_INLINE)
624: /* ??? The "softfloat.h" interface is to call set_float_rounding_mode.
625: With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
626: sets the one field. */
627: tcg_gen_st8_i32(tmp, cpu_env,
628: offsetof(CPUState, fp_status.float_rounding_mode));
629: #else
630: gen_helper_setroundmode(tmp);
631: #endif
632:
633: tcg_temp_free_i32(tmp);
634: }
635:
636: static void gen_qual_flushzero(DisasContext *ctx, int fn11)
637: {
638: TCGv_i32 tmp;
639:
640: fn11 &= QUAL_U;
641: if (fn11 == ctx->tb_ftz) {
642: return;
643: }
644: ctx->tb_ftz = fn11;
645:
646: tmp = tcg_temp_new_i32();
647: if (fn11) {
648: /* Underflow is enabled, use the FPCR setting. */
649: tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUState, fpcr_flush_to_zero));
650: } else {
651: /* Underflow is disabled, force flush-to-zero. */
652: tcg_gen_movi_i32(tmp, 1);
653: }
654:
655: #if defined(CONFIG_SOFTFLOAT_INLINE)
656: tcg_gen_st8_i32(tmp, cpu_env,
657: offsetof(CPUState, fp_status.flush_to_zero));
658: #else
659: gen_helper_setflushzero(tmp);
660: #endif
661:
662: tcg_temp_free_i32(tmp);
663: }
664:
665: static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
666: {
667: TCGv val = tcg_temp_new();
668: if (reg == 31) {
669: tcg_gen_movi_i64(val, 0);
670: } else if (fn11 & QUAL_S) {
671: gen_helper_ieee_input_s(val, cpu_fir[reg]);
672: } else if (is_cmp) {
673: gen_helper_ieee_input_cmp(val, cpu_fir[reg]);
674: } else {
675: gen_helper_ieee_input(val, cpu_fir[reg]);
676: }
677: return val;
678: }
679:
680: static void gen_fp_exc_clear(void)
681: {
682: #if defined(CONFIG_SOFTFLOAT_INLINE)
683: TCGv_i32 zero = tcg_const_i32(0);
684: tcg_gen_st8_i32(zero, cpu_env,
685: offsetof(CPUState, fp_status.float_exception_flags));
686: tcg_temp_free_i32(zero);
687: #else
688: gen_helper_fp_exc_clear();
689: #endif
690: }
691:
692: static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
693: {
694: /* ??? We ought to be able to do something with imprecise exceptions.
695: E.g. notice we're still in the trap shadow of something within the
696: TB and do not generate the code to signal the exception; end the TB
697: when an exception is forced to arrive, either by consumption of a
698: register value or TRAPB or EXCB. */
699: TCGv_i32 exc = tcg_temp_new_i32();
700: TCGv_i32 reg;
701:
702: #if defined(CONFIG_SOFTFLOAT_INLINE)
703: tcg_gen_ld8u_i32(exc, cpu_env,
704: offsetof(CPUState, fp_status.float_exception_flags));
705: #else
706: gen_helper_fp_exc_get(exc);
707: #endif
708:
709: if (ignore) {
710: tcg_gen_andi_i32(exc, exc, ~ignore);
711: }
712:
713: /* ??? Pass in the regno of the destination so that the helper can
714: set EXC_MASK, which contains a bitmask of destination registers
715: that have caused arithmetic traps. A simple userspace emulation
716: does not require this. We do need it for a guest kernel's entArith,
717: or if we were to do something clever with imprecise exceptions. */
718: reg = tcg_const_i32(rc + 32);
719:
720: if (fn11 & QUAL_S) {
721: gen_helper_fp_exc_raise_s(exc, reg);
722: } else {
723: gen_helper_fp_exc_raise(exc, reg);
724: }
725:
726: tcg_temp_free_i32(reg);
727: tcg_temp_free_i32(exc);
728: }
729:
730: static inline void gen_fp_exc_raise(int rc, int fn11)
731: {
732: gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
733: }
734:
735: static void gen_fcvtlq(int rb, int rc)
736: {
737: if (unlikely(rc == 31)) {
738: return;
739: }
740: if (unlikely(rb == 31)) {
741: tcg_gen_movi_i64(cpu_fir[rc], 0);
742: } else {
743: TCGv tmp = tcg_temp_new();
744:
745: /* The arithmetic right shift here, plus the sign-extended mask below
746: yields a sign-extended result without an explicit ext32s_i64. */
747: tcg_gen_sari_i64(tmp, cpu_fir[rb], 32);
748: tcg_gen_shri_i64(cpu_fir[rc], cpu_fir[rb], 29);
749: tcg_gen_andi_i64(tmp, tmp, (int32_t)0xc0000000);
750: tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rc], 0x3fffffff);
751: tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
752:
753: tcg_temp_free(tmp);
754: }
755: }
756:
757: static void gen_fcvtql(int rb, int rc)
758: {
759: if (unlikely(rc == 31)) {
760: return;
761: }
762: if (unlikely(rb == 31)) {
763: tcg_gen_movi_i64(cpu_fir[rc], 0);
764: } else {
765: TCGv tmp = tcg_temp_new();
766:
767: tcg_gen_andi_i64(tmp, cpu_fir[rb], 0xC0000000);
768: tcg_gen_andi_i64(cpu_fir[rc], cpu_fir[rb], 0x3FFFFFFF);
769: tcg_gen_shli_i64(tmp, tmp, 32);
770: tcg_gen_shli_i64(cpu_fir[rc], cpu_fir[rc], 29);
771: tcg_gen_or_i64(cpu_fir[rc], cpu_fir[rc], tmp);
772:
773: tcg_temp_free(tmp);
774: }
775: }
776:
777: static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
778: {
779: if (rb != 31) {
780: int lab = gen_new_label();
781: TCGv tmp = tcg_temp_new();
782:
783: tcg_gen_ext32s_i64(tmp, cpu_fir[rb]);
784: tcg_gen_brcond_i64(TCG_COND_EQ, tmp, cpu_fir[rb], lab);
785: gen_excp(ctx, EXCP_ARITH, EXC_M_IOV);
786:
787: gen_set_label(lab);
788: }
789: gen_fcvtql(rb, rc);
790: }
791:
792: #define FARITH2(name) \
793: static inline void glue(gen_f, name)(int rb, int rc) \
794: { \
795: if (unlikely(rc == 31)) { \
796: return; \
797: } \
798: if (rb != 31) { \
799: gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
800: } else { \
801: TCGv tmp = tcg_const_i64(0); \
802: gen_helper_ ## name (cpu_fir[rc], tmp); \
803: tcg_temp_free(tmp); \
804: } \
805: }
806:
807: /* ??? VAX instruction qualifiers ignored. */
1.1.1.2 root 808: FARITH2(sqrtf)
809: FARITH2(sqrtg)
810: FARITH2(cvtgf)
811: FARITH2(cvtgq)
812: FARITH2(cvtqf)
813: FARITH2(cvtqg)
1.1.1.5 root 814:
815: static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
816: int rb, int rc, int fn11)
817: {
818: TCGv vb;
819:
820: /* ??? This is wrong: the instruction is not a nop, it still may
821: raise exceptions. */
822: if (unlikely(rc == 31)) {
823: return;
824: }
825:
826: gen_qual_roundmode(ctx, fn11);
827: gen_qual_flushzero(ctx, fn11);
828: gen_fp_exc_clear();
829:
830: vb = gen_ieee_input(rb, fn11, 0);
831: helper(cpu_fir[rc], vb);
832: tcg_temp_free(vb);
833:
834: gen_fp_exc_raise(rc, fn11);
835: }
836:
837: #define IEEE_ARITH2(name) \
838: static inline void glue(gen_f, name)(DisasContext *ctx, \
839: int rb, int rc, int fn11) \
840: { \
841: gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
842: }
843: IEEE_ARITH2(sqrts)
844: IEEE_ARITH2(sqrtt)
845: IEEE_ARITH2(cvtst)
846: IEEE_ARITH2(cvtts)
847:
848: static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
849: {
850: TCGv vb;
851: int ignore = 0;
852:
853: /* ??? This is wrong: the instruction is not a nop, it still may
854: raise exceptions. */
855: if (unlikely(rc == 31)) {
856: return;
857: }
858:
859: /* No need to set flushzero, since we have an integer output. */
860: gen_fp_exc_clear();
861: vb = gen_ieee_input(rb, fn11, 0);
862:
863: /* Almost all integer conversions use cropped rounding, and most
864: also do not have integer overflow enabled. Special case that. */
865: switch (fn11) {
866: case QUAL_RM_C:
867: gen_helper_cvttq_c(cpu_fir[rc], vb);
868: break;
869: case QUAL_V | QUAL_RM_C:
870: case QUAL_S | QUAL_V | QUAL_RM_C:
871: ignore = float_flag_inexact;
872: /* FALLTHRU */
873: case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
874: gen_helper_cvttq_svic(cpu_fir[rc], vb);
875: break;
876: default:
877: gen_qual_roundmode(ctx, fn11);
878: gen_helper_cvttq(cpu_fir[rc], vb);
879: ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
880: ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
881: break;
882: }
883: tcg_temp_free(vb);
884:
885: gen_fp_exc_raise_ignore(rc, fn11, ignore);
886: }
887:
888: static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
889: int rb, int rc, int fn11)
890: {
891: TCGv vb;
892:
893: /* ??? This is wrong: the instruction is not a nop, it still may
894: raise exceptions. */
895: if (unlikely(rc == 31)) {
896: return;
897: }
898:
899: gen_qual_roundmode(ctx, fn11);
900:
901: if (rb == 31) {
902: vb = tcg_const_i64(0);
903: } else {
904: vb = cpu_fir[rb];
905: }
906:
907: /* The only exception that can be raised by integer conversion
908: is inexact. Thus we only need to worry about exceptions when
909: inexact handling is requested. */
910: if (fn11 & QUAL_I) {
911: gen_fp_exc_clear();
912: helper(cpu_fir[rc], vb);
913: gen_fp_exc_raise(rc, fn11);
914: } else {
915: helper(cpu_fir[rc], vb);
916: }
917:
918: if (rb == 31) {
919: tcg_temp_free(vb);
920: }
921: }
922:
923: #define IEEE_INTCVT(name) \
924: static inline void glue(gen_f, name)(DisasContext *ctx, \
925: int rb, int rc, int fn11) \
926: { \
927: gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
928: }
929: IEEE_INTCVT(cvtqs)
930: IEEE_INTCVT(cvtqt)
931:
932: static void gen_cpys_internal(int ra, int rb, int rc, int inv_a, uint64_t mask)
933: {
934: TCGv va, vb, vmask;
935: int za = 0, zb = 0;
936:
937: if (unlikely(rc == 31)) {
938: return;
939: }
940:
941: vmask = tcg_const_i64(mask);
942:
943: TCGV_UNUSED_I64(va);
944: if (ra == 31) {
945: if (inv_a) {
946: va = vmask;
947: } else {
948: za = 1;
949: }
950: } else {
951: va = tcg_temp_new_i64();
952: tcg_gen_mov_i64(va, cpu_fir[ra]);
953: if (inv_a) {
954: tcg_gen_andc_i64(va, vmask, va);
955: } else {
956: tcg_gen_and_i64(va, va, vmask);
957: }
958: }
959:
960: TCGV_UNUSED_I64(vb);
961: if (rb == 31) {
962: zb = 1;
963: } else {
964: vb = tcg_temp_new_i64();
965: tcg_gen_andc_i64(vb, cpu_fir[rb], vmask);
966: }
967:
968: switch (za << 1 | zb) {
969: case 0 | 0:
970: tcg_gen_or_i64(cpu_fir[rc], va, vb);
971: break;
972: case 0 | 1:
973: tcg_gen_mov_i64(cpu_fir[rc], va);
974: break;
975: case 2 | 0:
976: tcg_gen_mov_i64(cpu_fir[rc], vb);
977: break;
978: case 2 | 1:
979: tcg_gen_movi_i64(cpu_fir[rc], 0);
980: break;
981: }
982:
983: tcg_temp_free(vmask);
984: if (ra != 31) {
985: tcg_temp_free(va);
986: }
987: if (rb != 31) {
988: tcg_temp_free(vb);
989: }
990: }
991:
992: static inline void gen_fcpys(int ra, int rb, int rc)
993: {
994: gen_cpys_internal(ra, rb, rc, 0, 0x8000000000000000ULL);
1.1.1.2 root 995: }
996:
1.1.1.5 root 997: static inline void gen_fcpysn(int ra, int rb, int rc)
998: {
999: gen_cpys_internal(ra, rb, rc, 1, 0x8000000000000000ULL);
1000: }
1001:
1002: static inline void gen_fcpyse(int ra, int rb, int rc)
1003: {
1004: gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
1005: }
1006:
1007: #define FARITH3(name) \
1008: static inline void glue(gen_f, name)(int ra, int rb, int rc) \
1009: { \
1010: TCGv va, vb; \
1011: \
1012: if (unlikely(rc == 31)) { \
1013: return; \
1014: } \
1015: if (ra == 31) { \
1016: va = tcg_const_i64(0); \
1017: } else { \
1018: va = cpu_fir[ra]; \
1019: } \
1020: if (rb == 31) { \
1021: vb = tcg_const_i64(0); \
1022: } else { \
1023: vb = cpu_fir[rb]; \
1024: } \
1025: \
1026: gen_helper_ ## name (cpu_fir[rc], va, vb); \
1027: \
1028: if (ra == 31) { \
1029: tcg_temp_free(va); \
1030: } \
1031: if (rb == 31) { \
1032: tcg_temp_free(vb); \
1033: } \
1034: }
1035:
1036: /* ??? VAX instruction qualifiers ignored. */
1.1.1.2 root 1037: FARITH3(addf)
1038: FARITH3(subf)
1039: FARITH3(mulf)
1040: FARITH3(divf)
1041: FARITH3(addg)
1042: FARITH3(subg)
1043: FARITH3(mulg)
1044: FARITH3(divg)
1045: FARITH3(cmpgeq)
1046: FARITH3(cmpglt)
1047: FARITH3(cmpgle)
1048:
1.1.1.5 root 1049: static void gen_ieee_arith3(DisasContext *ctx,
1050: void (*helper)(TCGv, TCGv, TCGv),
1051: int ra, int rb, int rc, int fn11)
1052: {
1053: TCGv va, vb;
1054:
1055: /* ??? This is wrong: the instruction is not a nop, it still may
1056: raise exceptions. */
1057: if (unlikely(rc == 31)) {
1058: return;
1059: }
1060:
1061: gen_qual_roundmode(ctx, fn11);
1062: gen_qual_flushzero(ctx, fn11);
1063: gen_fp_exc_clear();
1064:
1065: va = gen_ieee_input(ra, fn11, 0);
1066: vb = gen_ieee_input(rb, fn11, 0);
1067: helper(cpu_fir[rc], va, vb);
1068: tcg_temp_free(va);
1069: tcg_temp_free(vb);
1070:
1071: gen_fp_exc_raise(rc, fn11);
1072: }
1073:
1074: #define IEEE_ARITH3(name) \
1075: static inline void glue(gen_f, name)(DisasContext *ctx, \
1076: int ra, int rb, int rc, int fn11) \
1077: { \
1078: gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
1079: }
1080: IEEE_ARITH3(adds)
1081: IEEE_ARITH3(subs)
1082: IEEE_ARITH3(muls)
1083: IEEE_ARITH3(divs)
1084: IEEE_ARITH3(addt)
1085: IEEE_ARITH3(subt)
1086: IEEE_ARITH3(mult)
1087: IEEE_ARITH3(divt)
1088:
1089: static void gen_ieee_compare(DisasContext *ctx,
1090: void (*helper)(TCGv, TCGv, TCGv),
1091: int ra, int rb, int rc, int fn11)
1092: {
1093: TCGv va, vb;
1094:
1095: /* ??? This is wrong: the instruction is not a nop, it still may
1096: raise exceptions. */
1097: if (unlikely(rc == 31)) {
1098: return;
1099: }
1100:
1101: gen_fp_exc_clear();
1102:
1103: va = gen_ieee_input(ra, fn11, 1);
1104: vb = gen_ieee_input(rb, fn11, 1);
1105: helper(cpu_fir[rc], va, vb);
1106: tcg_temp_free(va);
1107: tcg_temp_free(vb);
1108:
1109: gen_fp_exc_raise(rc, fn11);
1110: }
1111:
1112: #define IEEE_CMP3(name) \
1113: static inline void glue(gen_f, name)(DisasContext *ctx, \
1114: int ra, int rb, int rc, int fn11) \
1115: { \
1116: gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
1117: }
1118: IEEE_CMP3(cmptun)
1119: IEEE_CMP3(cmpteq)
1120: IEEE_CMP3(cmptlt)
1121: IEEE_CMP3(cmptle)
1122:
1123: static inline uint64_t zapnot_mask(uint8_t lit)
1124: {
1125: uint64_t mask = 0;
1126: int i;
1127:
1128: for (i = 0; i < 8; ++i) {
1129: if ((lit >> i) & 1)
1130: mask |= 0xffull << (i * 8);
1131: }
1132: return mask;
1133: }
1134:
1135: /* Implement zapnot with an immediate operand, which expands to some
1136: form of immediate AND. This is a basic building block in the
1137: definition of many of the other byte manipulation instructions. */
1138: static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
1139: {
1140: switch (lit) {
1141: case 0x00:
1142: tcg_gen_movi_i64(dest, 0);
1143: break;
1144: case 0x01:
1145: tcg_gen_ext8u_i64(dest, src);
1146: break;
1147: case 0x03:
1148: tcg_gen_ext16u_i64(dest, src);
1149: break;
1150: case 0x0f:
1151: tcg_gen_ext32u_i64(dest, src);
1152: break;
1153: case 0xff:
1154: tcg_gen_mov_i64(dest, src);
1155: break;
1156: default:
1157: tcg_gen_andi_i64 (dest, src, zapnot_mask (lit));
1158: break;
1159: }
1160: }
1161:
1162: static inline void gen_zapnot(int ra, int rb, int rc, int islit, uint8_t lit)
1.1 root 1163: {
1.1.1.2 root 1164: if (unlikely(rc == 31))
1165: return;
1.1.1.5 root 1166: else if (unlikely(ra == 31))
1167: tcg_gen_movi_i64(cpu_ir[rc], 0);
1168: else if (islit)
1169: gen_zapnoti(cpu_ir[rc], cpu_ir[ra], lit);
1170: else
1171: gen_helper_zapnot (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1172: }
1.1 root 1173:
1.1.1.5 root 1174: static inline void gen_zap(int ra, int rb, int rc, int islit, uint8_t lit)
1175: {
1176: if (unlikely(rc == 31))
1177: return;
1178: else if (unlikely(ra == 31))
1179: tcg_gen_movi_i64(cpu_ir[rc], 0);
1180: else if (islit)
1181: gen_zapnoti(cpu_ir[rc], cpu_ir[ra], ~lit);
1182: else
1183: gen_helper_zap (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1184: }
1185:
1186:
1187: /* EXTWH, EXTLH, EXTQH */
1188: static void gen_ext_h(int ra, int rb, int rc, int islit,
1189: uint8_t lit, uint8_t byte_mask)
1190: {
1191: if (unlikely(rc == 31))
1192: return;
1193: else if (unlikely(ra == 31))
1194: tcg_gen_movi_i64(cpu_ir[rc], 0);
1195: else {
1.1.1.2 root 1196: if (islit) {
1.1.1.5 root 1197: lit = (64 - (lit & 7) * 8) & 0x3f;
1198: tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit);
1.1.1.2 root 1199: } else {
1.1.1.5 root 1200: TCGv tmp1 = tcg_temp_new();
1.1.1.2 root 1201: tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
1202: tcg_gen_shli_i64(tmp1, tmp1, 3);
1.1.1.3 root 1203: tcg_gen_neg_i64(tmp1, tmp1);
1204: tcg_gen_andi_i64(tmp1, tmp1, 0x3f);
1.1.1.2 root 1205: tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
1206: tcg_temp_free(tmp1);
1207: }
1.1.1.5 root 1208: gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
1209: }
1.1 root 1210: }
1211:
1.1.1.5 root 1212: /* EXTBL, EXTWL, EXTLL, EXTQL */
1213: static void gen_ext_l(int ra, int rb, int rc, int islit,
1214: uint8_t lit, uint8_t byte_mask)
1.1 root 1215: {
1.1.1.2 root 1216: if (unlikely(rc == 31))
1217: return;
1.1.1.5 root 1218: else if (unlikely(ra == 31))
1219: tcg_gen_movi_i64(cpu_ir[rc], 0);
1220: else {
1.1.1.2 root 1221: if (islit) {
1.1.1.5 root 1222: tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], (lit & 7) * 8);
1.1.1.2 root 1223: } else {
1224: TCGv tmp = tcg_temp_new();
1225: tcg_gen_andi_i64(tmp, cpu_ir[rb], 7);
1226: tcg_gen_shli_i64(tmp, tmp, 3);
1227: tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], tmp);
1228: tcg_temp_free(tmp);
1229: }
1.1.1.5 root 1230: gen_zapnoti(cpu_ir[rc], cpu_ir[rc], byte_mask);
1231: }
1232: }
1233:
1234: /* INSWH, INSLH, INSQH */
1235: static void gen_ins_h(int ra, int rb, int rc, int islit,
1236: uint8_t lit, uint8_t byte_mask)
1237: {
1238: if (unlikely(rc == 31))
1239: return;
1240: else if (unlikely(ra == 31) || (islit && (lit & 7) == 0))
1241: tcg_gen_movi_i64(cpu_ir[rc], 0);
1242: else {
1243: TCGv tmp = tcg_temp_new();
1244:
1245: /* The instruction description has us left-shift the byte mask
1246: and extract bits <15:8> and apply that zap at the end. This
1247: is equivalent to simply performing the zap first and shifting
1248: afterward. */
1249: gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
1250:
1251: if (islit) {
1252: /* Note that we have handled the lit==0 case above. */
1253: tcg_gen_shri_i64 (cpu_ir[rc], tmp, 64 - (lit & 7) * 8);
1254: } else {
1255: TCGv shift = tcg_temp_new();
1256:
1257: /* If (B & 7) == 0, we need to shift by 64 and leave a zero.
1258: Do this portably by splitting the shift into two parts:
1259: shift_count-1 and 1. Arrange for the -1 by using
1260: ones-complement instead of twos-complement in the negation:
1261: ~((B & 7) * 8) & 63. */
1262:
1263: tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1264: tcg_gen_shli_i64(shift, shift, 3);
1265: tcg_gen_not_i64(shift, shift);
1266: tcg_gen_andi_i64(shift, shift, 0x3f);
1267:
1268: tcg_gen_shr_i64(cpu_ir[rc], tmp, shift);
1269: tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[rc], 1);
1270: tcg_temp_free(shift);
1271: }
1272: tcg_temp_free(tmp);
1273: }
1274: }
1275:
1276: /* INSBL, INSWL, INSLL, INSQL */
1277: static void gen_ins_l(int ra, int rb, int rc, int islit,
1278: uint8_t lit, uint8_t byte_mask)
1279: {
1280: if (unlikely(rc == 31))
1281: return;
1282: else if (unlikely(ra == 31))
1283: tcg_gen_movi_i64(cpu_ir[rc], 0);
1284: else {
1285: TCGv tmp = tcg_temp_new();
1286:
1287: /* The instruction description has us left-shift the byte mask
1288: the same number of byte slots as the data and apply the zap
1289: at the end. This is equivalent to simply performing the zap
1290: first and shifting afterward. */
1291: gen_zapnoti (tmp, cpu_ir[ra], byte_mask);
1292:
1293: if (islit) {
1294: tcg_gen_shli_i64(cpu_ir[rc], tmp, (lit & 7) * 8);
1295: } else {
1296: TCGv shift = tcg_temp_new();
1297: tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1298: tcg_gen_shli_i64(shift, shift, 3);
1299: tcg_gen_shl_i64(cpu_ir[rc], tmp, shift);
1300: tcg_temp_free(shift);
1301: }
1302: tcg_temp_free(tmp);
1303: }
1304: }
1305:
1306: /* MSKWH, MSKLH, MSKQH */
1307: static void gen_msk_h(int ra, int rb, int rc, int islit,
1308: uint8_t lit, uint8_t byte_mask)
1309: {
1310: if (unlikely(rc == 31))
1311: return;
1312: else if (unlikely(ra == 31))
1313: tcg_gen_movi_i64(cpu_ir[rc], 0);
1314: else if (islit) {
1315: gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~((byte_mask << (lit & 7)) >> 8));
1316: } else {
1317: TCGv shift = tcg_temp_new();
1318: TCGv mask = tcg_temp_new();
1319:
1320: /* The instruction description is as above, where the byte_mask
1321: is shifted left, and then we extract bits <15:8>. This can be
1322: emulated with a right-shift on the expanded byte mask. This
1323: requires extra care because for an input <2:0> == 0 we need a
1324: shift of 64 bits in order to generate a zero. This is done by
1325: splitting the shift into two parts, the variable shift - 1
1326: followed by a constant 1 shift. The code we expand below is
1327: equivalent to ~((B & 7) * 8) & 63. */
1328:
1329: tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1330: tcg_gen_shli_i64(shift, shift, 3);
1331: tcg_gen_not_i64(shift, shift);
1332: tcg_gen_andi_i64(shift, shift, 0x3f);
1333: tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1334: tcg_gen_shr_i64(mask, mask, shift);
1335: tcg_gen_shri_i64(mask, mask, 1);
1336:
1337: tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
1338:
1339: tcg_temp_free(mask);
1340: tcg_temp_free(shift);
1341: }
1342: }
1343:
1344: /* MSKBL, MSKWL, MSKLL, MSKQL */
1345: static void gen_msk_l(int ra, int rb, int rc, int islit,
1346: uint8_t lit, uint8_t byte_mask)
1347: {
1348: if (unlikely(rc == 31))
1349: return;
1350: else if (unlikely(ra == 31))
1.1.1.2 root 1351: tcg_gen_movi_i64(cpu_ir[rc], 0);
1.1.1.5 root 1352: else if (islit) {
1353: gen_zapnoti (cpu_ir[rc], cpu_ir[ra], ~(byte_mask << (lit & 7)));
1354: } else {
1355: TCGv shift = tcg_temp_new();
1356: TCGv mask = tcg_temp_new();
1357:
1358: tcg_gen_andi_i64(shift, cpu_ir[rb], 7);
1359: tcg_gen_shli_i64(shift, shift, 3);
1360: tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1361: tcg_gen_shl_i64(mask, mask, shift);
1362:
1363: tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], mask);
1364:
1365: tcg_temp_free(mask);
1366: tcg_temp_free(shift);
1367: }
1.1.1.2 root 1368: }
1369:
1370: /* Code to call arith3 helpers */
1371: #define ARITH3(name) \
1.1.1.4 root 1372: static inline void glue(gen_, name)(int ra, int rb, int rc, int islit,\
1373: uint8_t lit) \
1.1.1.2 root 1374: { \
1375: if (unlikely(rc == 31)) \
1376: return; \
1377: \
1378: if (ra != 31) { \
1379: if (islit) { \
1380: TCGv tmp = tcg_const_i64(lit); \
1381: gen_helper_ ## name(cpu_ir[rc], cpu_ir[ra], tmp); \
1382: tcg_temp_free(tmp); \
1383: } else \
1384: gen_helper_ ## name (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); \
1385: } else { \
1386: TCGv tmp1 = tcg_const_i64(0); \
1387: if (islit) { \
1388: TCGv tmp2 = tcg_const_i64(lit); \
1389: gen_helper_ ## name (cpu_ir[rc], tmp1, tmp2); \
1390: tcg_temp_free(tmp2); \
1391: } else \
1392: gen_helper_ ## name (cpu_ir[rc], tmp1, cpu_ir[rb]); \
1393: tcg_temp_free(tmp1); \
1394: } \
1395: }
1396: ARITH3(cmpbge)
1397: ARITH3(addlv)
1398: ARITH3(sublv)
1399: ARITH3(addqv)
1400: ARITH3(subqv)
1401: ARITH3(umulh)
1402: ARITH3(mullv)
1403: ARITH3(mulqv)
1.1.1.5 root 1404: ARITH3(minub8)
1405: ARITH3(minsb8)
1406: ARITH3(minuw4)
1407: ARITH3(minsw4)
1408: ARITH3(maxub8)
1409: ARITH3(maxsb8)
1410: ARITH3(maxuw4)
1411: ARITH3(maxsw4)
1412: ARITH3(perr)
1413:
1414: #define MVIOP2(name) \
1415: static inline void glue(gen_, name)(int rb, int rc) \
1416: { \
1417: if (unlikely(rc == 31)) \
1418: return; \
1419: if (unlikely(rb == 31)) \
1420: tcg_gen_movi_i64(cpu_ir[rc], 0); \
1421: else \
1422: gen_helper_ ## name (cpu_ir[rc], cpu_ir[rb]); \
1423: }
1424: MVIOP2(pklb)
1425: MVIOP2(pkwb)
1426: MVIOP2(unpkbl)
1427: MVIOP2(unpkbw)
1.1.1.2 root 1428:
1.1.1.5 root 1429: static void gen_cmp(TCGCond cond, int ra, int rb, int rc,
1430: int islit, uint8_t lit)
1.1.1.2 root 1431: {
1.1.1.5 root 1432: TCGv va, vb;
1.1.1.2 root 1433:
1.1.1.5 root 1434: if (unlikely(rc == 31)) {
1435: return;
1436: }
1.1.1.2 root 1437:
1.1.1.5 root 1438: if (ra == 31) {
1439: va = tcg_const_i64(0);
1440: } else {
1441: va = cpu_ir[ra];
1442: }
1443: if (islit) {
1444: vb = tcg_const_i64(lit);
1445: } else {
1446: vb = cpu_ir[rb];
1447: }
1448:
1449: tcg_gen_setcond_i64(cond, cpu_ir[rc], va, vb);
1450:
1451: if (ra == 31) {
1452: tcg_temp_free(va);
1453: }
1454: if (islit) {
1455: tcg_temp_free(vb);
1456: }
1457: }
1458:
1459: static void gen_rx(int ra, int set)
1460: {
1461: TCGv_i32 tmp;
1.1.1.2 root 1462:
1463: if (ra != 31) {
1.1.1.5 root 1464: tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, offsetof(CPUState, intr_flag));
1465: }
1.1 root 1466:
1.1.1.5 root 1467: tmp = tcg_const_i32(set);
1468: tcg_gen_st8_i32(tmp, cpu_env, offsetof(CPUState, intr_flag));
1469: tcg_temp_free_i32(tmp);
1.1 root 1470: }
1471:
1.1.1.6 ! root 1472: static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
! 1473: {
! 1474: /* We're emulating OSF/1 PALcode. Many of these are trivial access
! 1475: to internal cpu registers. */
! 1476:
! 1477: /* Unprivileged PAL call */
! 1478: if (palcode >= 0x80 && palcode < 0xC0) {
! 1479: switch (palcode) {
! 1480: case 0x86:
! 1481: /* IMB */
! 1482: /* No-op inside QEMU. */
! 1483: break;
! 1484: case 0x9E:
! 1485: /* RDUNIQUE */
! 1486: tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_unique);
! 1487: break;
! 1488: case 0x9F:
! 1489: /* WRUNIQUE */
! 1490: tcg_gen_mov_i64(cpu_unique, cpu_ir[IR_A0]);
! 1491: break;
! 1492: default:
! 1493: return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xbf);
! 1494: }
! 1495: return NO_EXIT;
! 1496: }
! 1497:
! 1498: #ifndef CONFIG_USER_ONLY
! 1499: /* Privileged PAL code */
! 1500: if (palcode < 0x40 && (ctx->tb->flags & TB_FLAGS_USER_MODE) == 0) {
! 1501: switch (palcode) {
! 1502: case 0x01:
! 1503: /* CFLUSH */
! 1504: /* No-op inside QEMU. */
! 1505: break;
! 1506: case 0x02:
! 1507: /* DRAINA */
! 1508: /* No-op inside QEMU. */
! 1509: break;
! 1510: case 0x2D:
! 1511: /* WRVPTPTR */
! 1512: tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env, offsetof(CPUState, vptptr));
! 1513: break;
! 1514: case 0x31:
! 1515: /* WRVAL */
! 1516: tcg_gen_mov_i64(cpu_sysval, cpu_ir[IR_A0]);
! 1517: break;
! 1518: case 0x32:
! 1519: /* RDVAL */
! 1520: tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_sysval);
! 1521: break;
! 1522:
! 1523: case 0x35: {
! 1524: /* SWPIPL */
! 1525: TCGv tmp;
! 1526:
! 1527: /* Note that we already know we're in kernel mode, so we know
! 1528: that PS only contains the 3 IPL bits. */
! 1529: tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUState, ps));
! 1530:
! 1531: /* But make sure and store only the 3 IPL bits from the user. */
! 1532: tmp = tcg_temp_new();
! 1533: tcg_gen_andi_i64(tmp, cpu_ir[IR_A0], PS_INT_MASK);
! 1534: tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUState, ps));
! 1535: tcg_temp_free(tmp);
! 1536: break;
! 1537: }
! 1538:
! 1539: case 0x36:
! 1540: /* RDPS */
! 1541: tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUState, ps));
! 1542: break;
! 1543: case 0x38:
! 1544: /* WRUSP */
! 1545: tcg_gen_mov_i64(cpu_usp, cpu_ir[IR_A0]);
! 1546: break;
! 1547: case 0x3A:
! 1548: /* RDUSP */
! 1549: tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_usp);
! 1550: break;
! 1551: case 0x3C:
! 1552: /* WHAMI */
! 1553: tcg_gen_ld32s_i64(cpu_ir[IR_V0], cpu_env,
! 1554: offsetof(CPUState, cpu_index));
! 1555: break;
! 1556:
! 1557: default:
! 1558: return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3f);
! 1559: }
! 1560: return NO_EXIT;
! 1561: }
! 1562: #endif
! 1563:
! 1564: return gen_invalid(ctx);
! 1565: }
! 1566:
! 1567: #ifndef CONFIG_USER_ONLY
! 1568:
! 1569: #define PR_BYTE 0x100000
! 1570: #define PR_LONG 0x200000
! 1571:
! 1572: static int cpu_pr_data(int pr)
! 1573: {
! 1574: switch (pr) {
! 1575: case 0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
! 1576: case 1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
! 1577: case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
! 1578: case 3: return offsetof(CPUAlphaState, trap_arg0);
! 1579: case 4: return offsetof(CPUAlphaState, trap_arg1);
! 1580: case 5: return offsetof(CPUAlphaState, trap_arg2);
! 1581: case 6: return offsetof(CPUAlphaState, exc_addr);
! 1582: case 7: return offsetof(CPUAlphaState, palbr);
! 1583: case 8: return offsetof(CPUAlphaState, ptbr);
! 1584: case 9: return offsetof(CPUAlphaState, vptptr);
! 1585: case 10: return offsetof(CPUAlphaState, unique);
! 1586: case 11: return offsetof(CPUAlphaState, sysval);
! 1587: case 12: return offsetof(CPUAlphaState, usp);
! 1588:
! 1589: case 32 ... 39:
! 1590: return offsetof(CPUAlphaState, shadow[pr - 32]);
! 1591: case 40 ... 63:
! 1592: return offsetof(CPUAlphaState, scratch[pr - 40]);
! 1593: }
! 1594: return 0;
! 1595: }
! 1596:
! 1597: static void gen_mfpr(int ra, int regno)
! 1598: {
! 1599: int data = cpu_pr_data(regno);
! 1600:
! 1601: /* In our emulated PALcode, these processor registers have no
! 1602: side effects from reading. */
! 1603: if (ra == 31) {
! 1604: return;
! 1605: }
! 1606:
! 1607: /* The basic registers are data only, and unknown registers
! 1608: are read-zero, write-ignore. */
! 1609: if (data == 0) {
! 1610: tcg_gen_movi_i64(cpu_ir[ra], 0);
! 1611: } else if (data & PR_BYTE) {
! 1612: tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, data & ~PR_BYTE);
! 1613: } else if (data & PR_LONG) {
! 1614: tcg_gen_ld32s_i64(cpu_ir[ra], cpu_env, data & ~PR_LONG);
! 1615: } else {
! 1616: tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
! 1617: }
! 1618: }
! 1619:
! 1620: static void gen_mtpr(int rb, int regno)
! 1621: {
! 1622: TCGv tmp;
! 1623:
! 1624: if (rb == 31) {
! 1625: tmp = tcg_const_i64(0);
! 1626: } else {
! 1627: tmp = cpu_ir[rb];
! 1628: }
! 1629:
! 1630: /* These two register numbers perform a TLB cache flush. Thankfully we
! 1631: can only do this inside PALmode, which means that the current basic
! 1632: block cannot be affected by the change in mappings. */
! 1633: if (regno == 255) {
! 1634: /* TBIA */
! 1635: gen_helper_tbia();
! 1636: } else if (regno == 254) {
! 1637: /* TBIS */
! 1638: gen_helper_tbis(tmp);
! 1639: } else {
! 1640: /* The basic registers are data only, and unknown registers
! 1641: are read-zero, write-ignore. */
! 1642: int data = cpu_pr_data(regno);
! 1643: if (data != 0) {
! 1644: if (data & PR_BYTE) {
! 1645: tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
! 1646: } else if (data & PR_LONG) {
! 1647: tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
! 1648: } else {
! 1649: tcg_gen_st_i64(tmp, cpu_env, data);
! 1650: }
! 1651: }
! 1652: }
! 1653:
! 1654: if (rb == 31) {
! 1655: tcg_temp_free(tmp);
! 1656: }
! 1657: }
! 1658: #endif /* !USER_ONLY*/
! 1659:
1.1.1.5 root 1660: static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
1.1 root 1661: {
1662: uint32_t palcode;
1.1.1.6 ! root 1663: int32_t disp21, disp16;
! 1664: #ifndef CONFIG_USER_ONLY
! 1665: int32_t disp12;
! 1666: #endif
1.1.1.5 root 1667: uint16_t fn11;
1.1.1.6 ! root 1668: uint8_t opc, ra, rb, rc, fpfn, fn7, islit, real_islit;
1.1.1.2 root 1669: uint8_t lit;
1.1.1.5 root 1670: ExitStatus ret;
1.1 root 1671:
1672: /* Decode all instruction fields */
1673: opc = insn >> 26;
1674: ra = (insn >> 21) & 0x1F;
1675: rb = (insn >> 16) & 0x1F;
1676: rc = insn & 0x1F;
1.1.1.5 root 1677: real_islit = islit = (insn >> 12) & 1;
1.1.1.2 root 1678: if (rb == 31 && !islit) {
1679: islit = 1;
1680: lit = 0;
1681: } else
1682: lit = (insn >> 13) & 0xFF;
1.1 root 1683: palcode = insn & 0x03FFFFFF;
1684: disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
1685: disp16 = (int16_t)(insn & 0x0000FFFF);
1.1.1.6 ! root 1686: #ifndef CONFIG_USER_ONLY
1.1 root 1687: disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
1.1.1.6 ! root 1688: #endif
1.1 root 1689: fn11 = (insn >> 5) & 0x000007FF;
1690: fpfn = fn11 & 0x3F;
1691: fn7 = (insn >> 5) & 0x0000007F;
1.1.1.5 root 1692: LOG_DISAS("opc %02x ra %2d rb %2d rc %2d disp16 %6d\n",
1.1.1.2 root 1693: opc, ra, rb, rc, disp16);
1.1.1.5 root 1694:
1695: ret = NO_EXIT;
1.1 root 1696: switch (opc) {
1697: case 0x00:
1698: /* CALL_PAL */
1.1.1.6 ! root 1699: ret = gen_call_pal(ctx, palcode);
! 1700: break;
1.1 root 1701: case 0x01:
1702: /* OPC01 */
1703: goto invalid_opc;
1704: case 0x02:
1705: /* OPC02 */
1706: goto invalid_opc;
1707: case 0x03:
1708: /* OPC03 */
1709: goto invalid_opc;
1710: case 0x04:
1711: /* OPC04 */
1712: goto invalid_opc;
1713: case 0x05:
1714: /* OPC05 */
1715: goto invalid_opc;
1716: case 0x06:
1717: /* OPC06 */
1718: goto invalid_opc;
1719: case 0x07:
1720: /* OPC07 */
1721: goto invalid_opc;
1722: case 0x08:
1723: /* LDA */
1.1.1.2 root 1724: if (likely(ra != 31)) {
1725: if (rb != 31)
1726: tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16);
1727: else
1728: tcg_gen_movi_i64(cpu_ir[ra], disp16);
1729: }
1.1 root 1730: break;
1731: case 0x09:
1732: /* LDAH */
1.1.1.2 root 1733: if (likely(ra != 31)) {
1734: if (rb != 31)
1735: tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16);
1736: else
1737: tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16);
1738: }
1.1 root 1739: break;
1740: case 0x0A:
1741: /* LDBU */
1.1.1.6 ! root 1742: if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
! 1743: gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
! 1744: break;
! 1745: }
! 1746: goto invalid_opc;
1.1 root 1747: case 0x0B:
1748: /* LDQ_U */
1.1.1.2 root 1749: gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
1.1 root 1750: break;
1751: case 0x0C:
1752: /* LDWU */
1.1.1.6 ! root 1753: if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
! 1754: gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
! 1755: break;
! 1756: }
! 1757: goto invalid_opc;
1.1 root 1758: case 0x0D:
1759: /* STW */
1.1.1.5 root 1760: gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
1.1 root 1761: break;
1762: case 0x0E:
1763: /* STB */
1.1.1.5 root 1764: gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
1.1 root 1765: break;
1766: case 0x0F:
1767: /* STQ_U */
1.1.1.5 root 1768: gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
1.1 root 1769: break;
1770: case 0x10:
1771: switch (fn7) {
1772: case 0x00:
1773: /* ADDL */
1.1.1.2 root 1774: if (likely(rc != 31)) {
1775: if (ra != 31) {
1776: if (islit) {
1777: tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
1778: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
1779: } else {
1780: tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1781: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
1782: }
1783: } else {
1784: if (islit)
1785: tcg_gen_movi_i64(cpu_ir[rc], lit);
1786: else
1787: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
1788: }
1789: }
1.1 root 1790: break;
1791: case 0x02:
1792: /* S4ADDL */
1.1.1.2 root 1793: if (likely(rc != 31)) {
1794: if (ra != 31) {
1795: TCGv tmp = tcg_temp_new();
1796: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1797: if (islit)
1798: tcg_gen_addi_i64(tmp, tmp, lit);
1799: else
1800: tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
1801: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1802: tcg_temp_free(tmp);
1803: } else {
1804: if (islit)
1805: tcg_gen_movi_i64(cpu_ir[rc], lit);
1806: else
1807: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
1808: }
1809: }
1.1 root 1810: break;
1811: case 0x09:
1812: /* SUBL */
1.1.1.2 root 1813: if (likely(rc != 31)) {
1814: if (ra != 31) {
1815: if (islit)
1816: tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
1817: else
1818: tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1819: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
1820: } else {
1821: if (islit)
1822: tcg_gen_movi_i64(cpu_ir[rc], -lit);
1823: else {
1824: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1825: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
1826: }
1827: }
1.1 root 1828: break;
1829: case 0x0B:
1830: /* S4SUBL */
1.1.1.2 root 1831: if (likely(rc != 31)) {
1832: if (ra != 31) {
1833: TCGv tmp = tcg_temp_new();
1834: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1835: if (islit)
1836: tcg_gen_subi_i64(tmp, tmp, lit);
1837: else
1838: tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
1839: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1840: tcg_temp_free(tmp);
1841: } else {
1842: if (islit)
1843: tcg_gen_movi_i64(cpu_ir[rc], -lit);
1844: else {
1845: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1846: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
1847: }
1848: }
1849: }
1.1 root 1850: break;
1851: case 0x0F:
1852: /* CMPBGE */
1.1.1.2 root 1853: gen_cmpbge(ra, rb, rc, islit, lit);
1.1 root 1854: break;
1855: case 0x12:
1856: /* S8ADDL */
1.1.1.2 root 1857: if (likely(rc != 31)) {
1858: if (ra != 31) {
1859: TCGv tmp = tcg_temp_new();
1860: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1861: if (islit)
1862: tcg_gen_addi_i64(tmp, tmp, lit);
1863: else
1864: tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
1865: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1866: tcg_temp_free(tmp);
1867: } else {
1868: if (islit)
1869: tcg_gen_movi_i64(cpu_ir[rc], lit);
1870: else
1871: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
1872: }
1873: }
1.1 root 1874: break;
1875: case 0x1B:
1876: /* S8SUBL */
1.1.1.2 root 1877: if (likely(rc != 31)) {
1878: if (ra != 31) {
1879: TCGv tmp = tcg_temp_new();
1880: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1881: if (islit)
1882: tcg_gen_subi_i64(tmp, tmp, lit);
1883: else
1884: tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
1885: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
1886: tcg_temp_free(tmp);
1887: } else {
1888: if (islit)
1889: tcg_gen_movi_i64(cpu_ir[rc], -lit);
1890: else
1891: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1892: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
1893: }
1894: }
1895: }
1.1 root 1896: break;
1897: case 0x1D:
1898: /* CMPULT */
1.1.1.2 root 1899: gen_cmp(TCG_COND_LTU, ra, rb, rc, islit, lit);
1.1 root 1900: break;
1901: case 0x20:
1902: /* ADDQ */
1.1.1.2 root 1903: if (likely(rc != 31)) {
1904: if (ra != 31) {
1905: if (islit)
1906: tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
1907: else
1908: tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1909: } else {
1910: if (islit)
1911: tcg_gen_movi_i64(cpu_ir[rc], lit);
1912: else
1913: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
1914: }
1915: }
1.1 root 1916: break;
1917: case 0x22:
1918: /* S4ADDQ */
1.1.1.2 root 1919: if (likely(rc != 31)) {
1920: if (ra != 31) {
1921: TCGv tmp = tcg_temp_new();
1922: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1923: if (islit)
1924: tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
1925: else
1926: tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1927: tcg_temp_free(tmp);
1928: } else {
1929: if (islit)
1930: tcg_gen_movi_i64(cpu_ir[rc], lit);
1931: else
1932: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
1933: }
1934: }
1.1 root 1935: break;
1936: case 0x29:
1937: /* SUBQ */
1.1.1.2 root 1938: if (likely(rc != 31)) {
1939: if (ra != 31) {
1940: if (islit)
1941: tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
1942: else
1943: tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1944: } else {
1945: if (islit)
1946: tcg_gen_movi_i64(cpu_ir[rc], -lit);
1947: else
1948: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1949: }
1950: }
1.1 root 1951: break;
1952: case 0x2B:
1953: /* S4SUBQ */
1.1.1.2 root 1954: if (likely(rc != 31)) {
1955: if (ra != 31) {
1956: TCGv tmp = tcg_temp_new();
1957: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
1958: if (islit)
1959: tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
1960: else
1961: tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1962: tcg_temp_free(tmp);
1963: } else {
1964: if (islit)
1965: tcg_gen_movi_i64(cpu_ir[rc], -lit);
1966: else
1967: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
1968: }
1969: }
1.1 root 1970: break;
1971: case 0x2D:
1972: /* CMPEQ */
1.1.1.2 root 1973: gen_cmp(TCG_COND_EQ, ra, rb, rc, islit, lit);
1.1 root 1974: break;
1975: case 0x32:
1976: /* S8ADDQ */
1.1.1.2 root 1977: if (likely(rc != 31)) {
1978: if (ra != 31) {
1979: TCGv tmp = tcg_temp_new();
1980: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
1981: if (islit)
1982: tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
1983: else
1984: tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
1985: tcg_temp_free(tmp);
1986: } else {
1987: if (islit)
1988: tcg_gen_movi_i64(cpu_ir[rc], lit);
1989: else
1990: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
1991: }
1992: }
1.1 root 1993: break;
1994: case 0x3B:
1995: /* S8SUBQ */
1.1.1.2 root 1996: if (likely(rc != 31)) {
1997: if (ra != 31) {
1998: TCGv tmp = tcg_temp_new();
1999: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
2000: if (islit)
2001: tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
2002: else
2003: tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
2004: tcg_temp_free(tmp);
2005: } else {
2006: if (islit)
2007: tcg_gen_movi_i64(cpu_ir[rc], -lit);
2008: else
2009: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
2010: }
2011: }
1.1 root 2012: break;
2013: case 0x3D:
2014: /* CMPULE */
1.1.1.2 root 2015: gen_cmp(TCG_COND_LEU, ra, rb, rc, islit, lit);
1.1 root 2016: break;
2017: case 0x40:
2018: /* ADDL/V */
1.1.1.2 root 2019: gen_addlv(ra, rb, rc, islit, lit);
1.1 root 2020: break;
2021: case 0x49:
2022: /* SUBL/V */
1.1.1.2 root 2023: gen_sublv(ra, rb, rc, islit, lit);
1.1 root 2024: break;
2025: case 0x4D:
2026: /* CMPLT */
1.1.1.2 root 2027: gen_cmp(TCG_COND_LT, ra, rb, rc, islit, lit);
1.1 root 2028: break;
2029: case 0x60:
2030: /* ADDQ/V */
1.1.1.2 root 2031: gen_addqv(ra, rb, rc, islit, lit);
1.1 root 2032: break;
2033: case 0x69:
2034: /* SUBQ/V */
1.1.1.2 root 2035: gen_subqv(ra, rb, rc, islit, lit);
1.1 root 2036: break;
2037: case 0x6D:
2038: /* CMPLE */
1.1.1.2 root 2039: gen_cmp(TCG_COND_LE, ra, rb, rc, islit, lit);
1.1 root 2040: break;
2041: default:
2042: goto invalid_opc;
2043: }
2044: break;
2045: case 0x11:
2046: switch (fn7) {
2047: case 0x00:
2048: /* AND */
1.1.1.2 root 2049: if (likely(rc != 31)) {
2050: if (ra == 31)
2051: tcg_gen_movi_i64(cpu_ir[rc], 0);
2052: else if (islit)
2053: tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], lit);
2054: else
2055: tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2056: }
1.1 root 2057: break;
2058: case 0x08:
2059: /* BIC */
1.1.1.2 root 2060: if (likely(rc != 31)) {
2061: if (ra != 31) {
2062: if (islit)
2063: tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
2064: else
2065: tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2066: } else
2067: tcg_gen_movi_i64(cpu_ir[rc], 0);
2068: }
1.1 root 2069: break;
2070: case 0x14:
2071: /* CMOVLBS */
1.1.1.5 root 2072: gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
1.1 root 2073: break;
2074: case 0x16:
2075: /* CMOVLBC */
1.1.1.5 root 2076: gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
1.1 root 2077: break;
2078: case 0x20:
2079: /* BIS */
1.1.1.2 root 2080: if (likely(rc != 31)) {
2081: if (ra != 31) {
2082: if (islit)
2083: tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit);
2084: else
2085: tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1.1 root 2086: } else {
1.1.1.2 root 2087: if (islit)
2088: tcg_gen_movi_i64(cpu_ir[rc], lit);
2089: else
2090: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
1.1 root 2091: }
2092: }
2093: break;
2094: case 0x24:
2095: /* CMOVEQ */
1.1.1.5 root 2096: gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
1.1 root 2097: break;
2098: case 0x26:
2099: /* CMOVNE */
1.1.1.5 root 2100: gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
1.1 root 2101: break;
2102: case 0x28:
2103: /* ORNOT */
1.1.1.2 root 2104: if (likely(rc != 31)) {
2105: if (ra != 31) {
2106: if (islit)
2107: tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
2108: else
2109: tcg_gen_orc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2110: } else {
2111: if (islit)
2112: tcg_gen_movi_i64(cpu_ir[rc], ~lit);
2113: else
2114: tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
2115: }
2116: }
1.1 root 2117: break;
2118: case 0x40:
2119: /* XOR */
1.1.1.2 root 2120: if (likely(rc != 31)) {
2121: if (ra != 31) {
2122: if (islit)
2123: tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], lit);
2124: else
2125: tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2126: } else {
2127: if (islit)
2128: tcg_gen_movi_i64(cpu_ir[rc], lit);
2129: else
2130: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
2131: }
2132: }
1.1 root 2133: break;
2134: case 0x44:
2135: /* CMOVLT */
1.1.1.5 root 2136: gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
1.1 root 2137: break;
2138: case 0x46:
2139: /* CMOVGE */
1.1.1.5 root 2140: gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
1.1 root 2141: break;
2142: case 0x48:
2143: /* EQV */
1.1.1.2 root 2144: if (likely(rc != 31)) {
2145: if (ra != 31) {
2146: if (islit)
2147: tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
2148: else
2149: tcg_gen_eqv_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2150: } else {
2151: if (islit)
2152: tcg_gen_movi_i64(cpu_ir[rc], ~lit);
2153: else
2154: tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
2155: }
2156: }
1.1 root 2157: break;
2158: case 0x61:
2159: /* AMASK */
1.1.1.2 root 2160: if (likely(rc != 31)) {
1.1.1.6 ! root 2161: uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
! 2162:
! 2163: if (islit) {
! 2164: tcg_gen_movi_i64(cpu_ir[rc], lit & ~amask);
! 2165: } else {
! 2166: tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[rb], ~amask);
1.1.1.3 root 2167: }
1.1.1.2 root 2168: }
1.1 root 2169: break;
2170: case 0x64:
2171: /* CMOVLE */
1.1.1.5 root 2172: gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
1.1 root 2173: break;
2174: case 0x66:
2175: /* CMOVGT */
1.1.1.5 root 2176: gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
1.1 root 2177: break;
2178: case 0x6C:
2179: /* IMPLVER */
1.1.1.2 root 2180: if (rc != 31)
1.1.1.3 root 2181: tcg_gen_movi_i64(cpu_ir[rc], ctx->env->implver);
1.1 root 2182: break;
2183: default:
2184: goto invalid_opc;
2185: }
2186: break;
2187: case 0x12:
2188: switch (fn7) {
2189: case 0x02:
2190: /* MSKBL */
1.1.1.5 root 2191: gen_msk_l(ra, rb, rc, islit, lit, 0x01);
1.1 root 2192: break;
2193: case 0x06:
2194: /* EXTBL */
1.1.1.5 root 2195: gen_ext_l(ra, rb, rc, islit, lit, 0x01);
1.1 root 2196: break;
2197: case 0x0B:
2198: /* INSBL */
1.1.1.5 root 2199: gen_ins_l(ra, rb, rc, islit, lit, 0x01);
1.1 root 2200: break;
2201: case 0x12:
2202: /* MSKWL */
1.1.1.5 root 2203: gen_msk_l(ra, rb, rc, islit, lit, 0x03);
1.1 root 2204: break;
2205: case 0x16:
2206: /* EXTWL */
1.1.1.5 root 2207: gen_ext_l(ra, rb, rc, islit, lit, 0x03);
1.1 root 2208: break;
2209: case 0x1B:
2210: /* INSWL */
1.1.1.5 root 2211: gen_ins_l(ra, rb, rc, islit, lit, 0x03);
1.1 root 2212: break;
2213: case 0x22:
2214: /* MSKLL */
1.1.1.5 root 2215: gen_msk_l(ra, rb, rc, islit, lit, 0x0f);
1.1 root 2216: break;
2217: case 0x26:
2218: /* EXTLL */
1.1.1.5 root 2219: gen_ext_l(ra, rb, rc, islit, lit, 0x0f);
1.1 root 2220: break;
2221: case 0x2B:
2222: /* INSLL */
1.1.1.5 root 2223: gen_ins_l(ra, rb, rc, islit, lit, 0x0f);
1.1 root 2224: break;
2225: case 0x30:
2226: /* ZAP */
1.1.1.2 root 2227: gen_zap(ra, rb, rc, islit, lit);
1.1 root 2228: break;
2229: case 0x31:
2230: /* ZAPNOT */
1.1.1.2 root 2231: gen_zapnot(ra, rb, rc, islit, lit);
1.1 root 2232: break;
2233: case 0x32:
2234: /* MSKQL */
1.1.1.5 root 2235: gen_msk_l(ra, rb, rc, islit, lit, 0xff);
1.1 root 2236: break;
2237: case 0x34:
2238: /* SRL */
1.1.1.2 root 2239: if (likely(rc != 31)) {
2240: if (ra != 31) {
2241: if (islit)
2242: tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
2243: else {
2244: TCGv shift = tcg_temp_new();
2245: tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2246: tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], shift);
2247: tcg_temp_free(shift);
2248: }
2249: } else
2250: tcg_gen_movi_i64(cpu_ir[rc], 0);
2251: }
1.1 root 2252: break;
2253: case 0x36:
2254: /* EXTQL */
1.1.1.5 root 2255: gen_ext_l(ra, rb, rc, islit, lit, 0xff);
1.1 root 2256: break;
2257: case 0x39:
2258: /* SLL */
1.1.1.2 root 2259: if (likely(rc != 31)) {
2260: if (ra != 31) {
2261: if (islit)
2262: tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
2263: else {
2264: TCGv shift = tcg_temp_new();
2265: tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2266: tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], shift);
2267: tcg_temp_free(shift);
2268: }
2269: } else
2270: tcg_gen_movi_i64(cpu_ir[rc], 0);
2271: }
1.1 root 2272: break;
2273: case 0x3B:
2274: /* INSQL */
1.1.1.5 root 2275: gen_ins_l(ra, rb, rc, islit, lit, 0xff);
1.1 root 2276: break;
2277: case 0x3C:
2278: /* SRA */
1.1.1.2 root 2279: if (likely(rc != 31)) {
2280: if (ra != 31) {
2281: if (islit)
2282: tcg_gen_sari_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
2283: else {
2284: TCGv shift = tcg_temp_new();
2285: tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
2286: tcg_gen_sar_i64(cpu_ir[rc], cpu_ir[ra], shift);
2287: tcg_temp_free(shift);
2288: }
2289: } else
2290: tcg_gen_movi_i64(cpu_ir[rc], 0);
2291: }
1.1 root 2292: break;
2293: case 0x52:
2294: /* MSKWH */
1.1.1.5 root 2295: gen_msk_h(ra, rb, rc, islit, lit, 0x03);
1.1 root 2296: break;
2297: case 0x57:
2298: /* INSWH */
1.1.1.5 root 2299: gen_ins_h(ra, rb, rc, islit, lit, 0x03);
1.1 root 2300: break;
2301: case 0x5A:
2302: /* EXTWH */
1.1.1.5 root 2303: gen_ext_h(ra, rb, rc, islit, lit, 0x03);
1.1 root 2304: break;
2305: case 0x62:
2306: /* MSKLH */
1.1.1.5 root 2307: gen_msk_h(ra, rb, rc, islit, lit, 0x0f);
1.1 root 2308: break;
2309: case 0x67:
2310: /* INSLH */
1.1.1.5 root 2311: gen_ins_h(ra, rb, rc, islit, lit, 0x0f);
1.1 root 2312: break;
2313: case 0x6A:
2314: /* EXTLH */
1.1.1.5 root 2315: gen_ext_h(ra, rb, rc, islit, lit, 0x0f);
1.1 root 2316: break;
2317: case 0x72:
2318: /* MSKQH */
1.1.1.5 root 2319: gen_msk_h(ra, rb, rc, islit, lit, 0xff);
1.1 root 2320: break;
2321: case 0x77:
2322: /* INSQH */
1.1.1.5 root 2323: gen_ins_h(ra, rb, rc, islit, lit, 0xff);
1.1 root 2324: break;
2325: case 0x7A:
2326: /* EXTQH */
1.1.1.5 root 2327: gen_ext_h(ra, rb, rc, islit, lit, 0xff);
1.1 root 2328: break;
2329: default:
2330: goto invalid_opc;
2331: }
2332: break;
2333: case 0x13:
2334: switch (fn7) {
2335: case 0x00:
2336: /* MULL */
1.1.1.2 root 2337: if (likely(rc != 31)) {
2338: if (ra == 31)
2339: tcg_gen_movi_i64(cpu_ir[rc], 0);
2340: else {
2341: if (islit)
2342: tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
2343: else
2344: tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2345: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
2346: }
2347: }
1.1 root 2348: break;
2349: case 0x20:
2350: /* MULQ */
1.1.1.2 root 2351: if (likely(rc != 31)) {
2352: if (ra == 31)
2353: tcg_gen_movi_i64(cpu_ir[rc], 0);
2354: else if (islit)
2355: tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
2356: else
2357: tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
2358: }
1.1 root 2359: break;
2360: case 0x30:
2361: /* UMULH */
1.1.1.2 root 2362: gen_umulh(ra, rb, rc, islit, lit);
1.1 root 2363: break;
2364: case 0x40:
2365: /* MULL/V */
1.1.1.2 root 2366: gen_mullv(ra, rb, rc, islit, lit);
1.1 root 2367: break;
2368: case 0x60:
2369: /* MULQ/V */
1.1.1.2 root 2370: gen_mulqv(ra, rb, rc, islit, lit);
1.1 root 2371: break;
2372: default:
2373: goto invalid_opc;
2374: }
2375: break;
2376: case 0x14:
1.1.1.5 root 2377: switch (fpfn) { /* fn11 & 0x3F */
1.1 root 2378: case 0x04:
2379: /* ITOFS */
1.1.1.6 ! root 2380: if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
1.1 root 2381: goto invalid_opc;
1.1.1.6 ! root 2382: }
1.1.1.2 root 2383: if (likely(rc != 31)) {
2384: if (ra != 31) {
2385: TCGv_i32 tmp = tcg_temp_new_i32();
2386: tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
2387: gen_helper_memory_to_s(cpu_fir[rc], tmp);
2388: tcg_temp_free_i32(tmp);
2389: } else
2390: tcg_gen_movi_i64(cpu_fir[rc], 0);
2391: }
1.1 root 2392: break;
2393: case 0x0A:
2394: /* SQRTF */
1.1.1.6 ! root 2395: if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
! 2396: gen_fsqrtf(rb, rc);
! 2397: break;
! 2398: }
! 2399: goto invalid_opc;
1.1 root 2400: case 0x0B:
2401: /* SQRTS */
1.1.1.6 ! root 2402: if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
! 2403: gen_fsqrts(ctx, rb, rc, fn11);
! 2404: break;
! 2405: }
! 2406: goto invalid_opc;
1.1 root 2407: case 0x14:
2408: /* ITOFF */
1.1.1.6 ! root 2409: if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
1.1 root 2410: goto invalid_opc;
1.1.1.6 ! root 2411: }
1.1.1.2 root 2412: if (likely(rc != 31)) {
2413: if (ra != 31) {
2414: TCGv_i32 tmp = tcg_temp_new_i32();
2415: tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
2416: gen_helper_memory_to_f(cpu_fir[rc], tmp);
2417: tcg_temp_free_i32(tmp);
2418: } else
2419: tcg_gen_movi_i64(cpu_fir[rc], 0);
2420: }
1.1 root 2421: break;
2422: case 0x24:
2423: /* ITOFT */
1.1.1.6 ! root 2424: if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
1.1 root 2425: goto invalid_opc;
1.1.1.6 ! root 2426: }
1.1.1.2 root 2427: if (likely(rc != 31)) {
2428: if (ra != 31)
2429: tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
2430: else
2431: tcg_gen_movi_i64(cpu_fir[rc], 0);
2432: }
1.1 root 2433: break;
2434: case 0x2A:
2435: /* SQRTG */
1.1.1.6 ! root 2436: if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
! 2437: gen_fsqrtg(rb, rc);
! 2438: break;
! 2439: }
! 2440: goto invalid_opc;
1.1 root 2441: case 0x02B:
2442: /* SQRTT */
1.1.1.6 ! root 2443: if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
! 2444: gen_fsqrtt(ctx, rb, rc, fn11);
! 2445: break;
! 2446: }
! 2447: goto invalid_opc;
1.1 root 2448: default:
2449: goto invalid_opc;
2450: }
2451: break;
2452: case 0x15:
2453: /* VAX floating point */
2454: /* XXX: rounding mode and trap are ignored (!) */
1.1.1.5 root 2455: switch (fpfn) { /* fn11 & 0x3F */
1.1 root 2456: case 0x00:
2457: /* ADDF */
1.1.1.2 root 2458: gen_faddf(ra, rb, rc);
1.1 root 2459: break;
2460: case 0x01:
2461: /* SUBF */
1.1.1.2 root 2462: gen_fsubf(ra, rb, rc);
1.1 root 2463: break;
2464: case 0x02:
2465: /* MULF */
1.1.1.2 root 2466: gen_fmulf(ra, rb, rc);
1.1 root 2467: break;
2468: case 0x03:
2469: /* DIVF */
1.1.1.2 root 2470: gen_fdivf(ra, rb, rc);
1.1 root 2471: break;
2472: case 0x1E:
2473: /* CVTDG */
2474: #if 0 // TODO
1.1.1.2 root 2475: gen_fcvtdg(rb, rc);
1.1 root 2476: #else
2477: goto invalid_opc;
2478: #endif
2479: break;
2480: case 0x20:
2481: /* ADDG */
1.1.1.2 root 2482: gen_faddg(ra, rb, rc);
1.1 root 2483: break;
2484: case 0x21:
2485: /* SUBG */
1.1.1.2 root 2486: gen_fsubg(ra, rb, rc);
1.1 root 2487: break;
2488: case 0x22:
2489: /* MULG */
1.1.1.2 root 2490: gen_fmulg(ra, rb, rc);
1.1 root 2491: break;
2492: case 0x23:
2493: /* DIVG */
1.1.1.2 root 2494: gen_fdivg(ra, rb, rc);
1.1 root 2495: break;
2496: case 0x25:
2497: /* CMPGEQ */
1.1.1.2 root 2498: gen_fcmpgeq(ra, rb, rc);
1.1 root 2499: break;
2500: case 0x26:
2501: /* CMPGLT */
1.1.1.2 root 2502: gen_fcmpglt(ra, rb, rc);
1.1 root 2503: break;
2504: case 0x27:
2505: /* CMPGLE */
1.1.1.2 root 2506: gen_fcmpgle(ra, rb, rc);
1.1 root 2507: break;
2508: case 0x2C:
2509: /* CVTGF */
1.1.1.2 root 2510: gen_fcvtgf(rb, rc);
1.1 root 2511: break;
2512: case 0x2D:
2513: /* CVTGD */
2514: #if 0 // TODO
1.1.1.2 root 2515: gen_fcvtgd(rb, rc);
1.1 root 2516: #else
2517: goto invalid_opc;
2518: #endif
2519: break;
2520: case 0x2F:
2521: /* CVTGQ */
1.1.1.2 root 2522: gen_fcvtgq(rb, rc);
1.1 root 2523: break;
2524: case 0x3C:
2525: /* CVTQF */
1.1.1.2 root 2526: gen_fcvtqf(rb, rc);
1.1 root 2527: break;
2528: case 0x3E:
2529: /* CVTQG */
1.1.1.2 root 2530: gen_fcvtqg(rb, rc);
1.1 root 2531: break;
2532: default:
2533: goto invalid_opc;
2534: }
2535: break;
2536: case 0x16:
2537: /* IEEE floating-point */
1.1.1.5 root 2538: switch (fpfn) { /* fn11 & 0x3F */
1.1 root 2539: case 0x00:
2540: /* ADDS */
1.1.1.5 root 2541: gen_fadds(ctx, ra, rb, rc, fn11);
1.1 root 2542: break;
2543: case 0x01:
2544: /* SUBS */
1.1.1.5 root 2545: gen_fsubs(ctx, ra, rb, rc, fn11);
1.1 root 2546: break;
2547: case 0x02:
2548: /* MULS */
1.1.1.5 root 2549: gen_fmuls(ctx, ra, rb, rc, fn11);
1.1 root 2550: break;
2551: case 0x03:
2552: /* DIVS */
1.1.1.5 root 2553: gen_fdivs(ctx, ra, rb, rc, fn11);
1.1 root 2554: break;
2555: case 0x20:
2556: /* ADDT */
1.1.1.5 root 2557: gen_faddt(ctx, ra, rb, rc, fn11);
1.1 root 2558: break;
2559: case 0x21:
2560: /* SUBT */
1.1.1.5 root 2561: gen_fsubt(ctx, ra, rb, rc, fn11);
1.1 root 2562: break;
2563: case 0x22:
2564: /* MULT */
1.1.1.5 root 2565: gen_fmult(ctx, ra, rb, rc, fn11);
1.1 root 2566: break;
2567: case 0x23:
2568: /* DIVT */
1.1.1.5 root 2569: gen_fdivt(ctx, ra, rb, rc, fn11);
1.1 root 2570: break;
2571: case 0x24:
2572: /* CMPTUN */
1.1.1.5 root 2573: gen_fcmptun(ctx, ra, rb, rc, fn11);
1.1 root 2574: break;
2575: case 0x25:
2576: /* CMPTEQ */
1.1.1.5 root 2577: gen_fcmpteq(ctx, ra, rb, rc, fn11);
1.1 root 2578: break;
2579: case 0x26:
2580: /* CMPTLT */
1.1.1.5 root 2581: gen_fcmptlt(ctx, ra, rb, rc, fn11);
1.1 root 2582: break;
2583: case 0x27:
2584: /* CMPTLE */
1.1.1.5 root 2585: gen_fcmptle(ctx, ra, rb, rc, fn11);
1.1 root 2586: break;
2587: case 0x2C:
1.1.1.2 root 2588: if (fn11 == 0x2AC || fn11 == 0x6AC) {
1.1 root 2589: /* CVTST */
1.1.1.5 root 2590: gen_fcvtst(ctx, rb, rc, fn11);
1.1 root 2591: } else {
2592: /* CVTTS */
1.1.1.5 root 2593: gen_fcvtts(ctx, rb, rc, fn11);
1.1 root 2594: }
2595: break;
2596: case 0x2F:
2597: /* CVTTQ */
1.1.1.5 root 2598: gen_fcvttq(ctx, rb, rc, fn11);
1.1 root 2599: break;
2600: case 0x3C:
2601: /* CVTQS */
1.1.1.5 root 2602: gen_fcvtqs(ctx, rb, rc, fn11);
1.1 root 2603: break;
2604: case 0x3E:
2605: /* CVTQT */
1.1.1.5 root 2606: gen_fcvtqt(ctx, rb, rc, fn11);
1.1 root 2607: break;
2608: default:
2609: goto invalid_opc;
2610: }
2611: break;
2612: case 0x17:
2613: switch (fn11) {
2614: case 0x010:
2615: /* CVTLQ */
1.1.1.2 root 2616: gen_fcvtlq(rb, rc);
1.1 root 2617: break;
2618: case 0x020:
1.1.1.2 root 2619: if (likely(rc != 31)) {
1.1.1.5 root 2620: if (ra == rb) {
1.1 root 2621: /* FMOV */
1.1.1.5 root 2622: if (ra == 31)
2623: tcg_gen_movi_i64(cpu_fir[rc], 0);
2624: else
2625: tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
2626: } else {
1.1.1.2 root 2627: /* CPYS */
2628: gen_fcpys(ra, rb, rc);
1.1.1.5 root 2629: }
1.1 root 2630: }
2631: break;
2632: case 0x021:
2633: /* CPYSN */
1.1.1.2 root 2634: gen_fcpysn(ra, rb, rc);
1.1 root 2635: break;
2636: case 0x022:
2637: /* CPYSE */
1.1.1.2 root 2638: gen_fcpyse(ra, rb, rc);
1.1 root 2639: break;
2640: case 0x024:
2641: /* MT_FPCR */
1.1.1.2 root 2642: if (likely(ra != 31))
2643: gen_helper_store_fpcr(cpu_fir[ra]);
2644: else {
2645: TCGv tmp = tcg_const_i64(0);
2646: gen_helper_store_fpcr(tmp);
2647: tcg_temp_free(tmp);
2648: }
1.1 root 2649: break;
2650: case 0x025:
2651: /* MF_FPCR */
1.1.1.2 root 2652: if (likely(ra != 31))
2653: gen_helper_load_fpcr(cpu_fir[ra]);
1.1 root 2654: break;
2655: case 0x02A:
2656: /* FCMOVEQ */
1.1.1.5 root 2657: gen_fcmov(TCG_COND_EQ, ra, rb, rc);
1.1 root 2658: break;
2659: case 0x02B:
2660: /* FCMOVNE */
1.1.1.5 root 2661: gen_fcmov(TCG_COND_NE, ra, rb, rc);
1.1 root 2662: break;
2663: case 0x02C:
2664: /* FCMOVLT */
1.1.1.5 root 2665: gen_fcmov(TCG_COND_LT, ra, rb, rc);
1.1 root 2666: break;
2667: case 0x02D:
2668: /* FCMOVGE */
1.1.1.5 root 2669: gen_fcmov(TCG_COND_GE, ra, rb, rc);
1.1 root 2670: break;
2671: case 0x02E:
2672: /* FCMOVLE */
1.1.1.5 root 2673: gen_fcmov(TCG_COND_LE, ra, rb, rc);
1.1 root 2674: break;
2675: case 0x02F:
2676: /* FCMOVGT */
1.1.1.5 root 2677: gen_fcmov(TCG_COND_GT, ra, rb, rc);
1.1 root 2678: break;
2679: case 0x030:
2680: /* CVTQL */
1.1.1.2 root 2681: gen_fcvtql(rb, rc);
1.1 root 2682: break;
2683: case 0x130:
2684: /* CVTQL/V */
2685: case 0x530:
2686: /* CVTQL/SV */
1.1.1.5 root 2687: /* ??? I'm pretty sure there's nothing that /sv needs to do that
2688: /v doesn't do. The only thing I can think is that /sv is a
2689: valid instruction merely for completeness in the ISA. */
2690: gen_fcvtql_v(ctx, rb, rc);
1.1 root 2691: break;
2692: default:
2693: goto invalid_opc;
2694: }
2695: break;
2696: case 0x18:
2697: switch ((uint16_t)disp16) {
2698: case 0x0000:
2699: /* TRAPB */
1.1.1.5 root 2700: /* No-op. */
1.1 root 2701: break;
2702: case 0x0400:
2703: /* EXCB */
1.1.1.5 root 2704: /* No-op. */
1.1 root 2705: break;
2706: case 0x4000:
2707: /* MB */
2708: /* No-op */
2709: break;
2710: case 0x4400:
2711: /* WMB */
2712: /* No-op */
2713: break;
2714: case 0x8000:
2715: /* FETCH */
2716: /* No-op */
2717: break;
2718: case 0xA000:
2719: /* FETCH_M */
2720: /* No-op */
2721: break;
2722: case 0xC000:
2723: /* RPCC */
1.1.1.2 root 2724: if (ra != 31)
2725: gen_helper_load_pcc(cpu_ir[ra]);
1.1 root 2726: break;
2727: case 0xE000:
2728: /* RC */
1.1.1.5 root 2729: gen_rx(ra, 0);
1.1 root 2730: break;
2731: case 0xE800:
2732: /* ECB */
2733: break;
2734: case 0xF000:
2735: /* RS */
1.1.1.5 root 2736: gen_rx(ra, 1);
1.1 root 2737: break;
2738: case 0xF800:
2739: /* WH64 */
2740: /* No-op */
2741: break;
2742: default:
2743: goto invalid_opc;
2744: }
2745: break;
2746: case 0x19:
2747: /* HW_MFPR (PALcode) */
1.1.1.6 ! root 2748: #ifndef CONFIG_USER_ONLY
! 2749: if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
! 2750: gen_mfpr(ra, insn & 0xffff);
! 2751: break;
1.1.1.2 root 2752: }
1.1 root 2753: #endif
1.1.1.6 ! root 2754: goto invalid_opc;
1.1 root 2755: case 0x1A:
1.1.1.5 root 2756: /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2757: prediction stack action, which of course we don't implement. */
2758: if (rb != 31) {
1.1.1.2 root 2759: tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
1.1.1.5 root 2760: } else {
1.1.1.2 root 2761: tcg_gen_movi_i64(cpu_pc, 0);
1.1.1.5 root 2762: }
2763: if (ra != 31) {
1.1.1.2 root 2764: tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
1.1 root 2765: }
1.1.1.5 root 2766: ret = EXIT_PC_UPDATED;
1.1 root 2767: break;
2768: case 0x1B:
2769: /* HW_LD (PALcode) */
1.1.1.6 ! root 2770: #ifndef CONFIG_USER_ONLY
! 2771: if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
! 2772: TCGv addr;
! 2773:
! 2774: if (ra == 31) {
! 2775: break;
! 2776: }
! 2777:
! 2778: addr = tcg_temp_new();
1.1.1.2 root 2779: if (rb != 31)
2780: tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
2781: else
2782: tcg_gen_movi_i64(addr, disp12);
2783: switch ((insn >> 12) & 0xF) {
2784: case 0x0:
1.1.1.3 root 2785: /* Longword physical access (hw_ldl/p) */
1.1.1.6 ! root 2786: gen_helper_ldl_phys(cpu_ir[ra], addr);
1.1.1.2 root 2787: break;
2788: case 0x1:
1.1.1.3 root 2789: /* Quadword physical access (hw_ldq/p) */
1.1.1.6 ! root 2790: gen_helper_ldq_phys(cpu_ir[ra], addr);
1.1.1.2 root 2791: break;
2792: case 0x2:
1.1.1.3 root 2793: /* Longword physical access with lock (hw_ldl_l/p) */
1.1.1.6 ! root 2794: gen_helper_ldl_l_phys(cpu_ir[ra], addr);
1.1.1.2 root 2795: break;
2796: case 0x3:
1.1.1.3 root 2797: /* Quadword physical access with lock (hw_ldq_l/p) */
1.1.1.6 ! root 2798: gen_helper_ldq_l_phys(cpu_ir[ra], addr);
1.1.1.2 root 2799: break;
2800: case 0x4:
1.1.1.3 root 2801: /* Longword virtual PTE fetch (hw_ldl/v) */
1.1.1.6 ! root 2802: goto invalid_opc;
1.1.1.2 root 2803: case 0x5:
1.1.1.3 root 2804: /* Quadword virtual PTE fetch (hw_ldq/v) */
1.1.1.6 ! root 2805: goto invalid_opc;
1.1.1.2 root 2806: break;
2807: case 0x6:
2808: /* Incpu_ir[ra]id */
1.1.1.3 root 2809: goto invalid_opc;
1.1.1.2 root 2810: case 0x7:
2811: /* Incpu_ir[ra]id */
1.1.1.3 root 2812: goto invalid_opc;
1.1.1.2 root 2813: case 0x8:
1.1.1.3 root 2814: /* Longword virtual access (hw_ldl) */
1.1.1.6 ! root 2815: goto invalid_opc;
1.1.1.2 root 2816: case 0x9:
1.1.1.3 root 2817: /* Quadword virtual access (hw_ldq) */
1.1.1.6 ! root 2818: goto invalid_opc;
1.1.1.2 root 2819: case 0xA:
1.1.1.3 root 2820: /* Longword virtual access with protection check (hw_ldl/w) */
1.1.1.6 ! root 2821: tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
1.1.1.2 root 2822: break;
2823: case 0xB:
1.1.1.3 root 2824: /* Quadword virtual access with protection check (hw_ldq/w) */
1.1.1.6 ! root 2825: tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
1.1.1.2 root 2826: break;
2827: case 0xC:
1.1.1.3 root 2828: /* Longword virtual access with alt access mode (hw_ldl/a)*/
1.1.1.6 ! root 2829: goto invalid_opc;
1.1.1.2 root 2830: case 0xD:
1.1.1.3 root 2831: /* Quadword virtual access with alt access mode (hw_ldq/a) */
1.1.1.6 ! root 2832: goto invalid_opc;
1.1.1.2 root 2833: case 0xE:
2834: /* Longword virtual access with alternate access mode and
1.1.1.6 ! root 2835: protection checks (hw_ldl/wa) */
! 2836: tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
1.1.1.2 root 2837: break;
2838: case 0xF:
2839: /* Quadword virtual access with alternate access mode and
1.1.1.6 ! root 2840: protection checks (hw_ldq/wa) */
! 2841: tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
1.1.1.2 root 2842: break;
2843: }
2844: tcg_temp_free(addr);
1.1.1.6 ! root 2845: break;
1.1 root 2846: }
2847: #endif
1.1.1.6 ! root 2848: goto invalid_opc;
1.1 root 2849: case 0x1C:
2850: switch (fn7) {
2851: case 0x00:
2852: /* SEXTB */
1.1.1.6 ! root 2853: if ((ctx->tb->flags & TB_FLAGS_AMASK_BWX) == 0) {
1.1 root 2854: goto invalid_opc;
1.1.1.6 ! root 2855: }
1.1.1.2 root 2856: if (likely(rc != 31)) {
2857: if (islit)
2858: tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit));
2859: else
2860: tcg_gen_ext8s_i64(cpu_ir[rc], cpu_ir[rb]);
2861: }
1.1 root 2862: break;
2863: case 0x01:
2864: /* SEXTW */
1.1.1.6 ! root 2865: if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
! 2866: if (likely(rc != 31)) {
! 2867: if (islit) {
! 2868: tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
! 2869: } else {
! 2870: tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
! 2871: }
! 2872: }
! 2873: break;
1.1.1.2 root 2874: }
1.1.1.6 ! root 2875: goto invalid_opc;
1.1 root 2876: case 0x30:
2877: /* CTPOP */
1.1.1.6 ! root 2878: if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
! 2879: if (likely(rc != 31)) {
! 2880: if (islit) {
! 2881: tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
! 2882: } else {
! 2883: gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
! 2884: }
! 2885: }
! 2886: break;
1.1.1.2 root 2887: }
1.1.1.6 ! root 2888: goto invalid_opc;
1.1 root 2889: case 0x31:
2890: /* PERR */
1.1.1.6 ! root 2891: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2892: gen_perr(ra, rb, rc, islit, lit);
! 2893: break;
! 2894: }
! 2895: goto invalid_opc;
1.1 root 2896: case 0x32:
2897: /* CTLZ */
1.1.1.6 ! root 2898: if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
! 2899: if (likely(rc != 31)) {
! 2900: if (islit) {
! 2901: tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
! 2902: } else {
! 2903: gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
! 2904: }
! 2905: }
! 2906: break;
1.1.1.2 root 2907: }
1.1.1.6 ! root 2908: goto invalid_opc;
1.1 root 2909: case 0x33:
2910: /* CTTZ */
1.1.1.6 ! root 2911: if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
! 2912: if (likely(rc != 31)) {
! 2913: if (islit) {
! 2914: tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
! 2915: } else {
! 2916: gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
! 2917: }
! 2918: }
! 2919: break;
1.1.1.2 root 2920: }
1.1.1.6 ! root 2921: goto invalid_opc;
1.1 root 2922: case 0x34:
2923: /* UNPKBW */
1.1.1.6 ! root 2924: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2925: if (real_islit || ra != 31) {
! 2926: goto invalid_opc;
! 2927: }
! 2928: gen_unpkbw(rb, rc);
! 2929: break;
! 2930: }
! 2931: goto invalid_opc;
1.1 root 2932: case 0x35:
1.1.1.5 root 2933: /* UNPKBL */
1.1.1.6 ! root 2934: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2935: if (real_islit || ra != 31) {
! 2936: goto invalid_opc;
! 2937: }
! 2938: gen_unpkbl(rb, rc);
! 2939: break;
! 2940: }
! 2941: goto invalid_opc;
1.1 root 2942: case 0x36:
2943: /* PKWB */
1.1.1.6 ! root 2944: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2945: if (real_islit || ra != 31) {
! 2946: goto invalid_opc;
! 2947: }
! 2948: gen_pkwb(rb, rc);
! 2949: break;
! 2950: }
! 2951: goto invalid_opc;
1.1 root 2952: case 0x37:
2953: /* PKLB */
1.1.1.6 ! root 2954: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2955: if (real_islit || ra != 31) {
! 2956: goto invalid_opc;
! 2957: }
! 2958: gen_pklb(rb, rc);
! 2959: break;
! 2960: }
! 2961: goto invalid_opc;
1.1 root 2962: case 0x38:
2963: /* MINSB8 */
1.1.1.6 ! root 2964: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2965: gen_minsb8(ra, rb, rc, islit, lit);
! 2966: break;
! 2967: }
! 2968: goto invalid_opc;
1.1 root 2969: case 0x39:
2970: /* MINSW4 */
1.1.1.6 ! root 2971: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2972: gen_minsw4(ra, rb, rc, islit, lit);
! 2973: break;
! 2974: }
! 2975: goto invalid_opc;
1.1 root 2976: case 0x3A:
2977: /* MINUB8 */
1.1.1.6 ! root 2978: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2979: gen_minub8(ra, rb, rc, islit, lit);
! 2980: break;
! 2981: }
! 2982: goto invalid_opc;
1.1 root 2983: case 0x3B:
2984: /* MINUW4 */
1.1.1.6 ! root 2985: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2986: gen_minuw4(ra, rb, rc, islit, lit);
! 2987: break;
! 2988: }
! 2989: goto invalid_opc;
1.1 root 2990: case 0x3C:
2991: /* MAXUB8 */
1.1.1.6 ! root 2992: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 2993: gen_maxub8(ra, rb, rc, islit, lit);
! 2994: break;
! 2995: }
! 2996: goto invalid_opc;
1.1 root 2997: case 0x3D:
2998: /* MAXUW4 */
1.1.1.6 ! root 2999: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 3000: gen_maxuw4(ra, rb, rc, islit, lit);
! 3001: break;
! 3002: }
! 3003: goto invalid_opc;
1.1 root 3004: case 0x3E:
3005: /* MAXSB8 */
1.1.1.6 ! root 3006: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 3007: gen_maxsb8(ra, rb, rc, islit, lit);
! 3008: break;
! 3009: }
! 3010: goto invalid_opc;
1.1 root 3011: case 0x3F:
3012: /* MAXSW4 */
1.1.1.6 ! root 3013: if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
! 3014: gen_maxsw4(ra, rb, rc, islit, lit);
! 3015: break;
! 3016: }
! 3017: goto invalid_opc;
1.1 root 3018: case 0x70:
3019: /* FTOIT */
1.1.1.6 ! root 3020: if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
1.1 root 3021: goto invalid_opc;
1.1.1.6 ! root 3022: }
1.1.1.2 root 3023: if (likely(rc != 31)) {
3024: if (ra != 31)
3025: tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
3026: else
3027: tcg_gen_movi_i64(cpu_ir[rc], 0);
3028: }
1.1 root 3029: break;
3030: case 0x78:
3031: /* FTOIS */
1.1.1.6 ! root 3032: if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
1.1 root 3033: goto invalid_opc;
1.1.1.6 ! root 3034: }
1.1.1.2 root 3035: if (rc != 31) {
3036: TCGv_i32 tmp1 = tcg_temp_new_i32();
3037: if (ra != 31)
3038: gen_helper_s_to_memory(tmp1, cpu_fir[ra]);
3039: else {
3040: TCGv tmp2 = tcg_const_i64(0);
3041: gen_helper_s_to_memory(tmp1, tmp2);
3042: tcg_temp_free(tmp2);
3043: }
3044: tcg_gen_ext_i32_i64(cpu_ir[rc], tmp1);
3045: tcg_temp_free_i32(tmp1);
3046: }
1.1 root 3047: break;
3048: default:
3049: goto invalid_opc;
3050: }
3051: break;
3052: case 0x1D:
3053: /* HW_MTPR (PALcode) */
1.1.1.6 ! root 3054: #ifndef CONFIG_USER_ONLY
! 3055: if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
! 3056: gen_mtpr(rb, insn & 0xffff);
! 3057: break;
1.1.1.2 root 3058: }
1.1 root 3059: #endif
3060: goto invalid_opc;
1.1.1.6 ! root 3061: case 0x1E:
! 3062: /* HW_RET (PALcode) */
! 3063: #ifndef CONFIG_USER_ONLY
! 3064: if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
! 3065: if (rb == 31) {
! 3066: /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
! 3067: address from EXC_ADDR. This turns out to be useful for our
! 3068: emulation PALcode, so continue to accept it. */
! 3069: TCGv tmp = tcg_temp_new();
! 3070: tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUState, exc_addr));
! 3071: gen_helper_hw_ret(tmp);
! 3072: tcg_temp_free(tmp);
! 3073: } else {
! 3074: gen_helper_hw_ret(cpu_ir[rb]);
! 3075: }
! 3076: ret = EXIT_PC_UPDATED;
! 3077: break;
1.1 root 3078: }
3079: #endif
1.1.1.6 ! root 3080: goto invalid_opc;
1.1 root 3081: case 0x1F:
3082: /* HW_ST (PALcode) */
1.1.1.6 ! root 3083: #ifndef CONFIG_USER_ONLY
! 3084: if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
1.1.1.2 root 3085: TCGv addr, val;
3086: addr = tcg_temp_new();
3087: if (rb != 31)
3088: tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
3089: else
3090: tcg_gen_movi_i64(addr, disp12);
3091: if (ra != 31)
3092: val = cpu_ir[ra];
3093: else {
3094: val = tcg_temp_new();
3095: tcg_gen_movi_i64(val, 0);
3096: }
3097: switch ((insn >> 12) & 0xF) {
3098: case 0x0:
3099: /* Longword physical access */
1.1.1.6 ! root 3100: gen_helper_stl_phys(addr, val);
1.1.1.2 root 3101: break;
3102: case 0x1:
3103: /* Quadword physical access */
1.1.1.6 ! root 3104: gen_helper_stq_phys(addr, val);
1.1.1.2 root 3105: break;
3106: case 0x2:
3107: /* Longword physical access with lock */
1.1.1.6 ! root 3108: gen_helper_stl_c_phys(val, addr, val);
1.1.1.2 root 3109: break;
3110: case 0x3:
3111: /* Quadword physical access with lock */
1.1.1.6 ! root 3112: gen_helper_stq_c_phys(val, addr, val);
1.1.1.2 root 3113: break;
3114: case 0x4:
3115: /* Longword virtual access */
1.1.1.6 ! root 3116: goto invalid_opc;
1.1.1.2 root 3117: case 0x5:
3118: /* Quadword virtual access */
1.1.1.6 ! root 3119: goto invalid_opc;
1.1.1.2 root 3120: case 0x6:
3121: /* Invalid */
3122: goto invalid_opc;
3123: case 0x7:
3124: /* Invalid */
3125: goto invalid_opc;
3126: case 0x8:
3127: /* Invalid */
3128: goto invalid_opc;
3129: case 0x9:
3130: /* Invalid */
3131: goto invalid_opc;
3132: case 0xA:
3133: /* Invalid */
3134: goto invalid_opc;
3135: case 0xB:
3136: /* Invalid */
3137: goto invalid_opc;
3138: case 0xC:
3139: /* Longword virtual access with alternate access mode */
1.1.1.6 ! root 3140: goto invalid_opc;
1.1.1.2 root 3141: case 0xD:
3142: /* Quadword virtual access with alternate access mode */
1.1.1.6 ! root 3143: goto invalid_opc;
1.1.1.2 root 3144: case 0xE:
3145: /* Invalid */
3146: goto invalid_opc;
3147: case 0xF:
3148: /* Invalid */
3149: goto invalid_opc;
3150: }
1.1.1.3 root 3151: if (ra == 31)
1.1.1.2 root 3152: tcg_temp_free(val);
3153: tcg_temp_free(addr);
1.1.1.6 ! root 3154: break;
1.1 root 3155: }
3156: #endif
1.1.1.6 ! root 3157: goto invalid_opc;
1.1 root 3158: case 0x20:
3159: /* LDF */
1.1.1.2 root 3160: gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
1.1 root 3161: break;
3162: case 0x21:
3163: /* LDG */
1.1.1.2 root 3164: gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
1.1 root 3165: break;
3166: case 0x22:
3167: /* LDS */
1.1.1.2 root 3168: gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
1.1 root 3169: break;
3170: case 0x23:
3171: /* LDT */
1.1.1.2 root 3172: gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
1.1 root 3173: break;
3174: case 0x24:
3175: /* STF */
1.1.1.5 root 3176: gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
1.1 root 3177: break;
3178: case 0x25:
3179: /* STG */
1.1.1.5 root 3180: gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
1.1 root 3181: break;
3182: case 0x26:
3183: /* STS */
1.1.1.5 root 3184: gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
1.1 root 3185: break;
3186: case 0x27:
3187: /* STT */
1.1.1.5 root 3188: gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
1.1 root 3189: break;
3190: case 0x28:
3191: /* LDL */
1.1.1.2 root 3192: gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
1.1 root 3193: break;
3194: case 0x29:
3195: /* LDQ */
1.1.1.2 root 3196: gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
1.1 root 3197: break;
3198: case 0x2A:
3199: /* LDL_L */
1.1.1.2 root 3200: gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
1.1 root 3201: break;
3202: case 0x2B:
3203: /* LDQ_L */
1.1.1.2 root 3204: gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
1.1 root 3205: break;
3206: case 0x2C:
3207: /* STL */
1.1.1.5 root 3208: gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
1.1 root 3209: break;
3210: case 0x2D:
3211: /* STQ */
1.1.1.5 root 3212: gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
1.1 root 3213: break;
3214: case 0x2E:
3215: /* STL_C */
1.1.1.5 root 3216: ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
1.1 root 3217: break;
3218: case 0x2F:
3219: /* STQ_C */
1.1.1.5 root 3220: ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
1.1 root 3221: break;
3222: case 0x30:
3223: /* BR */
1.1.1.5 root 3224: ret = gen_bdirect(ctx, ra, disp21);
1.1 root 3225: break;
1.1.1.2 root 3226: case 0x31: /* FBEQ */
1.1.1.5 root 3227: ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
3228: break;
1.1.1.2 root 3229: case 0x32: /* FBLT */
1.1.1.5 root 3230: ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
3231: break;
1.1.1.2 root 3232: case 0x33: /* FBLE */
1.1.1.5 root 3233: ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
1.1 root 3234: break;
3235: case 0x34:
3236: /* BSR */
1.1.1.5 root 3237: ret = gen_bdirect(ctx, ra, disp21);
1.1 root 3238: break;
1.1.1.2 root 3239: case 0x35: /* FBNE */
1.1.1.5 root 3240: ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
3241: break;
1.1.1.2 root 3242: case 0x36: /* FBGE */
1.1.1.5 root 3243: ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
3244: break;
1.1.1.2 root 3245: case 0x37: /* FBGT */
1.1.1.5 root 3246: ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
1.1 root 3247: break;
3248: case 0x38:
3249: /* BLBC */
1.1.1.5 root 3250: ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
1.1 root 3251: break;
3252: case 0x39:
3253: /* BEQ */
1.1.1.5 root 3254: ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
1.1 root 3255: break;
3256: case 0x3A:
3257: /* BLT */
1.1.1.5 root 3258: ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
1.1 root 3259: break;
3260: case 0x3B:
3261: /* BLE */
1.1.1.5 root 3262: ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
1.1 root 3263: break;
3264: case 0x3C:
3265: /* BLBS */
1.1.1.5 root 3266: ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
1.1 root 3267: break;
3268: case 0x3D:
3269: /* BNE */
1.1.1.5 root 3270: ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
1.1 root 3271: break;
3272: case 0x3E:
3273: /* BGE */
1.1.1.5 root 3274: ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
1.1 root 3275: break;
3276: case 0x3F:
3277: /* BGT */
1.1.1.5 root 3278: ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
1.1 root 3279: break;
3280: invalid_opc:
1.1.1.5 root 3281: ret = gen_invalid(ctx);
1.1 root 3282: break;
3283: }
3284:
3285: return ret;
3286: }
3287:
1.1.1.4 root 3288: static inline void gen_intermediate_code_internal(CPUState *env,
3289: TranslationBlock *tb,
3290: int search_pc)
1.1 root 3291: {
3292: DisasContext ctx, *ctxp = &ctx;
3293: target_ulong pc_start;
3294: uint32_t insn;
3295: uint16_t *gen_opc_end;
1.1.1.2 root 3296: CPUBreakpoint *bp;
1.1 root 3297: int j, lj = -1;
1.1.1.5 root 3298: ExitStatus ret;
1.1.1.2 root 3299: int num_insns;
3300: int max_insns;
1.1 root 3301:
3302: pc_start = tb->pc;
3303: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1.1.1.5 root 3304:
3305: ctx.tb = tb;
3306: ctx.env = env;
1.1 root 3307: ctx.pc = pc_start;
1.1.1.6 ! root 3308: ctx.mem_idx = cpu_mmu_index(env);
1.1.1.5 root 3309:
3310: /* ??? Every TB begins with unset rounding mode, to be initialized on
3311: the first fp insn of the TB. Alternately we could define a proper
3312: default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
3313: to reset the FP_STATUS to that default at the end of any TB that
3314: changes the default. We could even (gasp) dynamiclly figure out
3315: what default would be most efficient given the running program. */
3316: ctx.tb_rm = -1;
3317: /* Similarly for flush-to-zero. */
3318: ctx.tb_ftz = -1;
3319:
1.1.1.2 root 3320: num_insns = 0;
3321: max_insns = tb->cflags & CF_COUNT_MASK;
3322: if (max_insns == 0)
3323: max_insns = CF_COUNT_MASK;
3324:
3325: gen_icount_start();
1.1.1.5 root 3326: do {
1.1.1.4 root 3327: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
3328: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1.1.1.2 root 3329: if (bp->pc == ctx.pc) {
1.1 root 3330: gen_excp(&ctx, EXCP_DEBUG, 0);
3331: break;
3332: }
3333: }
3334: }
3335: if (search_pc) {
3336: j = gen_opc_ptr - gen_opc_buf;
3337: if (lj < j) {
3338: lj++;
3339: while (lj < j)
3340: gen_opc_instr_start[lj++] = 0;
3341: }
1.1.1.3 root 3342: gen_opc_pc[lj] = ctx.pc;
3343: gen_opc_instr_start[lj] = 1;
3344: gen_opc_icount[lj] = num_insns;
1.1 root 3345: }
1.1.1.2 root 3346: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3347: gen_io_start();
1.1 root 3348: insn = ldl_code(ctx.pc);
1.1.1.2 root 3349: num_insns++;
3350:
1.1.1.5 root 3351: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
3352: tcg_gen_debug_insn_start(ctx.pc);
3353: }
1.1.1.3 root 3354:
1.1.1.5 root 3355: ctx.pc += 4;
3356: ret = translate_one(ctxp, insn);
1.1.1.3 root 3357:
1.1.1.6 ! root 3358: /* If we reach a page boundary, are single stepping,
! 3359: or exhaust instruction count, stop generation. */
! 3360: if (ret == NO_EXIT
! 3361: && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
! 3362: || gen_opc_ptr >= gen_opc_end
! 3363: || num_insns >= max_insns
! 3364: || singlestep
! 3365: || env->singlestep_enabled)) {
! 3366: ret = EXIT_PC_STALE;
1.1.1.3 root 3367: }
1.1.1.5 root 3368: } while (ret == NO_EXIT);
3369:
3370: if (tb->cflags & CF_LAST_IO) {
3371: gen_io_end();
1.1 root 3372: }
1.1.1.5 root 3373:
3374: switch (ret) {
3375: case EXIT_GOTO_TB:
3376: case EXIT_NORETURN:
3377: break;
3378: case EXIT_PC_STALE:
1.1.1.2 root 3379: tcg_gen_movi_i64(cpu_pc, ctx.pc);
1.1.1.5 root 3380: /* FALLTHRU */
3381: case EXIT_PC_UPDATED:
1.1.1.6 ! root 3382: if (env->singlestep_enabled) {
! 3383: gen_excp_1(EXCP_DEBUG, 0);
! 3384: } else {
! 3385: tcg_gen_exit_tb(0);
! 3386: }
1.1.1.5 root 3387: break;
3388: default:
3389: abort();
1.1 root 3390: }
1.1.1.5 root 3391:
1.1.1.2 root 3392: gen_icount_end(tb, num_insns);
1.1 root 3393: *gen_opc_ptr = INDEX_op_end;
3394: if (search_pc) {
3395: j = gen_opc_ptr - gen_opc_buf;
3396: lj++;
3397: while (lj <= j)
3398: gen_opc_instr_start[lj++] = 0;
3399: } else {
3400: tb->size = ctx.pc - pc_start;
1.1.1.2 root 3401: tb->icount = num_insns;
1.1 root 3402: }
1.1.1.5 root 3403:
3404: #ifdef DEBUG_DISAS
1.1.1.2 root 3405: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
3406: qemu_log("IN: %s\n", lookup_symbol(pc_start));
3407: log_target_disas(pc_start, ctx.pc - pc_start, 1);
3408: qemu_log("\n");
1.1 root 3409: }
3410: #endif
3411: }
3412:
1.1.1.2 root 3413: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1.1 root 3414: {
1.1.1.2 root 3415: gen_intermediate_code_internal(env, tb, 0);
1.1 root 3416: }
3417:
1.1.1.2 root 3418: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 3419: {
1.1.1.2 root 3420: gen_intermediate_code_internal(env, tb, 1);
1.1 root 3421: }
3422:
1.1.1.5 root 3423: struct cpu_def_t {
3424: const char *name;
3425: int implver, amask;
3426: };
3427:
3428: static const struct cpu_def_t cpu_defs[] = {
3429: { "ev4", IMPLVER_2106x, 0 },
3430: { "ev5", IMPLVER_21164, 0 },
3431: { "ev56", IMPLVER_21164, AMASK_BWX },
3432: { "pca56", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
3433: { "ev6", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
3434: { "ev67", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3435: | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
3436: { "ev68", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3437: | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
3438: { "21064", IMPLVER_2106x, 0 },
3439: { "21164", IMPLVER_21164, 0 },
3440: { "21164a", IMPLVER_21164, AMASK_BWX },
3441: { "21164pc", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
3442: { "21264", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
3443: { "21264a", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
3444: | AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }
3445: };
3446:
1.1 root 3447: CPUAlphaState * cpu_alpha_init (const char *cpu_model)
3448: {
3449: CPUAlphaState *env;
1.1.1.5 root 3450: int implver, amask, i, max;
1.1 root 3451:
3452: env = qemu_mallocz(sizeof(CPUAlphaState));
3453: cpu_exec_init(env);
1.1.1.2 root 3454: alpha_translate_init();
1.1 root 3455: tlb_flush(env, 1);
1.1.1.5 root 3456:
3457: /* Default to ev67; no reason not to emulate insns by default. */
3458: implver = IMPLVER_21264;
3459: amask = (AMASK_BWX | AMASK_FIX | AMASK_CIX | AMASK_MVI
3460: | AMASK_TRAP | AMASK_PREFETCH);
3461:
3462: max = ARRAY_SIZE(cpu_defs);
3463: for (i = 0; i < max; i++) {
3464: if (strcmp (cpu_model, cpu_defs[i].name) == 0) {
3465: implver = cpu_defs[i].implver;
3466: amask = cpu_defs[i].amask;
3467: break;
3468: }
3469: }
3470: env->implver = implver;
3471: env->amask = amask;
3472:
1.1 root 3473: #if defined (CONFIG_USER_ONLY)
1.1.1.6 ! root 3474: env->ps = PS_USER_MODE;
1.1.1.5 root 3475: cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
3476: | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
3477: #endif
3478: env->lock_addr = -1;
1.1.1.6 ! root 3479: env->fen = 1;
1.1 root 3480:
1.1.1.3 root 3481: qemu_init_vcpu(env);
1.1 root 3482: return env;
3483: }
3484:
1.1.1.6 ! root 3485: void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1.1.1.2 root 3486: {
3487: env->pc = gen_opc_pc[pc_pos];
3488: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.