One GCC example:
C-source
Code:
void * copy_32x4a(void *destparam, const void *srcparam, size_t size)
{
int *dest = destparam;
const int *src = srcparam;
int size32;
size32 = size / 16;
for (; size32; size32--) {
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
}
}
Compile option:
m68k-linux-gnu-gcc -mcpu=54455 -msoft-float -o example -Os -fomit-frame-pointer example.c
We use -Os to focus on compact code.
Generated code:
Code:
04: 202f 000c movel %sp@(12),%d0
08: 226f 0004 moveal %sp@(4),%a1
0c: 206f 0008 moveal %sp@(8),%a0
10: e888 lsrl #4,%d0
12: 6022 bras 36
14: 2290 movel %a0@,%a1@
16: 2368 0004 0004 movel %a0@(4),%a1@(4)
1c: 2368 0008 0008 movel %a0@(8),%a1@(8)
22: 2368 000c 000c movel %a0@(12),%a1@(12)
28: d3fc 0000 0010 addal #16,%a1
2e: d1fc 0000 0010 addal #16,%a0
34: 5380 subql #1,%d0
36: 4a80 tstl %d0
38: 66da bnes 14
3a: 4e75 rts
Code length produced by GCC = 56 Byte
Length of workloop = 9 instructions , 38 Byte
Expected code:
Code:
04: 202f 000c movel %sp@(12),%d0
08: 226f 0004 moveal %sp@(4),%a1
0c: 206f 0008 moveal %sp@(8),%a0
10: e888 lsrl #4,%d0
12: 6022 beq 20
14: 20d9 movel %a1@+,%a0@+
16: 20d9 movel %a1@+,%a0@+
18: 20d9 movel %a1@+,%a0@+
1a: 20d9 movel %a1@+,%a0@+
1c: 5380 subql #1,%d0
1e: 66da bnes 14
20: 4e75 rts
Expected code length = 30 Byte
Length of workloop = 6 instructions , 12 Byte
Issue 1:
Why does GCC not use the ConditionCodes already set by the 68k instruction but generates a unneeded
test.l?
Issue 2:
Why does GCC not use the much more efficient
(an)+ adressing mode but uses instead
d(an) mode plus an extra add instrcution ?
The (Ad)+,(Am)+ instruction is 2 Bytes instead of 6 Bytes.
And (Ad)+,(Am)+ does not need the extra two instructions to increment the pointers.
Issue 3:
Assuming that GCC decided to increment a pointer manually.
Why does GCC use addil to increment a pointer?
LEA should be the better choice for this as its 2 bytes shorter than addi.l