Sunday, April 28, 2013

I was looking into the problem Tursi reported where the link register is not properly restored. The issue here is that a few earlier improvements are combining to cause this. An earlier change was to merge modifications of the stack pointer in an effort to improve performance. Another one was to make R11 be a volatile register, whose value will be destroyed after a function call. The problem here is that since the example program uses stack space, but only needs to restore R11, an instruction like "mov *r10, r11" was issued. The dead code elimination pass saw this as a useless instruction, since R11 seemed to have no further use, and the stack pointer in R10 was not changed.

Here's what I'm talking about:

        bl   @puts
        mov  *r10, r11  # Instruction deemed unnecessary and deleted by DCE pass
        ai   r10, >6
        b    *r11

The fix here was to modify the invocation of the UNSPEC_RETURN instruction to use R11 as an input. This causes the dead code elimination pass to see that "mov *r10, r11" serves a useful purpose and is not to be removed. One bug down...

In other news, I've confirmed that the -ffunction-sections and -fdata-sections options work, as well as the section attribute. All this confirms that named section suppport is working as intended. The elf2card and elf2ea5 tools won't do anything with them, but I assume that linker files will be used to combine them into the standard .text .data and .bss sections.

The final bug is clearing a memory byte. Tursi is working on hardware which is uses write-only registers. The problem for him is that code like:
    *(volatile char*)0x9c02 = 0

results in an instruction like:
    sb @>9c02, @9c02

If the destination lies in RAM, this is fine. But write-only hardware could potentially return different values for each of the two memory fetches. In this case, it would be more appropriate to use something like this:
    clr r0
    movb r0, @>9c02

This is the same number of code bytes (6), and only a few cycles slower. Not too bad. Fixing this is really easy too. There was a mode for that instruction to specifically permit directly setting memory to zero. By removing that permission, everything works as intended.

No comments:

Post a Comment