Esempio n. 1
0
static void dec10_movem_m_r(DisasContext *dc)
{
    int i, pfix = dc->tb_flags & PFIX_FLAG;
    TCGv addr, t0;

    LOG_DIS("%s [r%d], r%d pi=%d ir=%x\n", __func__,
              dc->src, dc->dst, dc->postinc, dc->ir);

    addr = tcg_temp_new();
    t0 = tcg_temp_new();
    crisv10_prepare_memaddr(dc, addr, 4);
    tcg_gen_mov_tl(t0, addr);
    for (i = dc->dst; i >= 0; i--) {
        gen_load(dc, cpu_R[i], addr, 4, 0);
        tcg_gen_addi_tl(addr, addr, 4);
    }

    if (pfix && dc->mode == CRISV10_MODE_AUTOINC) {
        tcg_gen_mov_tl(cpu_R[dc->src], t0);
    }

    if (!pfix && dc->mode == CRISV10_MODE_AUTOINC) {
        tcg_gen_mov_tl(cpu_R[dc->src], addr);
    }
    tcg_temp_free(addr);
    tcg_temp_free(t0);
}
Esempio n. 2
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);
}
Esempio n. 3
0
static void crisv10_prepare_memaddr(DisasContext *dc,
                                    TCGv addr, unsigned int size)
{
    if (dc->tb_flags & PFIX_FLAG) {
        tcg_gen_mov_tl(addr, cpu_PR[PR_PREFIX]);
    } else {
        tcg_gen_mov_tl(addr, cpu_R[dc->src]);
    }
}
Esempio n. 4
0
static int dec10_alux_m(DisasContext *dc, int op)
{
    unsigned int size = (dc->size & 1) ? 2 : 1;
    unsigned int sx = !!(dc->size & 2);
    int insn_len = 2;
    int rd = dc->dst;
    TCGv t;

    LOG_DIS("addx size=%d sx=%d op=%d %d\n", size, sx, dc->src, dc->dst);

    t = tcg_temp_new();

    cris_cc_mask(dc, CC_MASK_NZVC);
    insn_len += dec10_prep_move_m(dc, sx, size, t);
    cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t, 4);
    if (dc->dst == 15) {
        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
        cris_prepare_jmp(dc, JMP_INDIRECT);
        dc->delayed_branch = 1;
        return insn_len;
    }

    tcg_temp_free(t);
    return insn_len;
}
Esempio n. 5
0
static void dec_call(DisasContext *dc)
{
    LOG_DIS("call r%d\n", dc->r0);

    tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
    tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);

    dc->is_jmp = DISAS_JUMP;
}
Esempio n. 6
0
/*
 * push_shack()
 *  Push next guest eip into shadow stack.
 */
