Commit 1e8d4eec4859574e7773fa3243fcc61fe7b534e7
1 parent
88920f34
more complete ARM shift fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1168 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
70 additions
and
7 deletions
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; | ... | ... |