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