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; | ... | ... |