|
|
1.1 root 1: /*
2: * Alpha emulation cpu translation for qemu.
3: *
4: * Copyright (c) 2007 Jocelyn Mayer
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, write to the Free Software
1.1.1.2 ! root 18: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
1.1 root 19: */
20:
21: #include <stdint.h>
22: #include <stdlib.h>
23: #include <stdio.h>
24:
25: #include "cpu.h"
26: #include "exec-all.h"
27: #include "disas.h"
1.1.1.2 ! root 28: #include "host-utils.h"
! 29: #include "tcg-op.h"
! 30: #include "qemu-common.h"
! 31:
! 32: #include "helper.h"
! 33: #define GEN_HELPER 1
! 34: #include "helper.h"
1.1 root 35:
1.1.1.2 ! root 36: /* #define DO_SINGLE_STEP */
1.1 root 37: #define ALPHA_DEBUG_DISAS
1.1.1.2 ! root 38: /* #define DO_TB_FLUSH */
! 39:
! 40:
! 41: #ifdef ALPHA_DEBUG_DISAS
! 42: # define LOG_DISAS(...) qemu_log(__VA_ARGS__)
! 43: #else
! 44: # define LOG_DISAS(...) do { } while (0)
! 45: #endif
1.1 root 46:
47: typedef struct DisasContext DisasContext;
48: struct DisasContext {
49: uint64_t pc;
50: int mem_idx;
51: #if !defined (CONFIG_USER_ONLY)
52: int pal_mode;
53: #endif
54: uint32_t amask;
55: };
56:
1.1.1.2 ! root 57: /* global register indexes */
! 58: static TCGv_ptr cpu_env;
! 59: static TCGv cpu_ir[31];
! 60: static TCGv cpu_fir[31];
! 61: static TCGv cpu_pc;
! 62: static TCGv cpu_lock;
1.1 root 63:
1.1.1.2 ! root 64: /* register names */
! 65: static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
1.1 root 66:
1.1.1.2 ! root 67: #include "gen-icount.h"
1.1 root 68:
1.1.1.2 ! root 69: static void alpha_translate_init(void)
1.1 root 70: {
1.1.1.2 ! root 71: int i;
! 72: char *p;
! 73: static int done_init = 0;
1.1 root 74:
1.1.1.2 ! root 75: if (done_init)
! 76: return;
1.1 root 77:
1.1.1.2 ! root 78: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1.1 root 79:
1.1.1.2 ! root 80: p = cpu_reg_names;
! 81: for (i = 0; i < 31; i++) {
! 82: sprintf(p, "ir%d", i);
! 83: cpu_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
! 84: offsetof(CPUState, ir[i]), p);
! 85: p += (i < 10) ? 4 : 5;
1.1 root 86:
1.1.1.2 ! root 87: sprintf(p, "fir%d", i);
! 88: cpu_fir[i] = tcg_global_mem_new_i64(TCG_AREG0,
! 89: offsetof(CPUState, fir[i]), p);
! 90: p += (i < 10) ? 5 : 6;
1.1 root 91: }
92:
1.1.1.2 ! root 93: cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
! 94: offsetof(CPUState, pc), "pc");
1.1 root 95:
1.1.1.2 ! root 96: cpu_lock = tcg_global_mem_new_i64(TCG_AREG0,
! 97: offsetof(CPUState, lock), "lock");
1.1 root 98:
1.1.1.2 ! root 99: /* register helpers */
! 100: #define GEN_HELPER 2
! 101: #include "helper.h"
1.1 root 102:
1.1.1.2 ! root 103: done_init = 1;
! 104: }
1.1 root 105:
1.1.1.2 ! root 106: static always_inline void gen_excp (DisasContext *ctx,
! 107: int exception, int error_code)
1.1 root 108: {
1.1.1.2 ! root 109: TCGv_i32 tmp1, tmp2;
! 110:
! 111: tcg_gen_movi_i64(cpu_pc, ctx->pc);
! 112: tmp1 = tcg_const_i32(exception);
! 113: tmp2 = tcg_const_i32(error_code);
! 114: gen_helper_excp(tmp1, tmp2);
! 115: tcg_temp_free_i32(tmp2);
! 116: tcg_temp_free_i32(tmp1);
1.1 root 117: }
118:
1.1.1.2 ! root 119: static always_inline void gen_invalid (DisasContext *ctx)
1.1 root 120: {
1.1.1.2 ! root 121: gen_excp(ctx, EXCP_OPCDEC, 0);
1.1 root 122: }
123:
1.1.1.2 ! root 124: static always_inline void gen_qemu_ldf (TCGv t0, TCGv t1, int flags)
1.1 root 125: {
1.1.1.2 ! root 126: TCGv tmp = tcg_temp_new();
! 127: TCGv_i32 tmp32 = tcg_temp_new_i32();
! 128: tcg_gen_qemu_ld32u(tmp, t1, flags);
! 129: tcg_gen_trunc_i64_i32(tmp32, tmp);
! 130: gen_helper_memory_to_f(t0, tmp32);
! 131: tcg_temp_free_i32(tmp32);
! 132: tcg_temp_free(tmp);
1.1 root 133: }
134:
1.1.1.2 ! root 135: static always_inline void gen_qemu_ldg (TCGv t0, TCGv t1, int flags)
1.1 root 136: {
1.1.1.2 ! root 137: TCGv tmp = tcg_temp_new();
! 138: tcg_gen_qemu_ld64(tmp, t1, flags);
! 139: gen_helper_memory_to_g(t0, tmp);
! 140: tcg_temp_free(tmp);
1.1 root 141: }
142:
1.1.1.2 ! root 143: static always_inline void gen_qemu_lds (TCGv t0, TCGv t1, int flags)
1.1 root 144: {
1.1.1.2 ! root 145: TCGv tmp = tcg_temp_new();
! 146: TCGv_i32 tmp32 = tcg_temp_new_i32();
! 147: tcg_gen_qemu_ld32u(tmp, t1, flags);
! 148: tcg_gen_trunc_i64_i32(tmp32, tmp);
! 149: gen_helper_memory_to_s(t0, tmp32);
! 150: tcg_temp_free_i32(tmp32);
! 151: tcg_temp_free(tmp);
1.1 root 152: }
153:
1.1.1.2 ! root 154: static always_inline void gen_qemu_ldl_l (TCGv t0, TCGv t1, int flags)
1.1 root 155: {
1.1.1.2 ! root 156: tcg_gen_mov_i64(cpu_lock, t1);
! 157: tcg_gen_qemu_ld32s(t0, t1, flags);
1.1 root 158: }
159:
1.1.1.2 ! root 160: static always_inline void gen_qemu_ldq_l (TCGv t0, TCGv t1, int flags)
1.1 root 161: {
1.1.1.2 ! root 162: tcg_gen_mov_i64(cpu_lock, t1);
! 163: tcg_gen_qemu_ld64(t0, t1, flags);
1.1 root 164: }
165:
1.1.1.2 ! root 166: static always_inline void gen_load_mem (DisasContext *ctx,
! 167: void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1, int flags),
! 168: int ra, int rb, int32_t disp16,
! 169: int fp, int clear)
1.1 root 170: {
1.1.1.2 ! root 171: TCGv addr;
! 172:
! 173: if (unlikely(ra == 31))
! 174: return;
! 175:
! 176: addr = tcg_temp_new();
! 177: if (rb != 31) {
! 178: tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
! 179: if (clear)
! 180: tcg_gen_andi_i64(addr, addr, ~0x7);
1.1 root 181: } else {
1.1.1.2 ! root 182: if (clear)
! 183: disp16 &= ~0x7;
! 184: tcg_gen_movi_i64(addr, disp16);
1.1 root 185: }
1.1.1.2 ! root 186: if (fp)
! 187: tcg_gen_qemu_load(cpu_fir[ra], addr, ctx->mem_idx);
! 188: else
! 189: tcg_gen_qemu_load(cpu_ir[ra], addr, ctx->mem_idx);
! 190: tcg_temp_free(addr);
1.1 root 191: }
192:
1.1.1.2 ! root 193: static always_inline void gen_qemu_stf (TCGv t0, TCGv t1, int flags)
1.1 root 194: {
1.1.1.2 ! root 195: TCGv_i32 tmp32 = tcg_temp_new_i32();
! 196: TCGv tmp = tcg_temp_new();
! 197: gen_helper_f_to_memory(tmp32, t0);
! 198: tcg_gen_extu_i32_i64(tmp, tmp32);
! 199: tcg_gen_qemu_st32(tmp, t1, flags);
! 200: tcg_temp_free(tmp);
! 201: tcg_temp_free_i32(tmp32);
1.1 root 202: }
203:
1.1.1.2 ! root 204: static always_inline void gen_qemu_stg (TCGv t0, TCGv t1, int flags)
1.1 root 205: {
1.1.1.2 ! root 206: TCGv tmp = tcg_temp_new();
! 207: gen_helper_g_to_memory(tmp, t0);
! 208: tcg_gen_qemu_st64(tmp, t1, flags);
! 209: tcg_temp_free(tmp);
1.1 root 210: }
211:
1.1.1.2 ! root 212: static always_inline void gen_qemu_sts (TCGv t0, TCGv t1, int flags)
1.1 root 213: {
1.1.1.2 ! root 214: TCGv_i32 tmp32 = tcg_temp_new_i32();
! 215: TCGv tmp = tcg_temp_new();
! 216: gen_helper_s_to_memory(tmp32, t0);
! 217: tcg_gen_extu_i32_i64(tmp, tmp32);
! 218: tcg_gen_qemu_st32(tmp, t1, flags);
! 219: tcg_temp_free(tmp);
! 220: tcg_temp_free_i32(tmp32);
1.1 root 221: }
222:
1.1.1.2 ! root 223: static always_inline void gen_qemu_stl_c (TCGv t0, TCGv t1, int flags)
1.1 root 224: {
1.1.1.2 ! root 225: int l1, l2;
! 226:
! 227: l1 = gen_new_label();
! 228: l2 = gen_new_label();
! 229: tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
! 230: tcg_gen_qemu_st32(t0, t1, flags);
! 231: tcg_gen_movi_i64(t0, 1);
! 232: tcg_gen_br(l2);
! 233: gen_set_label(l1);
! 234: tcg_gen_movi_i64(t0, 0);
! 235: gen_set_label(l2);
! 236: tcg_gen_movi_i64(cpu_lock, -1);
1.1 root 237: }
238:
1.1.1.2 ! root 239: static always_inline void gen_qemu_stq_c (TCGv t0, TCGv t1, int flags)
1.1 root 240: {
1.1.1.2 ! root 241: int l1, l2;
! 242:
! 243: l1 = gen_new_label();
! 244: l2 = gen_new_label();
! 245: tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
! 246: tcg_gen_qemu_st64(t0, t1, flags);
! 247: tcg_gen_movi_i64(t0, 1);
! 248: tcg_gen_br(l2);
! 249: gen_set_label(l1);
! 250: tcg_gen_movi_i64(t0, 0);
! 251: gen_set_label(l2);
! 252: tcg_gen_movi_i64(cpu_lock, -1);
1.1 root 253: }
254:
255: static always_inline void gen_store_mem (DisasContext *ctx,
1.1.1.2 ! root 256: void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1, int flags),
1.1 root 257: int ra, int rb, int32_t disp16,
1.1.1.2 ! root 258: int fp, int clear, int local)
1.1 root 259: {
1.1.1.2 ! root 260: TCGv addr;
! 261: if (local)
! 262: addr = tcg_temp_local_new();
! 263: else
! 264: addr = tcg_temp_new();
! 265: if (rb != 31) {
! 266: tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
! 267: if (clear)
! 268: tcg_gen_andi_i64(addr, addr, ~0x7);
! 269: } else {
! 270: if (clear)
! 271: disp16 &= ~0x7;
! 272: tcg_gen_movi_i64(addr, disp16);
1.1 root 273: }
1.1.1.2 ! root 274: if (ra != 31) {
! 275: if (fp)
! 276: tcg_gen_qemu_store(cpu_fir[ra], addr, ctx->mem_idx);
! 277: else
! 278: tcg_gen_qemu_store(cpu_ir[ra], addr, ctx->mem_idx);
! 279: } else {
! 280: TCGv zero;
! 281: if (local)
! 282: zero = tcg_const_local_i64(0);
! 283: else
! 284: zero = tcg_const_i64(0);
! 285: tcg_gen_qemu_store(zero, addr, ctx->mem_idx);
! 286: tcg_temp_free(zero);
1.1 root 287: }
1.1.1.2 ! root 288: tcg_temp_free(addr);
1.1 root 289: }
290:
291: static always_inline void gen_bcond (DisasContext *ctx,
1.1.1.2 ! root 292: TCGCond cond,
! 293: int ra, int32_t disp16, int mask)
1.1 root 294: {
1.1.1.2 ! root 295: int l1, l2;
! 296:
! 297: l1 = gen_new_label();
! 298: l2 = gen_new_label();
! 299: if (likely(ra != 31)) {
! 300: if (mask) {
! 301: TCGv tmp = tcg_temp_new();
! 302: tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
! 303: tcg_gen_brcondi_i64(cond, tmp, 0, l1);
! 304: tcg_temp_free(tmp);
! 305: } else
! 306: tcg_gen_brcondi_i64(cond, cpu_ir[ra], 0, l1);
1.1 root 307: } else {
1.1.1.2 ! root 308: /* Very uncommon case - Do not bother to optimize. */
! 309: TCGv tmp = tcg_const_i64(0);
! 310: tcg_gen_brcondi_i64(cond, tmp, 0, l1);
! 311: tcg_temp_free(tmp);
! 312: }
! 313: tcg_gen_movi_i64(cpu_pc, ctx->pc);
! 314: tcg_gen_br(l2);
! 315: gen_set_label(l1);
! 316: tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp16 << 2));
! 317: gen_set_label(l2);
1.1 root 318: }
319:
1.1.1.2 ! root 320: static always_inline void gen_fbcond (DisasContext *ctx, int opc,
1.1 root 321: int ra, int32_t disp16)
322: {
1.1.1.2 ! root 323: int l1, l2;
! 324: TCGv tmp;
! 325: TCGv src;
! 326:
! 327: l1 = gen_new_label();
! 328: l2 = gen_new_label();
! 329: if (ra != 31) {
! 330: tmp = tcg_temp_new();
! 331: src = cpu_fir[ra];
! 332: } else {
! 333: tmp = tcg_const_i64(0);
! 334: src = tmp;
1.1 root 335: }
1.1.1.2 ! root 336: switch (opc) {
! 337: case 0x31: /* FBEQ */
! 338: gen_helper_cmpfeq(tmp, src);
! 339: break;
! 340: case 0x32: /* FBLT */
! 341: gen_helper_cmpflt(tmp, src);
! 342: break;
! 343: case 0x33: /* FBLE */
! 344: gen_helper_cmpfle(tmp, src);
! 345: break;
! 346: case 0x35: /* FBNE */
! 347: gen_helper_cmpfne(tmp, src);
! 348: break;
! 349: case 0x36: /* FBGE */
! 350: gen_helper_cmpfge(tmp, src);
! 351: break;
! 352: case 0x37: /* FBGT */
! 353: gen_helper_cmpfgt(tmp, src);
! 354: break;
! 355: default:
! 356: abort();
! 357: }
! 358: tcg_gen_brcondi_i64(TCG_COND_NE, tmp, 0, l1);
! 359: tcg_gen_movi_i64(cpu_pc, ctx->pc);
! 360: tcg_gen_br(l2);
! 361: gen_set_label(l1);
! 362: tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp16 << 2));
! 363: gen_set_label(l2);
1.1 root 364: }
365:
1.1.1.2 ! root 366: static always_inline void gen_cmov (TCGCond inv_cond,
1.1 root 367: int ra, int rb, int rc,
1.1.1.2 ! root 368: int islit, uint8_t lit, int mask)
1.1 root 369: {
1.1.1.2 ! root 370: int l1;
1.1 root 371:
1.1.1.2 ! root 372: if (unlikely(rc == 31))
! 373: return;
1.1 root 374:
1.1.1.2 ! root 375: l1 = gen_new_label();
1.1 root 376:
1.1.1.2 ! root 377: if (ra != 31) {
! 378: if (mask) {
! 379: TCGv tmp = tcg_temp_new();
! 380: tcg_gen_andi_i64(tmp, cpu_ir[ra], 1);
! 381: tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
! 382: tcg_temp_free(tmp);
! 383: } else
! 384: tcg_gen_brcondi_i64(inv_cond, cpu_ir[ra], 0, l1);
! 385: } else {
! 386: /* Very uncommon case - Do not bother to optimize. */
! 387: TCGv tmp = tcg_const_i64(0);
! 388: tcg_gen_brcondi_i64(inv_cond, tmp, 0, l1);
! 389: tcg_temp_free(tmp);
! 390: }
1.1 root 391:
1.1.1.2 ! root 392: if (islit)
! 393: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 394: else
! 395: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
! 396: gen_set_label(l1);
1.1 root 397: }
398:
1.1.1.2 ! root 399: #define FARITH2(name) \
! 400: static always_inline void glue(gen_f, name)(int rb, int rc) \
! 401: { \
! 402: if (unlikely(rc == 31)) \
! 403: return; \
! 404: \
! 405: if (rb != 31) \
! 406: gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
! 407: else { \
! 408: TCGv tmp = tcg_const_i64(0); \
! 409: gen_helper_ ## name (cpu_fir[rc], tmp); \
! 410: tcg_temp_free(tmp); \
! 411: } \
! 412: }
! 413: FARITH2(sqrts)
! 414: FARITH2(sqrtf)
! 415: FARITH2(sqrtg)
! 416: FARITH2(sqrtt)
! 417: FARITH2(cvtgf)
! 418: FARITH2(cvtgq)
! 419: FARITH2(cvtqf)
! 420: FARITH2(cvtqg)
! 421: FARITH2(cvtst)
! 422: FARITH2(cvtts)
! 423: FARITH2(cvttq)
! 424: FARITH2(cvtqs)
! 425: FARITH2(cvtqt)
! 426: FARITH2(cvtlq)
! 427: FARITH2(cvtql)
! 428: FARITH2(cvtqlv)
! 429: FARITH2(cvtqlsv)
! 430:
! 431: #define FARITH3(name) \
! 432: static always_inline void glue(gen_f, name) (int ra, int rb, int rc) \
! 433: { \
! 434: if (unlikely(rc == 31)) \
! 435: return; \
! 436: \
! 437: if (ra != 31) { \
! 438: if (rb != 31) \
! 439: gen_helper_ ## name (cpu_fir[rc], cpu_fir[ra], cpu_fir[rb]); \
! 440: else { \
! 441: TCGv tmp = tcg_const_i64(0); \
! 442: gen_helper_ ## name (cpu_fir[rc], cpu_fir[ra], tmp); \
! 443: tcg_temp_free(tmp); \
! 444: } \
! 445: } else { \
! 446: TCGv tmp = tcg_const_i64(0); \
! 447: if (rb != 31) \
! 448: gen_helper_ ## name (cpu_fir[rc], tmp, cpu_fir[rb]); \
! 449: else \
! 450: gen_helper_ ## name (cpu_fir[rc], tmp, tmp); \
! 451: tcg_temp_free(tmp); \
! 452: } \
! 453: }
! 454:
! 455: FARITH3(addf)
! 456: FARITH3(subf)
! 457: FARITH3(mulf)
! 458: FARITH3(divf)
! 459: FARITH3(addg)
! 460: FARITH3(subg)
! 461: FARITH3(mulg)
! 462: FARITH3(divg)
! 463: FARITH3(cmpgeq)
! 464: FARITH3(cmpglt)
! 465: FARITH3(cmpgle)
! 466: FARITH3(adds)
! 467: FARITH3(subs)
! 468: FARITH3(muls)
! 469: FARITH3(divs)
! 470: FARITH3(addt)
! 471: FARITH3(subt)
! 472: FARITH3(mult)
! 473: FARITH3(divt)
! 474: FARITH3(cmptun)
! 475: FARITH3(cmpteq)
! 476: FARITH3(cmptlt)
! 477: FARITH3(cmptle)
! 478: FARITH3(cpys)
! 479: FARITH3(cpysn)
! 480: FARITH3(cpyse)
! 481:
! 482: #define FCMOV(name) \
! 483: static always_inline void glue(gen_f, name) (int ra, int rb, int rc) \
! 484: { \
! 485: int l1; \
! 486: TCGv tmp; \
! 487: \
! 488: if (unlikely(rc == 31)) \
! 489: return; \
! 490: \
! 491: l1 = gen_new_label(); \
! 492: tmp = tcg_temp_new(); \
! 493: if (ra != 31) { \
! 494: tmp = tcg_temp_new(); \
! 495: gen_helper_ ## name (tmp, cpu_fir[ra]); \
! 496: } else { \
! 497: tmp = tcg_const_i64(0); \
! 498: gen_helper_ ## name (tmp, tmp); \
! 499: } \
! 500: tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, l1); \
! 501: if (rb != 31) \
! 502: tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]); \
! 503: else \
! 504: tcg_gen_movi_i64(cpu_fir[rc], 0); \
! 505: gen_set_label(l1); \
! 506: }
! 507: FCMOV(cmpfeq)
! 508: FCMOV(cmpfne)
! 509: FCMOV(cmpflt)
! 510: FCMOV(cmpfge)
! 511: FCMOV(cmpfle)
! 512: FCMOV(cmpfgt)
1.1 root 513:
1.1.1.2 ! root 514: /* EXTWH, EXTWH, EXTLH, EXTQH */
! 515: static always_inline void gen_ext_h(void (*tcg_gen_ext_i64)(TCGv t0, TCGv t1),
! 516: int ra, int rb, int rc,
! 517: int islit, uint8_t lit)
1.1 root 518: {
1.1.1.2 ! root 519: if (unlikely(rc == 31))
! 520: return;
1.1 root 521:
1.1.1.2 ! root 522: if (ra != 31) {
! 523: if (islit) {
! 524: if (lit != 0)
! 525: tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 64 - ((lit & 7) * 8));
! 526: else
! 527: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]);
! 528: } else {
! 529: TCGv tmp1, tmp2;
! 530: tmp1 = tcg_temp_new();
! 531: tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
! 532: tcg_gen_shli_i64(tmp1, tmp1, 3);
! 533: tmp2 = tcg_const_i64(64);
! 534: tcg_gen_sub_i64(tmp1, tmp2, tmp1);
! 535: tcg_temp_free(tmp2);
! 536: tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
! 537: tcg_temp_free(tmp1);
! 538: }
! 539: if (tcg_gen_ext_i64)
! 540: tcg_gen_ext_i64(cpu_ir[rc], cpu_ir[rc]);
! 541: } else
! 542: tcg_gen_movi_i64(cpu_ir[rc], 0);
1.1 root 543: }
544:
1.1.1.2 ! root 545: /* EXTBL, EXTWL, EXTWL, EXTLL, EXTQL */
! 546: static always_inline void gen_ext_l(void (*tcg_gen_ext_i64)(TCGv t0, TCGv t1),
! 547: int ra, int rb, int rc,
! 548: int islit, uint8_t lit)
1.1 root 549: {
1.1.1.2 ! root 550: if (unlikely(rc == 31))
! 551: return;
1.1 root 552:
1.1.1.2 ! root 553: if (ra != 31) {
! 554: if (islit) {
! 555: tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], (lit & 7) * 8);
! 556: } else {
! 557: TCGv tmp = tcg_temp_new();
! 558: tcg_gen_andi_i64(tmp, cpu_ir[rb], 7);
! 559: tcg_gen_shli_i64(tmp, tmp, 3);
! 560: tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], tmp);
! 561: tcg_temp_free(tmp);
! 562: }
! 563: if (tcg_gen_ext_i64)
! 564: tcg_gen_ext_i64(cpu_ir[rc], cpu_ir[rc]);
! 565: } else
! 566: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 567: }
! 568:
! 569: /* Code to call arith3 helpers */
! 570: #define ARITH3(name) \
! 571: static always_inline void glue(gen_, name) (int ra, int rb, int rc, \
! 572: int islit, uint8_t lit) \
! 573: { \
! 574: if (unlikely(rc == 31)) \
! 575: return; \
! 576: \
! 577: if (ra != 31) { \
! 578: if (islit) { \
! 579: TCGv tmp = tcg_const_i64(lit); \
! 580: gen_helper_ ## name(cpu_ir[rc], cpu_ir[ra], tmp); \
! 581: tcg_temp_free(tmp); \
! 582: } else \
! 583: gen_helper_ ## name (cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); \
! 584: } else { \
! 585: TCGv tmp1 = tcg_const_i64(0); \
! 586: if (islit) { \
! 587: TCGv tmp2 = tcg_const_i64(lit); \
! 588: gen_helper_ ## name (cpu_ir[rc], tmp1, tmp2); \
! 589: tcg_temp_free(tmp2); \
! 590: } else \
! 591: gen_helper_ ## name (cpu_ir[rc], tmp1, cpu_ir[rb]); \
! 592: tcg_temp_free(tmp1); \
! 593: } \
! 594: }
! 595: ARITH3(cmpbge)
! 596: ARITH3(addlv)
! 597: ARITH3(sublv)
! 598: ARITH3(addqv)
! 599: ARITH3(subqv)
! 600: ARITH3(mskbl)
! 601: ARITH3(insbl)
! 602: ARITH3(mskwl)
! 603: ARITH3(inswl)
! 604: ARITH3(mskll)
! 605: ARITH3(insll)
! 606: ARITH3(zap)
! 607: ARITH3(zapnot)
! 608: ARITH3(mskql)
! 609: ARITH3(insql)
! 610: ARITH3(mskwh)
! 611: ARITH3(inswh)
! 612: ARITH3(msklh)
! 613: ARITH3(inslh)
! 614: ARITH3(mskqh)
! 615: ARITH3(insqh)
! 616: ARITH3(umulh)
! 617: ARITH3(mullv)
! 618: ARITH3(mulqv)
! 619:
! 620: static always_inline void gen_cmp(TCGCond cond,
! 621: int ra, int rb, int rc,
! 622: int islit, uint8_t lit)
! 623: {
! 624: int l1, l2;
! 625: TCGv tmp;
! 626:
! 627: if (unlikely(rc == 31))
! 628: return;
! 629:
! 630: l1 = gen_new_label();
! 631: l2 = gen_new_label();
! 632:
! 633: if (ra != 31) {
! 634: tmp = tcg_temp_new();
! 635: tcg_gen_mov_i64(tmp, cpu_ir[ra]);
! 636: } else
! 637: tmp = tcg_const_i64(0);
! 638: if (islit)
! 639: tcg_gen_brcondi_i64(cond, tmp, lit, l1);
! 640: else
! 641: tcg_gen_brcond_i64(cond, tmp, cpu_ir[rb], l1);
1.1 root 642:
1.1.1.2 ! root 643: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 644: tcg_gen_br(l2);
! 645: gen_set_label(l1);
! 646: tcg_gen_movi_i64(cpu_ir[rc], 1);
! 647: gen_set_label(l2);
1.1 root 648: }
649:
650: static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
651: {
652: uint32_t palcode;
653: int32_t disp21, disp16, disp12;
654: uint16_t fn11, fn16;
655: uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit;
1.1.1.2 ! root 656: uint8_t lit;
1.1 root 657: int ret;
658:
659: /* Decode all instruction fields */
660: opc = insn >> 26;
661: ra = (insn >> 21) & 0x1F;
662: rb = (insn >> 16) & 0x1F;
663: rc = insn & 0x1F;
664: sbz = (insn >> 13) & 0x07;
665: islit = (insn >> 12) & 1;
1.1.1.2 ! root 666: if (rb == 31 && !islit) {
! 667: islit = 1;
! 668: lit = 0;
! 669: } else
! 670: lit = (insn >> 13) & 0xFF;
1.1 root 671: palcode = insn & 0x03FFFFFF;
672: disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
673: disp16 = (int16_t)(insn & 0x0000FFFF);
674: disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
675: fn16 = insn & 0x0000FFFF;
676: fn11 = (insn >> 5) & 0x000007FF;
677: fpfn = fn11 & 0x3F;
678: fn7 = (insn >> 5) & 0x0000007F;
679: fn2 = (insn >> 5) & 0x00000003;
680: ret = 0;
1.1.1.2 ! root 681: LOG_DISAS("opc %02x ra %d rb %d rc %d disp16 %04x\n",
! 682: opc, ra, rb, rc, disp16);
1.1 root 683: switch (opc) {
684: case 0x00:
685: /* CALL_PAL */
686: if (palcode >= 0x80 && palcode < 0xC0) {
687: /* Unprivileged PAL call */
688: gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0);
689: #if !defined (CONFIG_USER_ONLY)
690: } else if (palcode < 0x40) {
691: /* Privileged PAL code */
692: if (ctx->mem_idx & 1)
693: goto invalid_opc;
694: else
695: gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x1F) << 6), 0);
696: #endif
697: } else {
698: /* Invalid PAL call */
699: goto invalid_opc;
700: }
701: ret = 3;
702: break;
703: case 0x01:
704: /* OPC01 */
705: goto invalid_opc;
706: case 0x02:
707: /* OPC02 */
708: goto invalid_opc;
709: case 0x03:
710: /* OPC03 */
711: goto invalid_opc;
712: case 0x04:
713: /* OPC04 */
714: goto invalid_opc;
715: case 0x05:
716: /* OPC05 */
717: goto invalid_opc;
718: case 0x06:
719: /* OPC06 */
720: goto invalid_opc;
721: case 0x07:
722: /* OPC07 */
723: goto invalid_opc;
724: case 0x08:
725: /* LDA */
1.1.1.2 ! root 726: if (likely(ra != 31)) {
! 727: if (rb != 31)
! 728: tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16);
! 729: else
! 730: tcg_gen_movi_i64(cpu_ir[ra], disp16);
! 731: }
1.1 root 732: break;
733: case 0x09:
734: /* LDAH */
1.1.1.2 ! root 735: if (likely(ra != 31)) {
! 736: if (rb != 31)
! 737: tcg_gen_addi_i64(cpu_ir[ra], cpu_ir[rb], disp16 << 16);
! 738: else
! 739: tcg_gen_movi_i64(cpu_ir[ra], disp16 << 16);
! 740: }
1.1 root 741: break;
742: case 0x0A:
743: /* LDBU */
744: if (!(ctx->amask & AMASK_BWX))
745: goto invalid_opc;
1.1.1.2 ! root 746: gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
1.1 root 747: break;
748: case 0x0B:
749: /* LDQ_U */
1.1.1.2 ! root 750: gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
1.1 root 751: break;
752: case 0x0C:
753: /* LDWU */
754: if (!(ctx->amask & AMASK_BWX))
755: goto invalid_opc;
1.1.1.2 ! root 756: gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 1);
1.1 root 757: break;
758: case 0x0D:
759: /* STW */
1.1.1.2 ! root 760: gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0, 0);
1.1 root 761: break;
762: case 0x0E:
763: /* STB */
1.1.1.2 ! root 764: gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0, 0);
1.1 root 765: break;
766: case 0x0F:
767: /* STQ_U */
1.1.1.2 ! root 768: gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1, 0);
1.1 root 769: break;
770: case 0x10:
771: switch (fn7) {
772: case 0x00:
773: /* ADDL */
1.1.1.2 ! root 774: if (likely(rc != 31)) {
! 775: if (ra != 31) {
! 776: if (islit) {
! 777: tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 778: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
! 779: } else {
! 780: tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 781: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
! 782: }
! 783: } else {
! 784: if (islit)
! 785: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 786: else
! 787: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
! 788: }
! 789: }
1.1 root 790: break;
791: case 0x02:
792: /* S4ADDL */
1.1.1.2 ! root 793: if (likely(rc != 31)) {
! 794: if (ra != 31) {
! 795: TCGv tmp = tcg_temp_new();
! 796: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
! 797: if (islit)
! 798: tcg_gen_addi_i64(tmp, tmp, lit);
! 799: else
! 800: tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
! 801: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
! 802: tcg_temp_free(tmp);
! 803: } else {
! 804: if (islit)
! 805: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 806: else
! 807: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
! 808: }
! 809: }
1.1 root 810: break;
811: case 0x09:
812: /* SUBL */
1.1.1.2 ! root 813: if (likely(rc != 31)) {
! 814: if (ra != 31) {
! 815: if (islit)
! 816: tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 817: else
! 818: tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 819: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
! 820: } else {
! 821: if (islit)
! 822: tcg_gen_movi_i64(cpu_ir[rc], -lit);
! 823: else {
! 824: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
! 825: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
! 826: }
! 827: }
1.1 root 828: break;
829: case 0x0B:
830: /* S4SUBL */
1.1.1.2 ! root 831: if (likely(rc != 31)) {
! 832: if (ra != 31) {
! 833: TCGv tmp = tcg_temp_new();
! 834: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
! 835: if (islit)
! 836: tcg_gen_subi_i64(tmp, tmp, lit);
! 837: else
! 838: tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
! 839: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
! 840: tcg_temp_free(tmp);
! 841: } else {
! 842: if (islit)
! 843: tcg_gen_movi_i64(cpu_ir[rc], -lit);
! 844: else {
! 845: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
! 846: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
! 847: }
! 848: }
! 849: }
1.1 root 850: break;
851: case 0x0F:
852: /* CMPBGE */
1.1.1.2 ! root 853: gen_cmpbge(ra, rb, rc, islit, lit);
1.1 root 854: break;
855: case 0x12:
856: /* S8ADDL */
1.1.1.2 ! root 857: if (likely(rc != 31)) {
! 858: if (ra != 31) {
! 859: TCGv tmp = tcg_temp_new();
! 860: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
! 861: if (islit)
! 862: tcg_gen_addi_i64(tmp, tmp, lit);
! 863: else
! 864: tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]);
! 865: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
! 866: tcg_temp_free(tmp);
! 867: } else {
! 868: if (islit)
! 869: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 870: else
! 871: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]);
! 872: }
! 873: }
1.1 root 874: break;
875: case 0x1B:
876: /* S8SUBL */
1.1.1.2 ! root 877: if (likely(rc != 31)) {
! 878: if (ra != 31) {
! 879: TCGv tmp = tcg_temp_new();
! 880: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
! 881: if (islit)
! 882: tcg_gen_subi_i64(tmp, tmp, lit);
! 883: else
! 884: tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]);
! 885: tcg_gen_ext32s_i64(cpu_ir[rc], tmp);
! 886: tcg_temp_free(tmp);
! 887: } else {
! 888: if (islit)
! 889: tcg_gen_movi_i64(cpu_ir[rc], -lit);
! 890: else
! 891: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
! 892: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
! 893: }
! 894: }
! 895: }
1.1 root 896: break;
897: case 0x1D:
898: /* CMPULT */
1.1.1.2 ! root 899: gen_cmp(TCG_COND_LTU, ra, rb, rc, islit, lit);
1.1 root 900: break;
901: case 0x20:
902: /* ADDQ */
1.1.1.2 ! root 903: if (likely(rc != 31)) {
! 904: if (ra != 31) {
! 905: if (islit)
! 906: tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 907: else
! 908: tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 909: } else {
! 910: if (islit)
! 911: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 912: else
! 913: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
! 914: }
! 915: }
1.1 root 916: break;
917: case 0x22:
918: /* S4ADDQ */
1.1.1.2 ! root 919: if (likely(rc != 31)) {
! 920: if (ra != 31) {
! 921: TCGv tmp = tcg_temp_new();
! 922: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
! 923: if (islit)
! 924: tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
! 925: else
! 926: tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
! 927: tcg_temp_free(tmp);
! 928: } else {
! 929: if (islit)
! 930: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 931: else
! 932: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
! 933: }
! 934: }
1.1 root 935: break;
936: case 0x29:
937: /* SUBQ */
1.1.1.2 ! root 938: if (likely(rc != 31)) {
! 939: if (ra != 31) {
! 940: if (islit)
! 941: tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 942: else
! 943: tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 944: } else {
! 945: if (islit)
! 946: tcg_gen_movi_i64(cpu_ir[rc], -lit);
! 947: else
! 948: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
! 949: }
! 950: }
1.1 root 951: break;
952: case 0x2B:
953: /* S4SUBQ */
1.1.1.2 ! root 954: if (likely(rc != 31)) {
! 955: if (ra != 31) {
! 956: TCGv tmp = tcg_temp_new();
! 957: tcg_gen_shli_i64(tmp, cpu_ir[ra], 2);
! 958: if (islit)
! 959: tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
! 960: else
! 961: tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
! 962: tcg_temp_free(tmp);
! 963: } else {
! 964: if (islit)
! 965: tcg_gen_movi_i64(cpu_ir[rc], -lit);
! 966: else
! 967: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
! 968: }
! 969: }
1.1 root 970: break;
971: case 0x2D:
972: /* CMPEQ */
1.1.1.2 ! root 973: gen_cmp(TCG_COND_EQ, ra, rb, rc, islit, lit);
1.1 root 974: break;
975: case 0x32:
976: /* S8ADDQ */
1.1.1.2 ! root 977: if (likely(rc != 31)) {
! 978: if (ra != 31) {
! 979: TCGv tmp = tcg_temp_new();
! 980: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
! 981: if (islit)
! 982: tcg_gen_addi_i64(cpu_ir[rc], tmp, lit);
! 983: else
! 984: tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
! 985: tcg_temp_free(tmp);
! 986: } else {
! 987: if (islit)
! 988: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 989: else
! 990: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
! 991: }
! 992: }
1.1 root 993: break;
994: case 0x3B:
995: /* S8SUBQ */
1.1.1.2 ! root 996: if (likely(rc != 31)) {
! 997: if (ra != 31) {
! 998: TCGv tmp = tcg_temp_new();
! 999: tcg_gen_shli_i64(tmp, cpu_ir[ra], 3);
! 1000: if (islit)
! 1001: tcg_gen_subi_i64(cpu_ir[rc], tmp, lit);
! 1002: else
! 1003: tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]);
! 1004: tcg_temp_free(tmp);
! 1005: } else {
! 1006: if (islit)
! 1007: tcg_gen_movi_i64(cpu_ir[rc], -lit);
! 1008: else
! 1009: tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]);
! 1010: }
! 1011: }
1.1 root 1012: break;
1013: case 0x3D:
1014: /* CMPULE */
1.1.1.2 ! root 1015: gen_cmp(TCG_COND_LEU, ra, rb, rc, islit, lit);
1.1 root 1016: break;
1017: case 0x40:
1018: /* ADDL/V */
1.1.1.2 ! root 1019: gen_addlv(ra, rb, rc, islit, lit);
1.1 root 1020: break;
1021: case 0x49:
1022: /* SUBL/V */
1.1.1.2 ! root 1023: gen_sublv(ra, rb, rc, islit, lit);
1.1 root 1024: break;
1025: case 0x4D:
1026: /* CMPLT */
1.1.1.2 ! root 1027: gen_cmp(TCG_COND_LT, ra, rb, rc, islit, lit);
1.1 root 1028: break;
1029: case 0x60:
1030: /* ADDQ/V */
1.1.1.2 ! root 1031: gen_addqv(ra, rb, rc, islit, lit);
1.1 root 1032: break;
1033: case 0x69:
1034: /* SUBQ/V */
1.1.1.2 ! root 1035: gen_subqv(ra, rb, rc, islit, lit);
1.1 root 1036: break;
1037: case 0x6D:
1038: /* CMPLE */
1.1.1.2 ! root 1039: gen_cmp(TCG_COND_LE, ra, rb, rc, islit, lit);
1.1 root 1040: break;
1041: default:
1042: goto invalid_opc;
1043: }
1044: break;
1045: case 0x11:
1046: switch (fn7) {
1047: case 0x00:
1048: /* AND */
1.1.1.2 ! root 1049: if (likely(rc != 31)) {
! 1050: if (ra == 31)
! 1051: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 1052: else if (islit)
! 1053: tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 1054: else
! 1055: tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 1056: }
1.1 root 1057: break;
1058: case 0x08:
1059: /* BIC */
1.1.1.2 ! root 1060: if (likely(rc != 31)) {
! 1061: if (ra != 31) {
! 1062: if (islit)
! 1063: tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
! 1064: else
! 1065: tcg_gen_andc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 1066: } else
! 1067: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 1068: }
1.1 root 1069: break;
1070: case 0x14:
1071: /* CMOVLBS */
1.1.1.2 ! root 1072: gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
1.1 root 1073: break;
1074: case 0x16:
1075: /* CMOVLBC */
1.1.1.2 ! root 1076: gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
1.1 root 1077: break;
1078: case 0x20:
1079: /* BIS */
1.1.1.2 ! root 1080: if (likely(rc != 31)) {
! 1081: if (ra != 31) {
! 1082: if (islit)
! 1083: tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 1084: else
! 1085: tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
1.1 root 1086: } else {
1.1.1.2 ! root 1087: if (islit)
! 1088: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 1089: else
! 1090: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
1.1 root 1091: }
1092: }
1093: break;
1094: case 0x24:
1095: /* CMOVEQ */
1.1.1.2 ! root 1096: gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
1.1 root 1097: break;
1098: case 0x26:
1099: /* CMOVNE */
1.1.1.2 ! root 1100: gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
1.1 root 1101: break;
1102: case 0x28:
1103: /* ORNOT */
1.1.1.2 ! root 1104: if (likely(rc != 31)) {
! 1105: if (ra != 31) {
! 1106: if (islit)
! 1107: tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
! 1108: else
! 1109: tcg_gen_orc_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 1110: } else {
! 1111: if (islit)
! 1112: tcg_gen_movi_i64(cpu_ir[rc], ~lit);
! 1113: else
! 1114: tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
! 1115: }
! 1116: }
1.1 root 1117: break;
1118: case 0x40:
1119: /* XOR */
1.1.1.2 ! root 1120: if (likely(rc != 31)) {
! 1121: if (ra != 31) {
! 1122: if (islit)
! 1123: tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 1124: else
! 1125: tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 1126: } else {
! 1127: if (islit)
! 1128: tcg_gen_movi_i64(cpu_ir[rc], lit);
! 1129: else
! 1130: tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
! 1131: }
! 1132: }
1.1 root 1133: break;
1134: case 0x44:
1135: /* CMOVLT */
1.1.1.2 ! root 1136: gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
1.1 root 1137: break;
1138: case 0x46:
1139: /* CMOVGE */
1.1.1.2 ! root 1140: gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
1.1 root 1141: break;
1142: case 0x48:
1143: /* EQV */
1.1.1.2 ! root 1144: if (likely(rc != 31)) {
! 1145: if (ra != 31) {
! 1146: if (islit)
! 1147: tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], ~lit);
! 1148: else
! 1149: tcg_gen_eqv_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 1150: } else {
! 1151: if (islit)
! 1152: tcg_gen_movi_i64(cpu_ir[rc], ~lit);
! 1153: else
! 1154: tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]);
! 1155: }
! 1156: }
1.1 root 1157: break;
1158: case 0x61:
1159: /* AMASK */
1.1.1.2 ! root 1160: if (likely(rc != 31)) {
! 1161: if (islit)
! 1162: tcg_gen_movi_i64(cpu_ir[rc], helper_amask(lit));
! 1163: else
! 1164: gen_helper_amask(cpu_ir[rc], cpu_ir[rb]);
! 1165: }
1.1 root 1166: break;
1167: case 0x64:
1168: /* CMOVLE */
1.1.1.2 ! root 1169: gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
1.1 root 1170: break;
1171: case 0x66:
1172: /* CMOVGT */
1.1.1.2 ! root 1173: gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
1.1 root 1174: break;
1175: case 0x6C:
1176: /* IMPLVER */
1.1.1.2 ! root 1177: if (rc != 31)
! 1178: gen_helper_load_implver(cpu_ir[rc]);
1.1 root 1179: break;
1180: default:
1181: goto invalid_opc;
1182: }
1183: break;
1184: case 0x12:
1185: switch (fn7) {
1186: case 0x02:
1187: /* MSKBL */
1.1.1.2 ! root 1188: gen_mskbl(ra, rb, rc, islit, lit);
1.1 root 1189: break;
1190: case 0x06:
1191: /* EXTBL */
1.1.1.2 ! root 1192: gen_ext_l(&tcg_gen_ext8u_i64, ra, rb, rc, islit, lit);
1.1 root 1193: break;
1194: case 0x0B:
1195: /* INSBL */
1.1.1.2 ! root 1196: gen_insbl(ra, rb, rc, islit, lit);
1.1 root 1197: break;
1198: case 0x12:
1199: /* MSKWL */
1.1.1.2 ! root 1200: gen_mskwl(ra, rb, rc, islit, lit);
1.1 root 1201: break;
1202: case 0x16:
1203: /* EXTWL */
1.1.1.2 ! root 1204: gen_ext_l(&tcg_gen_ext16u_i64, ra, rb, rc, islit, lit);
1.1 root 1205: break;
1206: case 0x1B:
1207: /* INSWL */
1.1.1.2 ! root 1208: gen_inswl(ra, rb, rc, islit, lit);
1.1 root 1209: break;
1210: case 0x22:
1211: /* MSKLL */
1.1.1.2 ! root 1212: gen_mskll(ra, rb, rc, islit, lit);
1.1 root 1213: break;
1214: case 0x26:
1215: /* EXTLL */
1.1.1.2 ! root 1216: gen_ext_l(&tcg_gen_ext32u_i64, ra, rb, rc, islit, lit);
1.1 root 1217: break;
1218: case 0x2B:
1219: /* INSLL */
1.1.1.2 ! root 1220: gen_insll(ra, rb, rc, islit, lit);
1.1 root 1221: break;
1222: case 0x30:
1223: /* ZAP */
1.1.1.2 ! root 1224: gen_zap(ra, rb, rc, islit, lit);
1.1 root 1225: break;
1226: case 0x31:
1227: /* ZAPNOT */
1.1.1.2 ! root 1228: gen_zapnot(ra, rb, rc, islit, lit);
1.1 root 1229: break;
1230: case 0x32:
1231: /* MSKQL */
1.1.1.2 ! root 1232: gen_mskql(ra, rb, rc, islit, lit);
1.1 root 1233: break;
1234: case 0x34:
1235: /* SRL */
1.1.1.2 ! root 1236: if (likely(rc != 31)) {
! 1237: if (ra != 31) {
! 1238: if (islit)
! 1239: tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
! 1240: else {
! 1241: TCGv shift = tcg_temp_new();
! 1242: tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
! 1243: tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], shift);
! 1244: tcg_temp_free(shift);
! 1245: }
! 1246: } else
! 1247: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 1248: }
1.1 root 1249: break;
1250: case 0x36:
1251: /* EXTQL */
1.1.1.2 ! root 1252: gen_ext_l(NULL, ra, rb, rc, islit, lit);
1.1 root 1253: break;
1254: case 0x39:
1255: /* SLL */
1.1.1.2 ! root 1256: if (likely(rc != 31)) {
! 1257: if (ra != 31) {
! 1258: if (islit)
! 1259: tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
! 1260: else {
! 1261: TCGv shift = tcg_temp_new();
! 1262: tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
! 1263: tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], shift);
! 1264: tcg_temp_free(shift);
! 1265: }
! 1266: } else
! 1267: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 1268: }
1.1 root 1269: break;
1270: case 0x3B:
1271: /* INSQL */
1.1.1.2 ! root 1272: gen_insql(ra, rb, rc, islit, lit);
1.1 root 1273: break;
1274: case 0x3C:
1275: /* SRA */
1.1.1.2 ! root 1276: if (likely(rc != 31)) {
! 1277: if (ra != 31) {
! 1278: if (islit)
! 1279: tcg_gen_sari_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f);
! 1280: else {
! 1281: TCGv shift = tcg_temp_new();
! 1282: tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f);
! 1283: tcg_gen_sar_i64(cpu_ir[rc], cpu_ir[ra], shift);
! 1284: tcg_temp_free(shift);
! 1285: }
! 1286: } else
! 1287: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 1288: }
1.1 root 1289: break;
1290: case 0x52:
1291: /* MSKWH */
1.1.1.2 ! root 1292: gen_mskwh(ra, rb, rc, islit, lit);
1.1 root 1293: break;
1294: case 0x57:
1295: /* INSWH */
1.1.1.2 ! root 1296: gen_inswh(ra, rb, rc, islit, lit);
1.1 root 1297: break;
1298: case 0x5A:
1299: /* EXTWH */
1.1.1.2 ! root 1300: gen_ext_h(&tcg_gen_ext16u_i64, ra, rb, rc, islit, lit);
1.1 root 1301: break;
1302: case 0x62:
1303: /* MSKLH */
1.1.1.2 ! root 1304: gen_msklh(ra, rb, rc, islit, lit);
1.1 root 1305: break;
1306: case 0x67:
1307: /* INSLH */
1.1.1.2 ! root 1308: gen_inslh(ra, rb, rc, islit, lit);
1.1 root 1309: break;
1310: case 0x6A:
1311: /* EXTLH */
1.1.1.2 ! root 1312: gen_ext_h(&tcg_gen_ext16u_i64, ra, rb, rc, islit, lit);
1.1 root 1313: break;
1314: case 0x72:
1315: /* MSKQH */
1.1.1.2 ! root 1316: gen_mskqh(ra, rb, rc, islit, lit);
1.1 root 1317: break;
1318: case 0x77:
1319: /* INSQH */
1.1.1.2 ! root 1320: gen_insqh(ra, rb, rc, islit, lit);
1.1 root 1321: break;
1322: case 0x7A:
1323: /* EXTQH */
1.1.1.2 ! root 1324: gen_ext_h(NULL, ra, rb, rc, islit, lit);
1.1 root 1325: break;
1326: default:
1327: goto invalid_opc;
1328: }
1329: break;
1330: case 0x13:
1331: switch (fn7) {
1332: case 0x00:
1333: /* MULL */
1.1.1.2 ! root 1334: if (likely(rc != 31)) {
! 1335: if (ra == 31)
! 1336: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 1337: else {
! 1338: if (islit)
! 1339: tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 1340: else
! 1341: tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 1342: tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]);
! 1343: }
! 1344: }
1.1 root 1345: break;
1346: case 0x20:
1347: /* MULQ */
1.1.1.2 ! root 1348: if (likely(rc != 31)) {
! 1349: if (ra == 31)
! 1350: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 1351: else if (islit)
! 1352: tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit);
! 1353: else
! 1354: tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
! 1355: }
1.1 root 1356: break;
1357: case 0x30:
1358: /* UMULH */
1.1.1.2 ! root 1359: gen_umulh(ra, rb, rc, islit, lit);
1.1 root 1360: break;
1361: case 0x40:
1362: /* MULL/V */
1.1.1.2 ! root 1363: gen_mullv(ra, rb, rc, islit, lit);
1.1 root 1364: break;
1365: case 0x60:
1366: /* MULQ/V */
1.1.1.2 ! root 1367: gen_mulqv(ra, rb, rc, islit, lit);
1.1 root 1368: break;
1369: default:
1370: goto invalid_opc;
1371: }
1372: break;
1373: case 0x14:
1374: switch (fpfn) { /* f11 & 0x3F */
1375: case 0x04:
1376: /* ITOFS */
1377: if (!(ctx->amask & AMASK_FIX))
1378: goto invalid_opc;
1.1.1.2 ! root 1379: if (likely(rc != 31)) {
! 1380: if (ra != 31) {
! 1381: TCGv_i32 tmp = tcg_temp_new_i32();
! 1382: tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
! 1383: gen_helper_memory_to_s(cpu_fir[rc], tmp);
! 1384: tcg_temp_free_i32(tmp);
! 1385: } else
! 1386: tcg_gen_movi_i64(cpu_fir[rc], 0);
! 1387: }
1.1 root 1388: break;
1389: case 0x0A:
1390: /* SQRTF */
1391: if (!(ctx->amask & AMASK_FIX))
1392: goto invalid_opc;
1.1.1.2 ! root 1393: gen_fsqrtf(rb, rc);
1.1 root 1394: break;
1395: case 0x0B:
1396: /* SQRTS */
1397: if (!(ctx->amask & AMASK_FIX))
1398: goto invalid_opc;
1.1.1.2 ! root 1399: gen_fsqrts(rb, rc);
1.1 root 1400: break;
1401: case 0x14:
1402: /* ITOFF */
1403: if (!(ctx->amask & AMASK_FIX))
1404: goto invalid_opc;
1.1.1.2 ! root 1405: if (likely(rc != 31)) {
! 1406: if (ra != 31) {
! 1407: TCGv_i32 tmp = tcg_temp_new_i32();
! 1408: tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
! 1409: gen_helper_memory_to_f(cpu_fir[rc], tmp);
! 1410: tcg_temp_free_i32(tmp);
! 1411: } else
! 1412: tcg_gen_movi_i64(cpu_fir[rc], 0);
! 1413: }
1.1 root 1414: break;
1415: case 0x24:
1416: /* ITOFT */
1417: if (!(ctx->amask & AMASK_FIX))
1418: goto invalid_opc;
1.1.1.2 ! root 1419: if (likely(rc != 31)) {
! 1420: if (ra != 31)
! 1421: tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
! 1422: else
! 1423: tcg_gen_movi_i64(cpu_fir[rc], 0);
! 1424: }
1.1 root 1425: break;
1426: case 0x2A:
1427: /* SQRTG */
1428: if (!(ctx->amask & AMASK_FIX))
1429: goto invalid_opc;
1.1.1.2 ! root 1430: gen_fsqrtg(rb, rc);
1.1 root 1431: break;
1432: case 0x02B:
1433: /* SQRTT */
1434: if (!(ctx->amask & AMASK_FIX))
1435: goto invalid_opc;
1.1.1.2 ! root 1436: gen_fsqrtt(rb, rc);
1.1 root 1437: break;
1438: default:
1439: goto invalid_opc;
1440: }
1441: break;
1442: case 0x15:
1443: /* VAX floating point */
1444: /* XXX: rounding mode and trap are ignored (!) */
1445: switch (fpfn) { /* f11 & 0x3F */
1446: case 0x00:
1447: /* ADDF */
1.1.1.2 ! root 1448: gen_faddf(ra, rb, rc);
1.1 root 1449: break;
1450: case 0x01:
1451: /* SUBF */
1.1.1.2 ! root 1452: gen_fsubf(ra, rb, rc);
1.1 root 1453: break;
1454: case 0x02:
1455: /* MULF */
1.1.1.2 ! root 1456: gen_fmulf(ra, rb, rc);
1.1 root 1457: break;
1458: case 0x03:
1459: /* DIVF */
1.1.1.2 ! root 1460: gen_fdivf(ra, rb, rc);
1.1 root 1461: break;
1462: case 0x1E:
1463: /* CVTDG */
1464: #if 0 // TODO
1.1.1.2 ! root 1465: gen_fcvtdg(rb, rc);
1.1 root 1466: #else
1467: goto invalid_opc;
1468: #endif
1469: break;
1470: case 0x20:
1471: /* ADDG */
1.1.1.2 ! root 1472: gen_faddg(ra, rb, rc);
1.1 root 1473: break;
1474: case 0x21:
1475: /* SUBG */
1.1.1.2 ! root 1476: gen_fsubg(ra, rb, rc);
1.1 root 1477: break;
1478: case 0x22:
1479: /* MULG */
1.1.1.2 ! root 1480: gen_fmulg(ra, rb, rc);
1.1 root 1481: break;
1482: case 0x23:
1483: /* DIVG */
1.1.1.2 ! root 1484: gen_fdivg(ra, rb, rc);
1.1 root 1485: break;
1486: case 0x25:
1487: /* CMPGEQ */
1.1.1.2 ! root 1488: gen_fcmpgeq(ra, rb, rc);
1.1 root 1489: break;
1490: case 0x26:
1491: /* CMPGLT */
1.1.1.2 ! root 1492: gen_fcmpglt(ra, rb, rc);
1.1 root 1493: break;
1494: case 0x27:
1495: /* CMPGLE */
1.1.1.2 ! root 1496: gen_fcmpgle(ra, rb, rc);
1.1 root 1497: break;
1498: case 0x2C:
1499: /* CVTGF */
1.1.1.2 ! root 1500: gen_fcvtgf(rb, rc);
1.1 root 1501: break;
1502: case 0x2D:
1503: /* CVTGD */
1504: #if 0 // TODO
1.1.1.2 ! root 1505: gen_fcvtgd(rb, rc);
1.1 root 1506: #else
1507: goto invalid_opc;
1508: #endif
1509: break;
1510: case 0x2F:
1511: /* CVTGQ */
1.1.1.2 ! root 1512: gen_fcvtgq(rb, rc);
1.1 root 1513: break;
1514: case 0x3C:
1515: /* CVTQF */
1.1.1.2 ! root 1516: gen_fcvtqf(rb, rc);
1.1 root 1517: break;
1518: case 0x3E:
1519: /* CVTQG */
1.1.1.2 ! root 1520: gen_fcvtqg(rb, rc);
1.1 root 1521: break;
1522: default:
1523: goto invalid_opc;
1524: }
1525: break;
1526: case 0x16:
1527: /* IEEE floating-point */
1528: /* XXX: rounding mode and traps are ignored (!) */
1529: switch (fpfn) { /* f11 & 0x3F */
1530: case 0x00:
1531: /* ADDS */
1.1.1.2 ! root 1532: gen_fadds(ra, rb, rc);
1.1 root 1533: break;
1534: case 0x01:
1535: /* SUBS */
1.1.1.2 ! root 1536: gen_fsubs(ra, rb, rc);
1.1 root 1537: break;
1538: case 0x02:
1539: /* MULS */
1.1.1.2 ! root 1540: gen_fmuls(ra, rb, rc);
1.1 root 1541: break;
1542: case 0x03:
1543: /* DIVS */
1.1.1.2 ! root 1544: gen_fdivs(ra, rb, rc);
1.1 root 1545: break;
1546: case 0x20:
1547: /* ADDT */
1.1.1.2 ! root 1548: gen_faddt(ra, rb, rc);
1.1 root 1549: break;
1550: case 0x21:
1551: /* SUBT */
1.1.1.2 ! root 1552: gen_fsubt(ra, rb, rc);
1.1 root 1553: break;
1554: case 0x22:
1555: /* MULT */
1.1.1.2 ! root 1556: gen_fmult(ra, rb, rc);
1.1 root 1557: break;
1558: case 0x23:
1559: /* DIVT */
1.1.1.2 ! root 1560: gen_fdivt(ra, rb, rc);
1.1 root 1561: break;
1562: case 0x24:
1563: /* CMPTUN */
1.1.1.2 ! root 1564: gen_fcmptun(ra, rb, rc);
1.1 root 1565: break;
1566: case 0x25:
1567: /* CMPTEQ */
1.1.1.2 ! root 1568: gen_fcmpteq(ra, rb, rc);
1.1 root 1569: break;
1570: case 0x26:
1571: /* CMPTLT */
1.1.1.2 ! root 1572: gen_fcmptlt(ra, rb, rc);
1.1 root 1573: break;
1574: case 0x27:
1575: /* CMPTLE */
1.1.1.2 ! root 1576: gen_fcmptle(ra, rb, rc);
1.1 root 1577: break;
1578: case 0x2C:
1579: /* XXX: incorrect */
1.1.1.2 ! root 1580: if (fn11 == 0x2AC || fn11 == 0x6AC) {
1.1 root 1581: /* CVTST */
1.1.1.2 ! root 1582: gen_fcvtst(rb, rc);
1.1 root 1583: } else {
1584: /* CVTTS */
1.1.1.2 ! root 1585: gen_fcvtts(rb, rc);
1.1 root 1586: }
1587: break;
1588: case 0x2F:
1589: /* CVTTQ */
1.1.1.2 ! root 1590: gen_fcvttq(rb, rc);
1.1 root 1591: break;
1592: case 0x3C:
1593: /* CVTQS */
1.1.1.2 ! root 1594: gen_fcvtqs(rb, rc);
1.1 root 1595: break;
1596: case 0x3E:
1597: /* CVTQT */
1.1.1.2 ! root 1598: gen_fcvtqt(rb, rc);
1.1 root 1599: break;
1600: default:
1601: goto invalid_opc;
1602: }
1603: break;
1604: case 0x17:
1605: switch (fn11) {
1606: case 0x010:
1607: /* CVTLQ */
1.1.1.2 ! root 1608: gen_fcvtlq(rb, rc);
1.1 root 1609: break;
1610: case 0x020:
1.1.1.2 ! root 1611: if (likely(rc != 31)) {
! 1612: if (ra == rb)
1.1 root 1613: /* FMOV */
1.1.1.2 ! root 1614: tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
! 1615: else
! 1616: /* CPYS */
! 1617: gen_fcpys(ra, rb, rc);
1.1 root 1618: }
1619: break;
1620: case 0x021:
1621: /* CPYSN */
1.1.1.2 ! root 1622: gen_fcpysn(ra, rb, rc);
1.1 root 1623: break;
1624: case 0x022:
1625: /* CPYSE */
1.1.1.2 ! root 1626: gen_fcpyse(ra, rb, rc);
1.1 root 1627: break;
1628: case 0x024:
1629: /* MT_FPCR */
1.1.1.2 ! root 1630: if (likely(ra != 31))
! 1631: gen_helper_store_fpcr(cpu_fir[ra]);
! 1632: else {
! 1633: TCGv tmp = tcg_const_i64(0);
! 1634: gen_helper_store_fpcr(tmp);
! 1635: tcg_temp_free(tmp);
! 1636: }
1.1 root 1637: break;
1638: case 0x025:
1639: /* MF_FPCR */
1.1.1.2 ! root 1640: if (likely(ra != 31))
! 1641: gen_helper_load_fpcr(cpu_fir[ra]);
1.1 root 1642: break;
1643: case 0x02A:
1644: /* FCMOVEQ */
1.1.1.2 ! root 1645: gen_fcmpfeq(ra, rb, rc);
1.1 root 1646: break;
1647: case 0x02B:
1648: /* FCMOVNE */
1.1.1.2 ! root 1649: gen_fcmpfne(ra, rb, rc);
1.1 root 1650: break;
1651: case 0x02C:
1652: /* FCMOVLT */
1.1.1.2 ! root 1653: gen_fcmpflt(ra, rb, rc);
1.1 root 1654: break;
1655: case 0x02D:
1656: /* FCMOVGE */
1.1.1.2 ! root 1657: gen_fcmpfge(ra, rb, rc);
1.1 root 1658: break;
1659: case 0x02E:
1660: /* FCMOVLE */
1.1.1.2 ! root 1661: gen_fcmpfle(ra, rb, rc);
1.1 root 1662: break;
1663: case 0x02F:
1664: /* FCMOVGT */
1.1.1.2 ! root 1665: gen_fcmpfgt(ra, rb, rc);
1.1 root 1666: break;
1667: case 0x030:
1668: /* CVTQL */
1.1.1.2 ! root 1669: gen_fcvtql(rb, rc);
1.1 root 1670: break;
1671: case 0x130:
1672: /* CVTQL/V */
1.1.1.2 ! root 1673: gen_fcvtqlv(rb, rc);
1.1 root 1674: break;
1675: case 0x530:
1676: /* CVTQL/SV */
1.1.1.2 ! root 1677: gen_fcvtqlsv(rb, rc);
1.1 root 1678: break;
1679: default:
1680: goto invalid_opc;
1681: }
1682: break;
1683: case 0x18:
1684: switch ((uint16_t)disp16) {
1685: case 0x0000:
1686: /* TRAPB */
1687: /* No-op. Just exit from the current tb */
1688: ret = 2;
1689: break;
1690: case 0x0400:
1691: /* EXCB */
1692: /* No-op. Just exit from the current tb */
1693: ret = 2;
1694: break;
1695: case 0x4000:
1696: /* MB */
1697: /* No-op */
1698: break;
1699: case 0x4400:
1700: /* WMB */
1701: /* No-op */
1702: break;
1703: case 0x8000:
1704: /* FETCH */
1705: /* No-op */
1706: break;
1707: case 0xA000:
1708: /* FETCH_M */
1709: /* No-op */
1710: break;
1711: case 0xC000:
1712: /* RPCC */
1.1.1.2 ! root 1713: if (ra != 31)
! 1714: gen_helper_load_pcc(cpu_ir[ra]);
1.1 root 1715: break;
1716: case 0xE000:
1717: /* RC */
1.1.1.2 ! root 1718: if (ra != 31)
! 1719: gen_helper_rc(cpu_ir[ra]);
1.1 root 1720: break;
1721: case 0xE800:
1722: /* ECB */
1723: /* XXX: TODO: evict tb cache at address rb */
1724: #if 0
1725: ret = 2;
1726: #else
1727: goto invalid_opc;
1728: #endif
1729: break;
1730: case 0xF000:
1731: /* RS */
1.1.1.2 ! root 1732: if (ra != 31)
! 1733: gen_helper_rs(cpu_ir[ra]);
1.1 root 1734: break;
1735: case 0xF800:
1736: /* WH64 */
1737: /* No-op */
1738: break;
1739: default:
1740: goto invalid_opc;
1741: }
1742: break;
1743: case 0x19:
1744: /* HW_MFPR (PALcode) */
1745: #if defined (CONFIG_USER_ONLY)
1746: goto invalid_opc;
1747: #else
1748: if (!ctx->pal_mode)
1749: goto invalid_opc;
1.1.1.2 ! root 1750: if (ra != 31) {
! 1751: TCGv tmp = tcg_const_i32(insn & 0xFF);
! 1752: gen_helper_mfpr(cpu_ir[ra], tmp, cpu_ir[ra]);
! 1753: tcg_temp_free(tmp);
! 1754: }
1.1 root 1755: break;
1756: #endif
1757: case 0x1A:
1.1.1.2 ! root 1758: if (rb != 31)
! 1759: tcg_gen_andi_i64(cpu_pc, cpu_ir[rb], ~3);
! 1760: else
! 1761: tcg_gen_movi_i64(cpu_pc, 0);
! 1762: if (ra != 31)
! 1763: tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
1.1 root 1764: /* Those four jumps only differ by the branch prediction hint */
1765: switch (fn2) {
1766: case 0x0:
1767: /* JMP */
1768: break;
1769: case 0x1:
1770: /* JSR */
1771: break;
1772: case 0x2:
1773: /* RET */
1774: break;
1775: case 0x3:
1776: /* JSR_COROUTINE */
1777: break;
1778: }
1779: ret = 1;
1780: break;
1781: case 0x1B:
1782: /* HW_LD (PALcode) */
1783: #if defined (CONFIG_USER_ONLY)
1784: goto invalid_opc;
1785: #else
1786: if (!ctx->pal_mode)
1787: goto invalid_opc;
1.1.1.2 ! root 1788: if (ra != 31) {
! 1789: TCGv addr = tcg_temp_new();
! 1790: if (rb != 31)
! 1791: tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
! 1792: else
! 1793: tcg_gen_movi_i64(addr, disp12);
! 1794: switch ((insn >> 12) & 0xF) {
! 1795: case 0x0:
! 1796: /* Longword physical access */
! 1797: gen_helper_ldl_raw(cpu_ir[ra], addr);
! 1798: break;
! 1799: case 0x1:
! 1800: /* Quadword physical access */
! 1801: gen_helper_ldq_raw(cpu_ir[ra], addr);
! 1802: break;
! 1803: case 0x2:
! 1804: /* Longword physical access with lock */
! 1805: gen_helper_ldl_l_raw(cpu_ir[ra], addr);
! 1806: break;
! 1807: case 0x3:
! 1808: /* Quadword physical access with lock */
! 1809: gen_helper_ldq_l_raw(cpu_ir[ra], addr);
! 1810: break;
! 1811: case 0x4:
! 1812: /* Longword virtual PTE fetch */
! 1813: gen_helper_ldl_kernel(cpu_ir[ra], addr);
! 1814: break;
! 1815: case 0x5:
! 1816: /* Quadword virtual PTE fetch */
! 1817: gen_helper_ldq_kernel(cpu_ir[ra], addr);
! 1818: break;
! 1819: case 0x6:
! 1820: /* Incpu_ir[ra]id */
! 1821: goto incpu_ir[ra]id_opc;
! 1822: case 0x7:
! 1823: /* Incpu_ir[ra]id */
! 1824: goto incpu_ir[ra]id_opc;
! 1825: case 0x8:
! 1826: /* Longword virtual access */
! 1827: gen_helper_st_virt_to_phys(addr, addr);
! 1828: gen_helper_ldl_raw(cpu_ir[ra], addr);
! 1829: break;
! 1830: case 0x9:
! 1831: /* Quadword virtual access */
! 1832: gen_helper_st_virt_to_phys(addr, addr);
! 1833: gen_helper_ldq_raw(cpu_ir[ra], addr);
! 1834: break;
! 1835: case 0xA:
! 1836: /* Longword virtual access with protection check */
! 1837: tcg_gen_qemu_ld32s(cpu_ir[ra], addr, ctx->flags);
! 1838: break;
! 1839: case 0xB:
! 1840: /* Quadword virtual access with protection check */
! 1841: tcg_gen_qemu_ld64(cpu_ir[ra], addr, ctx->flags);
! 1842: break;
! 1843: case 0xC:
! 1844: /* Longword virtual access with altenate access mode */
! 1845: gen_helper_set_alt_mode();
! 1846: gen_helper_st_virt_to_phys(addr, addr);
! 1847: gen_helper_ldl_raw(cpu_ir[ra], addr);
! 1848: gen_helper_restore_mode();
! 1849: break;
! 1850: case 0xD:
! 1851: /* Quadword virtual access with altenate access mode */
! 1852: gen_helper_set_alt_mode();
! 1853: gen_helper_st_virt_to_phys(addr, addr);
! 1854: gen_helper_ldq_raw(cpu_ir[ra], addr);
! 1855: gen_helper_restore_mode();
! 1856: break;
! 1857: case 0xE:
! 1858: /* Longword virtual access with alternate access mode and
! 1859: * protection checks
! 1860: */
! 1861: gen_helper_set_alt_mode();
! 1862: gen_helper_ldl_data(cpu_ir[ra], addr);
! 1863: gen_helper_restore_mode();
! 1864: break;
! 1865: case 0xF:
! 1866: /* Quadword virtual access with alternate access mode and
! 1867: * protection checks
! 1868: */
! 1869: gen_helper_set_alt_mode();
! 1870: gen_helper_ldq_data(cpu_ir[ra], addr);
! 1871: gen_helper_restore_mode();
! 1872: break;
! 1873: }
! 1874: tcg_temp_free(addr);
1.1 root 1875: }
1876: break;
1877: #endif
1878: case 0x1C:
1879: switch (fn7) {
1880: case 0x00:
1881: /* SEXTB */
1882: if (!(ctx->amask & AMASK_BWX))
1883: goto invalid_opc;
1.1.1.2 ! root 1884: if (likely(rc != 31)) {
! 1885: if (islit)
! 1886: tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit));
! 1887: else
! 1888: tcg_gen_ext8s_i64(cpu_ir[rc], cpu_ir[rb]);
! 1889: }
1.1 root 1890: break;
1891: case 0x01:
1892: /* SEXTW */
1893: if (!(ctx->amask & AMASK_BWX))
1894: goto invalid_opc;
1.1.1.2 ! root 1895: if (likely(rc != 31)) {
! 1896: if (islit)
! 1897: tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
! 1898: else
! 1899: tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
! 1900: }
1.1 root 1901: break;
1902: case 0x30:
1903: /* CTPOP */
1904: if (!(ctx->amask & AMASK_CIX))
1905: goto invalid_opc;
1.1.1.2 ! root 1906: if (likely(rc != 31)) {
! 1907: if (islit)
! 1908: tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
! 1909: else
! 1910: gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
! 1911: }
1.1 root 1912: break;
1913: case 0x31:
1914: /* PERR */
1915: if (!(ctx->amask & AMASK_MVI))
1916: goto invalid_opc;
1917: /* XXX: TODO */
1918: goto invalid_opc;
1919: break;
1920: case 0x32:
1921: /* CTLZ */
1922: if (!(ctx->amask & AMASK_CIX))
1923: goto invalid_opc;
1.1.1.2 ! root 1924: if (likely(rc != 31)) {
! 1925: if (islit)
! 1926: tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
! 1927: else
! 1928: gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
! 1929: }
1.1 root 1930: break;
1931: case 0x33:
1932: /* CTTZ */
1933: if (!(ctx->amask & AMASK_CIX))
1934: goto invalid_opc;
1.1.1.2 ! root 1935: if (likely(rc != 31)) {
! 1936: if (islit)
! 1937: tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
! 1938: else
! 1939: gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
! 1940: }
1.1 root 1941: break;
1942: case 0x34:
1943: /* UNPKBW */
1944: if (!(ctx->amask & AMASK_MVI))
1945: goto invalid_opc;
1946: /* XXX: TODO */
1947: goto invalid_opc;
1948: break;
1949: case 0x35:
1950: /* UNPKWL */
1951: if (!(ctx->amask & AMASK_MVI))
1952: goto invalid_opc;
1953: /* XXX: TODO */
1954: goto invalid_opc;
1955: break;
1956: case 0x36:
1957: /* PKWB */
1958: if (!(ctx->amask & AMASK_MVI))
1959: goto invalid_opc;
1960: /* XXX: TODO */
1961: goto invalid_opc;
1962: break;
1963: case 0x37:
1964: /* PKLB */
1965: if (!(ctx->amask & AMASK_MVI))
1966: goto invalid_opc;
1967: /* XXX: TODO */
1968: goto invalid_opc;
1969: break;
1970: case 0x38:
1971: /* MINSB8 */
1972: if (!(ctx->amask & AMASK_MVI))
1973: goto invalid_opc;
1974: /* XXX: TODO */
1975: goto invalid_opc;
1976: break;
1977: case 0x39:
1978: /* MINSW4 */
1979: if (!(ctx->amask & AMASK_MVI))
1980: goto invalid_opc;
1981: /* XXX: TODO */
1982: goto invalid_opc;
1983: break;
1984: case 0x3A:
1985: /* MINUB8 */
1986: if (!(ctx->amask & AMASK_MVI))
1987: goto invalid_opc;
1988: /* XXX: TODO */
1989: goto invalid_opc;
1990: break;
1991: case 0x3B:
1992: /* MINUW4 */
1993: if (!(ctx->amask & AMASK_MVI))
1994: goto invalid_opc;
1995: /* XXX: TODO */
1996: goto invalid_opc;
1997: break;
1998: case 0x3C:
1999: /* MAXUB8 */
2000: if (!(ctx->amask & AMASK_MVI))
2001: goto invalid_opc;
2002: /* XXX: TODO */
2003: goto invalid_opc;
2004: break;
2005: case 0x3D:
2006: /* MAXUW4 */
2007: if (!(ctx->amask & AMASK_MVI))
2008: goto invalid_opc;
2009: /* XXX: TODO */
2010: goto invalid_opc;
2011: break;
2012: case 0x3E:
2013: /* MAXSB8 */
2014: if (!(ctx->amask & AMASK_MVI))
2015: goto invalid_opc;
2016: /* XXX: TODO */
2017: goto invalid_opc;
2018: break;
2019: case 0x3F:
2020: /* MAXSW4 */
2021: if (!(ctx->amask & AMASK_MVI))
2022: goto invalid_opc;
2023: /* XXX: TODO */
2024: goto invalid_opc;
2025: break;
2026: case 0x70:
2027: /* FTOIT */
2028: if (!(ctx->amask & AMASK_FIX))
2029: goto invalid_opc;
1.1.1.2 ! root 2030: if (likely(rc != 31)) {
! 2031: if (ra != 31)
! 2032: tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
! 2033: else
! 2034: tcg_gen_movi_i64(cpu_ir[rc], 0);
! 2035: }
1.1 root 2036: break;
2037: case 0x78:
2038: /* FTOIS */
2039: if (!(ctx->amask & AMASK_FIX))
2040: goto invalid_opc;
1.1.1.2 ! root 2041: if (rc != 31) {
! 2042: TCGv_i32 tmp1 = tcg_temp_new_i32();
! 2043: if (ra != 31)
! 2044: gen_helper_s_to_memory(tmp1, cpu_fir[ra]);
! 2045: else {
! 2046: TCGv tmp2 = tcg_const_i64(0);
! 2047: gen_helper_s_to_memory(tmp1, tmp2);
! 2048: tcg_temp_free(tmp2);
! 2049: }
! 2050: tcg_gen_ext_i32_i64(cpu_ir[rc], tmp1);
! 2051: tcg_temp_free_i32(tmp1);
! 2052: }
1.1 root 2053: break;
2054: default:
2055: goto invalid_opc;
2056: }
2057: break;
2058: case 0x1D:
2059: /* HW_MTPR (PALcode) */
2060: #if defined (CONFIG_USER_ONLY)
2061: goto invalid_opc;
2062: #else
2063: if (!ctx->pal_mode)
2064: goto invalid_opc;
1.1.1.2 ! root 2065: else {
! 2066: TCGv tmp1 = tcg_const_i32(insn & 0xFF);
! 2067: if (ra != 31)
! 2068: gen_helper_mtpr(tmp1, cpu_ir[ra]);
! 2069: else {
! 2070: TCGv tmp2 = tcg_const_i64(0);
! 2071: gen_helper_mtpr(tmp1, tmp2);
! 2072: tcg_temp_free(tmp2);
! 2073: }
! 2074: tcg_temp_free(tmp1);
! 2075: ret = 2;
! 2076: }
1.1 root 2077: break;
2078: #endif
2079: case 0x1E:
2080: /* HW_REI (PALcode) */
2081: #if defined (CONFIG_USER_ONLY)
2082: goto invalid_opc;
2083: #else
2084: if (!ctx->pal_mode)
2085: goto invalid_opc;
2086: if (rb == 31) {
2087: /* "Old" alpha */
1.1.1.2 ! root 2088: gen_helper_hw_rei();
1.1 root 2089: } else {
1.1.1.2 ! root 2090: TCGv tmp;
! 2091:
! 2092: if (ra != 31) {
! 2093: tmp = tcg_temp_new();
! 2094: tcg_gen_addi_i64(tmp, cpu_ir[rb], (((int64_t)insn << 51) >> 51));
! 2095: } else
! 2096: tmp = tcg_const_i64(((int64_t)insn << 51) >> 51);
! 2097: gen_helper_hw_ret(tmp);
! 2098: tcg_temp_free(tmp);
1.1 root 2099: }
2100: ret = 2;
2101: break;
2102: #endif
2103: case 0x1F:
2104: /* HW_ST (PALcode) */
2105: #if defined (CONFIG_USER_ONLY)
2106: goto invalid_opc;
2107: #else
2108: if (!ctx->pal_mode)
2109: goto invalid_opc;
1.1.1.2 ! root 2110: else {
! 2111: TCGv addr, val;
! 2112: addr = tcg_temp_new();
! 2113: if (rb != 31)
! 2114: tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
! 2115: else
! 2116: tcg_gen_movi_i64(addr, disp12);
! 2117: if (ra != 31)
! 2118: val = cpu_ir[ra];
! 2119: else {
! 2120: val = tcg_temp_new();
! 2121: tcg_gen_movi_i64(val, 0);
! 2122: }
! 2123: switch ((insn >> 12) & 0xF) {
! 2124: case 0x0:
! 2125: /* Longword physical access */
! 2126: gen_helper_stl_raw(val, addr);
! 2127: break;
! 2128: case 0x1:
! 2129: /* Quadword physical access */
! 2130: gen_helper_stq_raw(val, addr);
! 2131: break;
! 2132: case 0x2:
! 2133: /* Longword physical access with lock */
! 2134: gen_helper_stl_c_raw(val, val, addr);
! 2135: break;
! 2136: case 0x3:
! 2137: /* Quadword physical access with lock */
! 2138: gen_helper_stq_c_raw(val, val, addr);
! 2139: break;
! 2140: case 0x4:
! 2141: /* Longword virtual access */
! 2142: gen_helper_st_virt_to_phys(addr, addr);
! 2143: gen_helper_stl_raw(val, addr);
! 2144: break;
! 2145: case 0x5:
! 2146: /* Quadword virtual access */
! 2147: gen_helper_st_virt_to_phys(addr, addr);
! 2148: gen_helper_stq_raw(val, addr);
! 2149: break;
! 2150: case 0x6:
! 2151: /* Invalid */
! 2152: goto invalid_opc;
! 2153: case 0x7:
! 2154: /* Invalid */
! 2155: goto invalid_opc;
! 2156: case 0x8:
! 2157: /* Invalid */
! 2158: goto invalid_opc;
! 2159: case 0x9:
! 2160: /* Invalid */
! 2161: goto invalid_opc;
! 2162: case 0xA:
! 2163: /* Invalid */
! 2164: goto invalid_opc;
! 2165: case 0xB:
! 2166: /* Invalid */
! 2167: goto invalid_opc;
! 2168: case 0xC:
! 2169: /* Longword virtual access with alternate access mode */
! 2170: gen_helper_set_alt_mode();
! 2171: gen_helper_st_virt_to_phys(addr, addr);
! 2172: gen_helper_stl_raw(val, addr);
! 2173: gen_helper_restore_mode();
! 2174: break;
! 2175: case 0xD:
! 2176: /* Quadword virtual access with alternate access mode */
! 2177: gen_helper_set_alt_mode();
! 2178: gen_helper_st_virt_to_phys(addr, addr);
! 2179: gen_helper_stl_raw(val, addr);
! 2180: gen_helper_restore_mode();
! 2181: break;
! 2182: case 0xE:
! 2183: /* Invalid */
! 2184: goto invalid_opc;
! 2185: case 0xF:
! 2186: /* Invalid */
! 2187: goto invalid_opc;
! 2188: }
! 2189: if (ra != 31)
! 2190: tcg_temp_free(val);
! 2191: tcg_temp_free(addr);
1.1 root 2192: }
2193: ret = 2;
2194: break;
2195: #endif
2196: case 0x20:
2197: /* LDF */
1.1.1.2 ! root 2198: gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
1.1 root 2199: break;
2200: case 0x21:
2201: /* LDG */
1.1.1.2 ! root 2202: gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
1.1 root 2203: break;
2204: case 0x22:
2205: /* LDS */
1.1.1.2 ! root 2206: gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
1.1 root 2207: break;
2208: case 0x23:
2209: /* LDT */
1.1.1.2 ! root 2210: gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
1.1 root 2211: break;
2212: case 0x24:
2213: /* STF */
1.1.1.2 ! root 2214: gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0, 0);
1.1 root 2215: break;
2216: case 0x25:
2217: /* STG */
1.1.1.2 ! root 2218: gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0, 0);
1.1 root 2219: break;
2220: case 0x26:
2221: /* STS */
1.1.1.2 ! root 2222: gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0, 0);
1.1 root 2223: break;
2224: case 0x27:
2225: /* STT */
1.1.1.2 ! root 2226: gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0, 0);
1.1 root 2227: break;
2228: case 0x28:
2229: /* LDL */
1.1.1.2 ! root 2230: gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
1.1 root 2231: break;
2232: case 0x29:
2233: /* LDQ */
1.1.1.2 ! root 2234: gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
1.1 root 2235: break;
2236: case 0x2A:
2237: /* LDL_L */
1.1.1.2 ! root 2238: gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
1.1 root 2239: break;
2240: case 0x2B:
2241: /* LDQ_L */
1.1.1.2 ! root 2242: gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
1.1 root 2243: break;
2244: case 0x2C:
2245: /* STL */
1.1.1.2 ! root 2246: gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0, 0);
1.1 root 2247: break;
2248: case 0x2D:
2249: /* STQ */
1.1.1.2 ! root 2250: gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0, 0);
1.1 root 2251: break;
2252: case 0x2E:
2253: /* STL_C */
1.1.1.2 ! root 2254: gen_store_mem(ctx, &gen_qemu_stl_c, ra, rb, disp16, 0, 0, 1);
1.1 root 2255: break;
2256: case 0x2F:
2257: /* STQ_C */
1.1.1.2 ! root 2258: gen_store_mem(ctx, &gen_qemu_stq_c, ra, rb, disp16, 0, 0, 1);
1.1 root 2259: break;
2260: case 0x30:
2261: /* BR */
1.1.1.2 ! root 2262: if (ra != 31)
! 2263: tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
! 2264: tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
1.1 root 2265: ret = 1;
2266: break;
1.1.1.2 ! root 2267: case 0x31: /* FBEQ */
! 2268: case 0x32: /* FBLT */
! 2269: case 0x33: /* FBLE */
! 2270: gen_fbcond(ctx, opc, ra, disp16);
1.1 root 2271: ret = 1;
2272: break;
2273: case 0x34:
2274: /* BSR */
1.1.1.2 ! root 2275: if (ra != 31)
! 2276: tcg_gen_movi_i64(cpu_ir[ra], ctx->pc);
! 2277: tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp21 << 2));
1.1 root 2278: ret = 1;
2279: break;
1.1.1.2 ! root 2280: case 0x35: /* FBNE */
! 2281: case 0x36: /* FBGE */
! 2282: case 0x37: /* FBGT */
! 2283: gen_fbcond(ctx, opc, ra, disp16);
1.1 root 2284: ret = 1;
2285: break;
2286: case 0x38:
2287: /* BLBC */
1.1.1.2 ! root 2288: gen_bcond(ctx, TCG_COND_EQ, ra, disp16, 1);
1.1 root 2289: ret = 1;
2290: break;
2291: case 0x39:
2292: /* BEQ */
1.1.1.2 ! root 2293: gen_bcond(ctx, TCG_COND_EQ, ra, disp16, 0);
1.1 root 2294: ret = 1;
2295: break;
2296: case 0x3A:
2297: /* BLT */
1.1.1.2 ! root 2298: gen_bcond(ctx, TCG_COND_LT, ra, disp16, 0);
1.1 root 2299: ret = 1;
2300: break;
2301: case 0x3B:
2302: /* BLE */
1.1.1.2 ! root 2303: gen_bcond(ctx, TCG_COND_LE, ra, disp16, 0);
1.1 root 2304: ret = 1;
2305: break;
2306: case 0x3C:
2307: /* BLBS */
1.1.1.2 ! root 2308: gen_bcond(ctx, TCG_COND_NE, ra, disp16, 1);
1.1 root 2309: ret = 1;
2310: break;
2311: case 0x3D:
2312: /* BNE */
1.1.1.2 ! root 2313: gen_bcond(ctx, TCG_COND_NE, ra, disp16, 0);
1.1 root 2314: ret = 1;
2315: break;
2316: case 0x3E:
2317: /* BGE */
1.1.1.2 ! root 2318: gen_bcond(ctx, TCG_COND_GE, ra, disp16, 0);
1.1 root 2319: ret = 1;
2320: break;
2321: case 0x3F:
2322: /* BGT */
1.1.1.2 ! root 2323: gen_bcond(ctx, TCG_COND_GT, ra, disp16, 0);
1.1 root 2324: ret = 1;
2325: break;
2326: invalid_opc:
2327: gen_invalid(ctx);
2328: ret = 3;
2329: break;
2330: }
2331:
2332: return ret;
2333: }
2334:
1.1.1.2 ! root 2335: static always_inline void gen_intermediate_code_internal (CPUState *env,
! 2336: TranslationBlock *tb,
! 2337: int search_pc)
1.1 root 2338: {
2339: #if defined ALPHA_DEBUG_DISAS
2340: static int insn_count;
2341: #endif
2342: DisasContext ctx, *ctxp = &ctx;
2343: target_ulong pc_start;
2344: uint32_t insn;
2345: uint16_t *gen_opc_end;
1.1.1.2 ! root 2346: CPUBreakpoint *bp;
1.1 root 2347: int j, lj = -1;
2348: int ret;
1.1.1.2 ! root 2349: int num_insns;
! 2350: int max_insns;
1.1 root 2351:
2352: pc_start = tb->pc;
2353: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2354: ctx.pc = pc_start;
2355: ctx.amask = env->amask;
2356: #if defined (CONFIG_USER_ONLY)
2357: ctx.mem_idx = 0;
2358: #else
2359: ctx.mem_idx = ((env->ps >> 3) & 3);
2360: ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
2361: #endif
1.1.1.2 ! root 2362: num_insns = 0;
! 2363: max_insns = tb->cflags & CF_COUNT_MASK;
! 2364: if (max_insns == 0)
! 2365: max_insns = CF_COUNT_MASK;
! 2366:
! 2367: gen_icount_start();
1.1 root 2368: for (ret = 0; ret == 0;) {
1.1.1.2 ! root 2369: if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
! 2370: TAILQ_FOREACH(bp, &env->breakpoints, entry) {
! 2371: if (bp->pc == ctx.pc) {
1.1 root 2372: gen_excp(&ctx, EXCP_DEBUG, 0);
2373: break;
2374: }
2375: }
2376: }
2377: if (search_pc) {
2378: j = gen_opc_ptr - gen_opc_buf;
2379: if (lj < j) {
2380: lj++;
2381: while (lj < j)
2382: gen_opc_instr_start[lj++] = 0;
2383: gen_opc_pc[lj] = ctx.pc;
2384: gen_opc_instr_start[lj] = 1;
1.1.1.2 ! root 2385: gen_opc_icount[lj] = num_insns;
1.1 root 2386: }
2387: }
1.1.1.2 ! root 2388: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
! 2389: gen_io_start();
1.1 root 2390: #if defined ALPHA_DEBUG_DISAS
2391: insn_count++;
1.1.1.2 ! root 2392: LOG_DISAS("pc " TARGET_FMT_lx " mem_idx %d\n",
! 2393: ctx.pc, ctx.mem_idx);
1.1 root 2394: #endif
2395: insn = ldl_code(ctx.pc);
2396: #if defined ALPHA_DEBUG_DISAS
2397: insn_count++;
1.1.1.2 ! root 2398: LOG_DISAS("opcode %08x %d\n", insn, insn_count);
1.1 root 2399: #endif
1.1.1.2 ! root 2400: num_insns++;
1.1 root 2401: ctx.pc += 4;
2402: ret = translate_one(ctxp, insn);
2403: if (ret != 0)
2404: break;
2405: /* if we reach a page boundary or are single stepping, stop
2406: * generation
2407: */
2408: if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
1.1.1.2 ! root 2409: num_insns >= max_insns) {
1.1 root 2410: break;
2411: }
1.1.1.2 ! root 2412:
! 2413: if (env->singlestep_enabled) {
! 2414: gen_excp(&ctx, EXCP_DEBUG, 0);
! 2415: break;
! 2416: }
! 2417:
1.1 root 2418: #if defined (DO_SINGLE_STEP)
2419: break;
2420: #endif
2421: }
2422: if (ret != 1 && ret != 3) {
1.1.1.2 ! root 2423: tcg_gen_movi_i64(cpu_pc, ctx.pc);
1.1 root 2424: }
2425: #if defined (DO_TB_FLUSH)
1.1.1.2 ! root 2426: gen_helper_tb_flush();
1.1 root 2427: #endif
1.1.1.2 ! root 2428: if (tb->cflags & CF_LAST_IO)
! 2429: gen_io_end();
1.1 root 2430: /* Generate the return instruction */
1.1.1.2 ! root 2431: tcg_gen_exit_tb(0);
! 2432: gen_icount_end(tb, num_insns);
1.1 root 2433: *gen_opc_ptr = INDEX_op_end;
2434: if (search_pc) {
2435: j = gen_opc_ptr - gen_opc_buf;
2436: lj++;
2437: while (lj <= j)
2438: gen_opc_instr_start[lj++] = 0;
2439: } else {
2440: tb->size = ctx.pc - pc_start;
1.1.1.2 ! root 2441: tb->icount = num_insns;
1.1 root 2442: }
2443: #if defined ALPHA_DEBUG_DISAS
1.1.1.2 ! root 2444: log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
! 2445: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
! 2446: qemu_log("IN: %s\n", lookup_symbol(pc_start));
! 2447: log_target_disas(pc_start, ctx.pc - pc_start, 1);
! 2448: qemu_log("\n");
1.1 root 2449: }
2450: #endif
2451: }
2452:
1.1.1.2 ! root 2453: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1.1 root 2454: {
1.1.1.2 ! root 2455: gen_intermediate_code_internal(env, tb, 0);
1.1 root 2456: }
2457:
1.1.1.2 ! root 2458: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1.1 root 2459: {
1.1.1.2 ! root 2460: gen_intermediate_code_internal(env, tb, 1);
1.1 root 2461: }
2462:
2463: CPUAlphaState * cpu_alpha_init (const char *cpu_model)
2464: {
2465: CPUAlphaState *env;
2466: uint64_t hwpcb;
2467:
2468: env = qemu_mallocz(sizeof(CPUAlphaState));
2469: cpu_exec_init(env);
1.1.1.2 ! root 2470: alpha_translate_init();
1.1 root 2471: tlb_flush(env, 1);
2472: /* XXX: should not be hardcoded */
2473: env->implver = IMPLVER_2106x;
2474: env->ps = 0x1F00;
2475: #if defined (CONFIG_USER_ONLY)
2476: env->ps |= 1 << 3;
2477: #endif
2478: pal_init(env);
2479: /* Initialize IPR */
2480: hwpcb = env->ipr[IPR_PCBB];
2481: env->ipr[IPR_ASN] = 0;
2482: env->ipr[IPR_ASTEN] = 0;
2483: env->ipr[IPR_ASTSR] = 0;
2484: env->ipr[IPR_DATFX] = 0;
2485: /* XXX: fix this */
2486: // env->ipr[IPR_ESP] = ldq_raw(hwpcb + 8);
2487: // env->ipr[IPR_KSP] = ldq_raw(hwpcb + 0);
2488: // env->ipr[IPR_SSP] = ldq_raw(hwpcb + 16);
2489: // env->ipr[IPR_USP] = ldq_raw(hwpcb + 24);
2490: env->ipr[IPR_FEN] = 0;
2491: env->ipr[IPR_IPL] = 31;
2492: env->ipr[IPR_MCES] = 0;
2493: env->ipr[IPR_PERFMON] = 0; /* Implementation specific */
2494: // env->ipr[IPR_PTBR] = ldq_raw(hwpcb + 32);
2495: env->ipr[IPR_SISR] = 0;
2496: env->ipr[IPR_VIRBND] = -1ULL;
2497:
2498: return env;
2499: }
2500:
1.1.1.2 ! root 2501: void gen_pc_load(CPUState *env, TranslationBlock *tb,
! 2502: unsigned long searched_pc, int pc_pos, void *puc)
! 2503: {
! 2504: env->pc = gen_opc_pc[pc_pos];
! 2505: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.