diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-12-08 23:40:14 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-12-08 23:40:14 +0000 |
commit | 1e8d4eec4859574e7773fa3243fcc61fe7b534e7 (patch) | |
tree | cab3e85962e3317946dd53a11c91639dc6dd4eeb | |
parent | 88920f344d5352dc0bb57539c4639344e9e0e0fe (diff) |
more complete ARM shift fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1168 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | target-arm/op.c | 38 | ||||
-rw-r--r-- | target-arm/translate.c | 39 |
2 files changed, 70 insertions, 7 deletions
diff --git a/target-arm/op.c b/target-arm/op.c index 7545bb0f13..6596de76fa 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -463,6 +463,7 @@ void OPPROTO op_swpl_T0_T1(void) /* shifts */ /* T1 based */ + void OPPROTO op_shll_T1_im(void) { T1 = T1 << PARAM1; @@ -473,11 +474,21 @@ void OPPROTO op_shrl_T1_im(void) T1 = (uint32_t)T1 >> PARAM1; } +void OPPROTO op_shrl_T1_0(void) +{ + T1 = 0; +} + void OPPROTO op_sarl_T1_im(void) { T1 = (int32_t)T1 >> PARAM1; } +void OPPROTO op_sarl_T1_0(void) +{ + T1 = (int32_t)T1 >> 31; +} + void OPPROTO op_rorl_T1_im(void) { int shift; @@ -503,12 +514,24 @@ void OPPROTO op_shrl_T1_im_cc(void) 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; @@ -536,11 +559,21 @@ void OPPROTO op_shrl_T2_im(void) T2 = (uint32_t)T2 >> PARAM1; } +void OPPROTO op_shrl_T2_0(void) +{ + T2 = 0; +} + void OPPROTO op_sarl_T2_im(void) { T2 = (int32_t)T2 >> PARAM1; } +void OPPROTO op_sarl_T2_0(void) +{ + T2 = (int32_t)T2 >> 31; +} + void OPPROTO op_rorl_T2_im(void) { int shift; @@ -548,6 +581,11 @@ void OPPROTO op_rorl_T2_im(void) T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift)); } +void OPPROTO op_rrxl_T2(void) +{ + T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31); +} + /* T1 based, use T0 as shift count */ void OPPROTO op_shll_T1_T0(void) diff --git a/target-arm/translate.c b/target-arm/translate.c index 18caa81212..56efa41e10 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -94,6 +94,13 @@ static GenOpFunc1 *gen_shift_T1_im[4] = { gen_op_rorl_T1_im, }; +static GenOpFunc *gen_shift_T1_0[4] = { + NULL, + gen_op_shrl_T1_0, + gen_op_sarl_T1_0, + gen_op_rrxl_T1, +}; + static GenOpFunc1 *gen_shift_T2_im[4] = { gen_op_shll_T2_im, gen_op_shrl_T2_im, @@ -101,6 +108,13 @@ static GenOpFunc1 *gen_shift_T2_im[4] = { gen_op_rorl_T2_im, }; +static GenOpFunc *gen_shift_T2_0[4] = { + NULL, + gen_op_shrl_T2_0, + gen_op_sarl_T2_0, + gen_op_rrxl_T2, +}; + static GenOpFunc1 *gen_shift_T1_im_cc[4] = { gen_op_shll_T1_im_cc, gen_op_shrl_T1_im_cc, @@ -108,6 +122,13 @@ static GenOpFunc1 *gen_shift_T1_im_cc[4] = { 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, @@ -272,7 +293,7 @@ static inline void gen_movl_reg_T1(DisasContext *s, int reg) static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) { - int val, rm, shift; + int val, rm, shift, shiftop; if (!(insn & (1 << 25))) { /* immediate */ @@ -286,8 +307,11 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) rm = (insn) & 0xf; shift = (insn >> 7) & 0x1f; gen_movl_T2_reg(s, rm); + shiftop = (insn >> 5) & 3; if (shift != 0) { - gen_shift_T2_im[(insn >> 5) & 3](shift); + gen_shift_T2_im[shiftop](shift); + } else if (shiftop != 0) { + gen_shift_T2_0[shiftop](); } if (!(insn & (1 << 23))) gen_op_subl_T1_T2(); @@ -365,11 +389,12 @@ static void disas_arm_insn(DisasContext *s) } else { gen_shift_T1_im[shiftop](shift); } - } else if (shiftop == 3) { - if (logic_cc) - gen_op_rrxl_T1_cc(); - else - gen_op_rrxl_T1(); + } else if (shiftop != 0) { + if (logic_cc) { + gen_shift_T1_0_cc[shiftop](); + } else { + gen_shift_T1_0[shiftop](); + } } } else { rs = (insn >> 8) & 0xf; |