Annotation of qemu/target-lm32/translate.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.