Commit 6e295807acbaf7eb3200a685376fb968ebdb8571

Authored by bellard
1 parent f2674e31

ARM fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@314 c046a42c-6fe2-441c-8c8c-71466251a162
arm-dis.c
@@ -560,8 +560,8 @@ static arm_regname regnames[] = @@ -560,8 +560,8 @@ static arm_regname regnames[] =
560 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }} 560 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}
561 }; 561 };
562 562
563 -/* Default to GCC register name set. */  
564 -static unsigned int regname_selected = 1; 563 +/* Default to STD register name set. */
  564 +static unsigned int regname_selected = 2;
565 565
566 #define NUM_ARM_REGNAMES NUM_ELEM (regnames) 566 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
567 #define arm_regnames regnames[regname_selected].reg_names 567 #define arm_regnames regnames[regname_selected].reg_names
exec-arm.h
@@ -30,3 +30,11 @@ register uint32_t T2 asm(AREG3); @@ -30,3 +30,11 @@ register uint32_t T2 asm(AREG3);
30 void cpu_lock(void); 30 void cpu_lock(void);
31 void cpu_unlock(void); 31 void cpu_unlock(void);
32 void cpu_loop_exit(void); 32 void cpu_loop_exit(void);
  33 +
  34 +static inline int compute_cpsr(void)
  35 +{
  36 + int ZF;
  37 + ZF = (env->NZF == 0);
  38 + return env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
  39 + (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
  40 +}
op-arm.c
@@ -154,11 +154,11 @@ void OPPROTO op_adcl_T0_T1_cc(void) @@ -154,11 +154,11 @@ void OPPROTO op_adcl_T0_T1_cc(void)
154 FORCE_RET(); 154 FORCE_RET();
155 } 155 }
156 156
157 -#define OPSUB(sub, sbc, T0, T1) \ 157 +#define OPSUB(sub, sbc, res, T0, T1) \
158 \ 158 \
159 void OPPROTO op_ ## sub ## l_T0_T1(void) \ 159 void OPPROTO op_ ## sub ## l_T0_T1(void) \
160 { \ 160 { \
161 - T0 -= T1; \ 161 + res = T0 - T1; \
162 } \ 162 } \
163 \ 163 \
164 void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ 164 void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \
@@ -167,13 +167,14 @@ void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ @@ -167,13 +167,14 @@ void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \
167 src1 = T0; \ 167 src1 = T0; \
168 T0 -= T1; \ 168 T0 -= T1; \
169 env->NZF = T0; \ 169 env->NZF = T0; \
170 - env->CF = src1 < T1; \ 170 + env->CF = src1 >= T1; \
171 env->VF = (src1 ^ T1) & (src1 ^ T0); \ 171 env->VF = (src1 ^ T1) & (src1 ^ T0); \
  172 + res = T0; \
172 } \ 173 } \
173 \ 174 \
174 void OPPROTO op_ ## sbc ## l_T0_T1(void) \ 175 void OPPROTO op_ ## sbc ## l_T0_T1(void) \
175 { \ 176 { \
176 - T0 = T0 - T1 + env->CF - 1; \ 177 + res = T0 - T1 + env->CF - 1; \
177 } \ 178 } \
178 \ 179 \
179 void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ 180 void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \
@@ -182,20 +183,20 @@ void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ @@ -182,20 +183,20 @@ void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \
182 src1 = T0; \ 183 src1 = T0; \
183 if (!env->CF) { \ 184 if (!env->CF) { \
184 T0 = T0 - T1 - 1; \ 185 T0 = T0 - T1 - 1; \
185 - T0 += T1; \  
186 - env->CF = src1 < T1; \ 186 + env->CF = src1 >= T1; \
187 } else { \ 187 } else { \
188 T0 = T0 - T1; \ 188 T0 = T0 - T1; \
189 - env->CF = src1 <= T1; \ 189 + env->CF = src1 > T1; \
190 } \ 190 } \
191 env->VF = (src1 ^ T1) & (src1 ^ T0); \ 191 env->VF = (src1 ^ T1) & (src1 ^ T0); \
192 env->NZF = T0; \ 192 env->NZF = T0; \
  193 + res = T0; \
