File:  [Qemu by Fabrice Bellard] / qemu / target-lm32 / translate.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:52:16 2018 UTC (3 years, 7 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

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

unix.superglobalmegacorp.com