void push_shack(CPUState *env, TCGv_ptr cpu_env, target_ulong next_eip)
{
    // label
    int label_do_push = gen_new_label(); 
    // prepare registers
    TCGv_ptr temp_shack_end = tcg_temp_local_new_ptr(); // store shack end
    TCGv_ptr temp_shack_top = tcg_temp_local_new_ptr(); // store shack top
    TCGv temp_next_eip = tcg_temp_local_new(); // store eip
    // load common values
    tcg_gen_ld_ptr(temp_shack_end, cpu_env, offsetof(CPUState, shack_end));
    tcg_gen_ld_ptr(temp_shack_top, cpu_env, offsetof(CPUState, shack_top));
    tcg_gen_mov_tl(temp_next_eip, tcg_const_tl(next_eip));
    // check shack full?
    tcg_gen_brcond_ptr(TCG_COND_NE,temp_shack_top,temp_shack_end,label_do_push); // if not full
    // flush here
    TCGv_ptr temp_shack_start = tcg_temp_new_ptr(); // store shack start
    //tcg_en_st_tl(tcg_const_tl(0), cpu_env, offsetof(CPUState, shadow_ret_count)); // reset ret count
    tcg_gen_ld_ptr(temp_shack_start, cpu_env, offsetof(CPUState, shack));
    tcg_gen_mov_tl(temp_shack_top, temp_shack_start);
    tcg_temp_free_ptr(temp_shack_start);
    // call helper: flush the hash
    gen_helper_shack_flush(cpu_env);
    // end of flush
    gen_set_label(label_do_push);
    // do push here
    // push guest eip
    tcg_gen_st_ptr(temp_next_eip, temp_shack_top, 0); // store guest eip
    tcg_gen_addi_ptr(temp_shack_top, temp_shack_top, sizeof(uint64_t)); // increase top
    // call helper: check if we can fill the ret directly, or need to add hash-pair
    gen_helper_shack_push(cpu_env, temp_next_eip);
    // store back top
    tcg_gen_st_ptr(temp_shack_top, cpu_env, offsetof(CPUState, shack_top));
    // clean up
    tcg_temp_free(temp_next_eip);
    tcg_temp_free_ptr(temp_shack_top);
    tcg_temp_free_ptr(temp_shack_end);
}
Esempio n. 7
0
static void dec10_reg_mov_pr(DisasContext *dc)
{
    LOG_DIS("move p%d r%d sz=%d\n", dc->dst, dc->src, preg_sizes_v10[dc->dst]);
    cris_lock_irq(dc);
    if (dc->src == 15) {
        tcg_gen_mov_tl(env_btarget, cpu_PR[dc->dst]);
        cris_prepare_jmp(dc, JMP_INDIRECT);
        return;
    }
    if (dc->dst == PR_CCS) {
        cris_evaluate_flags(dc); 
    }
    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->src],
                 cpu_R[dc->src], cpu_PR[dc->dst], preg_sizes_v10[dc->dst]);
}
Esempio n. 8
0
static unsigned int dec10_ind_move_m_pr(DisasContext *dc)
{
    unsigned int insn_len = 2, rd = dc->dst;
    TCGv t, addr;

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

    addr = tcg_temp_new();
    t = tcg_temp_new();
    insn_len += dec10_prep_move_m(dc, 0, 4, t);
    if (rd == 15) {
        tcg_gen_mov_tl(env_btarget, t);
        cris_prepare_jmp(dc, JMP_INDIRECT);
        dc->delayed_branch = 1;
        return insn_len;
    }

    tcg_gen_mov_tl(cpu_PR[rd], t);
    dc->cpustate_changed = 1;
    tcg_temp_free(addr);
    tcg_temp_free(t);
    return insn_len;
}
Esempio n. 9
0
/*
 * pop_shack()
 *  Pop next host eip from shadow stack.
 */
