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 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 566 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
567 567 #define arm_regnames regnames[regname_selected].reg_names
... ...
exec-arm.h
... ... @@ -30,3 +30,11 @@ register uint32_t T2 asm(AREG3);
30 30 void cpu_lock(void);
31 31 void cpu_unlock(void);
32 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 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 159 void OPPROTO op_ ## sub ## l_T0_T1(void) \
160 160 { \
161   - T0 -= T1; \
  161 + res = T0 - T1; \
162 162 } \
163 163 \
164 164 void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \
... ... @@ -167,13 +167,14 @@ void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \
167 167 src1 = T0; \
168 168 T0 -= T1; \
169 169 env->NZF = T0; \
170   - env->CF = src1 < T1; \
  170 + env->CF = src1 >= T1; \
171 171 env->VF = (src1 ^ T1) & (src1 ^ T0); \
  172 + res = T0; \
172 173 } \
173 174 \
174 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 180 void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \
... ... @@ -182,20 +183,20 @@ void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \
182 183 src1 = T0; \
183 184 if (!env->CF) { \
184 185 T0 = T0 - T1 - 1; \
185   - T0 += T1; \
186   - env->CF = src1 < T1; \
  186 + env->CF = src1 >= T1; \
187 187 } else { \
188 188 T0 = T0 - T1; \
189   - env->CF = src1 <= T1; \
  189 + env->CF = src1 > T1; \
190 190 } \
191 191 env->VF = (src1 ^ T1) & (src1 ^ T0); \
192 192 env->NZF = T0; \
  193 + res = T0; \
193 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 201 void OPPROTO op_andl_T0_T1(void)
201 202 {
... ... @@ -222,11 +223,16 @@ void OPPROTO op_notl_T1(void)
222 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 228 env->NZF = T0;
228 229 }
229 230  
  231 +void OPPROTO op_logic_T1_cc(void)
  232 +{
  233 + env->NZF = T1;
  234 +}
  235 +
230 236 #define EIP (env->regs[15])
231 237  
232 238 void OPPROTO op_test_eq(void)
... ... @@ -334,10 +340,7 @@ void OPPROTO op_jmp(void)
334 340  
335 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 346 /* NOTE: N = 1 and Z = 1 cannot be stored currently */
... ...
translate-arm.c
... ... @@ -34,6 +34,8 @@ typedef struct DisasContext {
34 34 struct TranslationBlock *tb;
35 35 } DisasContext;
36 36  
  37 +#define DISAS_JUMP_NEXT 4
  38 +
37 39 /* XXX: move that elsewhere */
38 40 static uint16_t *gen_opc_ptr;
39 41 static uint32_t *gen_opparam_ptr;
... ... @@ -333,10 +335,11 @@ static void disas_arm_insn(DisasContext *s)
333 335 /* if not always execute, we generate a conditional jump to
334 336 next instruction */
335 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 343 int set_cc, logic_cc, shiftop;
341 344  
342 345 op1 = (insn >> 21) & 0xf;
... ... @@ -367,7 +370,7 @@ static void disas_arm_insn(DisasContext *s)
367 370 }
368 371 }
369 372 } else {
370   - rs = (insn >> 16) & 0xf;
  373 + rs = (insn >> 8) & 0xf;
371 374 gen_movl_T0_reg(s, rs);
372 375 if (logic_cc) {
373 376 gen_shift_T1_T0_cc[shiftop]();
... ... @@ -385,10 +388,14 @@ static void disas_arm_insn(DisasContext *s)
385 388 case 0x00:
386 389 gen_op_andl_T0_T1();
387 390 gen_movl_reg_T0(s, rd);
  391 + if (logic_cc)
  392 + gen_op_logic_T0_cc();
388 393 break;
389 394 case 0x01:
390 395 gen_op_xorl_T0_T1();
391 396 gen_movl_reg_T0(s, rd);
  397 + if (logic_cc)
  398 + gen_op_logic_T0_cc();
392 399 break;
393 400 case 0x02:
394 401 if (set_cc)
... ... @@ -435,11 +442,13 @@ static void disas_arm_insn(DisasContext *s)
435 442 case 0x08:
436 443 if (set_cc) {
437 444 gen_op_andl_T0_T1();
  445 + gen_op_logic_T0_cc();
438 446 }
439 447 break;
440 448 case 0x09:
441 449 if (set_cc) {
442 450 gen_op_xorl_T0_T1();
  451 + gen_op_logic_T0_cc();
443 452 }
444 453 break;
445 454 case 0x0a:
... ... @@ -455,22 +464,28 @@ static void disas_arm_insn(DisasContext *s)
455 464 case 0x0c:
456 465 gen_op_orl_T0_T1();
457 466 gen_movl_reg_T0(s, rd);
  467 + if (logic_cc)
  468 + gen_op_logic_T0_cc();
458 469 break;
459 470 case 0x0d:
460 471 gen_movl_reg_T1(s, rd);
  472 + if (logic_cc)
  473 + gen_op_logic_T1_cc();
461 474 break;
462 475 case 0x0e:
463 476 gen_op_bicl_T0_T1();
464 477 gen_movl_reg_T0(s, rd);
  478 + if (logic_cc)
  479 + gen_op_logic_T0_cc();
465 480 break;
466 481 default:
467 482 case 0x0f:
468 483 gen_op_notl_T1();
469 484 gen_movl_reg_T1(s, rd);
  485 + if (logic_cc)
  486 + gen_op_logic_T1_cc();
470 487 break;
471 488 }
472   - if (logic_cc)
473   - gen_op_logic_cc();
474 489 } else {
475 490 /* other instructions */
476 491 op1 = (insn >> 24) & 0xf;
... ... @@ -494,7 +509,7 @@ static void disas_arm_insn(DisasContext *s)
494 509 gen_op_addl_T0_T1();
495 510 }
496 511 if (insn & (1 << 20))
497   - gen_op_logic_cc();
  512 + gen_op_logic_T0_cc();
498 513 gen_movl_reg_T0(s, rd);
499 514 } else {
500 515 /* 64 bit mul */
... ... @@ -551,10 +566,12 @@ static void disas_arm_insn(DisasContext *s)
551 566 /* store */
552 567 gen_op_stw_T0_T1();
553 568 }
554   - if (!(insn & (1 << 24)))
  569 + if (!(insn & (1 << 24))) {
555 570 gen_add_datah_offset(s, insn);
556   - if (insn & (1 << 21))
557 571 gen_movl_reg_T1(s, rn);
  572 + } else if (insn & (1 << 21)) {
  573 + gen_movl_reg_T1(s, rn);
  574 + }
558 575 }
559 576 break;
560 577 case 0x4:
... ... @@ -582,40 +599,94 @@ static void disas_arm_insn(DisasContext *s)
582 599 else
583 600 gen_op_stl_T0_T1();
584 601 }
585   - if (!(insn & (1 << 24)))
  602 + if (!(insn & (1 << 24))) {
586 603 gen_add_data_offset(s, insn);
587   - if (insn & (1 << 21))
588 604 gen_movl_reg_T1(s, rn);
  605 + } else if (insn & (1 << 21))
  606 + gen_movl_reg_T1(s, rn); {
  607 + }
589 608 break;
590 609 case 0x08:
591 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 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 690 break;
620 691 case 0xa:
621 692 case 0xb:
... ... @@ -641,6 +712,66 @@ static void disas_arm_insn(DisasContext *s)
641 712 gen_op_swi();
642 713 s->is_jmp = DISAS_JUMP;
643 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 775 default:
645 776 illegal_op:
646 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 819 disas_arm_insn(dc);
689 820 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
690 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 829 /* indicate that the hash table must be used to find the next TB */
699 830 gen_op_movl_T0_0();
  831 + break;
  832 + case DISAS_TB_JUMP:
  833 + /* nothing more to generate */
  834 + break;
700 835 }
701 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 891 else
757 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 }
... ...