There isn't a general programming subforum so it'll have to do here! I'm coding for the Genesis anyway so close enough So far I've been gathering a game framework in small pieces, and it's nearly time to put them together to make a complete game, but this has been bothering me: I can't find good examples of function calling conventions. So far I've just been winging it, passing parameters via registers and backing then up when necessary, but it's not going to work well when the code gets complex. My two questions: 1. Should I settle on an "all round solution" to passing function parameters to a subroutine? Should they all go via the stack, or via registers, a mixture of both? 2. How should I back up registers before branching to a subroutine? Should it be done before the jump or after, and should I back up the lot or is it really important to be selective about backing up only the ones used? It probably helps to say I have no idea how fast this CPU is and how much damage I can cause to performance by not being very picky about each individual case; which is what I've been doing so far, but it's very time consuming and prone to errors. Obviously in cases that show up as bottlenecks I would dive in and make some custom arrangements. This is the last thing on my checklist that needs settling on before starting the big work, since it's a right royal mess to change once I've started. So, how was it done back in the day?
The usual convention for 68000 cpu is to always pass parameters on stack. That may become a problem for a function you call hundreds or thousands time per frame. Even worst GCC always pass parameters as long word (32 bits) on stack even for word and byte parameters, SP has to be aligned on word so we could expect word for byte but not long word for simple word. About the save registers convention, normally a function have to save all modified registers but D0,D1 and A0,A1. D0,D1 and A0,A1 are considered as "free" registers, D0 is used to return function result if any. If you don't plan to mix C and ASM i suggest you to use registers to pass arguments and you can define your own "registers convention"
Awesome, cheers for the advice! I'm going to try writing a few macros to backup various registers and play around with mixing some of my code together to see what kind of issues I run into. I've already had big problems with trashed registers when returning from a function, usually because of child functions that I hadn't taken into account, so this is becoming a problem even very early on. Maybe it just gets better with practice, assembly is still quite new to me despite having a full game framework written!
The usual method when you write a function in assembly is to start by saving all registers you will modify and restore them before returning to the caller, this way the caller doesn't have to care or even know what you do in the function, also this is generally the optimal way for registers preservation As i told you can consider A0,A1 and D0,D1 as free register, this way a short method does not necessary need to save registers (if it uses only D0,D1 and A0,A1), of course the caller then need to consider than registers D0,D1 and A0,A1 are lost when it calls a function...
That makes a lot of sense, I like the idea of the "free" registers. I'll see what I can come up with.
I use registers to pass parameters and any register than I use as a parameter will be used by a scratch reg in the call. D0, D1 and D2 are always trashable in my stuff, so are A0 and A1. A6 is reserved for return address of very frequently called routines, A5 for quick VDP access. Rest is up for grabs