I have been trying to build a home-brew B cross-compiler for my Ti-89 for a few months now, and am finally at the point at which I would like to generate assembly which my calculator executes. The language is 'B' in the sense that there is only 1 type which is the integer/pointer. I don't understand how to implement function pointers on this platform. I was considering implementing function pointers in the following ways:
- Storing the address of the first instruction using an immediate value
- Deriving the address of the first instruction using the program counter and an offset
- Storing just the offset and calculating the address of the first instruction when the jump is taken.
The first method definitely won't work since assembly programs on the Ti-89 are copied into RAM before being executed. I would have no way of knowing at compile time where the function would be located. Also, according to the Ti-89/Ti-92 Plus Developer Guide on page 24, "ASM programs may move during heap garbage collect. Pointers to overriding system code would become invalid." This would imply that the second method would not necessarily work either, since it is possible that heap garbage collection happens after the address of the first instruction is calculated. Assuming what it says about the program moving is correct, this could cause the entire function to move. The third method will work in specific cases, but the problem is I don't necessarily know where in the assembly program the function will be called. Thus I would need a different offset for each place the function could be called, and I have no way of calculating that offset as far as I know.
TIGCC allows for function pointers, so how the heck do they implement them? Is there something I'm missing?
Links:
- Ti-89/Ti-92 Developer Guide: https://tiplanet.org/modules/archives/downloads2/1446144333/sdk8992pguide.pdf
- TIGCC: http://tigcc.ticalc.org/doc/
- My project: https://github.com/been-jamming/TiBc
I followed the suggestion of @lurker. The assembly seems to just push the address onto the stack without much more info. From testing, if my function was named
my_functhen the assembly looks likemove.l #my_func,-4(%fp)which is just pushing the function pointer. I'm guessing the assembler converts it to pushing the immediate relative the PC, and not just the actual address within the binary. This would mean that I read the documentation I referenced earlier wrong. What I think it was trying to say is that you cannot refer to the addresses within the binary in memory, but you can refer to addresses within the temporary copy it puts in RAM. This would make more sense since the operating system wouldn't really be running in the background while the assembly program runs anyways. I have to assume that the garbage collection is something that can only happen after the program executes.