[Bug c/60918] New: [mips] unaligned memory copy with LWL/LWR
Alex.Schoenberger at ies dot tu-darmstadt.de
gcc-bugzilla@gcc.gnu.org
Tue Apr 22 09:09:00 GMT 2014
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60918
Bug ID: 60918
Summary: [mips] unaligned memory copy with LWL/LWR
Product: gcc
Version: 4.8.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: Alex.Schoenberger at ies dot tu-darmstadt.de
* GCC configuration:
--with-newlib --without-headers \
--enable-multilib --disable-werror \
--enable-languages="c" \
--disable-shared \
--disable-nls --disable-threads --disable-hosted-libstdcxx --disable-libssp \
--target=mips-elf --prefix=$PATH_TO_MIPS --with-gnu-ld --with-gnu-as \
--with-mprf=$PATH_TO_MIPS --with-gmp=$PATH_TO_MIPS --with-mpc=$PATH_TO_MIPS
* GCC call flags:
-EB -O2 -Wall -mips1 -c -s -msoft-float
* no error messages
* source code consists of two files. The generated assemling code differs if
I compose them
* mem.c - implementation of copy memory:
void * memcpy( void * destination, const void * source, int num ){
while(num){
--num;
((unsigned char *)destination)[num] = ((unsigned char *)source)[num];
}
return destination;
}
* error.c - call of memcpy
#include "mem.h"
typedef struct {
unsigned int field;
} struct_t;
int main()
{
unsigned int * address = (unsigned int *) 0x123c;
struct_t * var1 = (struct_t *) address[0]; // this emulates malloc ->
unknown return address
struct_t * var2 = (struct_t *) address[1];
var1->field = 0x12345678;
memcpy( var2, var1, sizeof(struct_t));
return 0;
}
* generated assembler code, compiler replaces "memcpy"-call with LWL/LWR
instructions:
Disassembly of section .text:
00000000 <.text>:
0: 8c04123c lw a0,4668(zero)
4: 3c021234 lui v0,0x1234
8: 24425678 addiu v0,v0,22136
c: 8c031240 lw v1,4672(zero)
10: ac820000 sw v0,0(a0)
14: 88850000 lwl a1,0(a0) -> first access: LWL command
18: 00001021 move v0,zero
1c: 98850003 lwr a1,3(a0) -> second access: LWR command
20: 00000000 nop
24: a8650000 swl a1,0(v1) -> for store operation the same procedure
28: 03e00008 jr ra
2c: b8650003 swr a1,3(v1) -> second store command
30: 10c00007 beqz a2,0x50 -> here "memcpy" starts
34: 00801021 move v0,a0
38: 24c6ffff addiu a2,a2,-1
3c: 00a61821 addu v1,a1,a2
40: 90670000 lbu a3,0(v1)
44: 00461821 addu v1,v0,a2
48: 14c0fffb bnez a2,0x38
4c: a0670000 sb a3,0(v1)
50: 03e00008 jr ra
54: 00000000 nop
* this leads to erronous run:
if my memory (big endian) content is:
@address: 11 22 33 44 55 66 77 88
lets assume "a1" contains zero in the beginning
lwl a1, 0(a0) -> a1 = 0x11220000
lwr a1, 3(a0) -> a1 = 0x11226677
the memory content is copied erronous, values 33[3(a0)], 44[4(a0)] and
55[5(a0)] are ignored
More information about the Gcc-bugs
mailing list