|
|
1.1 ! root 1: /* ! 2: * LatticeMico32 main translation routines. ! 3: * ! 4: * Copyright (c) 2010 Michael Walle <[email protected]> ! 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 "disas.h" ! 29: #include "helper.h" ! 30: #include "tcg-op.h" ! 31: #include "qemu-common.h" ! 32: ! 33: #include "hw/lm32_pic.h" ! 34: ! 35: #define GEN_HELPER 1 ! 36: #include "helper.h" ! 37: ! 38: #define DISAS_LM32 1 ! 39: #if DISAS_LM32 ! 40: # define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__) ! 41: #else ! 42: # define LOG_DIS(...) do { } while (0) ! 43: #endif ! 44: ! 45: #define EXTRACT_FIELD(src, start, end) \ ! 46: (((src) >> start) & ((1 << (end - start + 1)) - 1)) ! 47: ! 48: #define MEM_INDEX 0 ! 49: ! 50: static TCGv_ptr cpu_env; ! 51: static TCGv cpu_R[32]; ! 52: static TCGv cpu_pc; ! 53: static TCGv cpu_ie; ! 54: static TCGv cpu_icc; ! 55: static TCGv cpu_dcc; ! 56: static TCGv cpu_cc; ! 57: static TCGv cpu_cfg; ! 58: static TCGv cpu_eba; ! 59: static TCGv cpu_dc; ! 60: static TCGv cpu_deba; ! 61: static TCGv cpu_bp[4]; ! 62: static TCGv cpu_wp[4]; ! 63: ! 64: #include "gen-icount.h" ! 65: ! 66: enum { ! 67: OP_FMT_RI, ! 68: OP_FMT_RR, ! 69: OP_FMT_CR, ! 70: OP_FMT_I ! 71: }; ! 72: ! 73: /* This is the state at translation time. */ ! 74: typedef struct DisasContext { ! 75: CPUState *env; ! 76: target_ulong pc; ! 77: ! 78: /* Decoder. */ ! 79: int format; ! 80: uint32_t ir; ! 81: uint8_t opcode; ! 82: uint8_t r0, r1, r2, csr; ! 83: uint16_t imm5; ! 84: uint16_t imm16; ! 85: uint32_t imm26; ! 86: ! 87: unsigned int delayed_branch; ! 88: unsigned int tb_flags, synced_flags; /* tb dependent flags. */ ! 89: int is_jmp; ! 90: ! 91: int nr_nops; ! 92: struct TranslationBlock *tb; ! 93: int singlestep_enabled; ! 94: } DisasContext; ! 95: ! 96: static const char *regnames[] = { ! 97: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", ! 98: "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", ! 99: "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", ! 100: "r24", "r25", "r26/gp", "r27/fp", "r28/sp", "r29/ra", ! 101: "r30/ea", "r31/ba", "bp0", "bp1", "bp2", "bp3", "wp0", ! 102: "wp1", "wp2", "wp3" ! 103: }; ! 104: ! 105: static inline int zero_extend(unsigned int val, int width) ! 106: { ! 107: return val & ((1 << width) - 1); ! 108: } ! 109: ! 110: static inline int sign_extend(unsigned int val, int width) ! 111: { ! 112: int sval; ! 113: ! 114: /* LSL. */ ! 115: val <<= 32 - width; ! 116: sval = val; ! 117: /* ASR. */ ! 118: sval >>= 32 - width; ! 119: ! 120: return sval; ! 121: } ! 122: ! 123: static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) ! 124: { ! 125: TCGv_i32 tmp = tcg_const_i32(index); ! 126: ! 127: gen_helper_raise_exception(tmp); ! 128: tcg_temp_free_i32(tmp); ! 129: } ! 130: ! 131: static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) ! 132: { ! 133: TranslationBlock *tb; ! 134: ! 135: tb = dc->tb; ! 136: if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && ! 137: likely(!dc->singlestep_enabled)) { ! 138: tcg_gen_goto_tb(n); ! 139: tcg_gen_movi_tl(cpu_pc, dest); ! 140: tcg_gen_exit_tb((tcg_target_long)tb + n); ! 141: } else { ! 142: tcg_gen_movi_tl(cpu_pc, dest); ! 143: if (dc->singlestep_enabled) { ! 144: t_gen_raise_exception(dc, EXCP_DEBUG); ! 145: } ! 146: tcg_gen_exit_tb(0); ! 147: } ! 148: } ! 149: ! 150: static void dec_add(DisasContext *dc) ! 151: { ! 152: if (dc->format == OP_FMT_RI) { ! 153: if (dc->r0 == R_R0) { ! 154: if (dc->r1 == R_R0 && dc->imm16 == 0) { ! 155: LOG_DIS("nop\n"); ! 156: } else { ! 157: LOG_DIS("mvi r%d, %d\n", dc->r1, sign_extend(dc->imm16, 16)); ! 158: } ! 159: } else { ! 160: LOG_DIS("addi r%d, r%d, %d\n", dc->r1, dc->r0, ! 161: sign_extend(dc->imm16, 16)); ! 162: } ! 163: } else { ! 164: LOG_DIS("add r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 165: } ! 166: ! 167: if (dc->format == OP_FMT_RI) { ! 168: tcg_gen_addi_tl(cpu_R[dc->r1], cpu_R[dc->r0], ! 169: sign_extend(dc->imm16, 16)); ! 170: } else { ! 171: tcg_gen_add_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 172: } ! 173: } ! 174: ! 175: static void dec_and(DisasContext *dc) ! 176: { ! 177: if (dc->format == OP_FMT_RI) { ! 178: LOG_DIS("andi r%d, r%d, %d\n", dc->r1, dc->r0, ! 179: zero_extend(dc->imm16, 16)); ! 180: } else { ! 181: LOG_DIS("and r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 182: } ! 183: ! 184: if (dc->format == OP_FMT_RI) { ! 185: tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], ! 186: zero_extend(dc->imm16, 16)); ! 187: } else { ! 188: if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) { ! 189: tcg_gen_movi_tl(cpu_pc, dc->pc + 4); ! 190: gen_helper_hlt(); ! 191: } else { ! 192: tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 193: } ! 194: } ! 195: } ! 196: ! 197: static void dec_andhi(DisasContext *dc) ! 198: { ! 199: LOG_DIS("andhi r%d, r%d, %d\n", dc->r2, dc->r0, dc->imm16); ! 200: ! 201: tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16)); ! 202: } ! 203: ! 204: static void dec_b(DisasContext *dc) ! 205: { ! 206: if (dc->r0 == R_RA) { ! 207: LOG_DIS("ret\n"); ! 208: } else if (dc->r0 == R_EA) { ! 209: LOG_DIS("eret\n"); ! 210: } else if (dc->r0 == R_BA) { ! 211: LOG_DIS("bret\n"); ! 212: } else { ! 213: LOG_DIS("b r%d\n", dc->r0); ! 214: } ! 215: ! 216: /* restore IE.IE in case of an eret */ ! 217: if (dc->r0 == R_EA) { ! 218: TCGv t0 = tcg_temp_new(); ! 219: int l1 = gen_new_label(); ! 220: tcg_gen_andi_tl(t0, cpu_ie, IE_EIE); ! 221: tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE); ! 222: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_EIE, l1); ! 223: tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE); ! 224: gen_set_label(l1); ! 225: tcg_temp_free(t0); ! 226: } else if (dc->r0 == R_BA) { ! 227: TCGv t0 = tcg_temp_new(); ! 228: int l1 = gen_new_label(); ! 229: tcg_gen_andi_tl(t0, cpu_ie, IE_BIE); ! 230: tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE); ! 231: tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_BIE, l1); ! 232: tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE); ! 233: gen_set_label(l1); ! 234: tcg_temp_free(t0); ! 235: } ! 236: tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]); ! 237: ! 238: dc->is_jmp = DISAS_JUMP; ! 239: } ! 240: ! 241: static void dec_bi(DisasContext *dc) ! 242: { ! 243: LOG_DIS("bi %d\n", sign_extend(dc->imm26 << 2, 26)); ! 244: ! 245: gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26))); ! 246: ! 247: dc->is_jmp = DISAS_TB_JUMP; ! 248: } ! 249: ! 250: static inline void gen_cond_branch(DisasContext *dc, int cond) ! 251: { ! 252: int l1; ! 253: ! 254: l1 = gen_new_label(); ! 255: tcg_gen_brcond_tl(cond, cpu_R[dc->r0], cpu_R[dc->r1], l1); ! 256: gen_goto_tb(dc, 0, dc->pc + 4); ! 257: gen_set_label(l1); ! 258: gen_goto_tb(dc, 1, dc->pc + (sign_extend(dc->imm16 << 2, 16))); ! 259: dc->is_jmp = DISAS_TB_JUMP; ! 260: } ! 261: ! 262: static void dec_be(DisasContext *dc) ! 263: { ! 264: LOG_DIS("be r%d, r%d, %d\n", dc->r0, dc->r1, ! 265: sign_extend(dc->imm16, 16) * 4); ! 266: ! 267: gen_cond_branch(dc, TCG_COND_EQ); ! 268: } ! 269: ! 270: static void dec_bg(DisasContext *dc) ! 271: { ! 272: LOG_DIS("bg r%d, r%d, %d\n", dc->r0, dc->r1, ! 273: sign_extend(dc->imm16, 16 * 4)); ! 274: ! 275: gen_cond_branch(dc, TCG_COND_GT); ! 276: } ! 277: ! 278: static void dec_bge(DisasContext *dc) ! 279: { ! 280: LOG_DIS("bge r%d, r%d, %d\n", dc->r0, dc->r1, ! 281: sign_extend(dc->imm16, 16) * 4); ! 282: ! 283: gen_cond_branch(dc, TCG_COND_GE); ! 284: } ! 285: ! 286: static void dec_bgeu(DisasContext *dc) ! 287: { ! 288: LOG_DIS("bgeu r%d, r%d, %d\n", dc->r0, dc->r1, ! 289: sign_extend(dc->imm16, 16) * 4); ! 290: ! 291: gen_cond_branch(dc, TCG_COND_GEU); ! 292: } ! 293: ! 294: static void dec_bgu(DisasContext *dc) ! 295: { ! 296: LOG_DIS("bgu r%d, r%d, %d\n", dc->r0, dc->r1, ! 297: sign_extend(dc->imm16, 16) * 4); ! 298: ! 299: gen_cond_branch(dc, TCG_COND_GTU); ! 300: } ! 301: ! 302: static void dec_bne(DisasContext *dc) ! 303: { ! 304: LOG_DIS("bne r%d, r%d, %d\n", dc->r0, dc->r1, ! 305: sign_extend(dc->imm16, 16) * 4); ! 306: ! 307: gen_cond_branch(dc, TCG_COND_NE); ! 308: } ! 309: ! 310: static void dec_call(DisasContext *dc) ! 311: { ! 312: LOG_DIS("call r%d\n", dc->r0); ! 313: ! 314: tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4); ! 315: tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]); ! 316: ! 317: dc->is_jmp = DISAS_JUMP; ! 318: } ! 319: ! 320: static void dec_calli(DisasContext *dc) ! 321: { ! 322: LOG_DIS("calli %d\n", sign_extend(dc->imm26, 26) * 4); ! 323: ! 324: tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4); ! 325: gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26))); ! 326: ! 327: dc->is_jmp = DISAS_TB_JUMP; ! 328: } ! 329: ! 330: static inline void gen_compare(DisasContext *dc, int cond) ! 331: { ! 332: int rX = (dc->format == OP_FMT_RR) ? dc->r2 : dc->r1; ! 333: int rY = (dc->format == OP_FMT_RR) ? dc->r0 : dc->r0; ! 334: int rZ = (dc->format == OP_FMT_RR) ? dc->r1 : -1; ! 335: ! 336: if (dc->format == OP_FMT_RI) { ! 337: tcg_gen_setcondi_tl(cond, cpu_R[rX], cpu_R[rY], ! 338: sign_extend(dc->imm16, 16)); ! 339: } else { ! 340: tcg_gen_setcond_tl(cond, cpu_R[rX], cpu_R[rY], cpu_R[rZ]); ! 341: } ! 342: } ! 343: ! 344: static void dec_cmpe(DisasContext *dc) ! 345: { ! 346: if (dc->format == OP_FMT_RI) { ! 347: LOG_DIS("cmpei r%d, r%d, %d\n", dc->r0, dc->r1, ! 348: sign_extend(dc->imm16, 16)); ! 349: } else { ! 350: LOG_DIS("cmpe r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 351: } ! 352: ! 353: gen_compare(dc, TCG_COND_EQ); ! 354: } ! 355: ! 356: static void dec_cmpg(DisasContext *dc) ! 357: { ! 358: if (dc->format == OP_FMT_RI) { ! 359: LOG_DIS("cmpgi r%d, r%d, %d\n", dc->r0, dc->r1, ! 360: sign_extend(dc->imm16, 16)); ! 361: } else { ! 362: LOG_DIS("cmpg r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 363: } ! 364: ! 365: gen_compare(dc, TCG_COND_GT); ! 366: } ! 367: ! 368: static void dec_cmpge(DisasContext *dc) ! 369: { ! 370: if (dc->format == OP_FMT_RI) { ! 371: LOG_DIS("cmpgei r%d, r%d, %d\n", dc->r0, dc->r1, ! 372: sign_extend(dc->imm16, 16)); ! 373: } else { ! 374: LOG_DIS("cmpge r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 375: } ! 376: ! 377: gen_compare(dc, TCG_COND_GE); ! 378: } ! 379: ! 380: static void dec_cmpgeu(DisasContext *dc) ! 381: { ! 382: if (dc->format == OP_FMT_RI) { ! 383: LOG_DIS("cmpgeui r%d, r%d, %d\n", dc->r0, dc->r1, ! 384: sign_extend(dc->imm16, 16)); ! 385: } else { ! 386: LOG_DIS("cmpgeu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 387: } ! 388: ! 389: gen_compare(dc, TCG_COND_GEU); ! 390: } ! 391: ! 392: static void dec_cmpgu(DisasContext *dc) ! 393: { ! 394: if (dc->format == OP_FMT_RI) { ! 395: LOG_DIS("cmpgui r%d, r%d, %d\n", dc->r0, dc->r1, ! 396: sign_extend(dc->imm16, 16)); ! 397: } else { ! 398: LOG_DIS("cmpgu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 399: } ! 400: ! 401: gen_compare(dc, TCG_COND_GTU); ! 402: } ! 403: ! 404: static void dec_cmpne(DisasContext *dc) ! 405: { ! 406: if (dc->format == OP_FMT_RI) { ! 407: LOG_DIS("cmpnei r%d, r%d, %d\n", dc->r0, dc->r1, ! 408: sign_extend(dc->imm16, 16)); ! 409: } else { ! 410: LOG_DIS("cmpne r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 411: } ! 412: ! 413: gen_compare(dc, TCG_COND_NE); ! 414: } ! 415: ! 416: static void dec_divu(DisasContext *dc) ! 417: { ! 418: int l1; ! 419: ! 420: LOG_DIS("divu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 421: ! 422: if (!(dc->env->features & LM32_FEATURE_DIVIDE)) { ! 423: cpu_abort(dc->env, "hardware divider is not available\n"); ! 424: } ! 425: ! 426: l1 = gen_new_label(); ! 427: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1); ! 428: tcg_gen_movi_tl(cpu_pc, dc->pc); ! 429: t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO); ! 430: gen_set_label(l1); ! 431: tcg_gen_divu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 432: } ! 433: ! 434: static void dec_lb(DisasContext *dc) ! 435: { ! 436: TCGv t0; ! 437: ! 438: LOG_DIS("lb r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); ! 439: ! 440: t0 = tcg_temp_new(); ! 441: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 442: tcg_gen_qemu_ld8s(cpu_R[dc->r1], t0, MEM_INDEX); ! 443: tcg_temp_free(t0); ! 444: } ! 445: ! 446: static void dec_lbu(DisasContext *dc) ! 447: { ! 448: TCGv t0; ! 449: ! 450: LOG_DIS("lbu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); ! 451: ! 452: t0 = tcg_temp_new(); ! 453: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 454: tcg_gen_qemu_ld8u(cpu_R[dc->r1], t0, MEM_INDEX); ! 455: tcg_temp_free(t0); ! 456: } ! 457: ! 458: static void dec_lh(DisasContext *dc) ! 459: { ! 460: TCGv t0; ! 461: ! 462: LOG_DIS("lh r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); ! 463: ! 464: t0 = tcg_temp_new(); ! 465: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 466: tcg_gen_qemu_ld16s(cpu_R[dc->r1], t0, MEM_INDEX); ! 467: tcg_temp_free(t0); ! 468: } ! 469: ! 470: static void dec_lhu(DisasContext *dc) ! 471: { ! 472: TCGv t0; ! 473: ! 474: LOG_DIS("lhu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16); ! 475: ! 476: t0 = tcg_temp_new(); ! 477: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 478: tcg_gen_qemu_ld16u(cpu_R[dc->r1], t0, MEM_INDEX); ! 479: tcg_temp_free(t0); ! 480: } ! 481: ! 482: static void dec_lw(DisasContext *dc) ! 483: { ! 484: TCGv t0; ! 485: ! 486: LOG_DIS("lw r%d, (r%d+%d)\n", dc->r1, dc->r0, sign_extend(dc->imm16, 16)); ! 487: ! 488: t0 = tcg_temp_new(); ! 489: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 490: tcg_gen_qemu_ld32s(cpu_R[dc->r1], t0, MEM_INDEX); ! 491: tcg_temp_free(t0); ! 492: } ! 493: ! 494: static void dec_modu(DisasContext *dc) ! 495: { ! 496: int l1; ! 497: ! 498: LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1); ! 499: ! 500: if (!(dc->env->features & LM32_FEATURE_DIVIDE)) { ! 501: cpu_abort(dc->env, "hardware divider is not available\n"); ! 502: } ! 503: ! 504: l1 = gen_new_label(); ! 505: tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1); ! 506: tcg_gen_movi_tl(cpu_pc, dc->pc); ! 507: t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO); ! 508: gen_set_label(l1); ! 509: tcg_gen_remu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 510: } ! 511: ! 512: static void dec_mul(DisasContext *dc) ! 513: { ! 514: if (dc->format == OP_FMT_RI) { ! 515: LOG_DIS("muli r%d, r%d, %d\n", dc->r0, dc->r1, ! 516: sign_extend(dc->imm16, 16)); ! 517: } else { ! 518: LOG_DIS("mul r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 519: } ! 520: ! 521: if (!(dc->env->features & LM32_FEATURE_MULTIPLY)) { ! 522: cpu_abort(dc->env, "hardware multiplier is not available\n"); ! 523: } ! 524: ! 525: if (dc->format == OP_FMT_RI) { ! 526: tcg_gen_muli_tl(cpu_R[dc->r1], cpu_R[dc->r0], ! 527: sign_extend(dc->imm16, 16)); ! 528: } else { ! 529: tcg_gen_mul_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 530: } ! 531: } ! 532: ! 533: static void dec_nor(DisasContext *dc) ! 534: { ! 535: if (dc->format == OP_FMT_RI) { ! 536: LOG_DIS("nori r%d, r%d, %d\n", dc->r0, dc->r1, ! 537: zero_extend(dc->imm16, 16)); ! 538: } else { ! 539: LOG_DIS("nor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 540: } ! 541: ! 542: if (dc->format == OP_FMT_RI) { ! 543: TCGv t0 = tcg_temp_new(); ! 544: tcg_gen_movi_tl(t0, zero_extend(dc->imm16, 16)); ! 545: tcg_gen_nor_tl(cpu_R[dc->r1], cpu_R[dc->r0], t0); ! 546: tcg_temp_free(t0); ! 547: } else { ! 548: tcg_gen_nor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 549: } ! 550: } ! 551: ! 552: static void dec_or(DisasContext *dc) ! 553: { ! 554: if (dc->format == OP_FMT_RI) { ! 555: LOG_DIS("ori r%d, r%d, %d\n", dc->r1, dc->r0, ! 556: zero_extend(dc->imm16, 16)); ! 557: } else { ! 558: if (dc->r1 == R_R0) { ! 559: LOG_DIS("mv r%d, r%d\n", dc->r2, dc->r0); ! 560: } else { ! 561: LOG_DIS("or r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 562: } ! 563: } ! 564: ! 565: if (dc->format == OP_FMT_RI) { ! 566: tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], ! 567: zero_extend(dc->imm16, 16)); ! 568: } else { ! 569: tcg_gen_or_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 570: } ! 571: } ! 572: ! 573: static void dec_orhi(DisasContext *dc) ! 574: { ! 575: if (dc->r0 == R_R0) { ! 576: LOG_DIS("mvhi r%d, %d\n", dc->r1, dc->imm16); ! 577: } else { ! 578: LOG_DIS("orhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16); ! 579: } ! 580: ! 581: tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16)); ! 582: } ! 583: ! 584: static void dec_scall(DisasContext *dc) ! 585: { ! 586: if (dc->imm5 == 7) { ! 587: LOG_DIS("scall\n"); ! 588: } else if (dc->imm5 == 2) { ! 589: LOG_DIS("break\n"); ! 590: } else { ! 591: cpu_abort(dc->env, "invalid opcode\n"); ! 592: } ! 593: ! 594: if (dc->imm5 == 7) { ! 595: tcg_gen_movi_tl(cpu_pc, dc->pc); ! 596: t_gen_raise_exception(dc, EXCP_SYSTEMCALL); ! 597: } else { ! 598: tcg_gen_movi_tl(cpu_pc, dc->pc); ! 599: t_gen_raise_exception(dc, EXCP_BREAKPOINT); ! 600: } ! 601: } ! 602: ! 603: static void dec_rcsr(DisasContext *dc) ! 604: { ! 605: LOG_DIS("rcsr r%d, %d\n", dc->r2, dc->csr); ! 606: ! 607: switch (dc->csr) { ! 608: case CSR_IE: ! 609: tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie); ! 610: break; ! 611: case CSR_IM: ! 612: gen_helper_rcsr_im(cpu_R[dc->r2]); ! 613: break; ! 614: case CSR_IP: ! 615: gen_helper_rcsr_ip(cpu_R[dc->r2]); ! 616: break; ! 617: case CSR_CC: ! 618: tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc); ! 619: break; ! 620: case CSR_CFG: ! 621: tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cfg); ! 622: break; ! 623: case CSR_EBA: ! 624: tcg_gen_mov_tl(cpu_R[dc->r2], cpu_eba); ! 625: break; ! 626: case CSR_DC: ! 627: tcg_gen_mov_tl(cpu_R[dc->r2], cpu_dc); ! 628: break; ! 629: case CSR_DEBA: ! 630: tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba); ! 631: break; ! 632: case CSR_JTX: ! 633: gen_helper_rcsr_jtx(cpu_R[dc->r2]); ! 634: break; ! 635: case CSR_JRX: ! 636: gen_helper_rcsr_jrx(cpu_R[dc->r2]); ! 637: break; ! 638: case CSR_ICC: ! 639: case CSR_DCC: ! 640: case CSR_BP0: ! 641: case CSR_BP1: ! 642: case CSR_BP2: ! 643: case CSR_BP3: ! 644: case CSR_WP0: ! 645: case CSR_WP1: ! 646: case CSR_WP2: ! 647: case CSR_WP3: ! 648: cpu_abort(dc->env, "invalid read access csr=%x\n", dc->csr); ! 649: break; ! 650: default: ! 651: cpu_abort(dc->env, "read_csr: unknown csr=%x\n", dc->csr); ! 652: break; ! 653: } ! 654: } ! 655: ! 656: static void dec_sb(DisasContext *dc) ! 657: { ! 658: TCGv t0; ! 659: ! 660: LOG_DIS("sb (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1); ! 661: ! 662: t0 = tcg_temp_new(); ! 663: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 664: tcg_gen_qemu_st8(cpu_R[dc->r1], t0, MEM_INDEX); ! 665: tcg_temp_free(t0); ! 666: } ! 667: ! 668: static void dec_sextb(DisasContext *dc) ! 669: { ! 670: LOG_DIS("sextb r%d, r%d\n", dc->r2, dc->r0); ! 671: ! 672: if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) { ! 673: cpu_abort(dc->env, "hardware sign extender is not available\n"); ! 674: } ! 675: ! 676: tcg_gen_ext8s_tl(cpu_R[dc->r2], cpu_R[dc->r0]); ! 677: } ! 678: ! 679: static void dec_sexth(DisasContext *dc) ! 680: { ! 681: LOG_DIS("sexth r%d, r%d\n", dc->r2, dc->r0); ! 682: ! 683: if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) { ! 684: cpu_abort(dc->env, "hardware sign extender is not available\n"); ! 685: } ! 686: ! 687: tcg_gen_ext16s_tl(cpu_R[dc->r2], cpu_R[dc->r0]); ! 688: } ! 689: ! 690: static void dec_sh(DisasContext *dc) ! 691: { ! 692: TCGv t0; ! 693: ! 694: LOG_DIS("sh (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1); ! 695: ! 696: t0 = tcg_temp_new(); ! 697: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 698: tcg_gen_qemu_st16(cpu_R[dc->r1], t0, MEM_INDEX); ! 699: tcg_temp_free(t0); ! 700: } ! 701: ! 702: static void dec_sl(DisasContext *dc) ! 703: { ! 704: if (dc->format == OP_FMT_RI) { ! 705: LOG_DIS("sli r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5); ! 706: } else { ! 707: LOG_DIS("sl r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 708: } ! 709: ! 710: if (!(dc->env->features & LM32_FEATURE_SHIFT)) { ! 711: cpu_abort(dc->env, "hardware shifter is not available\n"); ! 712: } ! 713: ! 714: if (dc->format == OP_FMT_RI) { ! 715: tcg_gen_shli_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5); ! 716: } else { ! 717: TCGv t0 = tcg_temp_new(); ! 718: tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f); ! 719: tcg_gen_shl_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0); ! 720: tcg_temp_free(t0); ! 721: } ! 722: } ! 723: ! 724: static void dec_sr(DisasContext *dc) ! 725: { ! 726: if (dc->format == OP_FMT_RI) { ! 727: LOG_DIS("sri r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5); ! 728: } else { ! 729: LOG_DIS("sr r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 730: } ! 731: ! 732: if (!(dc->env->features & LM32_FEATURE_SHIFT)) { ! 733: if (dc->format == OP_FMT_RI) { ! 734: /* TODO: check r1 == 1 during runtime */ ! 735: } else { ! 736: if (dc->imm5 != 1) { ! 737: cpu_abort(dc->env, "hardware shifter is not available\n"); ! 738: } ! 739: } ! 740: } ! 741: ! 742: if (dc->format == OP_FMT_RI) { ! 743: tcg_gen_sari_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5); ! 744: } else { ! 745: TCGv t0 = tcg_temp_new(); ! 746: tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f); ! 747: tcg_gen_sar_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0); ! 748: tcg_temp_free(t0); ! 749: } ! 750: } ! 751: ! 752: static void dec_sru(DisasContext *dc) ! 753: { ! 754: if (dc->format == OP_FMT_RI) { ! 755: LOG_DIS("srui r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5); ! 756: } else { ! 757: LOG_DIS("sru r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 758: } ! 759: ! 760: if (!(dc->env->features & LM32_FEATURE_SHIFT)) { ! 761: if (dc->format == OP_FMT_RI) { ! 762: /* TODO: check r1 == 1 during runtime */ ! 763: } else { ! 764: if (dc->imm5 != 1) { ! 765: cpu_abort(dc->env, "hardware shifter is not available\n"); ! 766: } ! 767: } ! 768: } ! 769: ! 770: if (dc->format == OP_FMT_RI) { ! 771: tcg_gen_shri_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5); ! 772: } else { ! 773: TCGv t0 = tcg_temp_new(); ! 774: tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f); ! 775: tcg_gen_shr_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0); ! 776: tcg_temp_free(t0); ! 777: } ! 778: } ! 779: ! 780: static void dec_sub(DisasContext *dc) ! 781: { ! 782: LOG_DIS("sub r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 783: ! 784: tcg_gen_sub_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 785: } ! 786: ! 787: static void dec_sw(DisasContext *dc) ! 788: { ! 789: TCGv t0; ! 790: ! 791: LOG_DIS("sw (r%d+%d), r%d\n", dc->r0, sign_extend(dc->imm16, 16), dc->r1); ! 792: ! 793: t0 = tcg_temp_new(); ! 794: tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16)); ! 795: tcg_gen_qemu_st32(cpu_R[dc->r1], t0, MEM_INDEX); ! 796: tcg_temp_free(t0); ! 797: } ! 798: ! 799: static void dec_user(DisasContext *dc) ! 800: { ! 801: LOG_DIS("user"); ! 802: ! 803: cpu_abort(dc->env, "user insn undefined\n"); ! 804: } ! 805: ! 806: static void dec_wcsr(DisasContext *dc) ! 807: { ! 808: int no; ! 809: ! 810: LOG_DIS("wcsr r%d, %d\n", dc->r1, dc->csr); ! 811: ! 812: switch (dc->csr) { ! 813: case CSR_IE: ! 814: tcg_gen_mov_tl(cpu_ie, cpu_R[dc->r1]); ! 815: tcg_gen_movi_tl(cpu_pc, dc->pc + 4); ! 816: dc->is_jmp = DISAS_UPDATE; ! 817: break; ! 818: case CSR_IM: ! 819: /* mark as an io operation because it could cause an interrupt */ ! 820: if (use_icount) { ! 821: gen_io_start(); ! 822: } ! 823: gen_helper_wcsr_im(cpu_R[dc->r1]); ! 824: tcg_gen_movi_tl(cpu_pc, dc->pc + 4); ! 825: if (use_icount) { ! 826: gen_io_end(); ! 827: } ! 828: dc->is_jmp = DISAS_UPDATE; ! 829: break; ! 830: case CSR_IP: ! 831: /* mark as an io operation because it could cause an interrupt */ ! 832: if (use_icount) { ! 833: gen_io_start(); ! 834: } ! 835: gen_helper_wcsr_ip(cpu_R[dc->r1]); ! 836: tcg_gen_movi_tl(cpu_pc, dc->pc + 4); ! 837: if (use_icount) { ! 838: gen_io_end(); ! 839: } ! 840: dc->is_jmp = DISAS_UPDATE; ! 841: break; ! 842: case CSR_ICC: ! 843: /* TODO */ ! 844: break; ! 845: case CSR_DCC: ! 846: /* TODO */ ! 847: break; ! 848: case CSR_EBA: ! 849: tcg_gen_mov_tl(cpu_eba, cpu_R[dc->r1]); ! 850: break; ! 851: case CSR_DEBA: ! 852: tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]); ! 853: break; ! 854: case CSR_JTX: ! 855: gen_helper_wcsr_jtx(cpu_R[dc->r1]); ! 856: break; ! 857: case CSR_JRX: ! 858: gen_helper_wcsr_jrx(cpu_R[dc->r1]); ! 859: break; ! 860: case CSR_DC: ! 861: tcg_gen_mov_tl(cpu_dc, cpu_R[dc->r1]); ! 862: break; ! 863: case CSR_BP0: ! 864: case CSR_BP1: ! 865: case CSR_BP2: ! 866: case CSR_BP3: ! 867: no = dc->csr - CSR_BP0; ! 868: if (dc->env->num_bps <= no) { ! 869: cpu_abort(dc->env, "breakpoint #%i is not available\n", no); ! 870: } ! 871: tcg_gen_mov_tl(cpu_bp[no], cpu_R[dc->r1]); ! 872: break; ! 873: case CSR_WP0: ! 874: case CSR_WP1: ! 875: case CSR_WP2: ! 876: case CSR_WP3: ! 877: no = dc->csr - CSR_WP0; ! 878: if (dc->env->num_wps <= no) { ! 879: cpu_abort(dc->env, "watchpoint #%i is not available\n", no); ! 880: } ! 881: tcg_gen_mov_tl(cpu_wp[no], cpu_R[dc->r1]); ! 882: break; ! 883: case CSR_CC: ! 884: case CSR_CFG: ! 885: cpu_abort(dc->env, "invalid write access csr=%x\n", dc->csr); ! 886: break; ! 887: default: ! 888: cpu_abort(dc->env, "write_csr unknown csr=%x\n", dc->csr); ! 889: break; ! 890: } ! 891: } ! 892: ! 893: static void dec_xnor(DisasContext *dc) ! 894: { ! 895: if (dc->format == OP_FMT_RI) { ! 896: LOG_DIS("xnori r%d, r%d, %d\n", dc->r0, dc->r1, ! 897: zero_extend(dc->imm16, 16)); ! 898: } else { ! 899: if (dc->r1 == R_R0) { ! 900: LOG_DIS("not r%d, r%d\n", dc->r2, dc->r0); ! 901: } else { ! 902: LOG_DIS("xnor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 903: } ! 904: } ! 905: ! 906: if (dc->format == OP_FMT_RI) { ! 907: tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0], ! 908: zero_extend(dc->imm16, 16)); ! 909: tcg_gen_not_tl(cpu_R[dc->r1], cpu_R[dc->r1]); ! 910: } else { ! 911: tcg_gen_eqv_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 912: } ! 913: } ! 914: ! 915: static void dec_xor(DisasContext *dc) ! 916: { ! 917: if (dc->format == OP_FMT_RI) { ! 918: LOG_DIS("xori r%d, r%d, %d\n", dc->r0, dc->r1, ! 919: zero_extend(dc->imm16, 16)); ! 920: } else { ! 921: LOG_DIS("xor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1); ! 922: } ! 923: ! 924: if (dc->format == OP_FMT_RI) { ! 925: tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0], ! 926: zero_extend(dc->imm16, 16)); ! 927: } else { ! 928: tcg_gen_xor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); ! 929: } ! 930: } ! 931: ! 932: static void dec_ill(DisasContext *dc) ! 933: { ! 934: cpu_abort(dc->env, "unknown opcode 0x%02x\n", dc->opcode); ! 935: } ! 936: ! 937: typedef void (*DecoderInfo)(DisasContext *dc); ! 938: static const DecoderInfo decinfo[] = { ! 939: dec_sru, dec_nor, dec_mul, dec_sh, dec_lb, dec_sr, dec_xor, dec_lh, ! 940: dec_and, dec_xnor, dec_lw, dec_lhu, dec_sb, dec_add, dec_or, dec_sl, ! 941: dec_lbu, dec_be, dec_bg, dec_bge, dec_bgeu, dec_bgu, dec_sw, dec_bne, ! 942: dec_andhi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_orhi, ! 943: dec_cmpne, ! 944: dec_sru, dec_nor, dec_mul, dec_divu, dec_rcsr, dec_sr, dec_xor, dec_ill, ! 945: dec_and, dec_xnor, dec_ill, dec_scall, dec_sextb, dec_add, dec_or, dec_sl, ! 946: dec_b, dec_modu, dec_sub, dec_user, dec_wcsr, dec_ill, dec_call, dec_sexth, ! 947: dec_bi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_calli, ! 948: dec_cmpne ! 949: }; ! 950: ! 951: static inline void decode(DisasContext *dc) ! 952: { ! 953: uint32_t ir; ! 954: ! 955: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { ! 956: tcg_gen_debug_insn_start(dc->pc); ! 957: } ! 958: ! 959: dc->ir = ir = ldl_code(dc->pc); ! 960: LOG_DIS("%8.8x\t", dc->ir); ! 961: ! 962: /* try guessing 'empty' instruction memory, although it may be a valid ! 963: * instruction sequence (eg. srui r0, r0, 0) */ ! 964: if (dc->ir) { ! 965: dc->nr_nops = 0; ! 966: } else { ! 967: LOG_DIS("nr_nops=%d\t", dc->nr_nops); ! 968: dc->nr_nops++; ! 969: if (dc->nr_nops > 4) { ! 970: cpu_abort(dc->env, "fetching nop sequence\n"); ! 971: } ! 972: } ! 973: ! 974: dc->opcode = EXTRACT_FIELD(ir, 26, 31); ! 975: ! 976: dc->imm5 = EXTRACT_FIELD(ir, 0, 4); ! 977: dc->imm16 = EXTRACT_FIELD(ir, 0, 15); ! 978: dc->imm26 = EXTRACT_FIELD(ir, 0, 25); ! 979: ! 980: dc->csr = EXTRACT_FIELD(ir, 21, 25); ! 981: dc->r0 = EXTRACT_FIELD(ir, 21, 25); ! 982: dc->r1 = EXTRACT_FIELD(ir, 16, 20); ! 983: dc->r2 = EXTRACT_FIELD(ir, 11, 15); ! 984: ! 985: /* bit 31 seems to indicate insn type. */ ! 986: if (ir & (1 << 31)) { ! 987: dc->format = OP_FMT_RR; ! 988: } else { ! 989: dc->format = OP_FMT_RI; ! 990: } ! 991: ! 992: assert(ARRAY_SIZE(decinfo) == 64); ! 993: assert(dc->opcode < 64); ! 994: ! 995: decinfo[dc->opcode](dc); ! 996: } ! 997: ! 998: static void check_breakpoint(CPUState *env, DisasContext *dc) ! 999: { ! 1000: CPUBreakpoint *bp; ! 1001: ! 1002: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { ! 1003: QTAILQ_FOREACH(bp, &env->breakpoints, entry) { ! 1004: if (bp->pc == dc->pc) { ! 1005: tcg_gen_movi_tl(cpu_pc, dc->pc); ! 1006: t_gen_raise_exception(dc, EXCP_DEBUG); ! 1007: dc->is_jmp = DISAS_UPDATE; ! 1008: } ! 1009: } ! 1010: } ! 1011: } ! 1012: ! 1013: /* generate intermediate code for basic block 'tb'. */ ! 1014: static void gen_intermediate_code_internal(CPUState *env, ! 1015: TranslationBlock *tb, int search_pc) ! 1016: { ! 1017: struct DisasContext ctx, *dc = &ctx; ! 1018: uint16_t *gen_opc_end; ! 1019: uint32_t pc_start; ! 1020: int j, lj; ! 1021: uint32_t next_page_start; ! 1022: int num_insns; ! 1023: int max_insns; ! 1024: ! 1025: qemu_log_try_set_file(stderr); ! 1026: ! 1027: pc_start = tb->pc; ! 1028: dc->env = env; ! 1029: dc->tb = tb; ! 1030: ! 1031: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; ! 1032: ! 1033: dc->is_jmp = DISAS_NEXT; ! 1034: dc->pc = pc_start; ! 1035: dc->singlestep_enabled = env->singlestep_enabled; ! 1036: dc->nr_nops = 0; ! 1037: ! 1038: if (pc_start & 3) { ! 1039: cpu_abort(env, "LM32: unaligned PC=%x\n", pc_start); ! 1040: } ! 1041: ! 1042: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { ! 1043: qemu_log("-----------------------------------------\n"); ! 1044: log_cpu_state(env, 0); ! 1045: } ! 1046: ! 1047: next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; ! 1048: lj = -1; ! 1049: num_insns = 0; ! 1050: max_insns = tb->cflags & CF_COUNT_MASK; ! 1051: if (max_insns == 0) { ! 1052: max_insns = CF_COUNT_MASK; ! 1053: } ! 1054: ! 1055: gen_icount_start(); ! 1056: do { ! 1057: check_breakpoint(env, dc); ! 1058: ! 1059: if (search_pc) { ! 1060: j = gen_opc_ptr - gen_opc_buf; ! 1061: if (lj < j) { ! 1062: lj++; ! 1063: while (lj < j) { ! 1064: gen_opc_instr_start[lj++] = 0; ! 1065: } ! 1066: } ! 1067: gen_opc_pc[lj] = dc->pc; ! 1068: gen_opc_instr_start[lj] = 1; ! 1069: gen_opc_icount[lj] = num_insns; ! 1070: } ! 1071: ! 1072: /* Pretty disas. */ ! 1073: LOG_DIS("%8.8x:\t", dc->pc); ! 1074: ! 1075: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { ! 1076: gen_io_start(); ! 1077: } ! 1078: ! 1079: decode(dc); ! 1080: dc->pc += 4; ! 1081: num_insns++; ! 1082: ! 1083: } while (!dc->is_jmp ! 1084: && gen_opc_ptr < gen_opc_end ! 1085: && !env->singlestep_enabled ! 1086: && !singlestep ! 1087: && (dc->pc < next_page_start) ! 1088: && num_insns < max_insns); ! 1089: ! 1090: if (tb->cflags & CF_LAST_IO) { ! 1091: gen_io_end(); ! 1092: } ! 1093: ! 1094: if (unlikely(env->singlestep_enabled)) { ! 1095: if (dc->is_jmp == DISAS_NEXT) { ! 1096: tcg_gen_movi_tl(cpu_pc, dc->pc); ! 1097: } ! 1098: t_gen_raise_exception(dc, EXCP_DEBUG); ! 1099: } else { ! 1100: switch (dc->is_jmp) { ! 1101: case DISAS_NEXT: ! 1102: gen_goto_tb(dc, 1, dc->pc); ! 1103: break; ! 1104: default: ! 1105: case DISAS_JUMP: ! 1106: case DISAS_UPDATE: ! 1107: /* indicate that the hash table must be used ! 1108: to find the next TB */ ! 1109: tcg_gen_exit_tb(0); ! 1110: break; ! 1111: case DISAS_TB_JUMP: ! 1112: /* nothing more to generate */ ! 1113: break; ! 1114: } ! 1115: } ! 1116: ! 1117: gen_icount_end(tb, num_insns); ! 1118: *gen_opc_ptr = INDEX_op_end; ! 1119: if (search_pc) { ! 1120: j = gen_opc_ptr - gen_opc_buf; ! 1121: lj++; ! 1122: while (lj <= j) { ! 1123: gen_opc_instr_start[lj++] = 0; ! 1124: } ! 1125: } else { ! 1126: tb->size = dc->pc - pc_start; ! 1127: tb->icount = num_insns; ! 1128: } ! 1129: ! 1130: #ifdef DEBUG_DISAS ! 1131: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { ! 1132: qemu_log("\n"); ! 1133: log_target_disas(pc_start, dc->pc - pc_start, 0); ! 1134: qemu_log("\nisize=%d osize=%td\n", ! 1135: dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); ! 1136: } ! 1137: #endif ! 1138: } ! 1139: ! 1140: void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb) ! 1141: { ! 1142: gen_intermediate_code_internal(env, tb, 0); ! 1143: } ! 1144: ! 1145: void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb) ! 1146: { ! 1147: gen_intermediate_code_internal(env, tb, 1); ! 1148: } ! 1149: ! 1150: void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf, ! 1151: int flags) ! 1152: { ! 1153: int i; ! 1154: ! 1155: if (!env || !f) { ! 1156: return; ! 1157: } ! 1158: ! 1159: cpu_fprintf(f, "IN: PC=%x %s\n", ! 1160: env->pc, lookup_symbol(env->pc)); ! 1161: ! 1162: cpu_fprintf(f, "ie=%8.8x (IE=%x EIE=%x BIE=%x) im=%8.8x ip=%8.8x\n", ! 1163: env->ie, ! 1164: (env->ie & IE_IE) ? 1 : 0, ! 1165: (env->ie & IE_EIE) ? 1 : 0, ! 1166: (env->ie & IE_BIE) ? 1 : 0, ! 1167: lm32_pic_get_im(env->pic_state), ! 1168: lm32_pic_get_ip(env->pic_state)); ! 1169: cpu_fprintf(f, "eba=%8.8x deba=%8.8x\n", ! 1170: env->eba, ! 1171: env->deba); ! 1172: ! 1173: for (i = 0; i < 32; i++) { ! 1174: cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); ! 1175: if ((i + 1) % 4 == 0) { ! 1176: cpu_fprintf(f, "\n"); ! 1177: } ! 1178: } ! 1179: cpu_fprintf(f, "\n\n"); ! 1180: } ! 1181: ! 1182: void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos) ! 1183: { ! 1184: env->pc = gen_opc_pc[pc_pos]; ! 1185: } ! 1186: ! 1187: void lm32_translate_init(void) ! 1188: { ! 1189: int i; ! 1190: ! 1191: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); ! 1192: ! 1193: for (i = 0; i < ARRAY_SIZE(cpu_R); i++) { ! 1194: cpu_R[i] = tcg_global_mem_new(TCG_AREG0, ! 1195: offsetof(CPUState, regs[i]), ! 1196: regnames[i]); ! 1197: } ! 1198: ! 1199: for (i = 0; i < ARRAY_SIZE(cpu_bp); i++) { ! 1200: cpu_bp[i] = tcg_global_mem_new(TCG_AREG0, ! 1201: offsetof(CPUState, bp[i]), ! 1202: regnames[32+i]); ! 1203: } ! 1204: ! 1205: for (i = 0; i < ARRAY_SIZE(cpu_wp); i++) { ! 1206: cpu_wp[i] = tcg_global_mem_new(TCG_AREG0, ! 1207: offsetof(CPUState, wp[i]), ! 1208: regnames[36+i]); ! 1209: } ! 1210: ! 1211: cpu_pc = tcg_global_mem_new(TCG_AREG0, ! 1212: offsetof(CPUState, pc), ! 1213: "pc"); ! 1214: cpu_ie = tcg_global_mem_new(TCG_AREG0, ! 1215: offsetof(CPUState, ie), ! 1216: "ie"); ! 1217: cpu_icc = tcg_global_mem_new(TCG_AREG0, ! 1218: offsetof(CPUState, icc), ! 1219: "icc"); ! 1220: cpu_dcc = tcg_global_mem_new(TCG_AREG0, ! 1221: offsetof(CPUState, dcc), ! 1222: "dcc"); ! 1223: cpu_cc = tcg_global_mem_new(TCG_AREG0, ! 1224: offsetof(CPUState, cc), ! 1225: "cc"); ! 1226: cpu_cfg = tcg_global_mem_new(TCG_AREG0, ! 1227: offsetof(CPUState, cfg), ! 1228: "cfg"); ! 1229: cpu_eba = tcg_global_mem_new(TCG_AREG0, ! 1230: offsetof(CPUState, eba), ! 1231: "eba"); ! 1232: cpu_dc = tcg_global_mem_new(TCG_AREG0, ! 1233: offsetof(CPUState, dc), ! 1234: "dc"); ! 1235: cpu_deba = tcg_global_mem_new(TCG_AREG0, ! 1236: offsetof(CPUState, deba), ! 1237: "deba"); ! 1238: } ! 1239:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.