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