193 FORCE_RET(); \ 194 FORCE_RET(); \
194 } 195 }
195 196
196 -OPSUB(sub, sbc, T0, T1) 197 +OPSUB(sub, sbc, T0, T0, T1)
197 198
198 -OPSUB(rsb, rsc, T1, T0) 199 +OPSUB(rsb, rsc, T0, T1, T0)
199 200
200 void OPPROTO op_andl_T0_T1(void) 201 void OPPROTO op_andl_T0_T1(void)
201 { 202 {
@@ -222,11 +223,16 @@ void OPPROTO op_notl_T1(void) @@ -222,11 +223,16 @@ void OPPROTO op_notl_T1(void)
222 T1 = ~T1; 223 T1 = ~T1;
223 } 224 }
224 225
225 -void OPPROTO op_logic_cc(void) 226 +void OPPROTO op_logic_T0_cc(void)
226 { 227 {
227 env->NZF = T0; 228 env->NZF = T0;
228 } 229 }
229 230
  231 +void OPPROTO op_logic_T1_cc(void)
  232 +{
  233 + env->NZF = T1;
  234 +}
  235 +
230 #define EIP (env->regs[15]) 236 #define EIP (env->regs[15])
231 237
232 void OPPROTO op_test_eq(void) 238 void OPPROTO op_test_eq(void)
@@ -334,10 +340,7 @@ void OPPROTO op_jmp(void) @@ -334,10 +340,7 @@ void OPPROTO op_jmp(void)
334 340
335 void OPPROTO op_movl_T0_psr(void) 341 void OPPROTO op_movl_T0_psr(void)
336 { 342 {
337 - int ZF;  
338 - ZF = (env->NZF == 0);  
339 - T0 = env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) |  
340 - (env->CF << 29) | ((env->VF & 0x80000000) >> 3); 343 + T0 = compute_cpsr();
341 } 344 }
342 345
343 /* NOTE: N = 1 and Z = 1 cannot be stored currently */ 346 /* NOTE: N = 1 and Z = 1 cannot be stored currently */
translate-arm.c
@@ -34,6 +34,8 @@ typedef struct DisasContext { @@ -34,6 +34,8 @@ typedef struct DisasContext {
34 struct TranslationBlock *tb; 34 struct TranslationBlock *tb;
35 } DisasContext; 35 } DisasContext;
36 36
  37 +#define DISAS_JUMP_NEXT 4
  38 +
