Commit 1e8d4eec4859574e7773fa3243fcc61fe7b534e7

Authored by bellard
1 parent 88920f34

more complete ARM shift fix


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1168 c046a42c-6fe2-441c-8c8c-71466251a162
target-arm/op.c
... ... @@ -463,6 +463,7 @@ void OPPROTO op_swpl_T0_T1(void)
463 463 /* shifts */
464 464  
465 465 /* T1 based */
  466 +
466 467 void OPPROTO op_shll_T1_im(void)
467 468 {
468 469 T1 = T1 << PARAM1;
... ... @@ -473,11 +474,21 @@ void OPPROTO op_shrl_T1_im(void)
473 474 T1 = (uint32_t)T1 >> PARAM1;
474 475 }
475 476  
  477 +void OPPROTO op_shrl_T1_0(void)
  478 +{
  479 + T1 = 0;
  480 +}
  481 +
476 482 void OPPROTO op_sarl_T1_im(void)
477 483 {
478 484 T1 = (int32_t)T1 >> PARAM1;
479 485 }
480 486  
  487 +void OPPROTO op_sarl_T1_0(void)
  488 +{
  489 + T1 = (int32_t)T1 >> 31;
  490 +}
  491 +
481 492 void OPPROTO op_rorl_T1_im(void)
482 493 {
483 494 int shift;
... ... @@ -503,12 +514,24 @@ void OPPROTO op_shrl_T1_im_cc(void)
503 514 T1 = (uint32_t)T1 >> PARAM1;
504 515 }
505 516  
  517 +void OPPROTO op_shrl_T1_0_cc(void)
  518 +{
  519 + env->CF = (T1 >> 31) & 1;
  520 + T1 = 0;
  521 +}
  522 +
506 523 void OPPROTO op_sarl_T1_im_cc(void)
507 524 {
508 525 env->CF = (T1 >> (PARAM1 - 1)) & 1;
509 526 T1 = (int32_t)T1 >> PARAM1;
510 527 }
511 528  
  529 +void OPPROTO op_sarl_T1_0_cc(void)
  530 +{
  531 + env->CF = (T1 >> 31) & 1;
  532 + T1 = (int32_t)T1 >> 31;
  533 +}
  534 +
512 535 void OPPROTO op_rorl_T1_im_cc(void)
513 536 {
514 537 int shift;
... ... @@ -536,11 +559,21 @@ void OPPROTO op_shrl_T2_im(void)
536 559 T2 = (uint32_t)T2 >> PARAM1;
537 560 }
538 561  
  562 +void OPPROTO op_shrl_T2_0(void)
  563 +{
  564 + T2 = 0;
  565 +}
  566 +
539 567 void OPPROTO op_sarl_T2_im(void)
540 568 {
541 569 T2 = (int32_t)T2 >> PARAM1;
542 570 }
543 571  
  572 +void OPPROTO op_sarl_T2_0(void)
  573 +{
  574 + T2 = (int32_t)T2 >> 31;
  575 +}
  576 +
544 577 void OPPROTO op_rorl_T2_im(void)
545 578 {
546 579 int shift;
... ... @@ -548,6 +581,11 @@ void OPPROTO op_rorl_T2_im(void)
548 581 T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
549 582 }
550 583  
  584 +void OPPROTO op_rrxl_T2(void)
  585 +{
  586 + T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
  587 +}
  588 +
551 589 /* T1 based, use T0 as shift count */
552 590  
553 591 void OPPROTO op_shll_T1_T0(void)
... ...
target-arm/translate.c
... ... @@ -94,6 +94,13 @@ static GenOpFunc1 *gen_shift_T1_im[4] = {
94 94 gen_op_rorl_T1_im,
95 95 };
96 96  
  97 +static GenOpFunc *gen_shift_T1_0[4] = {
  98 + NULL,
  99 + gen_op_shrl_T1_0,
  100 + gen_op_sarl_T1_0,
  101 + gen_op_rrxl_T1,
  102 +};
  103 +
97 104 static GenOpFunc1 *gen_shift_T2_im[4] = {
98 105 gen_op_shll_T2_im,
99 106 gen_op_shrl_T2_im,
... ... @@ -101,6 +108,13 @@ static GenOpFunc1 *gen_shift_T2_im[4] = {
101 108 gen_op_rorl_T2_im,
102 109 };
103 110  
  111 +static GenOpFunc *gen_shift_T2_0[4] = {
  112 + NULL,
  113 + gen_op_shrl_T2_0,
  114 + gen_op_sarl_T2_0,
  115 + gen_op_rrxl_T2,
  116 +};
  117 +
104 118 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
105 119 gen_op_shll_T1_im_cc,
106 120 gen_op_shrl_T1_im_cc,
... ... @@ -108,6 +122,13 @@ static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
108 122 gen_op_rorl_T1_im_cc,
109 123 };
110 124  
  125 +static GenOpFunc *gen_shift_T1_0_cc[4] = {
  126 + NULL,
  127 + gen_op_shrl_T1_0_cc,
  128 + gen_op_sarl_T1_0_cc,
  129 + gen_op_rrxl_T1_cc,
  130 +};
  131 +
111 132 static GenOpFunc *gen_shift_T1_T0[4] = {
112 133 gen_op_shll_T1_T0,
113 134 gen_op_shrl_T1_T0,
... ... @@ -272,7 +293,7 @@ static inline void gen_movl_reg_T1(DisasContext *s, int reg)
272 293  
273 294 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
274 295 {
275   - int val, rm, shift;
  296 + int val, rm, shift, shiftop;
276 297  
277 298 if (!(insn & (1 << 25))) {
278 299 /* immediate */
... ... @@ -286,8 +307,11 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
286 307 rm = (insn) & 0xf;
287 308 shift = (insn >> 7) & 0x1f;
288 309 gen_movl_T2_reg(s, rm);
  310 + shiftop = (insn >> 5) & 3;
289 311 if (shift != 0) {
290   - gen_shift_T2_im[(insn >> 5) & 3](shift);
  312 + gen_shift_T2_im[shiftop](shift);
  313 + } else if (shiftop != 0) {
  314 + gen_shift_T2_0[shiftop]();
291 315 }
292 316 if (!(insn & (1 << 23)))
293 317 gen_op_subl_T1_T2();
... ... @@ -365,11 +389,12 @@ static void disas_arm_insn(DisasContext *s)
365 389 } else {
366 390 gen_shift_T1_im[shiftop](shift);
367 391 }
368   - } else if (shiftop == 3) {
369   - if (logic_cc)
370   - gen_op_rrxl_T1_cc();
371   - else
372   - gen_op_rrxl_T1();
  392 + } else if (shiftop != 0) {
  393 + if (logic_cc) {
  394 + gen_shift_T1_0_cc[shiftop]();
  395 + } else {
  396 + gen_shift_T1_0[shiftop]();
  397 + }
373 398 }
374 399 } else {
375 400 rs = (insn >> 8) & 0xf;
... ...