Now sending the attachment. :) Lauro
On Thu, 2007-03-15 at 16:35 -0300, Lauro Ramos Venancio wrote: > Qemu-arm is wrongly executing post-indexed loads when Rm and Rd are > the same register. For example: > > ldr r0, [r1], +r0 > > Current behavior: > r0 <- [r1] > r1 <- r1 + r0 > > Expected behavior: > addr <- r1 > r1 <- r1 + r0 > r0 <- [addr] > > The attached patch fixes this bug. Patched by me and Rodrigo Vivi. > This patch was made based on qemu 0.9. > > > Lauro Venancio
--- target-arm/op.c.orig 2007-03-09 18:40:02.000000000 -0300 +++ target-arm/op.c 2007-03-09 18:40:27.000000000 -0300 @@ -106,6 +106,11 @@ void OPPROTO op_movl_T0_T1(void) T0 = T1; } +void OPPROTO op_movl_T1_T0(void) +{ + T1 = T0; +} + void OPPROTO op_movl_T1_im(void) { T1 = PARAM1; --- target-arm/translate.c.orig 2007-03-09 18:40:02.000000000 -0300 +++ target-arm/translate.c 2007-03-09 18:40:32.000000000 -0300 @@ -383,23 +383,19 @@ static inline void gen_add_data_offset(D } } -static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, - int extra) +static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn) { int val, rm; if (insn & (1 << 22)) { /* immediate */ val = (insn & 0xf) | ((insn >> 4) & 0xf0); - val += extra; if (!(insn & (1 << 23))) val = -val; if (val != 0) gen_op_addl_T1_im(val); } else { /* register */ - if (extra) - gen_op_addl_T1_im(extra); rm = (insn) & 0xf; gen_movl_T2_reg(s, rm); if (!(insn & (1 << 23))) @@ -1534,14 +1530,17 @@ static void disas_arm_insn(CPUState * en } } } else { - int address_offset; /* Misc load/store */ rn = (insn >> 16) & 0xf; rd = (insn >> 12) & 0xf; gen_movl_T1_reg(s, rn); - if (insn & (1 << 24)) - gen_add_datah_offset(s, insn, 0); - address_offset = 0; + gen_movl_T0_reg(s, rn); + gen_add_datah_offset(s, insn); + /* writeback */ + if (!(insn & (1 << 24))||(insn & (1 << 21))) + gen_movl_reg_T1(s, rn); + if (!(insn & (1 << 24))) /* pos-indexed */ + gen_op_movl_T1_T0(); if (insn & (1 << 20)) { /* load */ switch(sh) { @@ -1574,20 +1573,11 @@ static void disas_arm_insn(CPUState * en gen_ldst(ldl, s); gen_movl_reg_T0(s, rd + 1); } - address_offset = -4; } else { /* store */ gen_movl_T0_reg(s, rd); gen_ldst(stw, s); } - if (!(insn & (1 << 24))) { - gen_add_datah_offset(s, insn, address_offset); - gen_movl_reg_T1(s, rn); - } else if (insn & (1 << 21)) { - if (address_offset) - gen_op_addl_T1_im(address_offset); - gen_movl_reg_T1(s, rn); - } } break; case 0x4: @@ -1607,9 +1597,14 @@ static void disas_arm_insn(CPUState * en rn = (insn >> 16) & 0xf; rd = (insn >> 12) & 0xf; gen_movl_T1_reg(s, rn); + gen_movl_T0_reg(s, rn); i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000); - if (insn & (1 << 24)) gen_add_data_offset(s, insn); + /* writeback */ + if (!(insn & (1 << 24))||(insn & (1 << 21))) + gen_movl_reg_T1(s, rn); + if (!(insn & (1 << 24))) /* pos-indexed */ + gen_op_movl_T1_T0(); if (insn & (1 << 20)) { /* load */ #if defined(CONFIG_USER_ONLY) @@ -1656,12 +1651,6 @@ static void disas_arm_insn(CPUState * en } #endif } - if (!(insn & (1 << 24))) { - gen_add_data_offset(s, insn); - gen_movl_reg_T1(s, rn); - } else if (insn & (1 << 21)) - gen_movl_reg_T1(s, rn); { - } break; case 0x08: case 0x09:
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel