PS2 Calling Convention

Discussion in 'Sony Programming and Development' started by Anonamous, Apr 23, 2019.

  1. Anonamous

    Anonamous Member

    Joined:
    Jan 10, 2012
    Messages:
    14
    Likes Received:
    6
    Does anyone happen to either have, or know where I might find accurate and reliable information regarding the calling convention used by the ee-gcc?

    I have found this http://www.dcs.gla.ac.uk/~wpc/reports/compilers/compilerindex/PS2.pdf

    However some of the information there seems sort of... out there... For example it says that an 8 byte input parameter is split into two and passed in an even/odd pair of input registers (eg a0/a1 or a2/a3) but I don't see how this can be accurate as I know that integers get sign extended to 8 bytes.

    There seems to be a lot of conflicting information which makes it difficult to get it right for the ghidra emotion engine compiler specifications.
     
    Shademp likes this.
  2. sp193

    sp193 Site Soldier

    Joined:
    Mar 29, 2012
    Messages:
    2,232
    Likes Received:
    1,073
    It uses the standard MIPS calling convention. The EE is 64-bit, so the calling conventions on it are slightly different from the 32-bit IOP.
    The EE's GPRs are 128-bit, but GCC is generally made to treat them as 64-bit. The only instructions that can use the upper 64-bit halves are MMI.

    For the IOP: $a0-$a3 are for the first 4 parameters. Any further parameters are stored from $sp+0x10. Stack alignment is 8-byte. Values are returned with $v0 & $v1.
    For the EE: $a0-$a3 are for the first 4 parameters, followed by $t0-$t3 for the next 4. Any further parameters are stored from $sp+0x10. Stack alignment is 16-byte. Values are returned with $v0 & $v1.

    For oversized parameters (i.e. passing a 64-bit value on the IOP), the adjacent register is used for passing the value. The same thing goes for return values ($v0 and $v1 can be used to return a 64-bit value).
     
  3. Anonamous

    Anonamous Member

    Joined:
    Jan 10, 2012
    Messages:
    14
    Likes Received:
    6
    Ah so it does use the temp registers for parameters before the stack. Thank you very much.

    From what I gather, $f12, and $f14 are used for input and $f0/$f2 for output floats? is it accurate that only the even ones are used although the ee cop1 only supports single precision?
     
    Last edited: Apr 23, 2019
  4. wisi

    wisi Rising Member

    Joined:
    Apr 16, 2016
    Messages:
    55
    Likes Received:
    76
    For floats, the EE uses $f12, $f13, $f14, $f15, $f16, $f17, $f18, $f19, and then $sp+0x00, $sp+0x08, $sp+0x10, etc. and $f0 for return.

    When a0-a3, t0-t3 are filled-up and more arguments are passed on stack, they go below the float arguments on stack - at $sp+0x00, $sp+0x08, for example and if there are floats arguments on stack, they go in $sp+0x10, $sp+0x18 after them (if there are three integers and two floats on stack - integers: $sp+0x00, $sp+0x08, $sp+0x10, and floats: $sp+0x18, $sp+0x20).

    Double precision floats are placed according to the same rules integers (8 to 64 bit) are placed - starting with a0-a3, t0-t3, then $sp+0x00, $sp+0x08, etc. and are returned in $v0 and calculation is done with dp* functions. So doubles and integers use the same sequence of registers and stack offsets and thus the order between them and the integers matters, while the order between the first eight floats and integers does not matter (and can't be determined from assembled code), as they use separate register sets. This is what a short test-code showed.
     
    Last edited: Apr 23, 2019
    Anonamous likes this.
  5. Anonamous

    Anonamous Member

    Joined:
    Jan 10, 2012
    Messages:
    14
    Likes Received:
    6
    Ok, I'm going to assume then that f20-f31 are preserved by the callee and not just the even registers. Thank you very much.
     
  6. wisi

    wisi Rising Member

    Joined:
    Apr 16, 2016
    Messages:
    55
    Likes Received:
    76
    I see that f20, f22, f24, f26, f28, f30 are saved by the callee before it uses then and are restored afterwards, but I don't see it using the odd registers between f20-f31, so maybe there is something different here. Maybe after the even registers are used-up, the stack is used. But I have no idea what the odd registers are kept for.
    Best check using test-code, as usually not all registers are not used for arguments are preserved (at least from the integer registers).
     
  7. smf

    smf mamedev

    Joined:
    Apr 14, 2005
    Messages:
    1,259
    Likes Received:
    92
    I haven't looked, but could it be double precision registers are numbered with even numbers and then there are double the number of single precision registers using the two halves and one is odd and the other is even?
     
  8. Anonamous

    Anonamous Member

    Joined:
    Jan 10, 2012
    Messages:
    14
    Likes Received:
    6
    Well, the ee cop1 doesn't have support for double precision. It is to my understanding that all double precision floats on the ps2 are 'soft-floats' so the compiler treats it as it would a struct.
     
  9. TriMesh

    TriMesh Site Supporter 2013-2017

    Joined:
    Jul 3, 2008
    Messages:
    2,364
    Likes Received:
    783
    I think the EE COP1 implementation only allows even numbered registers for single precision FP operations. Since it doesn't support double precision, it's quite possible that the odd numbered FP registers don't even exist.
     
    Anonamous likes this.
  10. smf

    smf mamedev

    Joined:
    Apr 14, 2005
    Messages:
    1,259
    Likes Received:
    92
    Interesting, I wonder if the cop1 was based on an existing design. Some of the ps1 asic was hacked up from off the shelf libraries, it wouldn't surprise me if the ps2 was the same.
     
  11. TriMesh

    TriMesh Site Supporter 2013-2017

    Joined:
    Jul 3, 2008
    Messages:
    2,364
    Likes Received:
    783
    Hard to tell - both the "single precision only" and "single precision only operates on even FP regs" are defined implementation options in the MIPS documents - so it could simply be the most stripped down version of the standard COP1. I can understand the logic behind doing this - the idea was that all the heavy-duty math work was handed off to the two VPUs.

    It's also hard to tell if even the overall design flow was the same between the PS1 and the PS2 - that interval between the early and late 90s was when a lot of changes were happening to EDA tools - in the early '90s, most of the vendors with standard cell approaches used technology specific netlists that were basically only usable on that specific vendor's process. There were people that used HDL based approaches, but it was considered a high risk strategy at the time (for example, SGI's decision to implement the N64 RCP in Verilog was considered to be one of the reasons that the schedule slipped since the tools were somewhat immature). By the late '90s, HDLs and their associated tools were much better developed and had become a much more mainstream option.
     
    Anonamous likes this.
  12. sp193

    sp193 Site Soldier

    Joined:
    Mar 29, 2012
    Messages:
    2,232
    Likes Received:
    1,073
    The FPU isn't IEEE754-compliant. Unless you can find such a thing around, wouldn't this mean that it's unique?
     
  13. TriMesh

    TriMesh Site Supporter 2013-2017

    Joined:
    Jul 3, 2008
    Messages:
    2,364
    Likes Received:
    783
    That's a very good point, and strongly suggests that the COP1 is some sort of custom implementation.
     
  14. smf

    smf mamedev

    Joined:
    Apr 14, 2005
    Messages:
    1,259
    Likes Received:
    92
    It depends on what you mean by unique, it doesn't necessarily mean they started from scratch. It may have evolved from an IEEE754 compliant FPU which they stripped back for die space or execution speed. You'd have to look at similarities between other FPUs
     
  15. Anonamous

    Anonamous Member

    Joined:
    Jan 10, 2012
    Messages:
    14
    Likes Received:
    6
  16. Anonamous

    Anonamous Member

    Joined:
    Jan 10, 2012
    Messages:
    14
    Likes Received:
    6
    I just happened to realize that they indeed must exist. If they didn't then there would be no reason for those registers to be cleared upon entry. Just load up a game in ps2-dis and have a look at the entry point, assuming it isn't packed.
     
  17. TriMesh

    TriMesh Site Supporter 2013-2017

    Joined:
    Jul 3, 2008
    Messages:
    2,364
    Likes Received:
    783
    I've seen plenty of cases where library code does things that are redundant because they made sense once - I'm not sure you can safely infer anything from this.
     
  18. wisi

    wisi Rising Member

    Joined:
    Apr 16, 2016
    Messages:
    55
    Likes Received:
    76
    The EE Core User's Manual specifies (implies) that all of the EE FPU FPRs are implemented and of the FCRs only FCR0 and FCR31 are implemented (control registers). Whether hardware features exist and how they operate is usually determined by reading the manuals and/or testing on the hardware. Of course, how they are used by official software is another matter and how they can be used by homebrew software it yet another matter.
     
  19. smf

    smf mamedev

    Joined:
    Apr 14, 2005
    Messages:
    1,259
    Likes Received:
    92
    And whether the documentation is correct or not is altogether another matter.

    Testing the hardware can be useful, but in some cases Sony made changes along the way.
     
  20. Anonamous

    Anonamous Member

    Joined:
    Jan 10, 2012
    Messages:
    14
    Likes Received:
    6
    I left my PS2 at home due to my dropping grades. However after finals and I return home I can run some thorough tests to check if they do indeed exist or not.
     

Share This Page