On 10/21/2009 07:25 AM, Mohamed Shafi wrote:
For accessing a->b GCC generates the following code:
move.l (sp-16), d3
lsrr.l #<16, d3
move.l (sp-12),d2
asll #<16,d2
or d3,d2
cmpeq.w #<2,d2
jf _L2
Because data registers are 40 bit for 'asll' operation the shift count
should be 16+8 or there should be sign extension from 32bit to 40 bits
after the 'or' operation. The target has instruction to sign extend
from 32bit to 40 bit.
Similarly there are other operation that requires sign/zero extension.
So is there any way to tell GCC that the data registers are 40bit and
there by expect it to generate sign/zero extension accordingly ?
Define a machine mode for your 40-bit type in cpu-modes.def. Depending
on how your 40-bit type is stored in memory, you'll use either
INT_MODE (RI, 5) // load-store uses exactly 5 bytes
FRACTIONAL_INT_MODE (RI, 40, 8) // load-store uses 8 bytes
Where I've arbitrarily chosen "RImode" as a mnemonic for Register
Integral Mode. Now you define arithmetic operations, as needed, on
RImode. You define the "extendsiri" pattern to be that sign-extend from
32-to-40-bit instruction. You define your comparison patterns on
RImode, and not on SImode, since your comparison instruction works on
the entire 40 bits.
You'll wind up with a selection of patterns in your machine description
that have a sign-extension pattern built in, depending on the exact
behaviour of your ISA. There are plenty of examples on x86_64, mips64,
and Alpha (to name a few) that have similar properties with SI and
DImodes. Examine the -fdump-rtl-combine-details dump for exemplars of
the canonical forms that the combiner creates when it tries to merge
sign-extension instructions into preceeding patterns.
r~