|
|
1.1 ! root 1: /* ! 2: * Xilinx MicroBlaze emulation for qemu: main translation routines. ! 3: * ! 4: * Copyright (c) 2009 Edgar E. Iglesias. ! 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, see <http://www.gnu.org/licenses/>. ! 18: */ ! 19: ! 20: #include <stdarg.h> ! 21: #include <stdlib.h> ! 22: #include <stdio.h> ! 23: #include <string.h> ! 24: #include <inttypes.h> ! 25: #include <assert.h> ! 26: ! 27: #include "cpu.h" ! 28: #include "exec-all.h" ! 29: #include "disas.h" ! 30: #include "tcg-op.h" ! 31: #include "helper.h" ! 32: #include "microblaze-decode.h" ! 33: #include "qemu-common.h" ! 34: ! 35: #define GEN_HELPER 1 ! 36: #include "helper.h" ! 37: ! 38: #define SIM_COMPAT 0 ! 39: #define DISAS_GNU 1 ! 40: #define DISAS_MB 1 ! 41: #if DISAS_MB && !SIM_COMPAT ! 42: # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) ! 43: #else ! 44: # define LOG_DIS(...) do { } while (0) ! 45: #endif ! 46: ! 47: #define D(x) ! 48: ! 49: #define EXTRACT_FIELD(src, start, end) \ ! 50: (((src) >> start) & ((1 << (end - start + 1)) - 1)) ! 51: ! 52: static TCGv env_debug; ! 53: static TCGv_ptr cpu_env; ! 54: static TCGv cpu_R[32]; ! 55: static TCGv cpu_SR[18]; ! 56: static TCGv env_imm; ! 57: static TCGv env_btaken; ! 58: static TCGv env_btarget; ! 59: static TCGv env_iflags; ! 60: ! 61: #include "gen-icount.h" ! 62: ! 63: /* This is the state at translation time. */ ! 64: typedef struct DisasContext { ! 65: CPUState *env; ! 66: target_ulong pc, ppc; ! 67: target_ulong cache_pc; ! 68: ! 69: /* Decoder. */ ! 70: int type_b; ! 71: uint32_t ir; ! 72: uint8_t opcode; ! 73: uint8_t rd, ra, rb; ! 74: uint16_t imm; ! 75: ! 76: unsigned int cpustate_changed; ! 77: unsigned int delayed_branch; ! 78: unsigned int tb_flags, synced_flags; /* tb dependent flags. */ ! 79: unsigned int clear_imm; ! 80: int is_jmp; ! 81: ! 82: #define JMP_NOJMP 0 ! 83: #define JMP_DIRECT 1 ! 84: #define JMP_INDIRECT 2 ! 85: unsigned int jmp; ! 86: uint32_t jmp_pc; ! 87: ! 88: int abort_at_next_insn; ! 89: int nr_nops; ! 90: struct TranslationBlock *tb; ! 91: int singlestep_enabled; ! 92: } DisasContext; ! 93: ! 94: const static char *regnames[] = ! 95: { ! 96: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", ! 97: "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", ! 98: "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", ! 99: "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", ! 100: }; ! 101: ! 102: const static char *special_regnames[] = ! 103: { ! 104: "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7", ! 105: "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", ! 106: "sr16", "sr17", "sr18" ! 107: }; ! 108: ! 109: /* Sign extend at translation time. */ ! 110: static inline int sign_extend(unsigned int val, unsigned int width) ! 111: { ! 112: int sval; ! 113: ! 114: /* LSL. */ ! 115: val <<= 31 - width; ! 116: sval = val; ! 117: /* ASR. */ ! 118: sval >>= 31 - width; ! 119: return sval; ! 120: } ! 121: ! 122: static inline void t_sync_flags(DisasContext *dc) ! 123: { ! 124: /* Synch the tb dependant flags between translator and runtime. */ ! 125: if (dc->tb_flags != dc->synced_flags) { ! 126: tcg_gen_movi_tl(env_iflags, dc->tb_flags); ! 127: dc->synced_flags = dc->tb_flags; ! 128: } ! 129: } ! 130: ! 131: static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) ! 132: { ! 133: TCGv_i32 tmp = tcg_const_i32(index); ! 134: ! 135: t_sync_flags(dc); ! 136: tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); ! 137: gen_helper_raise_exception(tmp); ! 138: tcg_temp_free_i32(tmp); ! 139: dc->is_jmp = DISAS_UPDATE; ! 140: } ! 141: ! 142: static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) ! 143: { ! 144: TranslationBlock *tb; ! 145: tb = dc->tb; ! 146: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { ! 147: tcg_gen_goto_tb(n); ! 148: tcg_gen_movi_tl(cpu_SR[SR_PC], dest); ! 149: tcg_gen_exit_tb((long)tb + n); ! 150: } else { ! 151: tcg_gen_movi_tl(cpu_SR[SR_PC], dest); ! 152: tcg_gen_exit_tb(0); ! 153: } ! 154: } ! 155: ! 156: static inline TCGv *dec_alu_op_b(DisasContext *dc) ! 157: { ! 158: if (dc->type_b) { ! 159: if (dc->tb_flags & IMM_FLAG) ! 160: tcg_gen_ori_tl(env_imm, env_imm, dc->imm); ! 161: else ! 162: tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm)); ! 163: return &env_imm; ! 164: } else ! 165: return &cpu_R[dc->rb]; ! 166: } ! 167: ! 168: static void dec_add(DisasContext *dc) ! 169: { ! 170: unsigned int k, c; ! 171: ! 172: k = dc->opcode & 4; ! 173: c = dc->opcode & 2; ! 174: ! 175: LOG_DIS("add%s%s%s r%d r%d r%d\n", ! 176: dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "", ! 177: dc->rd, dc->ra, dc->rb); ! 178: ! 179: if (k && !c && dc->rd) ! 180: tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); ! 181: else if (dc->rd) ! 182: gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)), ! 183: tcg_const_tl(k), tcg_const_tl(c)); ! 184: else { ! 185: TCGv d = tcg_temp_new(); ! 186: gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)), ! 187: tcg_const_tl(k), tcg_const_tl(c)); ! 188: tcg_temp_free(d); ! 189: } ! 190: } ! 191: ! 192: static void dec_sub(DisasContext *dc) ! 193: { ! 194: unsigned int u, cmp, k, c; ! 195: ! 196: u = dc->imm & 2; ! 197: k = dc->opcode & 4; ! 198: c = dc->opcode & 2; ! 199: cmp = (dc->imm & 1) && (!dc->type_b) && k; ! 200: ! 201: if (cmp) { ! 202: LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir); ! 203: if (dc->rd) { ! 204: if (u) ! 205: gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); ! 206: else ! 207: gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); ! 208: } ! 209: } else { ! 210: LOG_DIS("sub%s%s r%d, r%d r%d\n", ! 211: k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb); ! 212: ! 213: if (!k || c) { ! 214: TCGv t; ! 215: t = tcg_temp_new(); ! 216: if (dc->rd) ! 217: gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)), ! 218: tcg_const_tl(k), tcg_const_tl(c)); ! 219: else ! 220: gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)), ! 221: tcg_const_tl(k), tcg_const_tl(c)); ! 222: tcg_temp_free(t); ! 223: } ! 224: else if (dc->rd) ! 225: tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); ! 226: } ! 227: } ! 228: ! 229: static void dec_pattern(DisasContext *dc) ! 230: { ! 231: unsigned int mode; ! 232: int l1; ! 233: ! 234: mode = dc->opcode & 3; ! 235: switch (mode) { ! 236: case 0: ! 237: /* pcmpbf. */ ! 238: LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); ! 239: if (dc->rd) ! 240: gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); ! 241: break; ! 242: case 2: ! 243: LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); ! 244: if (dc->rd) { ! 245: TCGv t0 = tcg_temp_local_new(); ! 246: l1 = gen_new_label(); ! 247: tcg_gen_movi_tl(t0, 1); ! 248: tcg_gen_brcond_tl(TCG_COND_EQ, ! 249: cpu_R[dc->ra], cpu_R[dc->rb], l1); ! 250: tcg_gen_movi_tl(t0, 0); ! 251: gen_set_label(l1); ! 252: tcg_gen_mov_tl(cpu_R[dc->rd], t0); ! 253: tcg_temp_free(t0); ! 254: } ! 255: break; ! 256: case 3: ! 257: LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); ! 258: l1 = gen_new_label(); ! 259: if (dc->rd) { ! 260: TCGv t0 = tcg_temp_local_new(); ! 261: tcg_gen_movi_tl(t0, 1); ! 262: tcg_gen_brcond_tl(TCG_COND_NE, ! 263: cpu_R[dc->ra], cpu_R[dc->rb], l1); ! 264: tcg_gen_movi_tl(t0, 0); ! 265: gen_set_label(l1); ! 266: tcg_gen_mov_tl(cpu_R[dc->rd], t0); ! 267: tcg_temp_free(t0); ! 268: } ! 269: break; ! 270: default: ! 271: cpu_abort(dc->env, ! 272: "unsupported pattern insn opcode=%x\n", dc->opcode); ! 273: break; ! 274: } ! 275: } ! 276: ! 277: static void dec_and(DisasContext *dc) ! 278: { ! 279: unsigned int not; ! 280: ! 281: if (!dc->type_b && (dc->imm & (1 << 10))) { ! 282: dec_pattern(dc); ! 283: return; ! 284: } ! 285: ! 286: not = dc->opcode & (1 << 1); ! 287: LOG_DIS("and%s\n", not ? "n" : ""); ! 288: ! 289: if (!dc->rd) ! 290: return; ! 291: ! 292: if (not) { ! 293: TCGv t = tcg_temp_new(); ! 294: tcg_gen_not_tl(t, *(dec_alu_op_b(dc))); ! 295: tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t); ! 296: tcg_temp_free(t); ! 297: } else ! 298: tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); ! 299: } ! 300: ! 301: static void dec_or(DisasContext *dc) ! 302: { ! 303: if (!dc->type_b && (dc->imm & (1 << 10))) { ! 304: dec_pattern(dc); ! 305: return; ! 306: } ! 307: ! 308: LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm); ! 309: if (dc->rd) ! 310: tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); ! 311: } ! 312: ! 313: static void dec_xor(DisasContext *dc) ! 314: { ! 315: if (!dc->type_b && (dc->imm & (1 << 10))) { ! 316: dec_pattern(dc); ! 317: return; ! 318: } ! 319: ! 320: LOG_DIS("xor r%d\n", dc->rd); ! 321: if (dc->rd) ! 322: tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); ! 323: } ! 324: ! 325: static void read_carry(DisasContext *dc, TCGv d) ! 326: { ! 327: tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31); ! 328: } ! 329: ! 330: static void write_carry(DisasContext *dc, TCGv v) ! 331: { ! 332: TCGv t0 = tcg_temp_new(); ! 333: tcg_gen_shli_tl(t0, v, 31); ! 334: tcg_gen_sari_tl(t0, t0, 31); ! 335: tcg_gen_mov_tl(env_debug, t0); ! 336: tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC)); ! 337: tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], ! 338: ~(MSR_C | MSR_CC)); ! 339: tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0); ! 340: tcg_temp_free(t0); ! 341: } ! 342: ! 343: ! 344: static inline void msr_read(DisasContext *dc, TCGv d) ! 345: { ! 346: tcg_gen_mov_tl(d, cpu_SR[SR_MSR]); ! 347: } ! 348: ! 349: static inline void msr_write(DisasContext *dc, TCGv v) ! 350: { ! 351: dc->cpustate_changed = 1; ! 352: tcg_gen_mov_tl(cpu_SR[SR_MSR], v); ! 353: /* PVR, we have a processor version register. */ ! 354: tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10)); ! 355: } ! 356: ! 357: static void dec_msr(DisasContext *dc) ! 358: { ! 359: TCGv t0, t1; ! 360: unsigned int sr, to, rn; ! 361: ! 362: sr = dc->imm & ((1 << 14) - 1); ! 363: to = dc->imm & (1 << 14); ! 364: dc->type_b = 1; ! 365: if (to) ! 366: dc->cpustate_changed = 1; ! 367: ! 368: /* msrclr and msrset. */ ! 369: if (!(dc->imm & (1 << 15))) { ! 370: unsigned int clr = dc->ir & (1 << 16); ! 371: ! 372: LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set", ! 373: dc->rd, dc->imm); ! 374: if (dc->rd) ! 375: msr_read(dc, cpu_R[dc->rd]); ! 376: ! 377: t0 = tcg_temp_new(); ! 378: t1 = tcg_temp_new(); ! 379: msr_read(dc, t0); ! 380: tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc))); ! 381: ! 382: if (clr) { ! 383: tcg_gen_not_tl(t1, t1); ! 384: tcg_gen_and_tl(t0, t0, t1); ! 385: } else ! 386: tcg_gen_or_tl(t0, t0, t1); ! 387: msr_write(dc, t0); ! 388: tcg_temp_free(t0); ! 389: tcg_temp_free(t1); ! 390: tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4); ! 391: dc->is_jmp = DISAS_UPDATE; ! 392: return; ! 393: } ! 394: ! 395: #if !defined(CONFIG_USER_ONLY) ! 396: /* Catch read/writes to the mmu block. */ ! 397: if ((sr & ~0xff) == 0x1000) { ! 398: sr &= 7; ! 399: LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); ! 400: if (to) ! 401: gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]); ! 402: else ! 403: gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr)); ! 404: return; ! 405: } ! 406: #endif ! 407: ! 408: if (to) { ! 409: LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); ! 410: switch (sr) { ! 411: case 0: ! 412: break; ! 413: case 1: ! 414: msr_write(dc, cpu_R[dc->ra]); ! 415: break; ! 416: case 0x3: ! 417: tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]); ! 418: break; ! 419: case 0x5: ! 420: tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]); ! 421: break; ! 422: case 0x7: ! 423: /* Ignored at the moment. */ ! 424: break; ! 425: default: ! 426: cpu_abort(dc->env, "unknown mts reg %x\n", sr); ! 427: break; ! 428: } ! 429: } else { ! 430: LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm); ! 431: ! 432: switch (sr) { ! 433: case 0: ! 434: tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); ! 435: break; ! 436: case 1: ! 437: msr_read(dc, cpu_R[dc->rd]); ! 438: break; ! 439: case 0x3: ! 440: tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]); ! 441: break; ! 442: case 0x5: ! 443: tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]); ! 444: break; ! 445: case 0x7: ! 446: tcg_gen_movi_tl(cpu_R[dc->rd], 0); ! 447: break; ! 448: case 0xb: ! 449: tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]); ! 450: break; ! 451: case 0x2000: ! 452: case 0x2001: ! 453: case 0x2002: ! 454: case 0x2003: ! 455: case 0x2004: ! 456: case 0x2005: ! 457: case 0x2006: ! 458: case 0x2007: ! 459: case 0x2008: ! 460: case 0x2009: ! 461: case 0x200a: ! 462: case 0x200b: ! 463: case 0x200c: ! 464: rn = sr & 0xf; ! 465: tcg_gen_ld_tl(cpu_R[dc->rd], ! 466: cpu_env, offsetof(CPUState, pvr.regs[rn])); ! 467: break; ! 468: default: ! 469: cpu_abort(dc->env, "unknown mfs reg %x\n", sr); ! 470: break; ! 471: } ! 472: } ! 473: } ! 474: ! 475: /* 64-bit signed mul, lower result in d and upper in d2. */ ! 476: static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b) ! 477: { ! 478: TCGv_i64 t0, t1; ! 479: ! 480: t0 = tcg_temp_new_i64(); ! 481: t1 = tcg_temp_new_i64(); ! 482: ! 483: tcg_gen_ext_i32_i64(t0, a); ! 484: tcg_gen_ext_i32_i64(t1, b); ! 485: tcg_gen_mul_i64(t0, t0, t1); ! 486: ! 487: tcg_gen_trunc_i64_i32(d, t0); ! 488: tcg_gen_shri_i64(t0, t0, 32); ! 489: tcg_gen_trunc_i64_i32(d2, t0); ! 490: ! 491: tcg_temp_free_i64(t0); ! 492: tcg_temp_free_i64(t1); ! 493: } ! 494: ! 495: /* 64-bit unsigned muls, lower result in d and upper in d2. */ ! 496: static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b) ! 497: { ! 498: TCGv_i64 t0, t1; ! 499: ! 500: t0 = tcg_temp_new_i64(); ! 501: t1 = tcg_temp_new_i64(); ! 502: ! 503: tcg_gen_extu_i32_i64(t0, a); ! 504: tcg_gen_extu_i32_i64(t1, b); ! 505: tcg_gen_mul_i64(t0, t0, t1); ! 506: ! 507: tcg_gen_trunc_i64_i32(d, t0); ! 508: tcg_gen_shri_i64(t0, t0, 32); ! 509: tcg_gen_trunc_i64_i32(d2, t0); ! 510: ! 511: tcg_temp_free_i64(t0); ! 512: tcg_temp_free_i64(t1); ! 513: } ! 514: ! 515: /* Multiplier unit. */ ! 516: static void dec_mul(DisasContext *dc) ! 517: { ! 518: TCGv d[2]; ! 519: unsigned int subcode; ! 520: ! 521: subcode = dc->imm & 3; ! 522: d[0] = tcg_temp_new(); ! 523: d[1] = tcg_temp_new(); ! 524: ! 525: if (dc->type_b) { ! 526: LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm); ! 527: t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc))); ! 528: goto done; ! 529: } ! 530: ! 531: switch (subcode) { ! 532: case 0: ! 533: LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); ! 534: t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]); ! 535: break; ! 536: case 1: ! 537: LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); ! 538: t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); ! 539: break; ! 540: case 2: ! 541: LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); ! 542: t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); ! 543: break; ! 544: case 3: ! 545: LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); ! 546: t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); ! 547: break; ! 548: default: ! 549: cpu_abort(dc->env, "unknown MUL insn %x\n", subcode); ! 550: break; ! 551: } ! 552: done: ! 553: tcg_temp_free(d[0]); ! 554: tcg_temp_free(d[1]); ! 555: } ! 556: ! 557: /* Div unit. */ ! 558: static void dec_div(DisasContext *dc) ! 559: { ! 560: unsigned int u; ! 561: ! 562: u = dc->imm & 2; ! 563: LOG_DIS("div\n"); ! 564: ! 565: /* FIXME: support div by zero exceptions. */ ! 566: if (u) ! 567: gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); ! 568: else ! 569: gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); ! 570: if (!dc->rd) ! 571: tcg_gen_movi_tl(cpu_R[dc->rd], 0); ! 572: } ! 573: ! 574: static void dec_barrel(DisasContext *dc) ! 575: { ! 576: TCGv t0; ! 577: unsigned int s, t; ! 578: ! 579: s = dc->imm & (1 << 10); ! 580: t = dc->imm & (1 << 9); ! 581: ! 582: LOG_DIS("bs%s%s r%d r%d r%d\n", ! 583: s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb); ! 584: ! 585: t0 = tcg_temp_new(); ! 586: ! 587: tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc))); ! 588: tcg_gen_andi_tl(t0, t0, 31); ! 589: ! 590: if (s) ! 591: tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); ! 592: else { ! 593: if (t) ! 594: tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); ! 595: else ! 596: tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); ! 597: } ! 598: } ! 599: ! 600: static void dec_bit(DisasContext *dc) ! 601: { ! 602: TCGv t0, t1; ! 603: unsigned int op; ! 604: ! 605: op = dc->ir & ((1 << 8) - 1); ! 606: switch (op) { ! 607: case 0x21: ! 608: /* src. */ ! 609: t0 = tcg_temp_new(); ! 610: ! 611: LOG_DIS("src r%d r%d\n", dc->rd, dc->ra); ! 612: tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1); ! 613: if (dc->rd) { ! 614: t1 = tcg_temp_new(); ! 615: read_carry(dc, t1); ! 616: tcg_gen_shli_tl(t1, t1, 31); ! 617: ! 618: tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); ! 619: tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1); ! 620: tcg_temp_free(t1); ! 621: } ! 622: ! 623: /* Update carry. */ ! 624: write_carry(dc, t0); ! 625: tcg_temp_free(t0); ! 626: break; ! 627: ! 628: case 0x1: ! 629: case 0x41: ! 630: /* srl. */ ! 631: t0 = tcg_temp_new(); ! 632: LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra); ! 633: ! 634: /* Update carry. */ ! 635: tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1); ! 636: write_carry(dc, t0); ! 637: tcg_temp_free(t0); ! 638: if (dc->rd) { ! 639: if (op == 0x41) ! 640: tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); ! 641: else ! 642: tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); ! 643: } ! 644: break; ! 645: case 0x60: ! 646: LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra); ! 647: tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); ! 648: break; ! 649: case 0x61: ! 650: LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra); ! 651: tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]); ! 652: break; ! 653: case 0x64: ! 654: /* wdc. */ ! 655: LOG_DIS("wdc r%d\n", dc->ra); ! 656: break; ! 657: case 0x68: ! 658: /* wic. */ ! 659: LOG_DIS("wic r%d\n", dc->ra); ! 660: break; ! 661: default: ! 662: cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n", ! 663: dc->pc, op, dc->rd, dc->ra, dc->rb); ! 664: break; ! 665: } ! 666: } ! 667: ! 668: static inline void sync_jmpstate(DisasContext *dc) ! 669: { ! 670: if (dc->jmp == JMP_DIRECT) { ! 671: dc->jmp = JMP_INDIRECT; ! 672: tcg_gen_movi_tl(env_btaken, 1); ! 673: tcg_gen_movi_tl(env_btarget, dc->jmp_pc); ! 674: } ! 675: } ! 676: ! 677: static void dec_imm(DisasContext *dc) ! 678: { ! 679: LOG_DIS("imm %x\n", dc->imm << 16); ! 680: tcg_gen_movi_tl(env_imm, (dc->imm << 16)); ! 681: dc->tb_flags |= IMM_FLAG; ! 682: dc->clear_imm = 0; ! 683: } ! 684: ! 685: static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr, ! 686: unsigned int size) ! 687: { ! 688: int mem_index = cpu_mmu_index(dc->env); ! 689: ! 690: if (size == 1) { ! 691: tcg_gen_qemu_ld8u(dst, addr, mem_index); ! 692: } else if (size == 2) { ! 693: tcg_gen_qemu_ld16u(dst, addr, mem_index); ! 694: } else if (size == 4) { ! 695: tcg_gen_qemu_ld32u(dst, addr, mem_index); ! 696: } else ! 697: cpu_abort(dc->env, "Incorrect load size %d\n", size); ! 698: } ! 699: ! 700: static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t) ! 701: { ! 702: unsigned int extimm = dc->tb_flags & IMM_FLAG; ! 703: ! 704: /* Treat the fast cases first. */ ! 705: if (!dc->type_b) { ! 706: *t = tcg_temp_new(); ! 707: tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]); ! 708: return t; ! 709: } ! 710: /* Immediate. */ ! 711: if (!extimm) { ! 712: if (dc->imm == 0) { ! 713: return &cpu_R[dc->ra]; ! 714: } ! 715: *t = tcg_temp_new(); ! 716: tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm)); ! 717: tcg_gen_add_tl(*t, cpu_R[dc->ra], *t); ! 718: } else { ! 719: *t = tcg_temp_new(); ! 720: tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc))); ! 721: } ! 722: ! 723: return t; ! 724: } ! 725: ! 726: static void dec_load(DisasContext *dc) ! 727: { ! 728: TCGv t, *addr; ! 729: unsigned int size; ! 730: ! 731: size = 1 << (dc->opcode & 3); ! 732: ! 733: LOG_DIS("l %x %d\n", dc->opcode, size); ! 734: t_sync_flags(dc); ! 735: addr = compute_ldst_addr(dc, &t); ! 736: ! 737: /* If we get a fault on a dslot, the jmpstate better be in sync. */ ! 738: sync_jmpstate(dc); ! 739: if (dc->rd) ! 740: gen_load(dc, cpu_R[dc->rd], *addr, size); ! 741: else { ! 742: gen_load(dc, env_imm, *addr, size); ! 743: } ! 744: ! 745: if (addr == &t) ! 746: tcg_temp_free(t); ! 747: } ! 748: ! 749: static void gen_store(DisasContext *dc, TCGv addr, TCGv val, ! 750: unsigned int size) ! 751: { ! 752: int mem_index = cpu_mmu_index(dc->env); ! 753: ! 754: if (size == 1) ! 755: tcg_gen_qemu_st8(val, addr, mem_index); ! 756: else if (size == 2) { ! 757: tcg_gen_qemu_st16(val, addr, mem_index); ! 758: } else if (size == 4) { ! 759: tcg_gen_qemu_st32(val, addr, mem_index); ! 760: } else ! 761: cpu_abort(dc->env, "Incorrect store size %d\n", size); ! 762: } ! 763: ! 764: static void dec_store(DisasContext *dc) ! 765: { ! 766: TCGv t, *addr; ! 767: unsigned int size; ! 768: ! 769: size = 1 << (dc->opcode & 3); ! 770: ! 771: LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : ""); ! 772: t_sync_flags(dc); ! 773: /* If we get a fault on a dslot, the jmpstate better be in sync. */ ! 774: sync_jmpstate(dc); ! 775: addr = compute_ldst_addr(dc, &t); ! 776: gen_store(dc, *addr, cpu_R[dc->rd], size); ! 777: if (addr == &t) ! 778: tcg_temp_free(t); ! 779: } ! 780: ! 781: static inline void eval_cc(DisasContext *dc, unsigned int cc, ! 782: TCGv d, TCGv a, TCGv b) ! 783: { ! 784: int l1; ! 785: ! 786: switch (cc) { ! 787: case CC_EQ: ! 788: l1 = gen_new_label(); ! 789: tcg_gen_movi_tl(env_btaken, 1); ! 790: tcg_gen_brcond_tl(TCG_COND_EQ, a, b, l1); ! 791: tcg_gen_movi_tl(env_btaken, 0); ! 792: gen_set_label(l1); ! 793: break; ! 794: case CC_NE: ! 795: l1 = gen_new_label(); ! 796: tcg_gen_movi_tl(env_btaken, 1); ! 797: tcg_gen_brcond_tl(TCG_COND_NE, a, b, l1); ! 798: tcg_gen_movi_tl(env_btaken, 0); ! 799: gen_set_label(l1); ! 800: break; ! 801: case CC_LT: ! 802: l1 = gen_new_label(); ! 803: tcg_gen_movi_tl(env_btaken, 1); ! 804: tcg_gen_brcond_tl(TCG_COND_LT, a, b, l1); ! 805: tcg_gen_movi_tl(env_btaken, 0); ! 806: gen_set_label(l1); ! 807: break; ! 808: case CC_LE: ! 809: l1 = gen_new_label(); ! 810: tcg_gen_movi_tl(env_btaken, 1); ! 811: tcg_gen_brcond_tl(TCG_COND_LE, a, b, l1); ! 812: tcg_gen_movi_tl(env_btaken, 0); ! 813: gen_set_label(l1); ! 814: break; ! 815: case CC_GE: ! 816: l1 = gen_new_label(); ! 817: tcg_gen_movi_tl(env_btaken, 1); ! 818: tcg_gen_brcond_tl(TCG_COND_GE, a, b, l1); ! 819: tcg_gen_movi_tl(env_btaken, 0); ! 820: gen_set_label(l1); ! 821: break; ! 822: case CC_GT: ! 823: l1 = gen_new_label(); ! 824: tcg_gen_movi_tl(env_btaken, 1); ! 825: tcg_gen_brcond_tl(TCG_COND_GT, a, b, l1); ! 826: tcg_gen_movi_tl(env_btaken, 0); ! 827: gen_set_label(l1); ! 828: break; ! 829: default: ! 830: cpu_abort(dc->env, "Unknown condition code %x.\n", cc); ! 831: break; ! 832: } ! 833: } ! 834: ! 835: static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false) ! 836: { ! 837: int l1; ! 838: ! 839: l1 = gen_new_label(); ! 840: /* Conditional jmp. */ ! 841: tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false); ! 842: tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1); ! 843: tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true); ! 844: gen_set_label(l1); ! 845: } ! 846: ! 847: static void dec_bcc(DisasContext *dc) ! 848: { ! 849: unsigned int cc; ! 850: unsigned int dslot; ! 851: ! 852: cc = EXTRACT_FIELD(dc->ir, 21, 23); ! 853: dslot = dc->ir & (1 << 25); ! 854: LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm); ! 855: ! 856: dc->delayed_branch = 1; ! 857: if (dslot) { ! 858: dc->delayed_branch = 2; ! 859: dc->tb_flags |= D_FLAG; ! 860: tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), ! 861: cpu_env, offsetof(CPUState, bimm)); ! 862: } ! 863: ! 864: tcg_gen_movi_tl(env_btarget, dc->pc); ! 865: tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); ! 866: eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0)); ! 867: dc->jmp = JMP_INDIRECT; ! 868: } ! 869: ! 870: static void dec_br(DisasContext *dc) ! 871: { ! 872: unsigned int dslot, link, abs; ! 873: ! 874: dslot = dc->ir & (1 << 20); ! 875: abs = dc->ir & (1 << 19); ! 876: link = dc->ir & (1 << 18); ! 877: LOG_DIS("br%s%s%s%s imm=%x\n", ! 878: abs ? "a" : "", link ? "l" : "", ! 879: dc->type_b ? "i" : "", dslot ? "d" : "", ! 880: dc->imm); ! 881: ! 882: dc->delayed_branch = 1; ! 883: if (dslot) { ! 884: dc->delayed_branch = 2; ! 885: dc->tb_flags |= D_FLAG; ! 886: tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), ! 887: cpu_env, offsetof(CPUState, bimm)); ! 888: } ! 889: if (link && dc->rd) ! 890: tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); ! 891: ! 892: dc->jmp = JMP_INDIRECT; ! 893: if (abs) { ! 894: tcg_gen_movi_tl(env_btaken, 1); ! 895: tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc))); ! 896: if (link && !(dc->tb_flags & IMM_FLAG) ! 897: && (dc->imm == 8 || dc->imm == 0x18)) ! 898: t_gen_raise_exception(dc, EXCP_BREAK); ! 899: if (dc->imm == 0) ! 900: t_gen_raise_exception(dc, EXCP_DEBUG); ! 901: } else { ! 902: if (dc->tb_flags & IMM_FLAG) { ! 903: tcg_gen_movi_tl(env_btaken, 1); ! 904: tcg_gen_movi_tl(env_btarget, dc->pc); ! 905: tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); ! 906: } else { ! 907: dc->jmp = JMP_DIRECT; ! 908: dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm); ! 909: } ! 910: } ! 911: } ! 912: ! 913: static inline void do_rti(DisasContext *dc) ! 914: { ! 915: TCGv t0, t1; ! 916: t0 = tcg_temp_new(); ! 917: t1 = tcg_temp_new(); ! 918: tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1); ! 919: tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE); ! 920: tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); ! 921: ! 922: tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); ! 923: tcg_gen_or_tl(t1, t1, t0); ! 924: msr_write(dc, t1); ! 925: tcg_temp_free(t1); ! 926: tcg_temp_free(t0); ! 927: dc->tb_flags &= ~DRTI_FLAG; ! 928: } ! 929: ! 930: static inline void do_rtb(DisasContext *dc) ! 931: { ! 932: TCGv t0, t1; ! 933: t0 = tcg_temp_new(); ! 934: t1 = tcg_temp_new(); ! 935: tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP); ! 936: tcg_gen_shri_tl(t0, t1, 1); ! 937: tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); ! 938: ! 939: tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); ! 940: tcg_gen_or_tl(t1, t1, t0); ! 941: msr_write(dc, t1); ! 942: tcg_temp_free(t1); ! 943: tcg_temp_free(t0); ! 944: dc->tb_flags &= ~DRTB_FLAG; ! 945: } ! 946: ! 947: static inline void do_rte(DisasContext *dc) ! 948: { ! 949: TCGv t0, t1; ! 950: t0 = tcg_temp_new(); ! 951: t1 = tcg_temp_new(); ! 952: ! 953: tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE); ! 954: tcg_gen_andi_tl(t1, t1, ~MSR_EIP); ! 955: tcg_gen_shri_tl(t0, t1, 1); ! 956: tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); ! 957: ! 958: tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); ! 959: tcg_gen_or_tl(t1, t1, t0); ! 960: msr_write(dc, t1); ! 961: tcg_temp_free(t1); ! 962: tcg_temp_free(t0); ! 963: dc->tb_flags &= ~DRTE_FLAG; ! 964: } ! 965: ! 966: static void dec_rts(DisasContext *dc) ! 967: { ! 968: unsigned int b_bit, i_bit, e_bit; ! 969: ! 970: i_bit = dc->ir & (1 << 21); ! 971: b_bit = dc->ir & (1 << 22); ! 972: e_bit = dc->ir & (1 << 23); ! 973: ! 974: dc->delayed_branch = 2; ! 975: dc->tb_flags |= D_FLAG; ! 976: tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), ! 977: cpu_env, offsetof(CPUState, bimm)); ! 978: ! 979: if (i_bit) { ! 980: LOG_DIS("rtid ir=%x\n", dc->ir); ! 981: dc->tb_flags |= DRTI_FLAG; ! 982: } else if (b_bit) { ! 983: LOG_DIS("rtbd ir=%x\n", dc->ir); ! 984: dc->tb_flags |= DRTB_FLAG; ! 985: } else if (e_bit) { ! 986: LOG_DIS("rted ir=%x\n", dc->ir); ! 987: dc->tb_flags |= DRTE_FLAG; ! 988: } else ! 989: LOG_DIS("rts ir=%x\n", dc->ir); ! 990: ! 991: tcg_gen_movi_tl(env_btaken, 1); ! 992: tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc))); ! 993: } ! 994: ! 995: static void dec_null(DisasContext *dc) ! 996: { ! 997: qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode); ! 998: dc->abort_at_next_insn = 1; ! 999: } ! 1000: ! 1001: static struct decoder_info { ! 1002: struct { ! 1003: uint32_t bits; ! 1004: uint32_t mask; ! 1005: }; ! 1006: void (*dec)(DisasContext *dc); ! 1007: } decinfo[] = { ! 1008: {DEC_ADD, dec_add}, ! 1009: {DEC_SUB, dec_sub}, ! 1010: {DEC_AND, dec_and}, ! 1011: {DEC_XOR, dec_xor}, ! 1012: {DEC_OR, dec_or}, ! 1013: {DEC_BIT, dec_bit}, ! 1014: {DEC_BARREL, dec_barrel}, ! 1015: {DEC_LD, dec_load}, ! 1016: {DEC_ST, dec_store}, ! 1017: {DEC_IMM, dec_imm}, ! 1018: {DEC_BR, dec_br}, ! 1019: {DEC_BCC, dec_bcc}, ! 1020: {DEC_RTS, dec_rts}, ! 1021: {DEC_MUL, dec_mul}, ! 1022: {DEC_DIV, dec_div}, ! 1023: {DEC_MSR, dec_msr}, ! 1024: {{0, 0}, dec_null} ! 1025: }; ! 1026: ! 1027: static inline void decode(DisasContext *dc) ! 1028: { ! 1029: uint32_t ir; ! 1030: int i; ! 1031: ! 1032: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) ! 1033: tcg_gen_debug_insn_start(dc->pc); ! 1034: ! 1035: dc->ir = ir = ldl_code(dc->pc); ! 1036: LOG_DIS("%8.8x\t", dc->ir); ! 1037: ! 1038: if (dc->ir) ! 1039: dc->nr_nops = 0; ! 1040: else { ! 1041: LOG_DIS("nr_nops=%d\t", dc->nr_nops); ! 1042: dc->nr_nops++; ! 1043: if (dc->nr_nops > 4) ! 1044: cpu_abort(dc->env, "fetching nop sequence\n"); ! 1045: } ! 1046: /* bit 2 seems to indicate insn type. */ ! 1047: dc->type_b = ir & (1 << 29); ! 1048: ! 1049: dc->opcode = EXTRACT_FIELD(ir, 26, 31); ! 1050: dc->rd = EXTRACT_FIELD(ir, 21, 25); ! 1051: dc->ra = EXTRACT_FIELD(ir, 16, 20); ! 1052: dc->rb = EXTRACT_FIELD(ir, 11, 15); ! 1053: dc->imm = EXTRACT_FIELD(ir, 0, 15); ! 1054: ! 1055: /* Large switch for all insns. */ ! 1056: for (i = 0; i < ARRAY_SIZE(decinfo); i++) { ! 1057: if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) { ! 1058: decinfo[i].dec(dc); ! 1059: break; ! 1060: } ! 1061: } ! 1062: } ! 1063: ! 1064: ! 1065: static void check_breakpoint(CPUState *env, DisasContext *dc) ! 1066: { ! 1067: CPUBreakpoint *bp; ! 1068: ! 1069: if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) { ! 1070: TAILQ_FOREACH(bp, &env->breakpoints, entry) { ! 1071: if (bp->pc == dc->pc) { ! 1072: t_gen_raise_exception(dc, EXCP_DEBUG); ! 1073: dc->is_jmp = DISAS_UPDATE; ! 1074: } ! 1075: } ! 1076: } ! 1077: } ! 1078: ! 1079: /* generate intermediate code for basic block 'tb'. */ ! 1080: static void ! 1081: gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, ! 1082: int search_pc) ! 1083: { ! 1084: uint16_t *gen_opc_end; ! 1085: uint32_t pc_start; ! 1086: int j, lj; ! 1087: struct DisasContext ctx; ! 1088: struct DisasContext *dc = &ctx; ! 1089: uint32_t next_page_start, org_flags; ! 1090: target_ulong npc; ! 1091: int num_insns; ! 1092: int max_insns; ! 1093: ! 1094: qemu_log_try_set_file(stderr); ! 1095: ! 1096: pc_start = tb->pc; ! 1097: dc->env = env; ! 1098: dc->tb = tb; ! 1099: org_flags = dc->synced_flags = dc->tb_flags = tb->flags; ! 1100: ! 1101: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; ! 1102: ! 1103: dc->is_jmp = DISAS_NEXT; ! 1104: dc->jmp = 0; ! 1105: dc->delayed_branch = !!(dc->tb_flags & D_FLAG); ! 1106: dc->ppc = pc_start; ! 1107: dc->pc = pc_start; ! 1108: dc->cache_pc = -1; ! 1109: dc->singlestep_enabled = env->singlestep_enabled; ! 1110: dc->cpustate_changed = 0; ! 1111: dc->abort_at_next_insn = 0; ! 1112: dc->nr_nops = 0; ! 1113: ! 1114: if (pc_start & 3) ! 1115: cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start); ! 1116: ! 1117: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { ! 1118: #if !SIM_COMPAT ! 1119: qemu_log("--------------\n"); ! 1120: log_cpu_state(env, 0); ! 1121: #endif ! 1122: } ! 1123: ! 1124: next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; ! 1125: lj = -1; ! 1126: num_insns = 0; ! 1127: max_insns = tb->cflags & CF_COUNT_MASK; ! 1128: if (max_insns == 0) ! 1129: max_insns = CF_COUNT_MASK; ! 1130: ! 1131: gen_icount_start(); ! 1132: do ! 1133: { ! 1134: #if SIM_COMPAT ! 1135: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { ! 1136: tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); ! 1137: gen_helper_debug(); ! 1138: } ! 1139: #endif ! 1140: check_breakpoint(env, dc); ! 1141: ! 1142: if (search_pc) { ! 1143: j = gen_opc_ptr - gen_opc_buf; ! 1144: if (lj < j) { ! 1145: lj++; ! 1146: while (lj < j) ! 1147: gen_opc_instr_start[lj++] = 0; ! 1148: } ! 1149: gen_opc_pc[lj] = dc->pc; ! 1150: gen_opc_instr_start[lj] = 1; ! 1151: gen_opc_icount[lj] = num_insns; ! 1152: } ! 1153: ! 1154: /* Pretty disas. */ ! 1155: LOG_DIS("%8.8x:\t", dc->pc); ! 1156: ! 1157: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) ! 1158: gen_io_start(); ! 1159: ! 1160: dc->clear_imm = 1; ! 1161: decode(dc); ! 1162: if (dc->clear_imm) ! 1163: dc->tb_flags &= ~IMM_FLAG; ! 1164: dc->ppc = dc->pc; ! 1165: dc->pc += 4; ! 1166: num_insns++; ! 1167: ! 1168: if (dc->delayed_branch) { ! 1169: dc->delayed_branch--; ! 1170: if (!dc->delayed_branch) { ! 1171: if (dc->tb_flags & DRTI_FLAG) ! 1172: do_rti(dc); ! 1173: if (dc->tb_flags & DRTB_FLAG) ! 1174: do_rtb(dc); ! 1175: if (dc->tb_flags & DRTE_FLAG) ! 1176: do_rte(dc); ! 1177: /* Clear the delay slot flag. */ ! 1178: dc->tb_flags &= ~D_FLAG; ! 1179: /* If it is a direct jump, try direct chaining. */ ! 1180: if (dc->jmp != JMP_DIRECT) { ! 1181: eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc)); ! 1182: dc->is_jmp = DISAS_JUMP; ! 1183: } ! 1184: break; ! 1185: } ! 1186: } ! 1187: if (env->singlestep_enabled) ! 1188: break; ! 1189: } while (!dc->is_jmp && !dc->cpustate_changed ! 1190: && gen_opc_ptr < gen_opc_end ! 1191: && !singlestep ! 1192: && (dc->pc < next_page_start) ! 1193: && num_insns < max_insns); ! 1194: ! 1195: npc = dc->pc; ! 1196: if (dc->jmp == JMP_DIRECT) { ! 1197: if (dc->tb_flags & D_FLAG) { ! 1198: dc->is_jmp = DISAS_UPDATE; ! 1199: tcg_gen_movi_tl(cpu_SR[SR_PC], npc); ! 1200: sync_jmpstate(dc); ! 1201: } else ! 1202: npc = dc->jmp_pc; ! 1203: } ! 1204: ! 1205: if (tb->cflags & CF_LAST_IO) ! 1206: gen_io_end(); ! 1207: /* Force an update if the per-tb cpu state has changed. */ ! 1208: if (dc->is_jmp == DISAS_NEXT ! 1209: && (dc->cpustate_changed || org_flags != dc->tb_flags)) { ! 1210: dc->is_jmp = DISAS_UPDATE; ! 1211: tcg_gen_movi_tl(cpu_SR[SR_PC], npc); ! 1212: } ! 1213: t_sync_flags(dc); ! 1214: ! 1215: if (unlikely(env->singlestep_enabled)) { ! 1216: t_gen_raise_exception(dc, EXCP_DEBUG); ! 1217: if (dc->is_jmp == DISAS_NEXT) ! 1218: tcg_gen_movi_tl(cpu_SR[SR_PC], npc); ! 1219: } else { ! 1220: switch(dc->is_jmp) { ! 1221: case DISAS_NEXT: ! 1222: gen_goto_tb(dc, 1, npc); ! 1223: break; ! 1224: default: ! 1225: case DISAS_JUMP: ! 1226: case DISAS_UPDATE: ! 1227: /* indicate that the hash table must be used ! 1228: to find the next TB */ ! 1229: tcg_gen_exit_tb(0); ! 1230: break; ! 1231: case DISAS_TB_JUMP: ! 1232: /* nothing more to generate */ ! 1233: break; ! 1234: } ! 1235: } ! 1236: gen_icount_end(tb, num_insns); ! 1237: *gen_opc_ptr = INDEX_op_end; ! 1238: if (search_pc) { ! 1239: j = gen_opc_ptr - gen_opc_buf; ! 1240: lj++; ! 1241: while (lj <= j) ! 1242: gen_opc_instr_start[lj++] = 0; ! 1243: } else { ! 1244: tb->size = dc->pc - pc_start; ! 1245: tb->icount = num_insns; ! 1246: } ! 1247: ! 1248: #ifdef DEBUG_DISAS ! 1249: #if !SIM_COMPAT ! 1250: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { ! 1251: qemu_log("\n"); ! 1252: #if DISAS_GNU ! 1253: log_target_disas(pc_start, dc->pc - pc_start, 0); ! 1254: #endif ! 1255: qemu_log("\nisize=%d osize=%zd\n", ! 1256: dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); ! 1257: } ! 1258: #endif ! 1259: #endif ! 1260: assert(!dc->abort_at_next_insn); ! 1261: } ! 1262: ! 1263: void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb) ! 1264: { ! 1265: gen_intermediate_code_internal(env, tb, 0); ! 1266: } ! 1267: ! 1268: void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) ! 1269: { ! 1270: gen_intermediate_code_internal(env, tb, 1); ! 1271: } ! 1272: ! 1273: void cpu_dump_state (CPUState *env, FILE *f, ! 1274: int (*cpu_fprintf)(FILE *f, const char *fmt, ...), ! 1275: int flags) ! 1276: { ! 1277: int i; ! 1278: ! 1279: if (!env || !f) ! 1280: return; ! 1281: ! 1282: cpu_fprintf(f, "IN: PC=%x %s\n", ! 1283: env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC])); ! 1284: cpu_fprintf(f, "rmsr=%x resr=%x debug[%x] imm=%x iflags=%x\n", ! 1285: env->sregs[SR_MSR], env->sregs[SR_ESR], ! 1286: env->debug, env->imm, env->iflags); ! 1287: cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s)\n", ! 1288: env->btaken, env->btarget, ! 1289: (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", ! 1290: (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel"); ! 1291: for (i = 0; i < 32; i++) { ! 1292: cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); ! 1293: if ((i + 1) % 4 == 0) ! 1294: cpu_fprintf(f, "\n"); ! 1295: } ! 1296: cpu_fprintf(f, "\n\n"); ! 1297: } ! 1298: ! 1299: CPUState *cpu_mb_init (const char *cpu_model) ! 1300: { ! 1301: CPUState *env; ! 1302: static int tcg_initialized = 0; ! 1303: int i; ! 1304: ! 1305: env = qemu_mallocz(sizeof(CPUState)); ! 1306: ! 1307: cpu_exec_init(env); ! 1308: cpu_reset(env); ! 1309: ! 1310: env->pvr.regs[0] = PVR0_PVR_FULL_MASK \ ! 1311: | PVR0_USE_BARREL_MASK \ ! 1312: | PVR0_USE_DIV_MASK \ ! 1313: | PVR0_USE_HW_MUL_MASK \ ! 1314: | PVR0_USE_EXC_MASK \ ! 1315: | PVR0_USE_ICACHE_MASK \ ! 1316: | PVR0_USE_DCACHE_MASK \ ! 1317: | PVR0_USE_MMU \ ! 1318: | (0xb << 8); ! 1319: env->pvr.regs[2] = PVR2_D_OPB_MASK \ ! 1320: | PVR2_D_LMB_MASK \ ! 1321: | PVR2_I_OPB_MASK \ ! 1322: | PVR2_I_LMB_MASK \ ! 1323: | PVR2_USE_MSR_INSTR \ ! 1324: | PVR2_USE_PCMP_INSTR \ ! 1325: | PVR2_USE_BARREL_MASK \ ! 1326: | PVR2_USE_DIV_MASK \ ! 1327: | PVR2_USE_HW_MUL_MASK \ ! 1328: | PVR2_USE_MUL64_MASK \ ! 1329: | 0; ! 1330: env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */ ! 1331: env->pvr.regs[11] = PVR11_USE_MMU; ! 1332: ! 1333: if (tcg_initialized) ! 1334: return env; ! 1335: ! 1336: tcg_initialized = 1; ! 1337: ! 1338: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); ! 1339: ! 1340: env_debug = tcg_global_mem_new(TCG_AREG0, ! 1341: offsetof(CPUState, debug), ! 1342: "debug0"); ! 1343: env_iflags = tcg_global_mem_new(TCG_AREG0, ! 1344: offsetof(CPUState, iflags), ! 1345: "iflags"); ! 1346: env_imm = tcg_global_mem_new(TCG_AREG0, ! 1347: offsetof(CPUState, imm), ! 1348: "imm"); ! 1349: env_btarget = tcg_global_mem_new(TCG_AREG0, ! 1350: offsetof(CPUState, btarget), ! 1351: "btarget"); ! 1352: env_btaken = tcg_global_mem_new(TCG_AREG0, ! 1353: offsetof(CPUState, btaken), ! 1354: "btaken"); ! 1355: for (i = 0; i < ARRAY_SIZE(cpu_R); i++) { ! 1356: cpu_R[i] = tcg_global_mem_new(TCG_AREG0, ! 1357: offsetof(CPUState, regs[i]), ! 1358: regnames[i]); ! 1359: } ! 1360: for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) { ! 1361: cpu_SR[i] = tcg_global_mem_new(TCG_AREG0, ! 1362: offsetof(CPUState, sregs[i]), ! 1363: special_regnames[i]); ! 1364: } ! 1365: #define GEN_HELPER 2 ! 1366: #include "helper.h" ! 1367: ! 1368: return env; ! 1369: } ! 1370: ! 1371: void cpu_reset (CPUState *env) ! 1372: { ! 1373: if (qemu_loglevel_mask(CPU_LOG_RESET)) { ! 1374: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); ! 1375: log_cpu_state(env, 0); ! 1376: } ! 1377: ! 1378: memset(env, 0, offsetof(CPUMBState, breakpoints)); ! 1379: tlb_flush(env, 1); ! 1380: ! 1381: env->sregs[SR_MSR] = 0; ! 1382: #if defined(CONFIG_USER_ONLY) ! 1383: /* start in user mode with interrupts enabled. */ ! 1384: env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp. */ ! 1385: #else ! 1386: mmu_init(&env->mmu); ! 1387: #endif ! 1388: } ! 1389: ! 1390: void gen_pc_load(CPUState *env, struct TranslationBlock *tb, ! 1391: unsigned long searched_pc, int pc_pos, void *puc) ! 1392: { ! 1393: env->sregs[SR_PC] = gen_opc_pc[pc_pos]; ! 1394: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.