qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] ARM load/store multiple bug
@ 2006-09-09 22:19 Justin Fletcher
  2006-09-09 23:43 ` Paul Brook
  0 siblings, 1 reply; 5+ messages in thread
From: Justin Fletcher @ 2006-09-09 22:19 UTC (permalink / raw)
  To: qemu-devel

Hiya,

I have found a bug in the implementation of the load/store multiple 
instructions in ARM (LDM and STM). These are defined in the ARM ARM to 
ignore bits 0 and 1 of the address when the load takes place - that is the 
base register for these operations is always treated as a 32bit aligned 
value (although its value is only rounded internally). This differs from 
the LDR/STR operation which uses the full width of instructions.

In other words :

    MOV   r0, #9
    LDMIA r0, {r1,r2}

Is equivalent to loading r1 with the value at 8, and r2 with the value at 
12. Contrast this with the following :

    MOV   r0, #9
    LDR   r1, [r0]
    LDR   r2, [r0,#4]

which would load r1 with the value at 8, rotated right 8 bits, and r2 with 
the value at 12, rotated right 8 bits.

I have not confirmed the behaviour or the LDR operation, but have found 
problems with the multiple register operations. My solution would be to 
add the equivalent of a BIC instruction in to the target-arm/translate.c 
to clear off the bottom two bits, around line 1695 :

---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<---

However, there isn't any such function and I'm unsure how to make that 
change. Any suggestions would be greatfully received.

-- 
Gerph <http://gerph.org/>
... Find answers on the street, in cracks beneath my feet.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] ARM load/store multiple bug
  2006-09-09 22:19 [Qemu-devel] ARM load/store multiple bug Justin Fletcher
@ 2006-09-09 23:43 ` Paul Brook
  2006-09-10 10:43   ` Justin Fletcher
  0 siblings, 1 reply; 5+ messages in thread
From: Paul Brook @ 2006-09-09 23:43 UTC (permalink / raw)
  To: qemu-devel

> ---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.

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.

Paul

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] ARM load/store multiple bug
  2006-09-09 23:43 ` Paul Brook
@ 2006-09-10 10:43   ` Justin Fletcher
  2006-09-10 16:46     ` Fabrice Bellard
  0 siblings, 1 reply; 5+ messages in thread
From: Justin Fletcher @ 2006-09-10 10:43 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

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.

-- 
Gerph <http://gerph.org/>
... Hand to mouth, we're picking up the thread

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] ARM load/store multiple bug
  2006-09-10 10:43   ` Justin Fletcher
@ 2006-09-10 16:46     ` Fabrice Bellard
  2006-09-10 17:15       ` Paul Brook
  0 siblings, 1 reply; 5+ messages in thread
From: Fabrice Bellard @ 2006-09-10 16:46 UTC (permalink / raw)
  To: qemu-devel

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.
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] ARM load/store multiple bug
  2006-09-10 16:46     ` Fabrice Bellard
@ 2006-09-10 17:15       ` Paul Brook
  0 siblings, 0 replies; 5+ messages in thread
From: Paul Brook @ 2006-09-10 17:15 UTC (permalink / raw)
  To: qemu-devel

On Sunday 10 September 2006 17:46, Fabrice Bellard wrote:
> 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().

I think additional bits will be required. The behavior of unaligned accesses 
depends on the instruction performing the access.

Paul

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-09-10 17:15 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-09 22:19 [Qemu-devel] ARM load/store multiple bug Justin Fletcher
2006-09-09 23:43 ` Paul Brook
2006-09-10 10:43   ` Justin Fletcher
2006-09-10 16:46     ` Fabrice Bellard
2006-09-10 17:15       ` Paul Brook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).