Hello SDCC-users,

  While working on the contiki OS, I found a strange behavior in SDCC.  I noticed when a variable was cast as (void *) the generated code differed than if cast as (u8_t*). 

Here is the example demonstrating the issue:



memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);

vs

memset((u8_t *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);





                           1600 ;       ../../core/net/uip-nd6-io.c:344: memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);

The problem/differences comes at 1610 when indexing into nd6_opt_llao to reach addr.  In the (void *) version 0x02 is added, ignoring the addition of UIP_LLADDR_LEN.

   05A9 90s00r01           1601         mov     dptr,#_nd6_opt_llao
   05AC E0                 1602         movx    a,@dptr
   05AD FA                 1603         mov     r2,a
   05AE A3                 1604         inc     dptr
   05AF E0                 1605         movx    a,@dptr
   05B0 FB                 1606         mov     r3,a
   05B1 A3                 1607         inc     dptr
   05B2 E0                 1608         movx    a,@dptr
   05B3 FC                 1609         mov     r4,a
   05B4 74 02              1610         mov     a,#0x02
   05B6 2A                 1611         add     a,r2
   05B7 FA                 1612         mov     r2,a
   05B8 E4                 1613         clr     a
   05B9 3B                 1614         addc    a,r3
   05BA FB                 1615         mov     r3,a
   05BB 74 06              1616         mov     a,#0x06
   05BD C0 E0              1617         push    acc
   05BF E4                 1618         clr     a
   05C0 C0 E0              1619         push    acc
   05C2 E4                 1620         clr     a
   05C3 C0 E0              1621         push    acc
   05C5 8A 82              1622         mov     dpl,r2
   05C7 8B 83              1623         mov     dph,r3
   05C9 8C F0              1624         mov     b,r4
   05CB 12s00r00           1625         lcall   _memset

In the (u8_t *) version the correct offset for addr of 10 is used:

                           1600 ;       ../../core/net/uip-nd6-io.c:344: memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);
   05A9 90s00r01           1601         mov     dptr,#_nd6_opt_llao
   05AC E0                 1602         movx    a,@dptr
   05AD FA                 1603         mov     r2,a
   05AE A3                 1604         inc     dptr
   05AF E0                 1605         movx    a,@dptr
   05B0 FB                 1606         mov     r3,a
   05B1 A3                 1607         inc     dptr
   05B2 E0                 1608         movx    a,@dptr
   05B3 FC                 1609         mov     r4,a
   05B4 74 0A              1610         mov     a,#0x0A
   05B6 2A                 1611         add     a,r2
   05B7 FA                 1612         mov     r2,a
   05B8 E4                 1613         clr     a
   05B9 3B                 1614         addc    a,r3
   05BA FB                 1615         mov     r3,a
   05BB 74 06              1616         mov     a,#0x06
   05BD C0 E0              1617         push    acc
   05BF E4                 1618         clr     a
   05C0 C0 E0              1619         push    acc
   05C2 E4                 1620         clr     a
   05C3 C0 E0              1621         push    acc
   05C5 8A 82              1622         mov     dpl,r2
   05C7 8B 83              1623         mov     dph,r3
   05C9 8C F0              1624         mov     b,r4
   05CB 12s00r00           1625         lcall   _memset



I submitted a bug tracker report with the following example program:

#include <string.h>
#define UIP_LLADDR_LEN 8

struct uip_802154_longaddr {
  unsigned char addr[8];
};
typedef struct uip_802154_longaddr uip_lladdr_t;

struct uip_nd6_opt_llao {
  unsigned char type;
  unsigned char len;
  uip_lladdr_t addr;
};

static struct uip_nd6_opt_llao *nd6_opt_llao;


void main (void)
{
  unsigned char buf[300];
  nd6_opt_llao = (struct uip_nd6_opt_llao *)buf;
  memset((unsigned char *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, 6);
}