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