|
|
1.1 ! root 1: /* ! 2: * CRISv10 emulation for qemu: main translation routines. ! 3: * ! 4: * Copyright (c) 2010 AXIS Communications AB ! 5: * Written by Edgar E. Iglesias. ! 6: * ! 7: * This library is free software; you can redistribute it and/or ! 8: * modify it under the terms of the GNU Lesser General Public ! 9: * License as published by the Free Software Foundation; either ! 10: * version 2 of the License, or (at your option) any later version. ! 11: * ! 12: * This library is distributed in the hope that it will be useful, ! 13: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 15: * Lesser General Public License for more details. ! 16: * ! 17: * You should have received a copy of the GNU Lesser General Public ! 18: * License along with this library; if not, see <http://www.gnu.org/licenses/>. ! 19: */ ! 20: ! 21: #include "crisv10-decode.h" ! 22: ! 23: static const char *regnames_v10[] = ! 24: { ! 25: "$r0", "$r1", "$r2", "$r3", ! 26: "$r4", "$r5", "$r6", "$r7", ! 27: "$r8", "$r9", "$r10", "$r11", ! 28: "$r12", "$r13", "$sp", "$pc", ! 29: }; ! 30: ! 31: static const char *pregnames_v10[] = ! 32: { ! 33: "$bz", "$vr", "$p2", "$p3", ! 34: "$wz", "$ccr", "$p6-prefix", "$mof", ! 35: "$dz", "$ibr", "$irp", "$srp", ! 36: "$bar", "$dccr", "$brp", "$usp", ! 37: }; ! 38: ! 39: /* We need this table to handle preg-moves with implicit width. */ ! 40: static int preg_sizes_v10[] = { ! 41: 1, /* bz. */ ! 42: 1, /* vr. */ ! 43: 1, /* pid. */ ! 44: 1, /* srs. */ ! 45: 2, /* wz. */ ! 46: 2, 2, 4, ! 47: 4, 4, 4, 4, ! 48: 4, 4, 4, 4, ! 49: }; ! 50: ! 51: static inline int dec10_size(unsigned int size) ! 52: { ! 53: size++; ! 54: if (size == 3) ! 55: size++; ! 56: return size; ! 57: } ! 58: ! 59: static inline void cris_illegal_insn(DisasContext *dc) ! 60: { ! 61: qemu_log("illegal insn at pc=%x\n", dc->pc); ! 62: t_gen_raise_exception(EXCP_BREAK); ! 63: } ! 64: ! 65: /* Prefix flag and register are used to handle the more complex ! 66: addressing modes. */ ! 67: static void cris_set_prefix(DisasContext *dc) ! 68: { ! 69: dc->clear_prefix = 0; ! 70: dc->tb_flags |= PFIX_FLAG; ! 71: tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], PFIX_FLAG); ! 72: ! 73: /* prefix insns dont clear the x flag. */ ! 74: dc->clear_x = 0; ! 75: cris_lock_irq(dc); ! 76: } ! 77: ! 78: static void crisv10_prepare_memaddr(DisasContext *dc, ! 79: TCGv addr, unsigned int size) ! 80: { ! 81: if (dc->tb_flags & PFIX_FLAG) { ! 82: tcg_gen_mov_tl(addr, cpu_PR[PR_PREFIX]); ! 83: } else { ! 84: tcg_gen_mov_tl(addr, cpu_R[dc->src]); ! 85: } ! 86: } ! 87: ! 88: static unsigned int crisv10_post_memaddr(DisasContext *dc, unsigned int size) ! 89: { ! 90: unsigned int insn_len = 0; ! 91: ! 92: if (dc->tb_flags & PFIX_FLAG) { ! 93: if (dc->mode == CRISV10_MODE_AUTOINC) { ! 94: tcg_gen_mov_tl(cpu_R[dc->src], cpu_PR[PR_PREFIX]); ! 95: } ! 96: } else { ! 97: if (dc->mode == CRISV10_MODE_AUTOINC) { ! 98: if (dc->src == 15) { ! 99: insn_len += size & ~1; ! 100: } else { ! 101: tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], size); ! 102: } ! 103: } ! 104: } ! 105: return insn_len; ! 106: } ! 107: ! 108: static int dec10_prep_move_m(DisasContext *dc, int s_ext, int memsize, ! 109: TCGv dst) ! 110: { ! 111: unsigned int rs, rd; ! 112: uint32_t imm; ! 113: int is_imm; ! 114: int insn_len = 0; ! 115: ! 116: rs = dc->src; ! 117: rd = dc->dst; ! 118: is_imm = rs == 15 && !(dc->tb_flags & PFIX_FLAG); ! 119: LOG_DIS("rs=%d rd=%d is_imm=%d mode=%d pfix=%d\n", ! 120: rs, rd, is_imm, dc->mode, dc->tb_flags & PFIX_FLAG); ! 121: ! 122: /* Load [$rs] onto T1. */ ! 123: if (is_imm) { ! 124: if (memsize != 4) { ! 125: if (s_ext) { ! 126: if (memsize == 1) ! 127: imm = ldsb_code(dc->pc + 2); ! 128: else ! 129: imm = ldsw_code(dc->pc + 2); ! 130: } else { ! 131: if (memsize == 1) ! 132: imm = ldub_code(dc->pc + 2); ! 133: else ! 134: imm = lduw_code(dc->pc + 2); ! 135: } ! 136: } else ! 137: imm = ldl_code(dc->pc + 2); ! 138: ! 139: tcg_gen_movi_tl(dst, imm); ! 140: ! 141: if (dc->mode == CRISV10_MODE_AUTOINC) { ! 142: insn_len += memsize; ! 143: if (memsize == 1) ! 144: insn_len++; ! 145: tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len); ! 146: } ! 147: } else { ! 148: TCGv addr; ! 149: ! 150: addr = tcg_temp_new(); ! 151: cris_flush_cc_state(dc); ! 152: crisv10_prepare_memaddr(dc, addr, memsize); ! 153: gen_load(dc, dst, addr, memsize, 0); ! 154: if (s_ext) ! 155: t_gen_sext(dst, dst, memsize); ! 156: else ! 157: t_gen_zext(dst, dst, memsize); ! 158: insn_len += crisv10_post_memaddr(dc, memsize); ! 159: tcg_temp_free(addr); ! 160: } ! 161: ! 162: if (dc->mode == CRISV10_MODE_INDIRECT && (dc->tb_flags & PFIX_FLAG)) { ! 163: dc->dst = dc->src; ! 164: } ! 165: return insn_len; ! 166: } ! 167: ! 168: static unsigned int dec10_quick_imm(DisasContext *dc) ! 169: { ! 170: int32_t imm, simm; ! 171: int op; ! 172: ! 173: /* sign extend. */ ! 174: imm = dc->ir & ((1 << 6) - 1); ! 175: simm = (int8_t) (imm << 2); ! 176: simm >>= 2; ! 177: switch (dc->opcode) { ! 178: case CRISV10_QIMM_BDAP_R0: ! 179: case CRISV10_QIMM_BDAP_R1: ! 180: case CRISV10_QIMM_BDAP_R2: ! 181: case CRISV10_QIMM_BDAP_R3: ! 182: simm = (int8_t)dc->ir; ! 183: LOG_DIS("bdap %d $r%d\n", simm, dc->dst); ! 184: LOG_DIS("pc=%x mode=%x quickimm %d r%d r%d\n", ! 185: dc->pc, dc->mode, dc->opcode, dc->src, dc->dst); ! 186: cris_set_prefix(dc); ! 187: if (dc->dst == 15) { ! 188: tcg_gen_movi_tl(cpu_PR[PR_PREFIX], dc->pc + 2 + simm); ! 189: } else { ! 190: tcg_gen_addi_tl(cpu_PR[PR_PREFIX], cpu_R[dc->dst], simm); ! 191: } ! 192: break; ! 193: ! 194: case CRISV10_QIMM_MOVEQ: ! 195: LOG_DIS("moveq %d, $r%d\n", simm, dc->dst); ! 196: ! 197: cris_cc_mask(dc, CC_MASK_NZVC); ! 198: cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], ! 199: cpu_R[dc->dst], tcg_const_tl(simm), 4); ! 200: break; ! 201: case CRISV10_QIMM_CMPQ: ! 202: LOG_DIS("cmpq %d, $r%d\n", simm, dc->dst); ! 203: ! 204: cris_cc_mask(dc, CC_MASK_NZVC); ! 205: cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst], ! 206: cpu_R[dc->dst], tcg_const_tl(simm), 4); ! 207: break; ! 208: case CRISV10_QIMM_ADDQ: ! 209: LOG_DIS("addq %d, $r%d\n", imm, dc->dst); ! 210: ! 211: cris_cc_mask(dc, CC_MASK_NZVC); ! 212: cris_alu(dc, CC_OP_ADD, cpu_R[dc->dst], ! 213: cpu_R[dc->dst], tcg_const_tl(imm), 4); ! 214: break; ! 215: case CRISV10_QIMM_ANDQ: ! 216: LOG_DIS("andq %d, $r%d\n", simm, dc->dst); ! 217: ! 218: cris_cc_mask(dc, CC_MASK_NZVC); ! 219: cris_alu(dc, CC_OP_AND, cpu_R[dc->dst], ! 220: cpu_R[dc->dst], tcg_const_tl(simm), 4); ! 221: break; ! 222: case CRISV10_QIMM_ASHQ: ! 223: LOG_DIS("ashq %d, $r%d\n", simm, dc->dst); ! 224: ! 225: cris_cc_mask(dc, CC_MASK_NZVC); ! 226: op = imm & (1 << 5); ! 227: imm &= 0x1f; ! 228: if (op) { ! 229: cris_alu(dc, CC_OP_ASR, cpu_R[dc->dst], ! 230: cpu_R[dc->dst], tcg_const_tl(imm), 4); ! 231: } else { ! 232: /* BTST */ ! 233: cris_update_cc_op(dc, CC_OP_FLAGS, 4); ! 234: gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst], ! 235: tcg_const_tl(imm), cpu_PR[PR_CCS]); ! 236: } ! 237: break; ! 238: case CRISV10_QIMM_LSHQ: ! 239: LOG_DIS("lshq %d, $r%d\n", simm, dc->dst); ! 240: ! 241: op = CC_OP_LSL; ! 242: if (imm & (1 << 5)) { ! 243: op = CC_OP_LSR; ! 244: } ! 245: imm &= 0x1f; ! 246: cris_cc_mask(dc, CC_MASK_NZVC); ! 247: cris_alu(dc, op, cpu_R[dc->dst], ! 248: cpu_R[dc->dst], tcg_const_tl(imm), 4); ! 249: break; ! 250: case CRISV10_QIMM_SUBQ: ! 251: LOG_DIS("subq %d, $r%d\n", imm, dc->dst); ! 252: ! 253: cris_cc_mask(dc, CC_MASK_NZVC); ! 254: cris_alu(dc, CC_OP_SUB, cpu_R[dc->dst], ! 255: cpu_R[dc->dst], tcg_const_tl(imm), 4); ! 256: break; ! 257: case CRISV10_QIMM_ORQ: ! 258: LOG_DIS("andq %d, $r%d\n", simm, dc->dst); ! 259: ! 260: cris_cc_mask(dc, CC_MASK_NZVC); ! 261: cris_alu(dc, CC_OP_OR, cpu_R[dc->dst], ! 262: cpu_R[dc->dst], tcg_const_tl(simm), 4); ! 263: break; ! 264: ! 265: case CRISV10_QIMM_BCC_R0: ! 266: if (!dc->ir) { ! 267: cpu_abort(dc->env, "opcode zero\n"); ! 268: } ! 269: case CRISV10_QIMM_BCC_R1: ! 270: case CRISV10_QIMM_BCC_R2: ! 271: case CRISV10_QIMM_BCC_R3: ! 272: imm = dc->ir & 0xff; ! 273: /* bit 0 is a sign bit. */ ! 274: if (imm & 1) { ! 275: imm |= 0xffffff00; /* sign extend. */ ! 276: imm &= ~1; /* get rid of the sign bit. */ ! 277: } ! 278: imm += 2; ! 279: LOG_DIS("b%s %d\n", cc_name(dc->cond), imm); ! 280: ! 281: cris_cc_mask(dc, 0); ! 282: cris_prepare_cc_branch(dc, imm, dc->cond); ! 283: break; ! 284: ! 285: default: ! 286: LOG_DIS("pc=%x mode=%x quickimm %d r%d r%d\n", ! 287: dc->pc, dc->mode, dc->opcode, dc->src, dc->dst); ! 288: cpu_abort(dc->env, "Unhandled quickimm\n"); ! 289: break; ! 290: } ! 291: return 2; ! 292: } ! 293: ! 294: static unsigned int dec10_setclrf(DisasContext *dc) ! 295: { ! 296: uint32_t flags; ! 297: unsigned int set = ~dc->opcode & 1; ! 298: ! 299: flags = EXTRACT_FIELD(dc->ir, 0, 3) ! 300: | (EXTRACT_FIELD(dc->ir, 12, 15) << 4); ! 301: LOG_DIS("%s set=%d flags=%x\n", __func__, set, flags); ! 302: ! 303: ! 304: if (flags & X_FLAG) { ! 305: dc->flagx_known = 1; ! 306: if (set) ! 307: dc->flags_x = X_FLAG; ! 308: else ! 309: dc->flags_x = 0; ! 310: } ! 311: ! 312: cris_evaluate_flags (dc); ! 313: cris_update_cc_op(dc, CC_OP_FLAGS, 4); ! 314: cris_update_cc_x(dc); ! 315: tcg_gen_movi_tl(cc_op, dc->cc_op); ! 316: ! 317: if (set) { ! 318: tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags); ! 319: } else { ! 320: tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags); ! 321: } ! 322: ! 323: dc->flags_uptodate = 1; ! 324: dc->clear_x = 0; ! 325: cris_lock_irq(dc); ! 326: return 2; ! 327: } ! 328: ! 329: static inline void dec10_reg_prep_sext(DisasContext *dc, int size, int sext, ! 330: TCGv dd, TCGv ds, TCGv sd, TCGv ss) ! 331: { ! 332: if (sext) { ! 333: t_gen_sext(dd, sd, size); ! 334: t_gen_sext(ds, ss, size); ! 335: } else { ! 336: t_gen_zext(dd, sd, size); ! 337: t_gen_zext(ds, ss, size); ! 338: } ! 339: } ! 340: ! 341: static void dec10_reg_alu(DisasContext *dc, int op, int size, int sext) ! 342: { ! 343: TCGv t[2]; ! 344: ! 345: t[0] = tcg_temp_new(); ! 346: t[1] = tcg_temp_new(); ! 347: dec10_reg_prep_sext(dc, size, sext, ! 348: t[0], t[1], cpu_R[dc->dst], cpu_R[dc->src]); ! 349: ! 350: if (op == CC_OP_LSL || op == CC_OP_LSR || op == CC_OP_ASR) { ! 351: tcg_gen_andi_tl(t[1], t[1], 63); ! 352: } ! 353: ! 354: assert(dc->dst != 15); ! 355: cris_alu(dc, op, cpu_R[dc->dst], t[0], t[1], size); ! 356: tcg_temp_free(t[0]); ! 357: tcg_temp_free(t[1]); ! 358: } ! 359: ! 360: static void dec10_reg_bound(DisasContext *dc, int size) ! 361: { ! 362: TCGv t; ! 363: ! 364: t = tcg_temp_local_new(); ! 365: t_gen_zext(t, cpu_R[dc->src], size); ! 366: cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[dc->dst], t, 4); ! 367: tcg_temp_free(t); ! 368: } ! 369: ! 370: static void dec10_reg_mul(DisasContext *dc, int size, int sext) ! 371: { ! 372: int op = sext ? CC_OP_MULS : CC_OP_MULU; ! 373: TCGv t[2]; ! 374: ! 375: t[0] = tcg_temp_new(); ! 376: t[1] = tcg_temp_new(); ! 377: dec10_reg_prep_sext(dc, size, sext, ! 378: t[0], t[1], cpu_R[dc->dst], cpu_R[dc->src]); ! 379: ! 380: cris_alu(dc, op, cpu_R[dc->dst], t[0], t[1], 4); ! 381: ! 382: tcg_temp_free(t[0]); ! 383: tcg_temp_free(t[1]); ! 384: } ! 385: ! 386: ! 387: static void dec10_reg_movs(DisasContext *dc) ! 388: { ! 389: int size = (dc->size & 1) + 1; ! 390: TCGv t; ! 391: ! 392: LOG_DIS("movx.%d $r%d, $r%d\n", size, dc->src, dc->dst); ! 393: cris_cc_mask(dc, CC_MASK_NZVC); ! 394: ! 395: t = tcg_temp_new(); ! 396: if (dc->ir & 32) ! 397: t_gen_sext(t, cpu_R[dc->src], size); ! 398: else ! 399: t_gen_zext(t, cpu_R[dc->src], size); ! 400: ! 401: cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, 4); ! 402: tcg_temp_free(t); ! 403: } ! 404: ! 405: static void dec10_reg_alux(DisasContext *dc, int op) ! 406: { ! 407: int size = (dc->size & 1) + 1; ! 408: TCGv t; ! 409: ! 410: LOG_DIS("movx.%d $r%d, $r%d\n", size, dc->src, dc->dst); ! 411: cris_cc_mask(dc, CC_MASK_NZVC); ! 412: ! 413: t = tcg_temp_new(); ! 414: if (dc->ir & 32) ! 415: t_gen_sext(t, cpu_R[dc->src], size); ! 416: else ! 417: t_gen_zext(t, cpu_R[dc->src], size); ! 418: ! 419: cris_alu(dc, op, cpu_R[dc->dst], cpu_R[dc->dst], t, 4); ! 420: tcg_temp_free(t); ! 421: } ! 422: ! 423: static void dec10_reg_mov_pr(DisasContext *dc) ! 424: { ! 425: LOG_DIS("move p%d r%d sz=%d\n", dc->dst, dc->src, preg_sizes_v10[dc->dst]); ! 426: cris_lock_irq(dc); ! 427: if (dc->src == 15) { ! 428: tcg_gen_mov_tl(env_btarget, cpu_PR[dc->dst]); ! 429: cris_prepare_jmp(dc, JMP_INDIRECT); ! 430: return; ! 431: } ! 432: if (dc->dst == PR_CCS) { ! 433: cris_evaluate_flags(dc); ! 434: } ! 435: cris_alu(dc, CC_OP_MOVE, cpu_R[dc->src], ! 436: cpu_R[dc->src], cpu_PR[dc->dst], preg_sizes_v10[dc->dst]); ! 437: } ! 438: ! 439: static void dec10_reg_abs(DisasContext *dc) ! 440: { ! 441: TCGv t0; ! 442: ! 443: LOG_DIS("abs $r%u, $r%u\n", dc->src, dc->dst); ! 444: ! 445: assert(dc->dst != 15); ! 446: t0 = tcg_temp_new(); ! 447: tcg_gen_sari_tl(t0, cpu_R[dc->src], 31); ! 448: tcg_gen_xor_tl(cpu_R[dc->dst], cpu_R[dc->src], t0); ! 449: tcg_gen_sub_tl(t0, cpu_R[dc->dst], t0); ! 450: ! 451: cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t0, 4); ! 452: tcg_temp_free(t0); ! 453: } ! 454: ! 455: static void dec10_reg_swap(DisasContext *dc) ! 456: { ! 457: TCGv t0; ! 458: ! 459: LOG_DIS("not $r%d, $r%d\n", dc->src, dc->dst); ! 460: ! 461: cris_cc_mask(dc, CC_MASK_NZVC); ! 462: t0 = tcg_temp_new(); ! 463: t_gen_mov_TN_reg(t0, dc->src); ! 464: if (dc->dst & 8) ! 465: tcg_gen_not_tl(t0, t0); ! 466: if (dc->dst & 4) ! 467: t_gen_swapw(t0, t0); ! 468: if (dc->dst & 2) ! 469: t_gen_swapb(t0, t0); ! 470: if (dc->dst & 1) ! 471: t_gen_swapr(t0, t0); ! 472: cris_alu(dc, CC_OP_MOVE, cpu_R[dc->src], cpu_R[dc->src], t0, 4); ! 473: tcg_temp_free(t0); ! 474: } ! 475: ! 476: static void dec10_reg_scc(DisasContext *dc) ! 477: { ! 478: int cond = dc->dst; ! 479: ! 480: LOG_DIS("s%s $r%u\n", cc_name(cond), dc->src); ! 481: ! 482: if (cond != CC_A) ! 483: { ! 484: int l1; ! 485: ! 486: gen_tst_cc (dc, cpu_R[dc->src], cond); ! 487: l1 = gen_new_label(); ! 488: tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->src], 0, l1); ! 489: tcg_gen_movi_tl(cpu_R[dc->src], 1); ! 490: gen_set_label(l1); ! 491: } else { ! 492: tcg_gen_movi_tl(cpu_R[dc->src], 1); ! 493: } ! 494: ! 495: cris_cc_mask(dc, 0); ! 496: } ! 497: ! 498: static unsigned int dec10_reg(DisasContext *dc) ! 499: { ! 500: TCGv t; ! 501: unsigned int insn_len = 2; ! 502: unsigned int size = dec10_size(dc->size); ! 503: unsigned int tmp; ! 504: ! 505: if (dc->size != 3) { ! 506: switch (dc->opcode) { ! 507: case CRISV10_REG_MOVE_R: ! 508: LOG_DIS("move.%d $r%d, $r%d\n", dc->size, dc->src, dc->dst); ! 509: cris_cc_mask(dc, CC_MASK_NZVC); ! 510: dec10_reg_alu(dc, CC_OP_MOVE, size, 0); ! 511: if (dc->dst == 15) { ! 512: tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); ! 513: cris_prepare_jmp(dc, JMP_INDIRECT); ! 514: dc->delayed_branch = 1; ! 515: } ! 516: break; ! 517: case CRISV10_REG_MOVX: ! 518: cris_cc_mask(dc, CC_MASK_NZVC); ! 519: dec10_reg_movs(dc); ! 520: break; ! 521: case CRISV10_REG_ADDX: ! 522: cris_cc_mask(dc, CC_MASK_NZVC); ! 523: dec10_reg_alux(dc, CC_OP_ADD); ! 524: break; ! 525: case CRISV10_REG_SUBX: ! 526: cris_cc_mask(dc, CC_MASK_NZVC); ! 527: dec10_reg_alux(dc, CC_OP_SUB); ! 528: break; ! 529: case CRISV10_REG_ADD: ! 530: LOG_DIS("add $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 531: cris_cc_mask(dc, CC_MASK_NZVC); ! 532: dec10_reg_alu(dc, CC_OP_ADD, size, 0); ! 533: break; ! 534: case CRISV10_REG_SUB: ! 535: LOG_DIS("sub $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 536: cris_cc_mask(dc, CC_MASK_NZVC); ! 537: dec10_reg_alu(dc, CC_OP_SUB, size, 0); ! 538: break; ! 539: case CRISV10_REG_CMP: ! 540: LOG_DIS("cmp $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 541: cris_cc_mask(dc, CC_MASK_NZVC); ! 542: dec10_reg_alu(dc, CC_OP_CMP, size, 0); ! 543: break; ! 544: case CRISV10_REG_BOUND: ! 545: LOG_DIS("bound $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 546: cris_cc_mask(dc, CC_MASK_NZVC); ! 547: dec10_reg_bound(dc, size); ! 548: break; ! 549: case CRISV10_REG_AND: ! 550: LOG_DIS("and $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 551: cris_cc_mask(dc, CC_MASK_NZVC); ! 552: dec10_reg_alu(dc, CC_OP_AND, size, 0); ! 553: break; ! 554: case CRISV10_REG_ADDI: ! 555: if (dc->src == 15) { ! 556: /* nop. */ ! 557: return 2; ! 558: } ! 559: t = tcg_temp_new(); ! 560: LOG_DIS("addi r%d r%d size=%d\n", dc->src, dc->dst, dc->size); ! 561: tcg_gen_shli_tl(t, cpu_R[dc->dst], dc->size & 3); ! 562: tcg_gen_add_tl(cpu_R[dc->src], cpu_R[dc->src], t); ! 563: tcg_temp_free(t); ! 564: break; ! 565: case CRISV10_REG_LSL: ! 566: LOG_DIS("lsl $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 567: cris_cc_mask(dc, CC_MASK_NZVC); ! 568: dec10_reg_alu(dc, CC_OP_LSL, size, 0); ! 569: break; ! 570: case CRISV10_REG_LSR: ! 571: LOG_DIS("lsr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 572: cris_cc_mask(dc, CC_MASK_NZVC); ! 573: dec10_reg_alu(dc, CC_OP_LSR, size, 0); ! 574: break; ! 575: case CRISV10_REG_ASR: ! 576: LOG_DIS("asr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 577: cris_cc_mask(dc, CC_MASK_NZVC); ! 578: dec10_reg_alu(dc, CC_OP_ASR, size, 1); ! 579: break; ! 580: case CRISV10_REG_OR: ! 581: LOG_DIS("or $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 582: cris_cc_mask(dc, CC_MASK_NZVC); ! 583: dec10_reg_alu(dc, CC_OP_OR, size, 0); ! 584: break; ! 585: case CRISV10_REG_NEG: ! 586: LOG_DIS("neg $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 587: cris_cc_mask(dc, CC_MASK_NZVC); ! 588: dec10_reg_alu(dc, CC_OP_NEG, size, 0); ! 589: break; ! 590: case CRISV10_REG_BIAP: ! 591: LOG_DIS("BIAP pc=%x reg %d r%d r%d size=%d\n", dc->pc, ! 592: dc->opcode, dc->src, dc->dst, size); ! 593: switch (size) { ! 594: case 4: tmp = 2; break; ! 595: case 2: tmp = 1; break; ! 596: case 1: tmp = 0; break; ! 597: default: ! 598: cpu_abort(dc->env, "Unhandled BIAP"); ! 599: break; ! 600: } ! 601: ! 602: t = tcg_temp_new(); ! 603: tcg_gen_shli_tl(t, cpu_R[dc->dst], tmp); ! 604: if (dc->src == 15) { ! 605: tcg_gen_addi_tl(cpu_PR[PR_PREFIX], t, ((dc->pc +2)| 1) + 1); ! 606: } else { ! 607: tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_R[dc->src], t); ! 608: } ! 609: tcg_temp_free(t); ! 610: cris_set_prefix(dc); ! 611: break; ! 612: ! 613: default: ! 614: LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc, ! 615: dc->opcode, dc->src, dc->dst); ! 616: cpu_abort(dc->env, "Unhandled opcode"); ! 617: break; ! 618: } ! 619: } else { ! 620: switch (dc->opcode) { ! 621: case CRISV10_REG_MOVX: ! 622: cris_cc_mask(dc, CC_MASK_NZVC); ! 623: dec10_reg_movs(dc); ! 624: break; ! 625: case CRISV10_REG_ADDX: ! 626: cris_cc_mask(dc, CC_MASK_NZVC); ! 627: dec10_reg_alux(dc, CC_OP_ADD); ! 628: break; ! 629: case CRISV10_REG_SUBX: ! 630: cris_cc_mask(dc, CC_MASK_NZVC); ! 631: dec10_reg_alux(dc, CC_OP_SUB); ! 632: break; ! 633: case CRISV10_REG_MOVE_SPR_R: ! 634: cris_evaluate_flags(dc); ! 635: cris_cc_mask(dc, 0); ! 636: dec10_reg_mov_pr(dc); ! 637: break; ! 638: case CRISV10_REG_MOVE_R_SPR: ! 639: LOG_DIS("move r%d p%d\n", dc->src, dc->dst); ! 640: cris_evaluate_flags(dc); ! 641: if (dc->src != 11) /* fast for srp. */ ! 642: dc->cpustate_changed = 1; ! 643: t_gen_mov_preg_TN(dc, dc->dst, cpu_R[dc->src]); ! 644: break; ! 645: case CRISV10_REG_SETF: ! 646: case CRISV10_REG_CLEARF: ! 647: dec10_setclrf(dc); ! 648: break; ! 649: case CRISV10_REG_SWAP: ! 650: dec10_reg_swap(dc); ! 651: break; ! 652: case CRISV10_REG_ABS: ! 653: cris_cc_mask(dc, CC_MASK_NZVC); ! 654: dec10_reg_abs(dc); ! 655: break; ! 656: case CRISV10_REG_LZ: ! 657: LOG_DIS("lz $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 658: cris_cc_mask(dc, CC_MASK_NZVC); ! 659: dec10_reg_alu(dc, CC_OP_LZ, 4, 0); ! 660: break; ! 661: case CRISV10_REG_XOR: ! 662: LOG_DIS("xor $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 663: cris_cc_mask(dc, CC_MASK_NZVC); ! 664: dec10_reg_alu(dc, CC_OP_XOR, 4, 0); ! 665: break; ! 666: case CRISV10_REG_BTST: ! 667: LOG_DIS("btst $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 668: cris_cc_mask(dc, CC_MASK_NZVC); ! 669: cris_update_cc_op(dc, CC_OP_FLAGS, 4); ! 670: gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst], ! 671: cpu_R[dc->src], cpu_PR[PR_CCS]); ! 672: break; ! 673: case CRISV10_REG_DSTEP: ! 674: LOG_DIS("dstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 675: cris_cc_mask(dc, CC_MASK_NZVC); ! 676: cris_alu(dc, CC_OP_DSTEP, cpu_R[dc->dst], ! 677: cpu_R[dc->dst], cpu_R[dc->src], 4); ! 678: break; ! 679: case CRISV10_REG_MSTEP: ! 680: LOG_DIS("mstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size); ! 681: cris_evaluate_flags(dc); ! 682: cris_cc_mask(dc, CC_MASK_NZVC); ! 683: cris_alu(dc, CC_OP_MSTEP, cpu_R[dc->dst], ! 684: cpu_R[dc->dst], cpu_R[dc->src], 4); ! 685: break; ! 686: case CRISV10_REG_SCC: ! 687: dec10_reg_scc(dc); ! 688: break; ! 689: default: ! 690: LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc, ! 691: dc->opcode, dc->src, dc->dst); ! 692: cpu_abort(dc->env, "Unhandled opcode"); ! 693: break; ! 694: } ! 695: } ! 696: return insn_len; ! 697: } ! 698: ! 699: static unsigned int dec10_ind_move_m_r(DisasContext *dc, unsigned int size) ! 700: { ! 701: unsigned int insn_len = 2; ! 702: TCGv t; ! 703: ! 704: LOG_DIS("%s: move.%d [$r%d], $r%d\n", __func__, ! 705: size, dc->src, dc->dst); ! 706: ! 707: cris_cc_mask(dc, CC_MASK_NZVC); ! 708: t = tcg_temp_new(); ! 709: insn_len += dec10_prep_move_m(dc, 0, size, t); ! 710: cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, size); ! 711: if (dc->dst == 15) { ! 712: tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); ! 713: cris_prepare_jmp(dc, JMP_INDIRECT); ! 714: dc->delayed_branch = 1; ! 715: return insn_len; ! 716: } ! 717: ! 718: tcg_temp_free(t); ! 719: return insn_len; ! 720: } ! 721: ! 722: static unsigned int dec10_ind_move_r_m(DisasContext *dc, unsigned int size) ! 723: { ! 724: unsigned int insn_len = 2; ! 725: TCGv addr; ! 726: ! 727: LOG_DIS("move.%d $r%d, [$r%d]\n", dc->size, dc->src, dc->dst); ! 728: addr = tcg_temp_new(); ! 729: crisv10_prepare_memaddr(dc, addr, size); ! 730: gen_store(dc, addr, cpu_R[dc->dst], size); ! 731: insn_len += crisv10_post_memaddr(dc, size); ! 732: ! 733: return insn_len; ! 734: } ! 735: ! 736: static unsigned int dec10_ind_move_m_pr(DisasContext *dc) ! 737: { ! 738: unsigned int insn_len = 2, rd = dc->dst; ! 739: TCGv t, addr; ! 740: ! 741: LOG_DIS("move.%d $p%d, [$r%d]\n", dc->size, dc->dst, dc->src); ! 742: cris_lock_irq(dc); ! 743: ! 744: addr = tcg_temp_new(); ! 745: t = tcg_temp_new(); ! 746: insn_len += dec10_prep_move_m(dc, 0, 4, t); ! 747: if (rd == 15) { ! 748: tcg_gen_mov_tl(env_btarget, t); ! 749: cris_prepare_jmp(dc, JMP_INDIRECT); ! 750: dc->delayed_branch = 1; ! 751: return insn_len; ! 752: } ! 753: ! 754: tcg_gen_mov_tl(cpu_PR[rd], t); ! 755: dc->cpustate_changed = 1; ! 756: tcg_temp_free(addr); ! 757: tcg_temp_free(t); ! 758: return insn_len; ! 759: } ! 760: ! 761: static unsigned int dec10_ind_move_pr_m(DisasContext *dc) ! 762: { ! 763: unsigned int insn_len = 2, size = preg_sizes_v10[dc->dst]; ! 764: TCGv addr, t0; ! 765: ! 766: LOG_DIS("move.%d $p%d, [$r%d]\n", dc->size, dc->dst, dc->src); ! 767: ! 768: addr = tcg_temp_new(); ! 769: crisv10_prepare_memaddr(dc, addr, size); ! 770: if (dc->dst == PR_CCS) { ! 771: t0 = tcg_temp_new(); ! 772: cris_evaluate_flags(dc); ! 773: tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG); ! 774: gen_store(dc, addr, t0, size); ! 775: tcg_temp_free(t0); ! 776: } else { ! 777: gen_store(dc, addr, cpu_PR[dc->dst], size); ! 778: } ! 779: t0 = tcg_temp_new(); ! 780: insn_len += crisv10_post_memaddr(dc, size); ! 781: cris_lock_irq(dc); ! 782: ! 783: return insn_len; ! 784: } ! 785: ! 786: static void dec10_movem_r_m(DisasContext *dc) ! 787: { ! 788: int i, pfix = dc->tb_flags & PFIX_FLAG; ! 789: TCGv addr, t0; ! 790: ! 791: LOG_DIS("%s r%d, [r%d] pi=%d ir=%x\n", __func__, ! 792: dc->dst, dc->src, dc->postinc, dc->ir); ! 793: ! 794: addr = tcg_temp_new(); ! 795: t0 = tcg_temp_new(); ! 796: crisv10_prepare_memaddr(dc, addr, 4); ! 797: tcg_gen_mov_tl(t0, addr); ! 798: for (i = dc->dst; i >= 0; i--) { ! 799: if ((pfix && dc->mode == CRISV10_MODE_AUTOINC) && dc->src == i) { ! 800: gen_store(dc, addr, t0, 4); ! 801: } else { ! 802: gen_store(dc, addr, cpu_R[i], 4); ! 803: } ! 804: tcg_gen_addi_tl(addr, addr, 4); ! 805: } ! 806: ! 807: if (pfix && dc->mode == CRISV10_MODE_AUTOINC) { ! 808: tcg_gen_mov_tl(cpu_R[dc->src], t0); ! 809: } ! 810: ! 811: if (!pfix && dc->mode == CRISV10_MODE_AUTOINC) { ! 812: tcg_gen_mov_tl(cpu_R[dc->src], addr); ! 813: } ! 814: tcg_temp_free(addr); ! 815: tcg_temp_free(t0); ! 816: } ! 817: ! 818: static void dec10_movem_m_r(DisasContext *dc) ! 819: { ! 820: int i, pfix = dc->tb_flags & PFIX_FLAG; ! 821: TCGv addr, t0; ! 822: ! 823: LOG_DIS("%s [r%d], r%d pi=%d ir=%x\n", __func__, ! 824: dc->src, dc->dst, dc->postinc, dc->ir); ! 825: ! 826: addr = tcg_temp_new(); ! 827: t0 = tcg_temp_new(); ! 828: crisv10_prepare_memaddr(dc, addr, 4); ! 829: tcg_gen_mov_tl(t0, addr); ! 830: for (i = dc->dst; i >= 0; i--) { ! 831: gen_load(dc, cpu_R[i], addr, 4, 0); ! 832: tcg_gen_addi_tl(addr, addr, 4); ! 833: } ! 834: ! 835: if (pfix && dc->mode == CRISV10_MODE_AUTOINC) { ! 836: tcg_gen_mov_tl(cpu_R[dc->src], t0); ! 837: } ! 838: ! 839: if (!pfix && dc->mode == CRISV10_MODE_AUTOINC) { ! 840: tcg_gen_mov_tl(cpu_R[dc->src], addr); ! 841: } ! 842: tcg_temp_free(addr); ! 843: tcg_temp_free(t0); ! 844: } ! 845: ! 846: static int dec10_ind_alu(DisasContext *dc, int op, unsigned int size) ! 847: { ! 848: int insn_len = 0; ! 849: int rd = dc->dst; ! 850: TCGv t[2]; ! 851: ! 852: cris_alu_m_alloc_temps(t); ! 853: insn_len += dec10_prep_move_m(dc, 0, size, t[0]); ! 854: cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t[0], size); ! 855: if (dc->dst == 15) { ! 856: tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); ! 857: cris_prepare_jmp(dc, JMP_INDIRECT); ! 858: dc->delayed_branch = 1; ! 859: return insn_len; ! 860: } ! 861: ! 862: cris_alu_m_free_temps(t); ! 863: ! 864: return insn_len; ! 865: } ! 866: ! 867: static int dec10_ind_bound(DisasContext *dc, unsigned int size) ! 868: { ! 869: int insn_len = 0; ! 870: int rd = dc->dst; ! 871: TCGv t; ! 872: ! 873: t = tcg_temp_local_new(); ! 874: insn_len += dec10_prep_move_m(dc, 0, size, t); ! 875: cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[rd], t, 4); ! 876: if (dc->dst == 15) { ! 877: tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); ! 878: cris_prepare_jmp(dc, JMP_INDIRECT); ! 879: dc->delayed_branch = 1; ! 880: return insn_len; ! 881: } ! 882: ! 883: tcg_temp_free(t); ! 884: return insn_len; ! 885: } ! 886: ! 887: static int dec10_alux_m(DisasContext *dc, int op) ! 888: { ! 889: unsigned int size = (dc->size & 1) ? 2 : 1; ! 890: unsigned int sx = !!(dc->size & 2); ! 891: int insn_len = 2; ! 892: int rd = dc->dst; ! 893: TCGv t; ! 894: ! 895: LOG_DIS("addx size=%d sx=%d op=%d %d\n", size, sx, dc->src, dc->dst); ! 896: ! 897: t = tcg_temp_new(); ! 898: ! 899: cris_cc_mask(dc, CC_MASK_NZVC); ! 900: insn_len += dec10_prep_move_m(dc, sx, size, t); ! 901: cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t, 4); ! 902: if (dc->dst == 15) { ! 903: tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]); ! 904: cris_prepare_jmp(dc, JMP_INDIRECT); ! 905: dc->delayed_branch = 1; ! 906: return insn_len; ! 907: } ! 908: ! 909: tcg_temp_free(t); ! 910: return insn_len; ! 911: } ! 912: ! 913: static int dec10_dip(DisasContext *dc) ! 914: { ! 915: int insn_len = 2; ! 916: uint32_t imm; ! 917: ! 918: LOG_DIS("dip pc=%x opcode=%d r%d r%d\n", ! 919: dc->pc, dc->opcode, dc->src, dc->dst); ! 920: if (dc->src == 15) { ! 921: imm = ldl_code(dc->pc + 2); ! 922: tcg_gen_movi_tl(cpu_PR[PR_PREFIX], imm); ! 923: if (dc->postinc) ! 924: insn_len += 4; ! 925: tcg_gen_addi_tl(cpu_R[15], cpu_R[15], insn_len - 2); ! 926: } else { ! 927: gen_load(dc, cpu_PR[PR_PREFIX], cpu_R[dc->src], 4, 0); ! 928: if (dc->postinc) ! 929: tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], 4); ! 930: } ! 931: ! 932: cris_set_prefix(dc); ! 933: return insn_len; ! 934: } ! 935: ! 936: static int dec10_bdap_m(DisasContext *dc, int size) ! 937: { ! 938: int insn_len = 2; ! 939: int rd = dc->dst; ! 940: ! 941: LOG_DIS("bdap_m pc=%x opcode=%d r%d r%d sz=%d\n", ! 942: dc->pc, dc->opcode, dc->src, dc->dst, size); ! 943: ! 944: assert(dc->dst != 15); ! 945: #if 0 ! 946: /* 8bit embedded offset? */ ! 947: if (!dc->postinc && (dc->ir & (1 << 11))) { ! 948: int simm = dc->ir & 0xff; ! 949: ! 950: /* cpu_abort(dc->env, "Unhandled opcode"); */ ! 951: /* sign extended. */ ! 952: simm = (int8_t)simm; ! 953: ! 954: tcg_gen_addi_tl(cpu_PR[PR_PREFIX], cpu_R[dc->dst], simm); ! 955: ! 956: cris_set_prefix(dc); ! 957: return insn_len; ! 958: } ! 959: #endif ! 960: /* Now the rest of the modes are truely indirect. */ ! 961: insn_len += dec10_prep_move_m(dc, 1, size, cpu_PR[PR_PREFIX]); ! 962: tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_PR[PR_PREFIX], cpu_R[rd]); ! 963: cris_set_prefix(dc); ! 964: return insn_len; ! 965: } ! 966: ! 967: static unsigned int dec10_ind(DisasContext *dc) ! 968: { ! 969: unsigned int insn_len = 2; ! 970: unsigned int size = dec10_size(dc->size); ! 971: uint32_t imm; ! 972: int32_t simm; ! 973: TCGv t[2]; ! 974: ! 975: if (dc->size != 3) { ! 976: switch (dc->opcode) { ! 977: case CRISV10_IND_MOVE_M_R: ! 978: return dec10_ind_move_m_r(dc, size); ! 979: break; ! 980: case CRISV10_IND_MOVE_R_M: ! 981: return dec10_ind_move_r_m(dc, size); ! 982: break; ! 983: case CRISV10_IND_CMP: ! 984: LOG_DIS("cmp size=%d op=%d %d\n", size, dc->src, dc->dst); ! 985: cris_cc_mask(dc, CC_MASK_NZVC); ! 986: insn_len += dec10_ind_alu(dc, CC_OP_CMP, size); ! 987: break; ! 988: case CRISV10_IND_TEST: ! 989: LOG_DIS("test size=%d op=%d %d\n", size, dc->src, dc->dst); ! 990: ! 991: cris_evaluate_flags(dc); ! 992: cris_cc_mask(dc, CC_MASK_NZVC); ! 993: cris_alu_m_alloc_temps(t); ! 994: insn_len += dec10_prep_move_m(dc, 0, size, t[0]); ! 995: tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3); ! 996: cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst], ! 997: t[0], tcg_const_tl(0), size); ! 998: cris_alu_m_free_temps(t); ! 999: break; ! 1000: case CRISV10_IND_ADD: ! 1001: LOG_DIS("add size=%d op=%d %d\n", size, dc->src, dc->dst); ! 1002: cris_cc_mask(dc, CC_MASK_NZVC); ! 1003: insn_len += dec10_ind_alu(dc, CC_OP_ADD, size); ! 1004: break; ! 1005: case CRISV10_IND_SUB: ! 1006: LOG_DIS("sub size=%d op=%d %d\n", size, dc->src, dc->dst); ! 1007: cris_cc_mask(dc, CC_MASK_NZVC); ! 1008: insn_len += dec10_ind_alu(dc, CC_OP_SUB, size); ! 1009: break; ! 1010: case CRISV10_IND_BOUND: ! 1011: LOG_DIS("bound size=%d op=%d %d\n", size, dc->src, dc->dst); ! 1012: cris_cc_mask(dc, CC_MASK_NZVC); ! 1013: insn_len += dec10_ind_bound(dc, size); ! 1014: break; ! 1015: case CRISV10_IND_AND: ! 1016: LOG_DIS("and size=%d op=%d %d\n", size, dc->src, dc->dst); ! 1017: cris_cc_mask(dc, CC_MASK_NZVC); ! 1018: insn_len += dec10_ind_alu(dc, CC_OP_AND, size); ! 1019: break; ! 1020: case CRISV10_IND_OR: ! 1021: LOG_DIS("or size=%d op=%d %d\n", size, dc->src, dc->dst); ! 1022: cris_cc_mask(dc, CC_MASK_NZVC); ! 1023: insn_len += dec10_ind_alu(dc, CC_OP_OR, size); ! 1024: break; ! 1025: case CRISV10_IND_MOVX: ! 1026: insn_len = dec10_alux_m(dc, CC_OP_MOVE); ! 1027: break; ! 1028: case CRISV10_IND_ADDX: ! 1029: insn_len = dec10_alux_m(dc, CC_OP_ADD); ! 1030: break; ! 1031: case CRISV10_IND_SUBX: ! 1032: insn_len = dec10_alux_m(dc, CC_OP_SUB); ! 1033: break; ! 1034: case CRISV10_IND_CMPX: ! 1035: insn_len = dec10_alux_m(dc, CC_OP_CMP); ! 1036: break; ! 1037: case CRISV10_IND_MUL: ! 1038: /* This is a reg insn coded in the mem indir space. */ ! 1039: LOG_DIS("mul pc=%x opcode=%d\n", dc->pc, dc->opcode); ! 1040: cris_cc_mask(dc, CC_MASK_NZVC); ! 1041: dec10_reg_mul(dc, size, dc->ir & (1 << 10)); ! 1042: break; ! 1043: case CRISV10_IND_BDAP_M: ! 1044: insn_len = dec10_bdap_m(dc, size); ! 1045: break; ! 1046: default: ! 1047: LOG_DIS("pc=%x var-ind.%d %d r%d r%d\n", ! 1048: dc->pc, size, dc->opcode, dc->src, dc->dst); ! 1049: cpu_abort(dc->env, "Unhandled opcode"); ! 1050: break; ! 1051: } ! 1052: return insn_len; ! 1053: } ! 1054: ! 1055: switch (dc->opcode) { ! 1056: case CRISV10_IND_MOVE_M_SPR: ! 1057: insn_len = dec10_ind_move_m_pr(dc); ! 1058: break; ! 1059: case CRISV10_IND_MOVE_SPR_M: ! 1060: insn_len = dec10_ind_move_pr_m(dc); ! 1061: break; ! 1062: case CRISV10_IND_JUMP_M: ! 1063: if (dc->src == 15) { ! 1064: LOG_DIS("jump.%d %d r%d r%d\n", size, ! 1065: dc->opcode, dc->src, dc->dst); ! 1066: imm = ldl_code(dc->pc + 2); ! 1067: if (dc->mode == CRISV10_MODE_AUTOINC) ! 1068: insn_len += size; ! 1069: ! 1070: t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len)); ! 1071: tcg_gen_movi_tl(env_btarget, imm); ! 1072: cris_prepare_jmp(dc, JMP_INDIRECT); ! 1073: dc->delayed_branch--; /* v10 has no dslot here. */ ! 1074: } else { ! 1075: if (dc->dst == 14) { ! 1076: LOG_DIS("break %d\n", dc->src); ! 1077: cris_evaluate_flags(dc); ! 1078: tcg_gen_movi_tl(env_pc, dc->pc + 2); ! 1079: t_gen_raise_exception(EXCP_BREAK); ! 1080: dc->is_jmp = DISAS_UPDATE; ! 1081: return insn_len; ! 1082: } ! 1083: LOG_DIS("%d: jump.%d %d r%d r%d\n", __LINE__, size, ! 1084: dc->opcode, dc->src, dc->dst); ! 1085: t[0] = tcg_temp_new(); ! 1086: t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len)); ! 1087: crisv10_prepare_memaddr(dc, t[0], size); ! 1088: gen_load(dc, env_btarget, t[0], 4, 0); ! 1089: insn_len += crisv10_post_memaddr(dc, size); ! 1090: cris_prepare_jmp(dc, JMP_INDIRECT); ! 1091: dc->delayed_branch--; /* v10 has no dslot here. */ ! 1092: tcg_temp_free(t[0]); ! 1093: } ! 1094: break; ! 1095: ! 1096: case CRISV10_IND_MOVEM_R_M: ! 1097: LOG_DIS("movem_r_m pc=%x opcode=%d r%d r%d\n", ! 1098: dc->pc, dc->opcode, dc->dst, dc->src); ! 1099: dec10_movem_r_m(dc); ! 1100: break; ! 1101: case CRISV10_IND_MOVEM_M_R: ! 1102: LOG_DIS("movem_m_r pc=%x opcode=%d\n", dc->pc, dc->opcode); ! 1103: dec10_movem_m_r(dc); ! 1104: break; ! 1105: case CRISV10_IND_JUMP_R: ! 1106: LOG_DIS("jmp pc=%x opcode=%d r%d r%d\n", ! 1107: dc->pc, dc->opcode, dc->dst, dc->src); ! 1108: tcg_gen_mov_tl(env_btarget, cpu_R[dc->src]); ! 1109: t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len)); ! 1110: cris_prepare_jmp(dc, JMP_INDIRECT); ! 1111: dc->delayed_branch--; /* v10 has no dslot here. */ ! 1112: break; ! 1113: case CRISV10_IND_MOVX: ! 1114: insn_len = dec10_alux_m(dc, CC_OP_MOVE); ! 1115: break; ! 1116: case CRISV10_IND_ADDX: ! 1117: insn_len = dec10_alux_m(dc, CC_OP_ADD); ! 1118: break; ! 1119: case CRISV10_IND_SUBX: ! 1120: insn_len = dec10_alux_m(dc, CC_OP_SUB); ! 1121: break; ! 1122: case CRISV10_IND_CMPX: ! 1123: insn_len = dec10_alux_m(dc, CC_OP_CMP); ! 1124: break; ! 1125: case CRISV10_IND_DIP: ! 1126: insn_len = dec10_dip(dc); ! 1127: break; ! 1128: case CRISV10_IND_BCC_M: ! 1129: ! 1130: cris_cc_mask(dc, 0); ! 1131: imm = ldsw_code(dc->pc + 2); ! 1132: simm = (int16_t)imm; ! 1133: simm += 4; ! 1134: ! 1135: LOG_DIS("bcc_m: b%s %x\n", cc_name(dc->cond), dc->pc + simm); ! 1136: cris_prepare_cc_branch(dc, simm, dc->cond); ! 1137: insn_len = 4; ! 1138: break; ! 1139: default: ! 1140: LOG_DIS("ERROR pc=%x opcode=%d\n", dc->pc, dc->opcode); ! 1141: cpu_abort(dc->env, "Unhandled opcode"); ! 1142: break; ! 1143: } ! 1144: ! 1145: return insn_len; ! 1146: } ! 1147: ! 1148: static unsigned int crisv10_decoder(DisasContext *dc) ! 1149: { ! 1150: unsigned int insn_len = 2; ! 1151: ! 1152: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) ! 1153: tcg_gen_debug_insn_start(dc->pc); ! 1154: ! 1155: /* Load a halfword onto the instruction register. */ ! 1156: dc->ir = lduw_code(dc->pc); ! 1157: ! 1158: /* Now decode it. */ ! 1159: dc->opcode = EXTRACT_FIELD(dc->ir, 6, 9); ! 1160: dc->mode = EXTRACT_FIELD(dc->ir, 10, 11); ! 1161: dc->src = EXTRACT_FIELD(dc->ir, 0, 3); ! 1162: dc->size = EXTRACT_FIELD(dc->ir, 4, 5); ! 1163: dc->cond = dc->dst = EXTRACT_FIELD(dc->ir, 12, 15); ! 1164: dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10); ! 1165: ! 1166: dc->clear_prefix = 1; ! 1167: ! 1168: /* FIXME: What if this insn insn't 2 in length?? */ ! 1169: if (dc->src == 15 || dc->dst == 15) ! 1170: tcg_gen_movi_tl(cpu_R[15], dc->pc + 2); ! 1171: ! 1172: switch (dc->mode) { ! 1173: case CRISV10_MODE_QIMMEDIATE: ! 1174: insn_len = dec10_quick_imm(dc); ! 1175: break; ! 1176: case CRISV10_MODE_REG: ! 1177: insn_len = dec10_reg(dc); ! 1178: break; ! 1179: case CRISV10_MODE_AUTOINC: ! 1180: case CRISV10_MODE_INDIRECT: ! 1181: insn_len = dec10_ind(dc); ! 1182: break; ! 1183: } ! 1184: ! 1185: if (dc->clear_prefix && dc->tb_flags & PFIX_FLAG) { ! 1186: dc->tb_flags &= ~PFIX_FLAG; ! 1187: tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~PFIX_FLAG); ! 1188: dc->cpustate_changed = 1; ! 1189: } ! 1190: ! 1191: /* CRISv10 locks out interrupts on dslots. */ ! 1192: if (dc->delayed_branch == 2) { ! 1193: cris_lock_irq(dc); ! 1194: } ! 1195: return insn_len; ! 1196: } ! 1197: ! 1198: static CPUCRISState *cpu_crisv10_init (CPUState *env) ! 1199: { ! 1200: int i; ! 1201: ! 1202: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); ! 1203: cc_x = tcg_global_mem_new(TCG_AREG0, ! 1204: offsetof(CPUState, cc_x), "cc_x"); ! 1205: cc_src = tcg_global_mem_new(TCG_AREG0, ! 1206: offsetof(CPUState, cc_src), "cc_src"); ! 1207: cc_dest = tcg_global_mem_new(TCG_AREG0, ! 1208: offsetof(CPUState, cc_dest), ! 1209: "cc_dest"); ! 1210: cc_result = tcg_global_mem_new(TCG_AREG0, ! 1211: offsetof(CPUState, cc_result), ! 1212: "cc_result"); ! 1213: cc_op = tcg_global_mem_new(TCG_AREG0, ! 1214: offsetof(CPUState, cc_op), "cc_op"); ! 1215: cc_size = tcg_global_mem_new(TCG_AREG0, ! 1216: offsetof(CPUState, cc_size), ! 1217: "cc_size"); ! 1218: cc_mask = tcg_global_mem_new(TCG_AREG0, ! 1219: offsetof(CPUState, cc_mask), ! 1220: "cc_mask"); ! 1221: ! 1222: env_pc = tcg_global_mem_new(TCG_AREG0, ! 1223: offsetof(CPUState, pc), ! 1224: "pc"); ! 1225: env_btarget = tcg_global_mem_new(TCG_AREG0, ! 1226: offsetof(CPUState, btarget), ! 1227: "btarget"); ! 1228: env_btaken = tcg_global_mem_new(TCG_AREG0, ! 1229: offsetof(CPUState, btaken), ! 1230: "btaken"); ! 1231: for (i = 0; i < 16; i++) { ! 1232: cpu_R[i] = tcg_global_mem_new(TCG_AREG0, ! 1233: offsetof(CPUState, regs[i]), ! 1234: regnames_v10[i]); ! 1235: } ! 1236: for (i = 0; i < 16; i++) { ! 1237: cpu_PR[i] = tcg_global_mem_new(TCG_AREG0, ! 1238: offsetof(CPUState, pregs[i]), ! 1239: pregnames_v10[i]); ! 1240: } ! 1241: ! 1242: return env; ! 1243: } ! 1244:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.