37 /* XXX: move that elsewhere */ 39 /* XXX: move that elsewhere */
38 static uint16_t *gen_opc_ptr; 40 static uint16_t *gen_opc_ptr;
39 static uint32_t *gen_opparam_ptr; 41 static uint32_t *gen_opparam_ptr;
@@ -333,10 +335,11 @@ static void disas_arm_insn(DisasContext *s) @@ -333,10 +335,11 @@ static void disas_arm_insn(DisasContext *s)
333 /* if not always execute, we generate a conditional jump to 335 /* if not always execute, we generate a conditional jump to
334 next instruction */ 336 next instruction */
335 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); 337 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
336 - s->is_jmp = 1; 338 + s->is_jmp = DISAS_JUMP_NEXT;
337 } 339 }
338 - if ((insn & 0x0c000000) == 0 &&  
339 - (insn & 0x00000090) != 0x90) { 340 + if (((insn & 0x0e000000) == 0 &&
  341 + (insn & 0x00000090) != 0x90) ||
  342 + ((insn & 0x0e000000) == (1 << 25))) {
340 int set_cc, logic_cc, shiftop; 343 int set_cc, logic_cc, shiftop;
341 344
342 op1 = (insn >> 21) & 0xf; 345 op1 = (insn >> 21) & 0xf;
@@ -367,7 +370,7 @@ static void disas_arm_insn(DisasContext *s) @@ -367,7 +370,7 @@ static void disas_arm_insn(DisasContext *s)
367 } 370 }
368 } 371 }
369 } else { 372 } else {
370 - rs = (insn >> 16) & 0xf; 373 + rs = (insn >> 8) & 0xf;
371 gen_movl_T0_reg(s, rs); 374 gen_movl_T0_reg(s, rs);
372 if (logic_cc) { 375 if (logic_cc) {
373 gen_shift_T1_T0_cc[shiftop](); 376 gen_shift_T1_T0_cc[shiftop]();
@@ -385,10 +388,14 @@ static void disas_arm_insn(DisasContext *s) @@ -385,10 +388,14 @@ static void disas_arm_insn(DisasContext *s)
385 case 0x00: 388 case 0x00:
386 gen_op_andl_T0_T1(); 389 gen_op_andl_T0_T1();
387 gen_movl_reg_T0(s, rd); 390 gen_movl_reg_T0(s, rd);
  391 + if (logic_cc)
  392 + gen_op_logic_T0_cc();
388 break; 393 break;
389 case 0x01: 394 case 0x01:
390 gen_op_xorl_T0_T1(); 395 gen_op_xorl_T0_T1();
391 gen_movl_reg_T0(s, rd); 396 gen_movl_reg_T0(s, rd);
  397 + if (logic_cc)
  398 + gen_op_logic_T0_cc();
392 break; 399 break;
393 case 0x02: 400 case 0x02:
394 if (set_cc) 401 if (set_cc)
@@ -435,11 +442,13 @@ static void disas_arm_insn(DisasContext *s) @@ -435,11 +442,13 @@ static void disas_arm_insn(DisasContext *s)
435 case 0x08: 442 case 0x08:
436 if (set_cc) { 443 if (set_cc) {
437 gen_op_andl_T0_T1(); 444 gen_op_andl_T0_T1();
  445 + gen_op_logic_T0_cc();
438 } 446 }
439 break; 447 break;
440 case 0x09: 448 case 0x09:
441 if (set_cc) { 449 if (set_cc) {
442 gen_op_xorl_T0_T1(); 450 gen_op_xorl_T0_T1();
  451 + gen_op_logic_T0_cc();
443 } 452 }
444 break; 453 break;
445 case 0x0a: 454 case 0x0a:
@@ -455,22 +464,28 @@ static void disas_arm_insn(DisasContext *s) @@ -455,22 +464,28 @@ static void disas_arm_insn(DisasContext *s)
455 case 0x0c: 464 case 0x0c:
456 gen_op_orl_T0_T1(); 465 gen_op_orl_T0_T1();
457 gen_movl_reg_T0(s, rd); 466 gen_movl_reg_T0(s, rd);
  467 + if (logic_cc)
  468 + gen_op_logic_T0_cc();
458 break; 469 break;
459 case 0x0d: 470 case 0x0d:
460 gen_movl_reg_T1(s, rd); 471 gen_movl_reg_T1(s, rd);
  472 + if (logic_cc)
  473 + gen_op_logic_T1_cc();
461 break; 474 break;
462 case 0x0e: 475 case 0x0e:
463 gen_op_bicl_T0_T1(); 476 gen_op_bicl_T0_T1();
464 gen_movl_reg_T0(s, rd); 477 gen_movl_reg_T0(s, rd);
  478 + if (logic_cc)
  479 + gen_op_logic_T0_cc();
465 break; 480 break;
466 default: 481 default:
467 case 0x0f: 482 case 0x0f:
468 gen_op_notl_T1(); 483 gen_op_notl_T1();
469 gen_movl_reg_T1(s, rd); 484 gen_movl_reg_T1(s, rd);
  485 + if (logic_cc)
  486 + gen_op_logic_T1_cc();
470 break; 487 break;
471 } 488 }
472 - if (logic_cc)  
473 - gen_op_logic_cc();  
474 } else { 489 } else {
475 /* other instructions */ 490 /* other instructions */
476 op1 = (insn >> 24) & 0xf; 491 op1 = (insn >> 24) & 0xf;
@@ -494,7 +509,7 @@ static void disas_arm_insn(DisasContext *s) @@ -494,7 +509,7 @@ static void disas_arm_insn(DisasContext *s)
494 gen_op_addl_T0_T1(); 509 gen_op_addl_T0_T1();
495 } 510 }
496 if (insn & (1 << 20)) 511 if (insn & (1 << 20))
497 - gen_op_logic_cc(); 512 + gen_op_logic_T0_cc();
498 gen_movl_reg_T0(s, rd); 513 gen_movl_reg_T0(s, rd);
499 } else { 514 } else {
500 /* 64 bit mul */ 515 /* 64 bit mul */
@@ -551,10 +566,12 @@ static void disas_arm_insn(DisasContext *s) @@ -551,10 +566,12 @@ static void disas_arm_insn(DisasContext *s)
551 /* store */ 566 /* store */
552 gen_op_stw_T0_T1(); 567 gen_op_stw_T0_T1();
553 } 568 }
554 - if (!(insn & (1 << 24))) 569 + if (!(insn & (1 << 24))) {
555 gen_add_datah_offset(s, insn); 570 gen_add_datah_offset(s, insn);
556 - if (insn & (1 << 21))  
557 gen_movl_reg_T1(s, rn); 571 gen_movl_reg_T1(s, rn);
  572 + } else if (insn & (1 << 21)) {
  573 + gen_movl_reg_T1(s, rn);
  574 + }
