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); } }
// #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER) void pop_shack(TCGv_ptr cpu_env, TCGv next_eip){ //----------------------TCG operations TCGv_ptr temp_shack_top = tcg_temp_new_ptr(); TCGv_ptr temp_shack_empty = tcg_temp_new_ptr(); TCGv_ptr temp_shack_top_next = tcg_temp_new_ptr(); TCGv_ptr temp_entry_ptr = tcg_temp_new_ptr(); TCGv_ptr temp_host_eip = tcg_temp_new_ptr(); TCGv temp_guest_eip = tcg_temp_local_new_i32(); TCGv temp_next_eip = tcg_temp_local_new_i32(); int eip_match_label = gen_new_label(); // create label int empty_label = gen_new_label(); // create label //load next_eip into temp_next_eip tcg_gen_mov_i32(temp_next_eip, next_eip); // load shack_top ptr into temp_shack_top tcg_gen_ld_ptr(temp_shack_top, cpu_env, offsetof(CPUState, shack_top)); tcg_gen_ld_ptr(temp_shack_empty, cpu_env, offsetof(CPUState, shack)); //check if stack is empty tcg_gen_brcond_ptr(TCG_COND_EQ, temp_shack_top, temp_shack_empty, empty_label); // get (shack_top - 8) tcg_gen_ld_ptr(temp_shack_top, cpu_env, offsetof(CPUState, shack_top)); tcg_gen_subi_tl(temp_shack_top_next, temp_shack_top, sizeof(uint64_t)); // get entry tcg_gen_ld_ptr(temp_entry_ptr, temp_shack_top_next, 0); // load entry.guest_eip tcg_gen_ld_ptr(temp_guest_eip, temp_entry_ptr, offsetof(shack_hash_entry, guest_eip)); // branch to label tcg_gen_brcond_ptr(TCG_COND_NE, temp_next_eip, temp_guest_eip, eip_match_label); //reload all temps. tcg_gen_ld_ptr(temp_shack_top, cpu_env, offsetof(CPUState, shack_top)); tcg_gen_subi_tl(temp_shack_top_next, temp_shack_top, sizeof(uint64_t)); tcg_gen_ld_ptr(temp_entry_ptr, temp_shack_top_next, 0); // load entry.host_eip into temp_host_eip tcg_gen_ld_ptr(temp_host_eip, temp_entry_ptr, offsetof(shack_hash_entry, host_eip)); // update shack_top tcg_gen_st_ptr(temp_shack_top_next, cpu_env, offsetof(CPUState, shack_top)); // jump *gen_opc_ptr++ = INDEX_op_jmp; *gen_opparam_ptr++ = temp_host_eip; // set label here gen_set_label(eip_match_label); // empty stack do nothing gen_set_label(empty_label); }
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); }
static inline void gen_cond_branch(DisasContext *dc, int cond) { TCGLabel *l1 = gen_new_label(); tcg_gen_brcond_tl(cond, cpu_R[dc->r0], cpu_R[dc->r1], l1); gen_goto_tb(dc, 0, dc->pc + 4); gen_set_label(l1); gen_goto_tb(dc, 1, dc->pc + (sign_extend(dc->imm16 << 2, 16))); dc->is_jmp = DISAS_TB_JUMP; }
/* Delayed conditional jump (bt or bf) */ static void gen_delayed_conditional_jump(DisasContext * ctx) { int l1; l1 = gen_new_label(); gen_op_jdelayed(l1); gen_goto_tb(ctx, 1, ctx->pc); gen_set_label(l1); gen_jump(ctx); }
/* Immediate conditional jump (bt or bf) */ static void gen_conditional_jump(DisasContext * ctx, target_ulong ift, target_ulong ifnott) { int l1; l1 = gen_new_label(); gen_op_jT(l1); gen_goto_tb(ctx, 0, ifnott); gen_set_label(l1); gen_goto_tb(ctx, 1, ift); }
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; }
/* * 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 }
static void dec_modu(DisasContext *dc) { TCGLabel *l1; LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1); if (!(dc->features & LM32_FEATURE_DIVIDE)) { qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n"); t_gen_illegal_insn(dc); return; } l1 = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1); tcg_gen_movi_tl(cpu_pc, dc->pc); t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO); gen_set_label(l1); tcg_gen_remu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]); }
static void dec10_reg_scc(DisasContext *dc) { int cond = dc->dst; LOG_DIS("s%s $r%u\n", cc_name(cond), dc->src); if (cond != CC_A) { int l1; gen_tst_cc (dc, cpu_R[dc->src], cond); l1 = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_R[dc->src], 0, l1); tcg_gen_movi_tl(cpu_R[dc->src], 1); gen_set_label(l1); } else { tcg_gen_movi_tl(cpu_R[dc->src], 1); } cris_cc_mask(dc, 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); }
/* * pop_shack() * Pop next host eip from shadow stack. */ void pop_shack(TCGv_ptr cpu_env, TCGv next_eip) { // labels int label_end = gen_new_label(); // prepare registers TCGv_ptr temp_shack_start = tcg_temp_local_new_ptr(); // store shack start TCGv_ptr temp_shack_top = tcg_temp_local_new_ptr(); // store shack top TCGv eip_on_shack = tcg_temp_local_new(); TCGv_ptr host_slot_addr = tcg_temp_local_new(); TCGv_ptr host_addr = tcg_temp_new(); // load common values tcg_gen_ld_ptr(temp_shack_start, cpu_env, offsetof(CPUState, shack)); tcg_gen_ld_ptr(temp_shack_top, cpu_env, offsetof(CPUState, shack_top)); // check if stack empty? tcg_gen_brcond_ptr(TCG_COND_EQ,temp_shack_top,temp_shack_start,label_end); // stack not empty, pop one tcg_gen_subi_ptr(temp_shack_top, temp_shack_top, sizeof(uint64_t)); // decrease top tcg_gen_st_ptr(temp_shack_top, cpu_env, offsetof(CPUState, shack_top)); // store back top tcg_gen_ld_tl(eip_on_shack, temp_shack_top, 0); // get eip // check if the same? tcg_gen_brcond_ptr(TCG_COND_NE,tcg_const_tl(next_eip),eip_on_shack,label_end); // go to "end" if not the same tcg_gen_ld_tl(host_slot_addr, temp_shack_top, sizeof(unsigned long)); // get slot addr tcg_gen_ld_ptr(host_addr, host_slot_addr, 0) ; // get host addr tcg_gen_brcond_ptr(TCG_COND_EQ,tcg_const_tl(0),host_addr,label_end); // go to "end" if addr is zero // jump! *gen_opc_ptr++ = INDEX_op_jmp; *gen_opparam_ptr++ = GET_TCGV_I32(host_addr); // label: end gen_set_label(label_end); tcg_temp_free(eip_on_shack); tcg_temp_free_ptr(host_slot_addr); tcg_temp_free_ptr(host_addr); tcg_temp_free_ptr(temp_shack_top); tcg_temp_free_ptr(temp_shack_start); }
/* * push_shack() * Push next guest eip into shadow stack. */ void push_shack(CPUState *env, TCGv_ptr cpu_env, target_ulong next_eip) //next_eip contains the guest return address { #ifdef OPT_SHACK /* find the corresponding slot */ struct shadow_pair *pair_ptr = find_hash_pair(env, next_eip); /* declare variables */ TCGv_ptr tcg_shack_top = tcg_temp_new_ptr(); TCGv_ptr tcg_shack_end = tcg_temp_new_ptr(); int lab_push = gen_new_label(); /* check if need flush * if(env->shack_top == env->shack_end) * env->shack_top = env->shack; */ tcg_gen_ld_ptr(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); //load shack top tcg_gen_ld_ptr(tcg_shack_end, cpu_env, offsetof(CPUState, shack_end)); //load shack end tcg_gen_brcond_i32(TCG_COND_NE, tcg_shack_top, tcg_shack_end, lab_push); //if(env->shack_top != env->shack_end): jmp to lab_push tcg_gen_ld_ptr(tcg_shack_top, cpu_env, offsetof(CPUState, shack)); //env->shack_top = env->shack (flush) tcg_gen_st_tl(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); // store shack top /* push the slot addr onto shack * env->shack_top = pair_ptr; * env->shack_top++; */ gen_set_label(lab_push); tcg_gen_ld_ptr(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); //load shack top tcg_gen_st_tl(tcg_const_ptr(pair_ptr), tcg_shack_top, 0); // env->shack_top = pair_ptr tcg_gen_addi_ptr(tcg_shack_top, tcg_shack_top, sizeof (void *)); //shack_top++ tcg_gen_st_tl(tcg_shack_top, cpu_env, offsetof(CPUState, shack_top)); // store shack top /* clean up */ tcg_temp_free_ptr(tcg_shack_top); tcg_temp_free_ptr(tcg_shack_end); #endif }