mirror of https://github.com/xemu-project/xemu.git
fix ARMv7 data processing instructions
Modernize parts of target-arm/translate.c in preparation for the modifications in the subsequent patch in this patch set. This is done in order to avoid writing new code to target-arm/translate.c that would use deprecated methods and/or variables. Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com> Signed-off-by: Paul Brook <paul@codesourcery.com>
This commit is contained in:
parent
f789743095
commit
e9bb4aa977
|
@ -207,7 +207,6 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
|
|||
#define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
#define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
#define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
|
||||
#define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
|
||||
|
||||
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
|
@ -436,6 +435,16 @@ static void gen_adc_T0_T1(void)
|
|||
dead_tmp(tmp);
|
||||
}
|
||||
|
||||
/* dest = T0 + T1 + CF. */
|
||||
static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
|
||||
{
|
||||
TCGv tmp;
|
||||
tcg_gen_add_i32(dest, t0, t1);
|
||||
tmp = load_cpu_field(CF);
|
||||
tcg_gen_add_i32(dest, dest, tmp);
|
||||
dead_tmp(tmp);
|
||||
}
|
||||
|
||||
/* dest = T0 - T1 + CF - 1. */
|
||||
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
|
||||
{
|
||||
|
@ -3446,11 +3455,11 @@ static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Generate an old-style exception return. */
|
||||
static void gen_exception_return(DisasContext *s)
|
||||
/* Generate an old-style exception return. Marks pc as dead. */
|
||||
static void gen_exception_return(DisasContext *s, TCGv pc)
|
||||
{
|
||||
TCGv tmp;
|
||||
gen_movl_reg_T0(s, 15);
|
||||
store_reg(s, 15, pc);
|
||||
tmp = load_cpu_field(spsr);
|
||||
gen_set_cpsr(tmp, 0xffffffff);
|
||||
dead_tmp(tmp);
|
||||
|
@ -6087,148 +6096,173 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
|
|||
/* immediate operand */
|
||||
val = insn & 0xff;
|
||||
shift = ((insn >> 8) & 0xf) * 2;
|
||||
if (shift)
|
||||
if (shift) {
|
||||
val = (val >> shift) | (val << (32 - shift));
|
||||
gen_op_movl_T1_im(val);
|
||||
if (logic_cc && shift)
|
||||
gen_set_CF_bit31(cpu_T[1]);
|
||||
}
|
||||
tmp2 = new_tmp();
|
||||
tcg_gen_movi_i32(tmp2, val);
|
||||
if (logic_cc && shift) {
|
||||
gen_set_CF_bit31(tmp2);
|
||||
}
|
||||
} else {
|
||||
/* register */
|
||||
rm = (insn) & 0xf;
|
||||
gen_movl_T1_reg(s, rm);
|
||||
tmp2 = load_reg(s, rm);
|
||||
shiftop = (insn >> 5) & 3;
|
||||
if (!(insn & (1 << 4))) {
|
||||
shift = (insn >> 7) & 0x1f;
|
||||
gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
|
||||
gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
|
||||
} else {
|
||||
rs = (insn >> 8) & 0xf;
|
||||
tmp = load_reg(s, rs);
|
||||
gen_arm_shift_reg(cpu_T[1], shiftop, tmp, logic_cc);
|
||||
gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
|
||||
}
|
||||
}
|
||||
if (op1 != 0x0f && op1 != 0x0d) {
|
||||
rn = (insn >> 16) & 0xf;
|
||||
gen_movl_T0_reg(s, rn);
|
||||
tmp = load_reg(s, rn);
|
||||
} else {
|
||||
TCGV_UNUSED(tmp);
|
||||
}
|
||||
rd = (insn >> 12) & 0xf;
|
||||
switch(op1) {
|
||||
case 0x00:
|
||||
gen_op_andl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
tcg_gen_and_i32(tmp, tmp, tmp2);
|
||||
if (logic_cc) {
|
||||
gen_logic_CC(tmp);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x01:
|
||||
gen_op_xorl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
tcg_gen_xor_i32(tmp, tmp, tmp2);
|
||||
if (logic_cc) {
|
||||
gen_logic_CC(tmp);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x02:
|
||||
if (set_cc && rd == 15) {
|
||||
/* SUBS r15, ... is used for exception return. */
|
||||
if (IS_USER(s))
|
||||
if (IS_USER(s)) {
|
||||
goto illegal_op;
|
||||
gen_op_subl_T0_T1_cc();
|
||||
gen_exception_return(s);
|
||||
}
|
||||
gen_helper_sub_cc(tmp, tmp, tmp2);
|
||||
gen_exception_return(s, tmp);
|
||||
} else {
|
||||
if (set_cc)
|
||||
gen_op_subl_T0_T1_cc();
|
||||
else
|
||||
gen_op_subl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (set_cc) {
|
||||
gen_helper_sub_cc(tmp, tmp, tmp2);
|
||||
} else {
|
||||
tcg_gen_sub_i32(tmp, tmp, tmp2);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
if (set_cc)
|
||||
gen_op_rsbl_T0_T1_cc();
|
||||
else
|
||||
gen_op_rsbl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (set_cc) {
|
||||
gen_helper_sub_cc(tmp, tmp2, tmp);
|
||||
} else {
|
||||
tcg_gen_sub_i32(tmp, tmp2, tmp);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x04:
|
||||
if (set_cc)
|
||||
gen_op_addl_T0_T1_cc();
|
||||
else
|
||||
gen_op_addl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (set_cc) {
|
||||
gen_helper_add_cc(tmp, tmp, tmp2);
|
||||
} else {
|
||||
tcg_gen_add_i32(tmp, tmp, tmp2);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x05:
|
||||
if (set_cc)
|
||||
gen_op_adcl_T0_T1_cc();
|
||||
else
|
||||
gen_adc_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (set_cc) {
|
||||
gen_helper_adc_cc(tmp, tmp, tmp2);
|
||||
} else {
|
||||
gen_add_carry(tmp, tmp, tmp2);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x06:
|
||||
if (set_cc)
|
||||
gen_op_sbcl_T0_T1_cc();
|
||||
else
|
||||
gen_sbc_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (set_cc) {
|
||||
gen_helper_sbc_cc(tmp, tmp, tmp2);
|
||||
} else {
|
||||
gen_sub_carry(tmp, tmp, tmp2);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x07:
|
||||
if (set_cc)
|
||||
gen_op_rscl_T0_T1_cc();
|
||||
else
|
||||
gen_rsc_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (set_cc) {
|
||||
gen_helper_sbc_cc(tmp, tmp2, tmp);
|
||||
} else {
|
||||
gen_sub_carry(tmp, tmp2, tmp);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x08:
|
||||
if (set_cc) {
|
||||
gen_op_andl_T0_T1();
|
||||
gen_op_logic_T0_cc();
|
||||
tcg_gen_and_i32(tmp, tmp, tmp2);
|
||||
gen_logic_CC(tmp);
|
||||
}
|
||||
dead_tmp(tmp);
|
||||
break;
|
||||
case 0x09:
|
||||
if (set_cc) {
|
||||
gen_op_xorl_T0_T1();
|
||||
gen_op_logic_T0_cc();
|
||||
tcg_gen_xor_i32(tmp, tmp, tmp2);
|
||||
gen_logic_CC(tmp);
|
||||
}
|
||||
dead_tmp(tmp);
|
||||
break;
|
||||
case 0x0a:
|
||||
if (set_cc) {
|
||||
gen_op_subl_T0_T1_cc();
|
||||
gen_helper_sub_cc(tmp, tmp, tmp2);
|
||||
}
|
||||
dead_tmp(tmp);
|
||||
break;
|
||||
case 0x0b:
|
||||
if (set_cc) {
|
||||
gen_op_addl_T0_T1_cc();
|
||||
gen_helper_add_cc(tmp, tmp, tmp2);
|
||||
}
|
||||
dead_tmp(tmp);
|
||||
break;
|
||||
case 0x0c:
|
||||
gen_op_orl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
tcg_gen_or_i32(tmp, tmp, tmp2);
|
||||
if (logic_cc) {
|
||||
gen_logic_CC(tmp);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
case 0x0d:
|
||||
if (logic_cc && rd == 15) {
|
||||
/* MOVS r15, ... is used for exception return. */
|
||||
if (IS_USER(s))
|
||||
if (IS_USER(s)) {
|
||||
goto illegal_op;
|
||||
gen_op_movl_T0_T1();
|
||||
gen_exception_return(s);
|
||||
}
|
||||
gen_exception_return(s, tmp2);
|
||||
} else {
|
||||
gen_movl_reg_T1(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T1_cc();
|
||||
if (logic_cc) {
|
||||
gen_logic_CC(tmp2);
|
||||
}
|
||||
store_reg(s, rd, tmp2);
|
||||
}
|
||||
break;
|
||||
case 0x0e:
|
||||
gen_op_bicl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
tcg_gen_bic_i32(tmp, tmp, tmp2);
|
||||
if (logic_cc) {
|
||||
gen_logic_CC(tmp);
|
||||
}
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
default:
|
||||
case 0x0f:
|
||||
gen_op_notl_T1();
|
||||
gen_movl_reg_T1(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T1_cc();
|
||||
tcg_gen_not_i32(tmp2, tmp2);
|
||||
if (logic_cc) {
|
||||
gen_logic_CC(tmp2);
|
||||
}
|
||||
store_reg(s, rd, tmp2);
|
||||
break;
|
||||
}
|
||||
if (op1 != 0x0f && op1 != 0x0d) {
|
||||
dead_tmp(tmp2);
|
||||
}
|
||||
} else {
|
||||
/* other instructions */
|
||||
op1 = (insn >> 24) & 0xf;
|
||||
|
|
Loading…
Reference in New Issue