ARM TCG conversion 3/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4140 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
f51bbbfefe
commit
9a119ff6c1
126
target-arm/op.c
126
target-arm/op.c
@ -317,55 +317,6 @@ void OPPROTO op_clrex(void)
|
|||||||
cpu_unlock();
|
cpu_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shifts */
|
|
||||||
|
|
||||||
/* T1 based, set C flag */
|
|
||||||
void OPPROTO op_shll_T1_im_cc(void)
|
|
||||||
{
|
|
||||||
env->CF = (T1 >> (32 - PARAM1)) & 1;
|
|
||||||
T1 = T1 << PARAM1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_shrl_T1_im_cc(void)
|
|
||||||
{
|
|
||||||
env->CF = (T1 >> (PARAM1 - 1)) & 1;
|
|
||||||
T1 = (uint32_t)T1 >> PARAM1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_shrl_T1_0_cc(void)
|
|
||||||
{
|
|
||||||
env->CF = (T1 >> 31) & 1;
|
|
||||||
T1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_sarl_T1_im_cc(void)
|
|
||||||
{
|
|
||||||
env->CF = (T1 >> (PARAM1 - 1)) & 1;
|
|
||||||
T1 = (int32_t)T1 >> PARAM1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_sarl_T1_0_cc(void)
|
|
||||||
{
|
|
||||||
env->CF = (T1 >> 31) & 1;
|
|
||||||
T1 = (int32_t)T1 >> 31;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_rorl_T1_im_cc(void)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
shift = PARAM1;
|
|
||||||
env->CF = (T1 >> (shift - 1)) & 1;
|
|
||||||
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_rrxl_T1_cc(void)
|
|
||||||
{
|
|
||||||
uint32_t c;
|
|
||||||
c = T1 & 1;
|
|
||||||
T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
|
|
||||||
env->CF = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* T1 based, use T0 as shift count */
|
/* T1 based, use T0 as shift count */
|
||||||
|
|
||||||
void OPPROTO op_shll_T1_T0(void)
|
void OPPROTO op_shll_T1_T0(void)
|
||||||
@ -573,83 +524,6 @@ void OPPROTO op_subl_T0_T1_usaturate(void)
|
|||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thumb shift by immediate */
|
|
||||||
void OPPROTO op_shll_T0_im_thumb_cc(void)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
shift = PARAM1;
|
|
||||||
if (shift != 0) {
|
|
||||||
env->CF = (T0 >> (32 - shift)) & 1;
|
|
||||||
T0 = T0 << shift;
|
|
||||||
}
|
|
||||||
env->NZF = T0;
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_shll_T0_im_thumb(void)
|
|
||||||
{
|
|
||||||
T0 = T0 << PARAM1;
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_shrl_T0_im_thumb_cc(void)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
|
|
||||||
shift = PARAM1;
|
|
||||||
if (shift == 0) {
|
|
||||||
env->CF = ((uint32_t)T0) >> 31;
|
|
||||||
T0 = 0;
|
|
||||||
} else {
|
|
||||||
env->CF = (T0 >> (shift - 1)) & 1;
|
|
||||||
T0 = T0 >> shift;
|
|
||||||
}
|
|
||||||
env->NZF = T0;
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_shrl_T0_im_thumb(void)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
|
|
||||||
shift = PARAM1;
|
|
||||||
if (shift == 0) {
|
|
||||||
T0 = 0;
|
|
||||||
} else {
|
|
||||||
T0 = T0 >> shift;
|
|
||||||
}
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_sarl_T0_im_thumb_cc(void)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
|
|
||||||
shift = PARAM1;
|
|
||||||
if (shift == 0) {
|
|
||||||
T0 = ((int32_t)T0) >> 31;
|
|
||||||
env->CF = T0 & 1;
|
|
||||||
} else {
|
|
||||||
env->CF = (T0 >> (shift - 1)) & 1;
|
|
||||||
T0 = ((int32_t)T0) >> shift;
|
|
||||||
}
|
|
||||||
env->NZF = T0;
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_sarl_T0_im_thumb(void)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
|
|
||||||
shift = PARAM1;
|
|
||||||
if (shift == 0) {
|
|
||||||
env->CF = T0 & 1;
|
|
||||||
} else {
|
|
||||||
T0 = ((int32_t)T0) >> shift;
|
|
||||||
}
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exceptions */
|
/* exceptions */
|
||||||
|
|
||||||
void OPPROTO op_swi(void)
|
void OPPROTO op_swi(void)
|
||||||
|
@ -228,12 +228,14 @@ static void gen_add16(TCGv t0, TCGv t1)
|
|||||||
dead_tmp(t1);
|
dead_tmp(t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
|
||||||
|
|
||||||
/* Set CF to the top bit of var. */
|
/* Set CF to the top bit of var. */
|
||||||
static void gen_set_CF_bit31(TCGv var)
|
static void gen_set_CF_bit31(TCGv var)
|
||||||
{
|
{
|
||||||
TCGv tmp = new_tmp();
|
TCGv tmp = new_tmp();
|
||||||
tcg_gen_shri_i32(tmp, var, 31);
|
tcg_gen_shri_i32(tmp, var, 31);
|
||||||
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, CF));
|
gen_set_CF(var);
|
||||||
dead_tmp(tmp);
|
dead_tmp(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,31 +284,67 @@ static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
|
|||||||
dead_tmp(tmp);
|
dead_tmp(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shift by immediate. Includes special handling for shift == 0. */
|
static void shifter_out_im(TCGv var, int shift)
|
||||||
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift)
|
|
||||||
{
|
{
|
||||||
if (shift != 0) {
|
TCGv tmp = new_tmp();
|
||||||
switch (shiftop) {
|
if (shift == 0) {
|
||||||
case 0: tcg_gen_shli_i32(var, var, shift); break;
|
tcg_gen_andi_i32(tmp, var, 1);
|
||||||
case 1: tcg_gen_shri_i32(var, var, shift); break;
|
|
||||||
case 2: tcg_gen_sari_i32(var, var, shift); break;
|
|
||||||
case 3: tcg_gen_rori_i32(var, var, shift); break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
TCGv tmp;
|
tcg_gen_shri_i32(tmp, var, shift);
|
||||||
|
if (shift != 31);
|
||||||
|
tcg_gen_andi_i32(tmp, tmp, 1);
|
||||||
|
}
|
||||||
|
gen_set_CF(tmp);
|
||||||
|
dead_tmp(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
switch (shiftop) {
|
/* Shift by immediate. Includes special handling for shift == 0. */
|
||||||
case 0: break;
|
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
|
||||||
case 1: tcg_gen_movi_i32(var, 0); break;
|
{
|
||||||
case 2: tcg_gen_sari_i32(var, var, 31); break;
|
switch (shiftop) {
|
||||||
case 3: /* rrx */
|
case 0: /* LSL */
|
||||||
tcg_gen_shri_i32(var, var, 1);
|
if (shift != 0) {
|
||||||
tmp = new_tmp();
|
if (flags)
|
||||||
|
shifter_out_im(var, 32 - shift);
|
||||||
|
tcg_gen_shli_i32(var, var, shift);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: /* LSR */
|
||||||
|
if (shift == 0) {
|
||||||
|
if (flags) {
|
||||||
|
tcg_gen_shri_i32(var, var, 31);
|
||||||
|
gen_set_CF(var);
|
||||||
|
}
|
||||||
|
tcg_gen_movi_i32(var, 0);
|
||||||
|
} else {
|
||||||
|
if (flags)
|
||||||
|
shifter_out_im(var, shift - 1);
|
||||||
|
tcg_gen_shri_i32(var, var, shift);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: /* ASR */
|
||||||
|
if (shift == 0)
|
||||||
|
shift = 32;
|
||||||
|
if (flags)
|
||||||
|
shifter_out_im(var, shift - 1);
|
||||||
|
if (shift == 32)
|
||||||
|
shift = 31;
|
||||||
|
tcg_gen_sari_i32(var, var, shift);
|
||||||
|
break;
|
||||||
|
case 3: /* ROR/RRX */
|
||||||
|
if (shift != 0) {
|
||||||
|
if (flags)
|
||||||
|
shifter_out_im(var, shift - 1);
|
||||||
|
tcg_gen_rori_i32(var, var, shift); break;
|
||||||
|
} else {
|
||||||
|
TCGv tmp = new_tmp();
|
||||||
tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
|
tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
|
||||||
|
if (flags)
|
||||||
|
shifter_out_im(var, 0);
|
||||||
|
tcg_gen_shri_i32(var, var, 1);
|
||||||
tcg_gen_shli_i32(tmp, tmp, 31);
|
tcg_gen_shli_i32(tmp, tmp, 31);
|
||||||
tcg_gen_or_i32(var, var, tmp);
|
tcg_gen_or_i32(var, var, tmp);
|
||||||
dead_tmp(tmp);
|
dead_tmp(tmp);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -392,20 +430,6 @@ const uint8_t table_logic_cc[16] = {
|
|||||||
1, /* mvn */
|
1, /* mvn */
|
||||||
};
|
};
|
||||||
|
|
||||||
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
|
|
||||||
gen_op_shll_T1_im_cc,
|
|
||||||
gen_op_shrl_T1_im_cc,
|
|
||||||
gen_op_sarl_T1_im_cc,
|
|
||||||
gen_op_rorl_T1_im_cc,
|
|
||||||
};
|
|
||||||
|
|
||||||
static GenOpFunc *gen_shift_T1_0_cc[4] = {
|
|
||||||
NULL,
|
|
||||||
gen_op_shrl_T1_0_cc,
|
|
||||||
gen_op_sarl_T1_0_cc,
|
|
||||||
gen_op_rrxl_T1_cc,
|
|
||||||
};
|
|
||||||
|
|
||||||
static GenOpFunc *gen_shift_T1_T0[4] = {
|
static GenOpFunc *gen_shift_T1_T0[4] = {
|
||||||
gen_op_shll_T1_T0,
|
gen_op_shll_T1_T0,
|
||||||
gen_op_shrl_T1_T0,
|
gen_op_shrl_T1_T0,
|
||||||
@ -420,18 +444,6 @@ static GenOpFunc *gen_shift_T1_T0_cc[4] = {
|
|||||||
gen_op_rorl_T1_T0_cc,
|
gen_op_rorl_T1_T0_cc,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GenOpFunc1 *gen_shift_T0_im_thumb_cc[3] = {
|
|
||||||
gen_op_shll_T0_im_thumb_cc,
|
|
||||||
gen_op_shrl_T0_im_thumb_cc,
|
|
||||||
gen_op_sarl_T0_im_thumb_cc,
|
|
||||||
};
|
|
||||||
|
|
||||||
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
|
|
||||||
gen_op_shll_T0_im_thumb,
|
|
||||||
gen_op_shrl_T0_im_thumb,
|
|
||||||
gen_op_sarl_T0_im_thumb,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Set PC and thumb state from T0. Clobbers T0. */
|
/* Set PC and thumb state from T0. Clobbers T0. */
|
||||||
static inline void gen_bx(DisasContext *s)
|
static inline void gen_bx(DisasContext *s)
|
||||||
{
|
{
|
||||||
@ -530,7 +542,7 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
|
|||||||
shift = (insn >> 7) & 0x1f;
|
shift = (insn >> 7) & 0x1f;
|
||||||
shiftop = (insn >> 5) & 3;
|
shiftop = (insn >> 5) & 3;
|
||||||
offset = load_reg(s, rm);
|
offset = load_reg(s, rm);
|
||||||
gen_arm_shift_im(offset, shiftop, shift);
|
gen_arm_shift_im(offset, shiftop, shift, 0);
|
||||||
if (!(insn & (1 << 23)))
|
if (!(insn & (1 << 23)))
|
||||||
tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
|
tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
|
||||||
else
|
else
|
||||||
@ -5126,15 +5138,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
|
|||||||
shiftop = (insn >> 5) & 3;
|
shiftop = (insn >> 5) & 3;
|
||||||
if (!(insn & (1 << 4))) {
|
if (!(insn & (1 << 4))) {
|
||||||
shift = (insn >> 7) & 0x1f;
|
shift = (insn >> 7) & 0x1f;
|
||||||
if (logic_cc) {
|
gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
|
||||||
if (shift != 0) {
|
|
||||||
gen_shift_T1_im_cc[shiftop](shift);
|
|
||||||
} else if (shiftop != 0) {
|
|
||||||
gen_shift_T1_0_cc[shiftop]();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gen_arm_shift_im(cpu_T[1], shiftop, shift);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
rs = (insn >> 8) & 0xf;
|
rs = (insn >> 8) & 0xf;
|
||||||
gen_movl_T0_reg(s, rs);
|
gen_movl_T0_reg(s, rs);
|
||||||
@ -6243,15 +6247,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
|
|||||||
shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
|
shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
|
||||||
conds = (insn & (1 << 20)) != 0;
|
conds = (insn & (1 << 20)) != 0;
|
||||||
logic_cc = (conds && thumb2_logic_op(op));
|
logic_cc = (conds && thumb2_logic_op(op));
|
||||||
if (logic_cc) {
|
gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
|
||||||
if (shift != 0) {
|
|
||||||
gen_shift_T1_im_cc[shiftop](shift);
|
|
||||||
} else if (shiftop != 0) {
|
|
||||||
gen_shift_T1_0_cc[shiftop]();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gen_arm_shift_im(cpu_T[1], shiftop, shift);
|
|
||||||
}
|
|
||||||
if (gen_thumb2_data_op(s, op, conds, 0))
|
if (gen_thumb2_data_op(s, op, conds, 0))
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
if (rd != 15)
|
if (rd != 15)
|
||||||
@ -6960,12 +6956,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
|
|||||||
/* shift immediate */
|
/* shift immediate */
|
||||||
rm = (insn >> 3) & 7;
|
rm = (insn >> 3) & 7;
|
||||||
shift = (insn >> 6) & 0x1f;
|
shift = (insn >> 6) & 0x1f;
|
||||||
gen_movl_T0_reg(s, rm);
|
tmp = load_reg(s, rm);
|
||||||
if (s->condexec_mask)
|
gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
|
||||||
gen_shift_T0_im_thumb[op](shift);
|
if (!s->condexec_mask)
|
||||||
else
|
gen_logic_CC(tmp);
|
||||||
gen_shift_T0_im_thumb_cc[op](shift);
|
store_reg(s, rd, tmp);
|
||||||
gen_movl_reg_T0(s, rd);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: case 3:
|
case 2: case 3:
|
||||||
|
Loading…
Reference in New Issue
Block a user