68000 assembly - subroutine calling conventions

Discussion in 'Sega Discussion' started by Headcrab, Jul 3, 2013.

  1. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    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?
     
  2. Stef

    Stef Member

    Joined:
    Nov 25, 2012
    Messages:
    22
    Likes Received:
    0
    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" :)
     
    Last edited: Jul 7, 2013
  3. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    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!
     
  4. Stef

    Stef Member

    Joined:
    Nov 25, 2012
    Messages:
    22
    Likes Received:
    0
    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...
     
    Last edited: Jul 10, 2013
  5. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    That makes a lot of sense, I like the idea of the "free" registers. I'll see what I can come up with.
     
  6. TmEE

    TmEE Peppy Member

    Joined:
    Aug 13, 2008
    Messages:
    362
    Likes Received:
    1
    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 :p
     

Share This Page