Post Reply 
Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
PS3 Port?
04-10-2019, 03:53 AM
Post: #8
RE: PS3 Port?
1. No, it's definitely more complicated than that.

Imagine the PSP's memory as a grid or checkerboard, and pointers as grid coordinates. A 32-bit value sits as grid position (1, 1) and ends at (4, 1), right? Endianess describes which direction I write the digits - to simplify, if my number is 2,468 then big endian has me write it "2 4 6 8" and little endian has me write "8 6 4 2".

The trouble is that then, I could later look at the value /specifically/ at (2, 1) - the second digit. You might say "that's wrong" or "don't do that" but PSP games didn't follow those rules; their developers had a guarantee that the software they wrote would ALWAYS run on a little endian device. No reason not to cheat a little to get to 60 FPS when it's a sure thing.

Games definitely do this, and it's imperative that in my example, a read at (2, 1) gives you "6" and not "4". This means that every possible operation that could touch memory - from jit or interpreted memory access, to HLE operations such as video and audio decoding - must be translated to little endian. This affects GPU emulation, HLE operations, everything. Anything that interacts with RAM.

Parameters/arguments are actually the one thing that is safe. In assembly, when a function is called most of the arguments are stored in registers, which don't have an endianess (well, except SIMD registers.) So you don't need to convert these, it only really matters when you interact with memory.

The real problem here is that you can end up with a tiny bug somewhere - a place where endianess was missed - and it can take a ton of time to debug and figure out why the game won't even boot and goes haywire.

2. If you look at the pull request I linked, it does add a somewhat functional (I don't know to what degree) PowerPC jit. It may use instructions not present on the PS3, but it's probably fine. That said, jit in PPSSPP basically has a few components:

* An emitter, which is basically an assembler. This writes host instructions (in this case, PowerPC) to RAM. For example, it might expose a member function ADDI(R0, R0, 123) which writes the PowerPC addi instruction and advances the code pointer. Typically, these are in Common/ because many of them originally came from Dolphin.

* A main jit class, which handles the translation of MIPS code to PowerPC code. For example, MIPS has a maddu instruction which takes two 32 bit integer registers, multiplies them, and then adds the result to a pair of 32 bit integer registers treated as a 64 bit register. This would probably translate to multiple PowerPC instructions. DISABLE makes it flush everything and go back to the interpreter for this instruction (which is what the current Wii U implementation does for maddu.)

* Two register cache classes, one for integer and the other for float regs, which coordinate the possible guest registers (MIPS has 32 integer, and 160 float) and where they currently "live" (either in a host register or in host RAM and need to be loaded.) This is used by the main jit methods to manage mapping them to host registers for the actual PowerPC instructions. PowerPC uses 32 integer / 32 float, but some integer registers are certainly reserved by the OS and can't be used.

When I initially started messing with PPSSPP's jit, I already knew Intel assembly, but I had to use a lot of MIPS reference material. You'll likely want to reference MIPS and PowerPC instruction set documentation. I will say: MIPS is a fairly clean instruction set, I really like it. The PSP has a bunch of extra instructions that aren't so beautiful, but core MIPS has a fairly clean encoding.

Beware of delay slots, they will confuse you at first. In MIPS, a branch of jump instruction does not change the code position immediately. It still executes the very next instruction, and then jumps after that. The jit class takes care of reordering this to not use any delay slot.

3. It's probably dangerous to assume that. If going based on age, the PS3 was released in 2006, only one year after the PSP was. They are both old devices at this point.

Ignoring CPU emulation (which should hopefully be fine with a jit, but will only be able to use the primary 3.2 Ghz POWER core of the PS3), GPU emulation is typically the bottleneck for emulating the PSP. On older PCs from 2006 or so, people often have to turn on graphics hacks that draw things wrong (and make effects look bad) for playable speed.

It's important to understand that the PSP's GPU has a lot of quirks. For example, it stores stencil in the alpha component (which requires a lot of workarounds to have graphics work right), and allows a lot of direct access to VRAM, palette look ups, and a lot of other things.

Even more importantly, the cost of drawing a small batch of prims thousands of times per frame was not too high, so games did it. However, OpenGL even on desktop (and especially on mobile) has a lot of overhead per draw, and is brought to its knees by such lazy drawing. We do a lot of work (which consumes CPU) to try to combine draws, although we can't always.

Point is, if the PS3's OpenGL implementation is known to be "slow" it could easily be the bottleneck.

On mobile phones, the arm64 jit does a great job, but terrible drivers are a huge problem. They consume a lot of CPU themselves, have lots of overhead per draw, etc. It helped a lot when we rearchitected things so the OpenGL driver calls all happen on a separate thread (ultimately, a separate arm64 core.) The PS3 probably won't have this luxury, as I doubt you can call OpenGL from the SPUs.

On that note, from a raw power perspective, I'm guessing the SPUs (where all those GFLOPS come from) won't be of much use to PPSSPP. Maybe they could be used for audio decoding or some graphics post-processing. Most of that raw power will likely go unused.

Linux (and Mac) both use SDL or Qt. Windows is a bit of a special case because there's a lot of Windows-specific debugging UI and code. There's also now a cross-platform web debugger which would be more appropriate for PS3 usage (potentially to debug jit issues, etc.)

The interpreter is in Core/MIPS/, mainly in MIPSInt.cpp and MIPSIntVFPU.cpp. There's also an IR Interpreter, which uses some of the jit framework. This translates MIPS code into an intermediate representation (IR) of bytecode, and then interprets the IR.

The long term goal of that was to create jit backends to do MIPS -> IR -> arm64, etc. That said, with GPU emulation as the biggest bottleneck, this hasn't been completed or gotten a lot of attention recently. To some degree, it was added as a faster option than interpreter for platforms that can't handle jit. Recent iPhones can actually run quite a few games full speed with IR Interpreter, although again that's because CPU emulation isn't the biggest bottleneck.

Find all posts by this user
Quote this message in a reply
Post Reply 

Messages In This Thread
PS3 Port? - o.g._m.a.k. - 01-11-2019, 05:15 AM
RE: PS3 Port? - o.g._m.a.k. - 03-28-2019, 06:26 AM
RE: PS3 Port? - GuilhermeGS2 - 03-29-2019, 06:19 PM
RE: PS3 Port? - o.g._m.a.k. - 03-31-2019, 05:34 AM
RE: PS3 Port? - R3xVF5 - 04-04-2019, 07:06 AM
RE: PS3 Port? - [Unknown] - 04-08-2019, 10:44 PM
RE: PS3 Port? - R3xVF5 - 04-09-2019, 06:27 AM
RE: PS3 Port? - [Unknown] - 04-10-2019 03:53 AM

Forum Jump: