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:
pbrook 2008-03-31 03:45:35 +00:00
parent f51bbbfefe
commit 9a119ff6c1
2 changed files with 65 additions and 196 deletions

View File

@ -317,55 +317,6 @@ void OPPROTO op_clrex(void)
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 */
void OPPROTO op_shll_T1_T0(void)
@ -573,83 +524,6 @@ void OPPROTO op_subl_T0_T1_usaturate(void)
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 */
void OPPROTO op_swi(void)

View File

@ -228,12 +228,14 @@ static void gen_add16(TCGv t0, TCGv 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. */
static void gen_set_CF_bit31(TCGv var)
{
TCGv tmp = new_tmp();
tcg_gen_shri_i32(tmp, var, 31);
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, CF));
gen_set_CF(var);
dead_tmp(tmp);
}
@ -282,31 +284,67 @@ static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
dead_tmp(tmp);
}
/* Shift by immediate. Includes special handling for shift == 0. */
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift)
static void shifter_out_im(TCGv var, int shift)
{
if (shift != 0) {
switch (shiftop) {
case 0: tcg_gen_shli_i32(var, var, shift); break;
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;
}
TCGv tmp = new_tmp();
if (shift == 0) {
tcg_gen_andi_i32(tmp, var, 1);
} 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);
}
/* Shift by immediate. Includes special handling for shift == 0. */
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
{
switch (shiftop) {
case 0: break;
case 1: tcg_gen_movi_i32(var, 0); break;
case 2: tcg_gen_sari_i32(var, var, 31); break;
case 3: /* rrx */
tcg_gen_shri_i32(var, var, 1);
tmp = new_tmp();
case 0: /* LSL */
if (shift != 0) {
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));
if (flags)
shifter_out_im(var, 0);
tcg_gen_shri_i32(var, var, 1);
tcg_gen_shli_i32(tmp, tmp, 31);
tcg_gen_or_i32(var, var, tmp);
dead_tmp(tmp);
break;
}
}
};
@ -392,20 +430,6 @@ const uint8_t table_logic_cc[16] = {
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] = {
gen_op_shll_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,
};
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. */
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;
shiftop = (insn >> 5) & 3;
offset = load_reg(s, rm);
gen_arm_shift_im(offset, shiftop, shift);
gen_arm_shift_im(offset, shiftop, shift, 0);
if (!(insn & (1 << 23)))
tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
else
@ -5126,15 +5138,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
shiftop = (insn >> 5) & 3;
if (!(insn & (1 << 4))) {
shift = (insn >> 7) & 0x1f;
if (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);
}
gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
} else {
rs = (insn >> 8) & 0xf;
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);
conds = (insn & (1 << 20)) != 0;
logic_cc = (conds && thumb2_logic_op(op));
if (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);
}
gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
if (gen_thumb2_data_op(s, op, conds, 0))
goto illegal_op;
if (rd != 15)
@ -6960,12 +6956,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
/* shift immediate */
rm = (insn >> 3) & 7;
shift = (insn >> 6) & 0x1f;
gen_movl_T0_reg(s, rm);
if (s->condexec_mask)
gen_shift_T0_im_thumb[op](shift);
else
gen_shift_T0_im_thumb_cc[op](shift);
gen_movl_reg_T0(s, rd);
tmp = load_reg(s, rm);
gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
if (!s->condexec_mask)
gen_logic_CC(tmp);
store_reg(s, rd, tmp);
}
break;
case 2: case 3: