Commit 5fd46862e5232d1840a9353c99b163f11b49a035

Authored by pbrook
1 parent 214201bd

ARM register index+writeback fix (Lauro Ramos Venancio).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2481 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 21 additions and 6 deletions
target-arm/translate.c
@@ -1537,6 +1537,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -1537,6 +1537,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
1537 } 1537 }
1538 } else { 1538 } else {
1539 int address_offset; 1539 int address_offset;
  1540 + int load;
1540 /* Misc load/store */ 1541 /* Misc load/store */
1541 rn = (insn >> 16) & 0xf; 1542 rn = (insn >> 16) & 0xf;
1542 rd = (insn >> 12) & 0xf; 1543 rd = (insn >> 12) & 0xf;
@@ -1558,7 +1559,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -1558,7 +1559,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
1558 gen_ldst(ldsw, s); 1559 gen_ldst(ldsw, s);
1559 break; 1560 break;
1560 } 1561 }
1561 - gen_movl_reg_T0(s, rd); 1562 + load = 1;
1562 } else if (sh & 2) { 1563 } else if (sh & 2) {
1563 /* doubleword */ 1564 /* doubleword */
1564 if (sh & 1) { 1565 if (sh & 1) {
@@ -1568,20 +1569,27 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -1568,20 +1569,27 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
1568 gen_op_addl_T1_im(4); 1569 gen_op_addl_T1_im(4);
1569 gen_movl_T0_reg(s, rd + 1); 1570 gen_movl_T0_reg(s, rd + 1);
1570 gen_ldst(stl, s); 1571 gen_ldst(stl, s);
  1572 + load = 0;
1571 } else { 1573 } else {
1572 /* load */ 1574 /* load */
1573 gen_ldst(ldl, s); 1575 gen_ldst(ldl, s);
1574 gen_movl_reg_T0(s, rd); 1576 gen_movl_reg_T0(s, rd);
1575 gen_op_addl_T1_im(4); 1577 gen_op_addl_T1_im(4);
1576 gen_ldst(ldl, s); 1578 gen_ldst(ldl, s);
1577 - gen_movl_reg_T0(s, rd + 1); 1579 + rd++;
  1580 + load = 1;
1578 } 1581 }
1579 address_offset = -4; 1582 address_offset = -4;
1580 } else { 1583 } else {
1581 /* store */ 1584 /* store */
1582 gen_movl_T0_reg(s, rd); 1585 gen_movl_T0_reg(s, rd);
1583 gen_ldst(stw, s); 1586 gen_ldst(stw, s);
  1587 + load = 0;
1584 } 1588 }
  1589 + /* Perform base writeback before the loaded value to
  1590 + ensure correct behavior with overlapping index registers.
  1591 + ldrd with base writeback is is undefined if the
  1592 + destination and index registers overlap. */
1585 if (!(insn & (1 << 24))) { 1593 if (!(insn & (1 << 24))) {
1586 gen_add_datah_offset(s, insn, address_offset); 1594 gen_add_datah_offset(s, insn, address_offset);
1587 gen_movl_reg_T1(s, rn); 1595 gen_movl_reg_T1(s, rn);
@@ -1590,6 +1598,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -1590,6 +1598,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
1590 gen_op_addl_T1_im(address_offset); 1598 gen_op_addl_T1_im(address_offset);
1591 gen_movl_reg_T1(s, rn); 1599 gen_movl_reg_T1(s, rn);
1592 } 1600 }
  1601 + if (load) {
  1602 + /* Complete the load. */
  1603 + gen_movl_reg_T0(s, rd);
  1604 + }
1593 } 1605 }
1594 break; 1606 break;
1595 case 0x4: 1607 case 0x4:
@@ -1633,10 +1645,6 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -1633,10 +1645,6 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
1633 gen_op_ldl_kernel(); 1645 gen_op_ldl_kernel();
1634 } 1646 }
1635 #endif 1647 #endif
1636 - if (rd == 15)  
1637 - gen_bx(s);  
1638 - else  
1639 - gen_movl_reg_T0(s, rd);  
1640 } else { 1648 } else {
1641 /* store */ 1649 /* store */
1642 gen_movl_T0_reg(s, rd); 1650 gen_movl_T0_reg(s, rd);
@@ -1665,6 +1673,13 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -1665,6 +1673,13 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
1665 } else if (insn & (1 << 21)) 1673 } else if (insn & (1 << 21))
1666 gen_movl_reg_T1(s, rn); { 1674 gen_movl_reg_T1(s, rn); {
1667 } 1675 }
  1676 + if (insn & (1 << 20)) {
  1677 + /* Complete the load. */
  1678 + if (rd == 15)
  1679 + gen_bx(s);
  1680 + else
  1681 + gen_movl_reg_T0(s, rd);
  1682 + }
1668 break; 1683 break;
1669 case 0x08: 1684 case 0x08:
1670 case 0x09: 1685 case 0x09: