Bluebie/micronucleus-t85 — pull request #30 by cpldcpu (2013-10-06 23:37:19+00:00)
Title: Major size reduction without any change in functionality

Hi,

I spent some time with the disassembly of micronucleus and found several opportunities to optimized the code density without changing the functionality. In total I managed to reduce the binary size by 70 bytes to 2086 bytes in total.

I submitted all modifications seperately, so please make sure to review them individually. You probably have better testing capabilities than I do.

1)	Use a local pointer in eraseApplicatoin() - saves 18 Bytes

2)	A single write is sufficient to invalidate magic word - saves 4 bytes. This may be a bit controversial, but it is obvious that the magic word only has to be altered, not be completely removed to invalidate.

3) Use old delay routines without NOP padding. This saves 16 bytes.

4)	Do modulo only on lower byte - saves 24 bytes

GCC generated some quite weird code from the modulo operations. Although highly optimized, most of the instructions are redundant. Is this a bug? The current solution is a bit hacky, but should also work when the page
size is changed in future devices.

Old code:

```assembler
uchar isLast = (((currentAddress&0xff) % SPM_PAGESIZE) == 0);
1e02: 80 91 69 00 lds r24, 0x0069
1e06: 90 91 6a 00 lds r25, 0x006A <-- redundant
1e0a: 8f 73 andi r24, 0x3F ; 63 <-- set Z flag if modulo==0
1e0c: 99 27 eor r25, r25 <-- redundant: clear R25 and Z flag
// definitely need this if! seems usbFunctionWrite gets called again in
future usbPoll's in the runloop!
if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our
page
1e0e: 89 2b or r24, r25 <--- redundant: set Z flag properly again
1e10: 39 f0 breq .+14 ; 0x1e20
1e12: 0d c0 rjmp .+26 ; 0x1e2e
```
New code:

```assembler
1dfa:	80 91 69 00	lds	r24, 0x0069
uchar isLast = ((currentAddress % SPM_PAGESIZE) == 0);

if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page
1dfe:	8f 73	andi	r24, 0x3F	; 63
1e00:	39 f0	breq	.+14	; 0x1e10
1e02:	0d c0	rjmp	.+26	; 0x1e1e
```

5)	Reduce accesses to global variable idlePolls, saves 8 bytes. Global variables cost a lot of space due to direct SRAM access.

There are a lot more places where more "free" bytes can be found. I may continue working on this.