示例#1
0
static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val,
                       unsigned int size, int mem_index)
{
    int l1 = gen_new_label();
    TCGv taddr = tcg_temp_local_new();
    TCGv tval = tcg_temp_local_new();
    TCGv t1 = tcg_temp_local_new();
    dc->postinc = 0;
    cris_evaluate_flags(dc);

    tcg_gen_mov_tl(taddr, addr);
    tcg_gen_mov_tl(tval, val);

    /* Store only if F flag isn't set */
    tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10);
    tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
    if (size == 1) {
        tcg_gen_qemu_st8(tval, taddr, mem_index);
    } else if (size == 2) {
        tcg_gen_qemu_st16(tval, taddr, mem_index);
    } else {
        tcg_gen_qemu_st32(tval, taddr, mem_index);
    }
    gen_set_label(l1);
    tcg_gen_shri_tl(t1, t1, 1);  /* shift F to P position */
    tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/
    tcg_temp_free(t1);
    tcg_temp_free(tval);
    tcg_temp_free(taddr);
}
示例#2
0
文件: translate.c 项目: binape/qemu
static void dec_sru(DisasContext *dc)
{
    if (dc->format == OP_FMT_RI) {
        LOG_DIS("srui r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
    } else {
        LOG_DIS("sru r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
    }

    if (dc->format == OP_FMT_RI) {
        if (!(dc->features & LM32_FEATURE_SHIFT) && (dc->imm5 != 1)) {
            qemu_log_mask(LOG_GUEST_ERROR,
                    "hardware shifter is not available\n");
            t_gen_illegal_insn(dc);
            return;
        }
        tcg_gen_shri_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
    } else {
        TCGLabel *l1 = gen_new_label();
        TCGLabel *l2 = gen_new_label();
        TCGv t0 = tcg_temp_local_new();
        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);

        if (!(dc->features & LM32_FEATURE_SHIFT)) {
            tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 1, l1);
            t_gen_illegal_insn(dc);
            tcg_gen_br(l2);
        }

        gen_set_label(l1);
        tcg_gen_shr_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
        gen_set_label(l2);

        tcg_temp_free(t0);
    }
}
示例#3
0
static unsigned int dec10_setclrf(DisasContext *dc)
{
    uint32_t flags;
    unsigned int set = ~dc->opcode & 1;

    flags = EXTRACT_FIELD(dc->ir, 0, 3)
            | (EXTRACT_FIELD(dc->ir, 12, 15) << 4);
    LOG_DIS("%s set=%d flags=%x\n", __func__, set, flags);


    if (flags & X_FLAG) {
        dc->flagx_known = 1;
        if (set)
            dc->flags_x = X_FLAG;
        else
            dc->flags_x = 0;
    }

    cris_evaluate_flags (dc);
    cris_update_cc_op(dc, CC_OP_FLAGS, 4);
    cris_update_cc_x(dc);
    tcg_gen_movi_tl(cc_op, dc->cc_op);

    if (set) {
        tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
    } else {
        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS],
                        ~(flags|F_FLAG_V10|P_FLAG_V10));
    }

    dc->flags_uptodate = 1;
    dc->clear_x = 0;
    cris_lock_irq(dc);
    return 2;
}
示例#4
0
static unsigned int crisv10_decoder(DisasContext *dc)
{
    unsigned int insn_len = 2;

    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
        tcg_gen_debug_insn_start(dc->pc);

    /* Load a halfword onto the instruction register.  */
    dc->ir = lduw_code(dc->pc);

    /* Now decode it.  */
    dc->opcode   = EXTRACT_FIELD(dc->ir, 6, 9);
    dc->mode     = EXTRACT_FIELD(dc->ir, 10, 11);
    dc->src      = EXTRACT_FIELD(dc->ir, 0, 3);
    dc->size     = EXTRACT_FIELD(dc->ir, 4, 5);
    dc->cond = dc->dst = EXTRACT_FIELD(dc->ir, 12, 15);
    dc->postinc  = EXTRACT_FIELD(dc->ir, 10, 10);

    dc->clear_prefix = 1;

    /* FIXME: What if this insn insn't 2 in length??  */
    if (dc->src == 15 || dc->dst == 15)
        tcg_gen_movi_tl(cpu_R[15], dc->pc + 2);

    switch (dc->mode) {
        case CRISV10_MODE_QIMMEDIATE:
            insn_len = dec10_quick_imm(dc);
            break;
        case CRISV10_MODE_REG:
            insn_len = dec10_reg(dc);
            break;
        case CRISV10_MODE_AUTOINC:
        case CRISV10_MODE_INDIRECT:
            insn_len = dec10_ind(dc);
            break;
    }

    if (dc->clear_prefix && dc->tb_flags & PFIX_FLAG) {
        dc->tb_flags &= ~PFIX_FLAG;
        tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~PFIX_FLAG);
        if (dc->tb_flags != dc->tb->flags) {
            dc->cpustate_changed = 1;
        }
    }

    /* CRISv10 locks out interrupts on dslots.  */
    if (dc->delayed_branch == 2) {
        cris_lock_irq(dc);
    }
    return insn_len;
}
示例#5
0
文件: translate.c 项目: binape/qemu
static void dec_b(DisasContext *dc)
{
    if (dc->r0 == R_RA) {
        LOG_DIS("ret\n");
    } else if (dc->r0 == R_EA) {
        LOG_DIS("eret\n");
    } else if (dc->r0 == R_BA) {
        LOG_DIS("bret\n");
    } else {
        LOG_DIS("b r%d\n", dc->r0);
    }

    /* restore IE.IE in case of an eret */
    if (dc->r0 == R_EA) {
        TCGv t0 = tcg_temp_new();
        TCGLabel *l1 = gen_new_label();
        tcg_gen_andi_tl(t0, cpu_ie, IE_EIE);
        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_EIE, l1);
        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
        gen_set_label(l1);
        tcg_temp_free(t0);
    } else if (dc->r0 == R_BA) {
        TCGv t0 = tcg_temp_new();
        TCGLabel *l1 = gen_new_label();
        tcg_gen_andi_tl(t0, cpu_ie, IE_BIE);
        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_BIE, l1);
        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
        gen_set_label(l1);
        tcg_temp_free(t0);
    }
    tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);

    dc->is_jmp = DISAS_JUMP;
}
示例#6
0
static void dec10_reg_alu(DisasContext *dc, int op, int size, int sext)
{
    TCGv t[2];

    t[0] = tcg_temp_new();
    t[1] = tcg_temp_new();
    dec10_reg_prep_sext(dc, size, sext,
                        t[0], t[1], cpu_R[dc->dst], cpu_R[dc->src]);

    if (op == CC_OP_LSL || op == CC_OP_LSR || op == CC_OP_ASR) {
        tcg_gen_andi_tl(t[1], t[1], 63);
    }

    assert(dc->dst != 15);
    cris_alu(dc, op, cpu_R[dc->dst], t[0], t[1], size);
    tcg_temp_free(t[0]);
    tcg_temp_free(t[1]);
}
示例#7
0
文件: translate.c 项目: binape/qemu
static void dec_and(DisasContext *dc)
{
    if (dc->format == OP_FMT_RI) {
        LOG_DIS("andi r%d, r%d, %d\n", dc->r1, dc->r0,
                zero_extend(dc->imm16, 16));
    } else {
        LOG_DIS("and r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
    }

    if (dc->format == OP_FMT_RI) {
        tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0],
                zero_extend(dc->imm16, 16));
    } else  {
        if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) {
            tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
            gen_helper_hlt(cpu_env);
        } else {
            tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
        }
    }
}
示例#8
0
文件: translate.c 项目: binape/qemu
static void dec_sl(DisasContext *dc)
{
    if (dc->format == OP_FMT_RI) {
        LOG_DIS("sli r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
    } else {
        LOG_DIS("sl r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
    }

    if (!(dc->features & LM32_FEATURE_SHIFT)) {
        qemu_log_mask(LOG_GUEST_ERROR, "hardware shifter is not available\n");
        t_gen_illegal_insn(dc);
        return;
    }

    if (dc->format == OP_FMT_RI) {
        tcg_gen_shli_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
    } else {
        TCGv t0 = tcg_temp_new();
        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
        tcg_gen_shl_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
        tcg_temp_free(t0);
    }
}
示例#9
0
static unsigned int dec10_ind_move_pr_m(DisasContext *dc)
{
    unsigned int insn_len = 2, size = preg_sizes_v10[dc->dst];
    TCGv addr, t0;

    LOG_DIS("move.%d $p%d, [$r%d]\n", dc->size, dc->dst, dc->src);

    addr = tcg_temp_new();
    crisv10_prepare_memaddr(dc, addr, size);
    if (dc->dst == PR_CCS) {
        t0 = tcg_temp_new();
        cris_evaluate_flags(dc);
        tcg_gen_andi_tl(t0, cpu_PR[PR_CCS], ~PFIX_FLAG);
        gen_store_v10(dc, addr, t0, size);
        tcg_temp_free(t0);
    } else {
        gen_store_v10(dc, addr, cpu_PR[dc->dst], size);
    }
    t0 = tcg_temp_new();
    insn_len += crisv10_post_memaddr(dc, size);
    cris_lock_irq(dc);

    return insn_len;
}
示例#10
0
文件: translate.c 项目: binape/qemu
static void dec_andhi(DisasContext *dc)
{
    LOG_DIS("andhi r%d, r%d, %d\n", dc->r2, dc->r0, dc->imm16);

    tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
}
示例#11
0
static unsigned int dec10_ind(DisasContext *dc)
{
    unsigned int insn_len = 2;
    unsigned int size = dec10_size(dc->size);
    uint32_t imm;
    int32_t simm;
    TCGv t[2];

    if (dc->size != 3) {
        switch (dc->opcode) {
            case CRISV10_IND_MOVE_M_R:
                return dec10_ind_move_m_r(dc, size);
                break;
            case CRISV10_IND_MOVE_R_M:
                return dec10_ind_move_r_m(dc, size);
                break;
            case CRISV10_IND_CMP:
                LOG_DIS("cmp size=%d op=%d %d\n",  size, dc->src, dc->dst);
                cris_cc_mask(dc, CC_MASK_NZVC);
                insn_len += dec10_ind_alu(dc, CC_OP_CMP, size);
                break;
            case CRISV10_IND_TEST:
                LOG_DIS("test size=%d op=%d %d\n",  size, dc->src, dc->dst);

                cris_evaluate_flags(dc);
                cris_cc_mask(dc, CC_MASK_NZVC);
                cris_alu_m_alloc_temps(t);
                insn_len += dec10_prep_move_m(dc, 0, size, t[0]);
                tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
                cris_alu(dc, CC_OP_CMP, cpu_R[dc->dst],
                         t[0], tcg_const_tl(0), size);
                cris_alu_m_free_temps(t);
                break;
            case CRISV10_IND_ADD:
                LOG_DIS("add size=%d op=%d %d\n",  size, dc->src, dc->dst);
                cris_cc_mask(dc, CC_MASK_NZVC);
                insn_len += dec10_ind_alu(dc, CC_OP_ADD, size);
                break;
            case CRISV10_IND_SUB:
                LOG_DIS("sub size=%d op=%d %d\n",  size, dc->src, dc->dst);
                cris_cc_mask(dc, CC_MASK_NZVC);
                insn_len += dec10_ind_alu(dc, CC_OP_SUB, size);
                break;
            case CRISV10_IND_BOUND:
                LOG_DIS("bound size=%d op=%d %d\n",  size, dc->src, dc->dst);
                cris_cc_mask(dc, CC_MASK_NZVC);
                insn_len += dec10_ind_bound(dc, size);
                break;
            case CRISV10_IND_AND:
                LOG_DIS("and size=%d op=%d %d\n",  size, dc->src, dc->dst);
                cris_cc_mask(dc, CC_MASK_NZVC);
                insn_len += dec10_ind_alu(dc, CC_OP_AND, size);
                break;
            case CRISV10_IND_OR:
                LOG_DIS("or size=%d op=%d %d\n",  size, dc->src, dc->dst);
                cris_cc_mask(dc, CC_MASK_NZVC);
                insn_len += dec10_ind_alu(dc, CC_OP_OR, size);
                break;
            case CRISV10_IND_MOVX:
                insn_len = dec10_alux_m(dc, CC_OP_MOVE);
                break;
            case CRISV10_IND_ADDX:
                insn_len = dec10_alux_m(dc, CC_OP_ADD);
                break;
            case CRISV10_IND_SUBX:
                insn_len = dec10_alux_m(dc, CC_OP_SUB);
                break;
            case CRISV10_IND_CMPX:
                insn_len = dec10_alux_m(dc, CC_OP_CMP);
                break;
            case CRISV10_IND_MUL:
                /* This is a reg insn coded in the mem indir space.  */
                LOG_DIS("mul pc=%x opcode=%d\n", dc->pc, dc->opcode);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_mul(dc, size, dc->ir & (1 << 10));
                break;
            case CRISV10_IND_BDAP_M:
                insn_len = dec10_bdap_m(dc, size);
                break;
            default:
                LOG_DIS("pc=%x var-ind.%d %d r%d r%d\n",
                          dc->pc, size, dc->opcode, dc->src, dc->dst);
                cpu_abort(dc->env, "Unhandled opcode");
                break;
        }
        return insn_len;
    }

    switch (dc->opcode) {
        case CRISV10_IND_MOVE_M_SPR:
            insn_len = dec10_ind_move_m_pr(dc);
            break;
        case CRISV10_IND_MOVE_SPR_M:
            insn_len = dec10_ind_move_pr_m(dc);
            break;
        case CRISV10_IND_JUMP_M:
            if (dc->src == 15) {
                LOG_DIS("jump.%d %d r%d r%d direct\n", size,
                         dc->opcode, dc->src, dc->dst);
                imm = ldl_code(dc->pc + 2);
                if (dc->mode == CRISV10_MODE_AUTOINC)
                    insn_len += size;

                t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len));
                dc->jmp_pc = imm;
                cris_prepare_jmp(dc, JMP_DIRECT);
                dc->delayed_branch--; /* v10 has no dslot here.  */
            } else {
                if (dc->dst == 14) {
                    LOG_DIS("break %d\n", dc->src);
                    cris_evaluate_flags(dc);
                    tcg_gen_movi_tl(env_pc, dc->pc + 2);
                    t_gen_raise_exception(EXCP_BREAK);
                    dc->is_jmp = DISAS_UPDATE;
                    return insn_len;
                }
                LOG_DIS("%d: jump.%d %d r%d r%d\n", __LINE__, size,
                         dc->opcode, dc->src, dc->dst);
                t[0] = tcg_temp_new();
                t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len));
                crisv10_prepare_memaddr(dc, t[0], size);
                gen_load(dc, env_btarget, t[0], 4, 0);
                insn_len += crisv10_post_memaddr(dc, size);
                cris_prepare_jmp(dc, JMP_INDIRECT);
                dc->delayed_branch--; /* v10 has no dslot here.  */
                tcg_temp_free(t[0]);
            }
            break;

        case CRISV10_IND_MOVEM_R_M:
            LOG_DIS("movem_r_m pc=%x opcode=%d r%d r%d\n",
                        dc->pc, dc->opcode, dc->dst, dc->src);
            dec10_movem_r_m(dc);
            break;
        case CRISV10_IND_MOVEM_M_R:
            LOG_DIS("movem_m_r pc=%x opcode=%d\n", dc->pc, dc->opcode);
            dec10_movem_m_r(dc);
            break;
        case CRISV10_IND_JUMP_R:
            LOG_DIS("jmp pc=%x opcode=%d r%d r%d\n",
                        dc->pc, dc->opcode, dc->dst, dc->src);
            tcg_gen_mov_tl(env_btarget, cpu_R[dc->src]);
            t_gen_mov_preg_TN(dc, dc->dst, tcg_const_tl(dc->pc + insn_len));
            cris_prepare_jmp(dc, JMP_INDIRECT);
            dc->delayed_branch--; /* v10 has no dslot here.  */
            break;
        case CRISV10_IND_MOVX:
            insn_len = dec10_alux_m(dc, CC_OP_MOVE);
            break;
        case CRISV10_IND_ADDX:
            insn_len = dec10_alux_m(dc, CC_OP_ADD);
            break;
        case CRISV10_IND_SUBX:
            insn_len = dec10_alux_m(dc, CC_OP_SUB);
            break;
        case CRISV10_IND_CMPX:
            insn_len = dec10_alux_m(dc, CC_OP_CMP);
            break;
        case CRISV10_IND_DIP:
            insn_len = dec10_dip(dc);
            break;
        case CRISV10_IND_BCC_M:

            cris_cc_mask(dc, 0);
            imm = ldsw_code(dc->pc + 2);
            simm = (int16_t)imm;
            simm += 4;

            LOG_DIS("bcc_m: b%s %x\n", cc_name(dc->cond), dc->pc + simm);
            cris_prepare_cc_branch(dc, simm, dc->cond);
            insn_len = 4;
            break;
        default:
            LOG_DIS("ERROR pc=%x opcode=%d\n", dc->pc, dc->opcode);
            cpu_abort(dc->env, "Unhandled opcode");
            break;
    }

    return insn_len;
}