558 } 575 }
559 break; 576 break;
560 case 0x4: 577 case 0x4:
@@ -582,40 +599,94 @@ static void disas_arm_insn(DisasContext *s) @@ -582,40 +599,94 @@ static void disas_arm_insn(DisasContext *s)
582 else 599 else
583 gen_op_stl_T0_T1(); 600 gen_op_stl_T0_T1();
584 } 601 }
585 - if (!(insn & (1 << 24))) 602 + if (!(insn & (1 << 24))) {
586 gen_add_data_offset(s, insn); 603 gen_add_data_offset(s, insn);
587 - if (insn & (1 << 21))  
588 gen_movl_reg_T1(s, rn); 604 gen_movl_reg_T1(s, rn);
  605 + } else if (insn & (1 << 21))
  606 + gen_movl_reg_T1(s, rn); {
  607 + }
589 break; 608 break;
590 case 0x08: 609 case 0x08:
591 case 0x09: 610 case 0x09:
592 - /* load/store multiple words */  
593 - if (insn & (1 << 22))  
594 - goto illegal_op; /* only usable in supervisor mode */  
595 - rn = (insn >> 16) & 0xf;  
596 - gen_movl_T1_reg(s, rn);  
597 - val = 4;  
598 - if (!(insn & (1 << 23)))  
599 - val = -val;  
600 - for(i=0;i<16;i++) {  
601 - if (insn & (1 << i)) {  
602 - if (insn & (1 << 24))  
603 - gen_op_addl_T1_im(val);  
604 - if (insn & (1 << 20)) {  
605 - /* load */  
606 - gen_op_ldl_T0_T1();  
607 - gen_movl_reg_T0(s, i); 611 + {
  612 + int j, n;
  613 + /* load/store multiple words */
  614 + /* XXX: store correct base if write back */
  615 + if (insn & (1 << 22))
  616 + goto illegal_op; /* only usable in supervisor mode */
  617 + rn = (insn >> 16) & 0xf;
  618 + gen_movl_T1_reg(s, rn);
  619 +
  620 + /* compute total size */
  621 + n = 0;
  622 + for(i=0;i<16;i++) {
  623 + if (insn & (1 << i))
  624 + n++;
  625 + }
  626 + /* XXX: test invalid n == 0 case ? */
  627 + if (insn & (1 << 23)) {
  628 + if (insn & (1 << 24)) {
  629 + /* pre increment */
  630 + gen_op_addl_T1_im(4);
608 } else { 631 } else {
609 - /* store */  
610 - gen_movl_T0_reg(s, i);  
611 - gen_op_stl_T0_T1(); 632 + /* post increment */
  633 + }
  634 + } else {
  635 + if (insn & (1 << 24)) {
  636 + /* pre decrement */
  637 + gen_op_addl_T1_im(-(n * 4));
  638 + } else {
  639 + /* post decrement */
  640 + if (n != 1)
  641 + gen_op_addl_T1_im(-((n - 1) * 4));
  642 + }
  643 + }
  644 + j = 0;
  645 + for(i=0;i<16;i++) {
  646 + if (insn & (1 << i)) {
  647 + if (insn & (1 << 20)) {
  648 + /* load */
  649 + gen_op_ldl_T0_T1();
  650 + gen_movl_reg_T0(s, i);
  651 + } else {
  652 + /* store */
  653 + if (i == 15) {
  654 + /* special case: r15 = PC + 12 */
  655 + val = (long)s->pc + 8;
  656 + gen_op_movl_TN_im[0](val);
  657 + } else {
  658 + gen_movl_T0_reg(s, i);
  659 + }
  660 + gen_op_stl_T0_T1();
  661 + }
  662 + j++;
  663 + /* no need to add after the last transfer */
  664 + if (j != n)
  665 + gen_op_addl_T1_im(4);
612 } 666 }
613 - if (!(insn & (1 << 24)))  
614 - gen_op_addl_T1_im(val); 667 + }
  668 + if (insn & (1 << 21)) {
  669 + /* write back */
  670 + if (insn & (1 << 23)) {
  671 + if (insn & (1 << 24)) {
  672 + /* pre increment */
  673 + } else {
  674 + /* post increment */
  675 + gen_op_addl_T1_im(4);
  676 + }
  677 + } else {
  678 + if (insn & (1 << 24)) {
  679 + /* pre decrement */
  680 + if (n != 1)
  681 + gen_op_addl_T1_im(-((n - 1) * 4));
  682 + } else {
  683 + /* post decrement */
  684 + gen_op_addl_T1_im(-(n * 4));
  685 + }
  686 + }
  687 + gen_movl_reg_T1(s, rn);
615 } 688 }
616 } 689 }
617 - if (insn & (1 << 21))  
618 - gen_movl_reg_T1(s, rn);  
619 break; 690 break;
620 case 0xa: 691 case 0xa:
621 case 0xb: 692 case 0xb:
@@ -641,6 +712,66 @@ static void disas_arm_insn(DisasContext *s) @@ -641,6 +712,66 @@ static void disas_arm_insn(DisasContext *s)
641 gen_op_swi(); 712 gen_op_swi();
642 s->is_jmp = DISAS_JUMP; 713 s->is_jmp = DISAS_JUMP;
643 break; 714 break;
  715 + case 0xc:
  716 + case 0xd:
  717 + rd = (insn >> 12) & 0x7;
  718 + rn = (insn >> 16) & 0xf;
  719 + gen_movl_T1_reg(s, rn);
  720 + val = (insn) & 0xff;
  721 + if (!(insn & (1 << 23)))
  722 + val = -val;
  723 + switch((insn >> 8) & 0xf) {
  724 + case 0x1:
  725 + /* load/store */
  726 + if ((insn & (1 << 24)))
  727 + gen_op_addl_T1_im(val);
  728 + /* XXX: do it */
  729 + if (!(insn & (1 << 24)))
  730 + gen_op_addl_T1_im(val);
  731 + if (insn & (1 << 21))
  732 + gen_movl_reg_T1(s, rn);
  733 + break;
  734 + case 0x2:
  735 + {
  736 + int n, i;
  737 + /* load store multiple */
  738 + if ((insn & (1 << 24)))
  739 + gen_op_addl_T1_im(val);
  740 + switch(insn & 0x00408000) {
  741 + case 0x00008000: n = 1; break;
  742 + case 0x00400000: n = 2; break;
  743 + case 0x00408000: n = 3; break;
  744 + default: n = 4; break;
  745 + }
  746 + for(i = 0;i < n; i++) {
  747 + /* XXX: do it */
  748 + }
  749 + if (!(insn & (1 << 24)))
  750 + gen_op_addl_T1_im(val);
  751 + if (insn & (1 << 21))
  752 + gen_movl_reg_T1(s, rn);
  753 + }
  754 + break;
  755 + default:
  756 + goto illegal_op;
  757 + }
  758 + break;
  759 + case 0x0e:
  760 + /* float ops */
  761 + /* XXX: do it */
  762 + switch((insn >> 20) & 0xf) {
  763 + case 0x2: /* wfs */
  764 + break;
  765 + case 0x3: /* rfs */
  766 + break;
  767 + case 0x4: /* wfc */
  768 + break;
  769 + case 0x5: /* rfc */
  770 + break;
  771 + default:
  772 + goto illegal_op;
  773 + }
  774 + break;