void pop_shack(TCGv_ptr cpu_env, TCGv next_eip)
{
#ifdef OPT_SHACK
    /* declare variables */
    int lab_end = gen_new_label();
    TCGv tcg_next_eip = tcg_temp_local_new();
    TCGv_ptr tcg_top_host_eip = tcg_temp_local_new_ptr();

    TCGv_ptr tcg_shack_top = tcg_temp_new_ptr();
    TCGv_ptr tcg_shack = tcg_temp_new_ptr();
    TCGv tcg_top_guest_eip = tcg_temp_new();
    
    /* check if shack is empty */
    tcg_gen_mov_tl(tcg_next_eip, next_eip);
    tcg_gen_ld_ptr(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); //load shack top
    tcg_gen_ld_ptr(tcg_shack, cpu_env, offsetof(CPUState, shack)); //load shack
    tcg_gen_brcond_i32(TCG_COND_EQ, tcg_shack_top, tcg_shack, lab_end); // if(shack_top == shack): jmp to lab_end
    
    /* shack not empty -> update shack top*/
    tcg_gen_ld_ptr(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); //load shack top
    tcg_gen_subi_i32(tcg_shack_top, tcg_shack_top, sizeof (void *)); //else: shack_top--
    tcg_gen_st_tl(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); // store shack top

    /* check if shack_top->guest_eip == tcg_next_eip */
    tcg_gen_ld_ptr(tcg_shack_top, tcg_shack_top, 0); // shack top = shack[shack_top]
    tcg_gen_ld_tl(tcg_top_guest_eip, tcg_shack_top, offsetof(struct shadow_pair, guest_eip)); //tcg_top_guest_eip = tcg_shack_top->guest_eip    
    tcg_gen_brcond_i32(TCG_COND_NE, tcg_top_guest_eip, tcg_next_eip, lab_end); // if(shack_top->guest_eip != next_eip): jmp to lab_end

    /* check if shack_top->host_eip is valid */
    
    tcg_gen_ld_ptr(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); //load shack top
    tcg_gen_ld_ptr(tcg_shack_top, tcg_shack_top, 0); // shack top = shack[shack_top]
    tcg_gen_ld_ptr(tcg_top_host_eip, tcg_shack_top, offsetof(struct shadow_pair, host_eip)); //tcg_top_host_eip = tcg_shack_top->host_eip
    tcg_gen_brcond_i32(TCG_COND_EQ, tcg_top_host_eip, tcg_const_ptr(NULL), lab_end); // if(shack_top->host_eip == NULL): jmp to lab_end

    /* update return addr*/
    *gen_opc_ptr++ = INDEX_op_jmp;
    *gen_opparam_ptr++ = tcg_top_host_eip;

    /* clean up */
    gen_set_label(lab_end);
    tcg_temp_free_ptr(tcg_shack_top);
    tcg_temp_free_ptr(tcg_shack);
    tcg_temp_free_ptr(tcg_top_host_eip);
    tcg_temp_free(tcg_top_guest_eip);
    tcg_temp_free(tcg_next_eip);
#endif
}
Esempio n. 10
0
static void dec_rcsr(DisasContext *dc)
{
    LOG_DIS("rcsr r%d, %d\n", dc->r2, dc->csr);

    switch (dc->csr) {
    case CSR_IE:
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie);
        break;
    case CSR_IM:
        gen_helper_rcsr_im(cpu_R[dc->r2], cpu_env);
        break;
    case CSR_IP:
        gen_helper_rcsr_ip(cpu_R[dc->r2], cpu_env);
        break;
    case CSR_CC:
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc);
        break;
    case CSR_CFG:
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cfg);
        break;
    case CSR_EBA:
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_eba);
        break;
    case CSR_DC:
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_dc);
        break;
    case CSR_DEBA:
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba);
        break;
    case CSR_JTX:
        gen_helper_rcsr_jtx(cpu_R[dc->r2], cpu_env);
        break;
    case CSR_JRX:
        gen_helper_rcsr_jrx(cpu_R[dc->r2], cpu_env);
        break;
    case CSR_ICC:
    case CSR_DCC:
    case CSR_BP0:
    case CSR_BP1:
    case CSR_BP2:
    case CSR_BP3:
    case CSR_WP0:
    case CSR_WP1:
    case CSR_WP2:
    case CSR_WP3:
        qemu_log_mask(LOG_GUEST_ERROR, "invalid read access csr=%x\n", dc->csr);
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "read_csr: unknown csr=%x\n", dc->csr);
        break;
    }
}
Esempio n. 11
0
static int dec10_ind_bound(DisasContext *dc, unsigned int size)
{
    int insn_len = 0;
    int rd = dc->dst;
    TCGv t;

    t = tcg_temp_local_new();
    insn_len += dec10_prep_move_m(dc, 0, size, t);
    cris_alu(dc, CC_OP_BOUND, cpu_R[dc->dst], cpu_R[rd], t, 4);
    if (dc->dst == 15) {
        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
        cris_prepare_jmp(dc, JMP_INDIRECT);
        dc->delayed_branch = 1;
        return insn_len;
    }

    tcg_temp_free(t);
    return insn_len;
}
Esempio n. 12
0
static unsigned int crisv10_post_memaddr(DisasContext *dc, unsigned int size)
{
    unsigned int insn_len = 0;

    if (dc->tb_flags & PFIX_FLAG) {
        if (dc->mode == CRISV10_MODE_AUTOINC) {
            tcg_gen_mov_tl(cpu_R[dc->src], cpu_PR[PR_PREFIX]);
        }
    } else {
        if (dc->mode == CRISV10_MODE_AUTOINC) {
            if (dc->src == 15) {
                insn_len += size & ~1;
            } else {
                tcg_gen_addi_tl(cpu_R[dc->src], cpu_R[dc->src], size);
            }
        }
    }
    return insn_len;
}
Esempio n. 13
0
static int dec10_ind_alu(DisasContext *dc, int op, unsigned int size)
{
    int insn_len = 0;
    int rd = dc->dst;
    TCGv t[2];

    cris_alu_m_alloc_temps(t);
    insn_len += dec10_prep_move_m(dc, 0, size, t[0]);
    cris_alu(dc, op, cpu_R[dc->dst], cpu_R[rd], t[0], size);
    if (dc->dst == 15) {
        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
        cris_prepare_jmp(dc, JMP_INDIRECT);
        dc->delayed_branch = 1;
        return insn_len;
    }

    cris_alu_m_free_temps(t);

    return insn_len;
}
Esempio n. 14
0
static unsigned int dec10_ind_move_m_r(DisasContext *dc, unsigned int size)
{
    unsigned int insn_len = 2;
    TCGv t;

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

    cris_cc_mask(dc, CC_MASK_NZVC);
    t = tcg_temp_new();
    insn_len += dec10_prep_move_m(dc, 0, size, t);
    cris_alu(dc, CC_OP_MOVE, cpu_R[dc->dst], cpu_R[dc->dst], t, size);
    if (dc->dst == 15) {
        tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
        cris_prepare_jmp(dc, JMP_INDIRECT);
        dc->delayed_branch = 1;
        return insn_len;
    }

    tcg_temp_free(t);
    return insn_len;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
static void dec_wcsr(DisasContext *dc)
{
    int no;

    LOG_DIS("wcsr r%d, %d\n", dc->r1, dc->csr);

    switch (dc->csr) {
    case CSR_IE:
        tcg_gen_mov_tl(cpu_ie, cpu_R[dc->r1]);
        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
        dc->is_jmp = DISAS_UPDATE;
        break;
    case CSR_IM:
        /* mark as an io operation because it could cause an interrupt */
        if (dc->tb->cflags & CF_USE_ICOUNT) {
            gen_io_start();
        }
        gen_helper_wcsr_im(cpu_env, cpu_R[dc->r1]);
        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
        if (dc->tb->cflags & CF_USE_ICOUNT) {
            gen_io_end();
        }
        dc->is_jmp = DISAS_UPDATE;
        break;
    case CSR_IP:
        /* mark as an io operation because it could cause an interrupt */
        if (dc->tb->cflags & CF_USE_ICOUNT) {
            gen_io_start();
        }
        gen_helper_wcsr_ip(cpu_env, cpu_R[dc->r1]);
        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
        if (dc->tb->cflags & CF_USE_ICOUNT) {
            gen_io_end();
        }
        dc->is_jmp = DISAS_UPDATE;
        break;
    case CSR_ICC:
        /* TODO */
        break;
    case CSR_DCC:
        /* TODO */
        break;
    case CSR_EBA:
        tcg_gen_mov_tl(cpu_eba, cpu_R[dc->r1]);
        break;
    case CSR_DEBA:
        tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]);
        break;
    case CSR_JTX:
        gen_helper_wcsr_jtx(cpu_env, cpu_R[dc->r1]);
        break;
    case CSR_JRX:
        gen_helper_wcsr_jrx(cpu_env, cpu_R[dc->r1]);
        break;
    case CSR_DC:
        gen_helper_wcsr_dc(cpu_env, cpu_R[dc->r1]);
        break;
    case CSR_BP0:
    case CSR_BP1:
    case CSR_BP2:
    case CSR_BP3:
        no = dc->csr - CSR_BP0;
        if (dc->num_breakpoints <= no) {
            qemu_log_mask(LOG_GUEST_ERROR,
                          "breakpoint #%i is not available\n", no);
            t_gen_illegal_insn(dc);
            break;
        }
        gen_helper_wcsr_bp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no));
        break;
    case CSR_WP0:
    case CSR_WP1:
    case CSR_WP2:
    case CSR_WP3:
        no = dc->csr - CSR_WP0;
        if (dc->num_watchpoints <= no) {
            qemu_log_mask(LOG_GUEST_ERROR,
                          "watchpoint #%i is not available\n", no);
            t_gen_illegal_insn(dc);
            break;
        }
        gen_helper_wcsr_wp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no));
        break;
    case CSR_CC:
    case CSR_CFG:
        qemu_log_mask(LOG_GUEST_ERROR, "invalid write access csr=%x\n",
                      dc->csr);
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "write_csr: unknown csr=%x\n",
                      dc->csr);
        break;
    }
}
Esempio n. 17
0
static unsigned int dec10_reg(DisasContext *dc)
{
    TCGv t;
    unsigned int insn_len = 2;
    unsigned int size = dec10_size(dc->size);
    unsigned int tmp;

    if (dc->size != 3) {
        switch (dc->opcode) {
            case CRISV10_REG_MOVE_R:
                LOG_DIS("move.%d $r%d, $r%d\n", dc->size, dc->src, dc->dst);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_MOVE, size, 0);
                if (dc->dst == 15) {
                    tcg_gen_mov_tl(env_btarget, cpu_R[dc->dst]);
                    cris_prepare_jmp(dc, JMP_INDIRECT);
                    dc->delayed_branch = 1;
                }
                break;
            case CRISV10_REG_MOVX:
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_movs(dc);
                break;
            case CRISV10_REG_ADDX:
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alux(dc, CC_OP_ADD);
                break;
            case CRISV10_REG_SUBX:
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alux(dc, CC_OP_SUB);
                break;
            case CRISV10_REG_ADD:
                LOG_DIS("add $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_ADD, size, 0);
                break;
            case CRISV10_REG_SUB:
                LOG_DIS("sub $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_SUB, size, 0);
                break;
            case CRISV10_REG_CMP:
                LOG_DIS("cmp $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_CMP, size, 0);
                break;
            case CRISV10_REG_BOUND:
                LOG_DIS("bound $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_bound(dc, size);
                break;
            case CRISV10_REG_AND:
                LOG_DIS("and $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_AND, size, 0);
                break;
            case CRISV10_REG_ADDI:
                if (dc->src == 15) {
                    /* nop.  */
                    return 2;
                }
                t = tcg_temp_new();
                LOG_DIS("addi r%d r%d size=%d\n", dc->src, dc->dst, dc->size);
                tcg_gen_shli_tl(t, cpu_R[dc->dst], dc->size & 3);
                tcg_gen_add_tl(cpu_R[dc->src], cpu_R[dc->src], t);
                tcg_temp_free(t);
                break;
            case CRISV10_REG_LSL:
                LOG_DIS("lsl $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_LSL, size, 0);
                break;
            case CRISV10_REG_LSR:
                LOG_DIS("lsr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_LSR, size, 0);
                break;
            case CRISV10_REG_ASR:
                LOG_DIS("asr $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_ASR, size, 1);
                break;
            case CRISV10_REG_OR:
                LOG_DIS("or $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_OR, size, 0);
                break;
            case CRISV10_REG_NEG:
                LOG_DIS("neg $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_NEG, size, 0);
                break;
            case CRISV10_REG_BIAP:
                LOG_DIS("BIAP pc=%x reg %d r%d r%d size=%d\n", dc->pc,
                         dc->opcode, dc->src, dc->dst, size);
                switch (size) {
                    case 4: tmp = 2; break;
                    case 2: tmp = 1; break;
                    case 1: tmp = 0; break;
                    default:
                        cpu_abort(dc->env, "Unhandled BIAP");
                        break;
                }

                t = tcg_temp_new();
                tcg_gen_shli_tl(t, cpu_R[dc->dst], tmp);
                if (dc->src == 15) {
                    tcg_gen_addi_tl(cpu_PR[PR_PREFIX], t, ((dc->pc +2)| 1) + 1);
                } else {
                    tcg_gen_add_tl(cpu_PR[PR_PREFIX], cpu_R[dc->src], t);
                }
                tcg_temp_free(t);
                cris_set_prefix(dc);
                break;

            default:
                LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
                         dc->opcode, dc->src, dc->dst);
                cpu_abort(dc->env, "Unhandled opcode");
                break;
        }
    } else {
        switch (dc->opcode) {
            case CRISV10_REG_MOVX:
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_movs(dc);
                break;
            case CRISV10_REG_ADDX:
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alux(dc, CC_OP_ADD);
                break;
            case CRISV10_REG_SUBX:
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alux(dc, CC_OP_SUB);
                break;
            case CRISV10_REG_MOVE_SPR_R:
                cris_evaluate_flags(dc);
                cris_cc_mask(dc, 0);
                dec10_reg_mov_pr(dc);
                break;
            case CRISV10_REG_MOVE_R_SPR:
                LOG_DIS("move r%d p%d\n", dc->src, dc->dst);
                cris_evaluate_flags(dc);
                if (dc->src != 11) /* fast for srp.  */
                    dc->cpustate_changed = 1;
                t_gen_mov_preg_TN(dc, dc->dst, cpu_R[dc->src]);
                break;
            case CRISV10_REG_SETF:
            case CRISV10_REG_CLEARF:
                dec10_setclrf(dc);
                break;
            case CRISV10_REG_SWAP:
                dec10_reg_swap(dc);
                break;
            case CRISV10_REG_ABS:
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_abs(dc);
                break;
            case CRISV10_REG_LZ:
                LOG_DIS("lz $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_LZ, 4, 0);
                break;
            case CRISV10_REG_XOR:
                LOG_DIS("xor $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                dec10_reg_alu(dc, CC_OP_XOR, 4, 0);
                break;
            case CRISV10_REG_BTST:
                LOG_DIS("btst $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                cris_update_cc_op(dc, CC_OP_FLAGS, 4);
                gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->dst],
                           cpu_R[dc->src], cpu_PR[PR_CCS]);
                break;
            case CRISV10_REG_DSTEP:
                LOG_DIS("dstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_cc_mask(dc, CC_MASK_NZVC);
                cris_alu(dc, CC_OP_DSTEP, cpu_R[dc->dst],
                            cpu_R[dc->dst], cpu_R[dc->src], 4);
                break;
            case CRISV10_REG_MSTEP:
                LOG_DIS("mstep $r%d, $r%d sz=%d\n", dc->src, dc->dst, size);
                cris_evaluate_flags(dc);
                cris_cc_mask(dc, CC_MASK_NZVC);
                cris_alu(dc, CC_OP_MSTEP, cpu_R[dc->dst],
                            cpu_R[dc->dst], cpu_R[dc->src], 4);
                break;
            case CRISV10_REG_SCC:
                dec10_reg_scc(dc);
                break;
            default:
                LOG_DIS("pc=%x reg %d r%d r%d\n", dc->pc,
                         dc->opcode, dc->src, dc->dst);
                cpu_abort(dc->env, "Unhandled opcode");
                break;
        }
    }
    return insn_len;
}
Esempio n. 18
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;
}