[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