644 default: 775 default:
645 illegal_op: 776 illegal_op:
646 gen_op_movl_T0_im((long)s->pc - 4); 777 gen_op_movl_T0_im((long)s->pc - 4);
@@ -688,15 +819,19 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc @@ -688,15 +819,19 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
688 disas_arm_insn(dc); 819 disas_arm_insn(dc);
689 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 820 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
690 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); 821 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
691 - /* we must store the eflags state if it is not already done */  
692 - if (dc->is_jmp != DISAS_TB_JUMP &&  
693 - dc->is_jmp != DISAS_JUMP) {  
694 - gen_op_movl_T0_im((long)dc->pc - 4);  
695 - gen_op_movl_reg_TN[0][15]();  
696 - }  
697 - if (dc->is_jmp != DISAS_TB_JUMP) { 822 + switch(dc->is_jmp) {
  823 + case DISAS_JUMP_NEXT:
  824 + case DISAS_NEXT:
  825 + gen_op_jmp((long)dc->tb, (long)dc->pc);
  826 + break;
  827 + default:
  828 + case DISAS_JUMP:
698 /* indicate that the hash table must be used to find the next TB */ 829 /* indicate that the hash table must be used to find the next TB */
699 gen_op_movl_T0_0(); 830 gen_op_movl_T0_0();
  831 + break;
  832 + case DISAS_TB_JUMP:
  833 + /* nothing more to generate */
  834 + break;
700 } 835 }
701 *gen_opc_ptr = INDEX_op_end; 836 *gen_opc_ptr = INDEX_op_end;
702 837
@@ -756,5 +891,10 @@ void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags) @@ -756,5 +891,10 @@ void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
756 else 891 else
757 fprintf(f, " "); 892 fprintf(f, " ");
758 } 893 }
759 - fprintf(f, "CPSR=%08x", env->cpsr); 894 + fprintf(f, "PSR=%08x %c%c%c%c\n",
  895 + env->cpsr,
  896 + env->cpsr & (1 << 31) ? 'N' : '-',
  897 + env->cpsr & (1 << 30) ? 'Z' : '-',
  898 + env->cpsr & (1 << 29) ? 'C' : '-',
  899 + env->cpsr & (1 << 28) ? 'V' : '-');
760 } 900 }