m32c-elf-gcc -mcpu=m32c (16 bit ints, 24 bit pointers) miscompiles
this:

int *foo (int *a, int b)
{
  return a-b;
}

as this:

_foo:
        enter   #0              ; 30    prologue_enter_24
        pushm   r1,r3,a0        ; 31    pushm
        ; end of prologue       ; 32    prologue_end
        mov.w   12[fb],r0       ; 27    movhi_op/1
        sha.w   #1,r0           ; 7     ashlhi3_i/1
        neg.w   r0              ; 8     neghi2/1
        mov.w   r0,a0           ; 10    zero_extendhipsi2
        mov.l   8[fb],r3r1      ; 28    movpsi_op/2
        add.l   a0,r3r1         ; 16    addpsi3/3
        mov.l   r3r1,mem0       ; 29    movpsi_op/2
        ; start of epilogue     ; 35    epilogue_start
        popm    r1,r3,a0        ; 36    popm
        exitd                   ; 37    epilogue_exitd_24

The key instructions are - neg, zero_extend, add.  This breaks if the
original value is, say, 2.  Neg gives 0xfffe, zero_extend gives
0x00fffe, and you end up adding 65534 to the pointer.

If I change sizetype to "long unsigned int", it's bigger than a
pointer, and the front end leaves an unexpected nop_convert in various
expressions, which causes ICEs.

There is no standard integer type the same size as pointers (24 bit,
PSImode).  IIRC, last time I tried to shoehorn in a PSImode sizetype,
gcc wanted a full set of math operators for it, which the chip doesn't
have (they have to be done in HI or SI mode)

I tried making sizetype signed, that ICEd too.

What's the right thing to do?

If the front end either sign extended, or had a POINTER_MINUS_EXPR,
things would just work.

DJ

Reply via email to