|
From: Borja F. <bor...@gm...> - 2010-09-28 20:56:26
|
I've just finished fixing the register calling convention. I had a huge TODO
in my code to handle passing chars in even registers and returning a char in
R24. I couldnt use the typical approach of using the Tablegen code to define
the calling convention because wide arguments are splitted into i8 pieces
making LLVM treat all args as chars so there was no easy way of knowing the
real size of each arg. I had to write it down in C++ code to check the real
argument size and allocate the regs using AVR's ABI spec.
A piece of code to show it:
typedef int t;
t foo(t a, t b, char c, int d)
{
return a+b+d;
}
foo: # @foo
.ent foo
# BB#0: # %entry
add r22, r18
adc r23, r19
adc r24, r20
adc r25, r21
add r22, r12
adc r23, r13
adc r24, r14
adc r25, r15
ret
GCC generated this:
120: cf 92 push r12
122: df 92 push r13
124: ef 92 push r14
126: ff 92 push r15
return (a + b +d);
128: 26 0f add r18, r22
12a: 37 1f adc r19, r23
12c: 48 1f adc r20, r24
12e: 59 1f adc r21, r25
130: 2c 0d add r18, r12
132: 3d 1d adc r19, r13
134: 4e 1d adc r20, r14
136: 5f 1d adc r21, r15
138: b9 01 movw r22, r18
13a: ca 01 movw r24, r20
13c: ff 90 pop r15
13e: ef 90 pop r14
140: df 90 pop r13
142: cf 90 pop r12
144: 08 95 ret
Forget the fact that our code isnt saving regs into the stack, that's
currently unimplemented, but notice those two movws are totally redundant,
pretty funny.
LLVM's site states that the new version will get released tomorrow, so i'll
start porting my code once that is done.
|