qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] ARM load/store multiple bug


From: Fabrice Bellard
Subject: Re: [Qemu-devel] ARM load/store multiple bug
Date: Sun, 10 Sep 2006 18:46:21 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040913

Note that QEMU supports specific unaligned access handling when using the softmmu code. It is possible to implement the ARM specific unaligned accesses without slowing down the aligned case. See the mips case with do_unaligned_access().

Regards,

Fabrice.

Justin Fletcher wrote:
On Sun, 10 Sep 2006, Paul Brook wrote:

---8<---
                         if (n != 1)
                             gen_op_addl_T1_im(-((n - 1) * 4));
                     }
                 }
                 j = 0;
/* Insert something like gen_op_bicl_T1_im(3); here */
                 for(i=0;i<16;i++) {
                     if (insn & (1 << i)) {
                         if (insn & (1 << 20)) {
---8<---


This is not sufficient. It breaks base register writeback.


Doh! Of course, yes.

I'll also note that the behavior is dependent on alignment traps being
disabled (and unaligned access on some cores). ie. for linux user mode
emulation the current behavior is acceptable.


Fair enough; it fails badly on some of the code in the OS I'm running on it. With a bit of looking around I decided the easiest way to do the operation and maintain the compatibility with the writeback was to introduce a pair of new operations for load and store, forced to aligned addresses. This is NOT, as you note, ideal because it moves the problem of the alignment checks and should probably be done better - I don't know the code well enough, I'm afraid, to know the right or best way to do it.

My solution is to add new operations to target-arm/op_mem.h :

----8<----
/* Load from aligned address T1 into T0 (used for LDM) */
#define MEM_LDA_OP(name) \
void OPPROTO glue(op_lda##name,MEMSUFFIX)(void) \
{ \
    /* JRF: Note should raise alignment fault if alignment in use and \
            b0 or b1 set */ \
    T0 = glue(ld##name,MEMSUFFIX)(T1 &~3); \
    FORCE_RET(); \
}
MEM_LDA_OP(l)

#undef MEM_LDA_OP

/* Store aligned address T0 into T1 (used for STM) */
#define MEM_STA_OP(name) \
void OPPROTO glue(op_sta##name,MEMSUFFIX)(void) \
{ \
    /* JRF: Note should raise alignment fault if alignment in use and \
            b0 or b1 set */ \
    glue(st##name,MEMSUFFIX)(T1 &~3, T0); \
    FORCE_RET(); \
}
MEM_STA_OP(l)

#undef MEM_STA_OP
----8<----

And to replace the load and store operations in the LDM/STM implementation in target-arm/translate.c to use these, eg :

       if (insn & (1 << 20)) {
         /* load */
         gen_ldst(ldal, s); /* JRF: was ldl */
         if (i == 15)

and :

           gen_movl_T0_reg(s, i);
         }
         gen_ldst(stal, s); /* JRF: was stl */
       }
       j++;

I realise that these are not good for the generic use, but they solve my problems and it may solve other people's if they happen to be using a similarly constructed OS.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]