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