News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: How do I skip an operation, or a section of code?  (Read 3005 times)

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
How do I skip an operation, or a section of code?
« on: April 01, 2019, 10:54:23 am »
I'm currently in the midst of hacking Vagrant Story (PS1), and so far I've been successful in editing data either through hex or using the tools provided by user Valendian. The problem is, for a long time I've wanted to remove what is called the "stats roulette", which happens right after defeating the bosses in the game. To illustrate, here is the roulette in action:

Spoiler:

The roulette as it plays in the game:

https://youtu.be/75VwUHJ4CuU

As it happens, I have no programming knowledge but I'm willing to learn. I downloaded pSX (version 1.13) which contains a built-in debugger, which I'm told can be used to "step through code" and pinpoint where exactly an instruction is being executed, in other words its RAM address. Browsing the utilities section, I also found another tool, the PSX address calculator (http://www.romhacking.net/utilities/1140/). My intention is to feed it the RAM address obtained with the debugger, to find where the instruction for the roulette is located in the ROM. Finally, I want to disable that operation or section of code in the ROM to make the change permanent.

I started by going to a point in the game where the roulette takes place, then looking at what happens in the debugger window. I'm using the r3000 debugger; the other ones either freeze or crash the game. As I finish the boss and the roulette plays, I look at the different windows in the debugger and the Memory one doesn't seem to change. To illustrate, this is what I see:

Spoiler:

I assumed "Memory" was for RAM, and CD-ROM was for ROM. Was I mistaken?

I also looked at the Registers window, and it showed some activity.

Spoiler:

So my first question is, am I generally in the right direction? Secondly, does my strategy of using the RAM address to find the ROM one and then disabling the operation make sense? And thirdly, is there a manual on how to use the pSX debugger so I can learn how to find the RAM address of the roulette?

Any help is appreciated.

tvtoon

  • Sr. Member
  • ****
  • Posts: 359
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #1 on: April 01, 2019, 04:10:39 pm »
I couldn't see the images, but from what you typed so far, you are coming along well.

In PlayStation, "memory" is a complex issue but usually means RAM (0x80######, 0xA0######, 0x00######). Two things I recommend: download the MIPS official specification to learn about branches and jumps used; change and test your code inside RAM whenever possible, before moving to CDROM commands if you need (nocash documentation).

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #2 on: April 01, 2019, 09:41:17 pm »
I couldn't see the images, but from what you typed so far, you are coming along well.
Ah. These links should work:

https://imgur.com/Vqcx0Ey

https://imgur.com/FyExGUW

https://imgur.com/Pg2VvVH

Two things I recommend: download the MIPS official specification to learn about branches and jumps used; change and test your code inside RAM whenever possible, before moving to CDROM commands if you need (nocash documentation).
I've found some resources on MIPS, but not the official specifications. Do you know where I can download them?

This is what I've found:

https://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formats

https://en.wikipedia.org/wiki/MIPS_architecture#MIPS_I

The PSOne uses MIPS I, is that correct?

tvtoon

  • Sr. Member
  • ****
  • Posts: 359
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #3 on: April 02, 2019, 03:24:08 pm »
There you go. You are looking for the instruction set.

PlayStation is MIPS I, but differ in some aspects of the platform. That is why I also recommend you search for the IDT "R3000.pdf", to hold details close to you.

STARWIN

  • Sr. Member
  • ****
  • Posts: 449
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #4 on: April 06, 2019, 09:26:27 am »
If you don't like pSX, you can also try no$psx. The help files contain his documentation, but it is also available here: http://problemkaputt.de/psx-spx.htm

You could check the CPU section there for an asm reference.

You generally want to find the code in question with the debugger. You didn't specify what you exactly want to change, but you could perhaps make it auto pick the first pick if it listens input at that point, or turn all the choices the same or try skipping the whole functionality, if you can see a way to do it without side-effects. These changes should be destructive in a way that lets you do your changes in-place, not having to search for free space (yay).

You can often find the original code spot in the ROM by searching for the machine code sequence from the CD ROM image. Although modifying the ROM should be done by extracting the file where the code is with cdmage, modifying it, and inserting it back, so either figure out the file from the ROM offset or search each file with a hex editor separately.

If you at some point need to turn your asm snippet into binary, try armips.

Valendian

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #5 on: April 06, 2019, 04:23:40 pm »
The GPU debug window is absolutely one of the best tools pSX has to offer (even if it is extremely buggy). It let's you find things in record time. Here is a walk-through of how to make the most out of it.


1. Fire up Vagrant Story in pSX

2. Get a roulette wheel on screen

3. Open a debug window

4. Open a GPU window

5. Menu->GPU->Capture

6. Step through the drawing process until it starts drawing the Roulette


7. This image is interesting, take note of the Program Counter (PC)


8. Place a break point


9. Now open the call stack and inspect


10. This one looks promising


11. Get rid of that conditional branch and test (debug -> run)


12. Okay found it, now let's open a Hex Editor and search for that instruction sequence


13. Apply the patch and save


Now that you know the basic process you can do similar things in future. You don't really need to understand everything that you see. Think of the branches as a sort of flow chart diagram, and blocks of code are only stitched together by the branches.

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #6 on: April 06, 2019, 07:04:20 pm »
There you go. You are looking for the instruction set.
Thanks. I downloaded the instructions quick reference.

PlayStation is MIPS I, but differ in some aspects of the platform. That is why I also recommend you search for the IDT "R3000.pdf", to hold details close to you.
Is this it? https://cgi.cse.unsw.edu.au/~cs3231/doc/R3000.pdf

From what I've read on this site, it looks like MIPS is actually simpler than assembly language, so I have that in my favor. I'm still grasping the fundamentals of it, very slowly.

@Starwin: I had come across that document and was wondering what it was. I'll look into that debugger, I can always use another option. I've also heard good things about armips; how it can be used to "inject" code into the game. A quite popular tool.

Spoiler:
The GPU debug window is absolutely one of the best tools pSX has to offer (even if it is extremely buggy). It let's you find things in record time. Here is a walk-through of how to make the most out of it.


1. Fire up Vagrant Story in pSX

2. Get a roulette wheel on screen

3. Open a debug window

4. Open a GPU window

5. Menu->GPU->Capture

6. Step through the drawing process until it starts drawing the Roulette


7. This image is interesting, take note of the Program Counter (PC)


8. Place a break point


9. Now open the call stack and inspect


10. This one looks promising


11. Get rid of that conditional branch and test (debug -> run)


12. Okay found it, now let's open a Hex Editor and search for that instruction sequence


13. Apply the patch and save


Now that you know the basic process you can do similar things in future. You don't really need to understand everything that you see. Think of the branches as a sort of flow chart diagram, and blocks of code are only stitched together by the branches.


Your tutorial is very illuminating. Thanks a lot.

I recognize those two call stack addresses (00000080, 800f4530); I was trying to revert them into ROM offsets or something. I've yet to learn how to place a breakpoint, so far I'm only using the Break command. I understand the general process (I think), but some of the steps you described are obscure to me. Long way...

In any case, I implemented the changes you provided. The result:

https://youtu.be/mTe3HUhAxRc

That's some real progress. Now I'm wondering if it's possible to remove the roulette but still display the text for Congratulations, Score, Map Completion and Riskbreaker Rank. In your example, it would display up to and including the "GrandMaster Breaker" text; then it would skip to the loot phase. Specifically, it would remove only the "Press Button" text, the "O" circle button icon and the roulette itself. Maybe it's the difference between skipping a branch entirely and modifying the instruction it leads to.

Thanks for dropping in, I was wondering when you might show up. I still have much to do before I'm done with this game.

Edit: I'm trying to follow your instructions, and I'm having a bit of trouble. I can capture the frames in the GPU window and step through them until the roulette appears; but I don't understand how you go from there to... anywhere. Looking at your first image, there's already so much stuff going on. I see a Breakpoints window (v00011c3c <-- where did you get this from, btw?), I see a Call stack window, but what is the large window below? This one:

https://imgur.com/SXaztI7

Also, why did you choose to display VRAM? Sorry for the questions, there's still too much I don't understand.
« Last Edit: April 06, 2019, 10:22:20 pm by the_E_y_Es »

Valendian

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #7 on: April 07, 2019, 06:56:56 am »
Don't worry if it doesn't make sense, I work beside professional programmers who can't understand assembly (honest).

That break point is a leftover from previous attempt and is not important.

Basically when you step through the GPU frames, each drawing action is captured in details shown on the top right of the GPU window. For each drawing command the GPU window will show you the following
Code: [Select]
Time that the drawing command was issued
Address of the drawing command data
Size of the drawing command data
PC (Program Counter) or the code that issued the drawing command
We care about the PC because it brings us to the exact code that issued the drawing command. That's where we place a break point. But we don't really care about this code (it just draws the image) what we really care about is where the code came from (thats where the higher level "boss killed" function is found). When the debugger breaks we can view the call stack. This will let us find the "boss killed" function. In this case the code we really care about is in the region 8010384C...80103D84 (from MENUF.PRG).

This function contains calls to drawing functions, they will look like this:
Code: [Select]
80103910: 0C04182A jal 0x001060a8        # Draw the Roulette

You can toggle those drawing functions off by replacing with zeros
Code: [Select]
80103910: 00000000 nop                   # Don't draw the Roulette

That's kind of all you need to know. The hack would go something like this.

First get rid of the visuals
Code: [Select]
80103910: 0C04182A jal 0x001060a8        # Draw the Roulette
80103914: 24C6FEF0 addiu r6,r6,0xfef0
# change to ...
80103910: 00000000 nop                   # Don't draw the Roulette
80103914: 24C6FEF0 addiu r6,r6,0xfef0    #


# and also
80103A68: 8C47989C lw r7,-0x6764(r2)
80103A6C: 0C041935 jal 0x001064d4        # Draws for "PRESS BUTTON"
80103A70: 24060030 addiu r6,r0,0x0030
# change to ...
80103A68: 8C47989C lw r7,-0x6764(r2)
80103A6C: 00000000 nop                   # Don't draw "PRESS BUTTON"
80103A70: 24060030 addiu r6,r0,0x0030

There's also a count down timer that needs to go too
Code: [Select]
80103984: 2CC20030 sltiu r2,r6,0x0030    # This may be a count down timer
80103988: 1040000D beq r2,r0,0x801039c0  # When T<30 check for circle button
# change to ...
80103984: 2CC20030 sltiu r2,r6,0x0030    # This may be a count down timer
80103988: 104000EF beq r2,r0,0x80103d48  # When T<30 we are done


Now there is still a visual for "PRESS BUTTON" (entering from stage right), I have no time but you may be able to track it down by removing the jal functions or by adjusting a different count down timer (sltui r2, ...)
« Last Edit: April 07, 2019, 07:39:54 am by Valendian »

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #8 on: April 07, 2019, 11:53:34 am »
Basically when you step through the GPU frames, each drawing action is captured in details shown on the top right of the GPU window. For each drawing command the GPU window will show you the following
Code: [Select]
Time that the drawing command was issued
Address of the drawing command data
Size of the drawing command data
PC (Program Counter) or the code that issued the drawing command

Yep, that's what I'm currently trying to do. I remember having all that beautiful information displayed by the GPU window, but I can't remember how I did it. I do know what you're referring to, however.

In this case the code we really care about is in the region 8010384C...80103D84 (from MENUF.PRG).
That certainly narrows it down. Cool.

Now there is still a visual for "PRESS BUTTON" (entering from stage right), I have no time but you may be able to track it down by removing the jal functions or by adjusting a different count down timer (sltui r2, ...)

Oh, I can do this one:



If I zero out those values, the PRESS BUTTON text no longer appears. I guess that's one way to do it...

I'm thinking about the "BONUS" text that appears in front of the roulette. Does your code remove it?

Anyway, I'm going back to that GPU -> Capture process, I want to get that information you mentioned (Program Counter, etc.)

tvtoon

  • Sr. Member
  • ****
  • Posts: 359
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #9 on: April 07, 2019, 12:14:47 pm »
Thanks. I downloaded the instructions quick reference.
Is this it? https://cgi.cse.unsw.edu.au/~cs3231/doc/R3000.pdf

From what I've read on this site, it looks like MIPS is actually simpler than assembly language, so I have that in my favor. I'm still grasping the fundamentals of it, very slowly.
Yeah, the IDT one is easier to get the general idea, but it has some wrong ideas compared to the official specification.

I see that you are doing well, persist and break it goods! :D

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 6893
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #10 on: April 07, 2019, 12:27:39 pm »
From what I've read on this site, it looks like MIPS is actually simpler than assembly language, so I have that in my favor. I'm still grasping the fundamentals of it, very slowly.

MIPS -IS- the Assembly language here. MIPS is the CPU used by the PS1 (and N64 and PS2).
Though from the brief time I used it, it seemed it might be TOO simple as I recall something that would've been easy to understand on other CPUs (XORs? Conditional branches? I forget exactly what at the moment) becoming harder to follow as it now needed multiple instructions (unless it was the specific game I was looking at).

I recall things using Immediate values were also more obfuscated as they would have to go through math with R0.
(though I admit that I hadn't spent a huge amount of time with MIPS, as well as GBA which seemed similarly a bit hard to follow at a short glance, compared to 6502, Z80 and 68000)
"My watch says 30 chickens" Google, 2018

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #11 on: April 07, 2019, 10:44:21 pm »
Oh boy. This is awesome. I followed your instructions, Valendian, and they work beautifully.

The hack would go something like this.

First get rid of the visuals
Code: [Select]
80103910: 0C04182A jal 0x001060a8        # Draw the Roulette
80103914: 24C6FEF0 addiu r6,r6,0xfef0
# change to ...
80103910: 00000000 nop                   # Don't draw the Roulette
80103914: 24C6FEF0 addiu r6,r6,0xfef0    #

I looked up that address (80103910) in the Memory window and found these instructions there: 2A 18 04 0c. Which just happens to be 0C04182A as shown by the Disassembly window, only backwards. Now it makes some sense to me... so I opened the ROM and checked for those instructions; I found two instances of it:



This is the roulette before it stops looping.



The roulette after it stops.

Zero'ing those took care of it, except for the sound effect of the roulette turning. The sound seems to continue after you regain control of Ashley, although it's somewhat muted.

Now the PRESS BUTTON graphics.

Code: [Select]
# and also
80103A68: 8C47989C lw r7,-0x6764(r2)
80103A6C: 0C041935 jal 0x001064d4        # Draws for "PRESS BUTTON"
80103A70: 24060030 addiu r6,r0,0x0030
# change to ...
80103A68: 8C47989C lw r7,-0x6764(r2)
80103A6C: 00000000 nop                   # Don't draw "PRESS BUTTON"
80103A70: 24060030 addiu r6,r0,0x0030

There are 3 instances of those:



This is the "enter stage right" one.



The one after the first, and before you press circle.



Last one, after you press circle.

Finally, the counter:

There's also a count down timer that needs to go too
Code: [Select]
80103984: 2CC20030 sltiu r2,r6,0x0030    # This may be a count down timer
80103988: 1040000D beq r2,r0,0x801039c0  # When T<30 check for circle button
# change to ...
80103984: 2CC20030 sltiu r2,r6,0x0030    # This may be a count down timer
80103988: 104000EF beq r2,r0,0x80103d48  # When T<30 we are done

Only one of that:



I changed it to EF 00 40 10 like you said. Worked like a charm.

The result:

https://youtu.be/Muyp6_iOvGU

I checked Ashley's stats afterwards; they hadn't increased.

This is the ideal setup for me; now I only have to remove the roulette sound. Any tips on how I can recognize it in the disassembly?
« Last Edit: April 07, 2019, 11:41:16 pm by the_E_y_Es »

Valendian

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #12 on: April 08, 2019, 02:33:40 pm »
Excellent work, this is extremely elite stuff your doing. And now for the cherry on top, here's the audio fix mixed in with your changes above. Looks like 0x00045988 is the play sound effect function. Most of them we wanna keep but need to get rid of two of them (start up sample and a looping sample)

Code: [Select]
801038F8: 0C041503 jal 0x0010540c        (change to 00000000 nop)
80103968: 0C011662 jal 0x00045988        (change to 00000000 nop) *** NEW ***
80103974: 0C011662 jal 0x00045988        (change to 00000000 nop) *** NEW ***
80103988: 1040000D beq r2,r0,0x801039c0  (change to 104000EF beq r2,r0,0x80103d48)
801039B0: 0C041935 jal 0x001064d4        (change to 00000000 nop)
80103A6C: 0C041935 jal 0x001064d4        (change to 00000000 nop)
80103B00: 0C041935 jal 0x001064d4        (change to 00000000 nop)
80103C64: 0C04182A jal 0x001060a8        (change to 00000000 nop)

Not bad work at all, very polished

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #13 on: April 08, 2019, 04:01:45 pm »
Excellent work, this is extremely elite stuff your doing.

Haha, well I don't know, but hey it's a pretty elegant solution. :)

Code: [Select]
801038F8: 0C041503 jal 0x0010540c        (change to 00000000 nop)
80103968: 0C011662 jal 0x00045988        (change to 00000000 nop) *** NEW ***
80103974: 0C011662 jal 0x00045988        (change to 00000000 nop) *** NEW ***
80103988: 1040000D beq r2,r0,0x801039c0  (change to 104000EF beq r2,r0,0x80103d48)
801039B0: 0C041935 jal 0x001064d4        (change to 00000000 nop)
80103A6C: 0C041935 jal 0x001064d4        (change to 00000000 nop)
80103B00: 0C041935 jal 0x001064d4        (change to 00000000 nop)
80103C64: 0C04182A jal 0x001060a8        (change to 00000000 nop)

All done. The start-up sample was at BF598CC, the looping one at BF598C0.

https://youtu.be/8wTCGSdGTyk

I can hardly believe it... it's a huge milestone for the mod, and a long time ambition for me personally. Cannot thank you enough.

One last thing: about that counter, is it possible to set other conditions like "when T > 3s, proceed"? I was just thinking it might feel better with a small pause there, before the loot phase comes in.

Valendian

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #14 on: April 09, 2019, 03:54:18 am »
You're welcome.

One last thing: about that counter, is it possible to set other conditions like "when T > 3s, proceed"? I was just thinking it might feel better with a small pause there, before the loot phase comes in.

Only one way to find out. Looking at the code though you probably just wanna compare to a T value smaller than 0x0030 (say 0x0006). You can also use beq vs bne
Code: [Select]
beq r2,r0,xxx # jump if T >= x
bne r2,r0,xxx # jump if T < x

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #15 on: April 09, 2019, 10:13:06 pm »
Looking at the code though you probably just wanna compare to a T value smaller than 0x0030 (say 0x0006).

By 0x0030 do you mean this guy?

Code: [Select]
80103984: 2CC20030 sltiu r2,r6,0x0030    # This may be a count down timer

So that 0x0030 means 30 seconds? I see. I don't suppose the "30" in 2CC20030 also represents the value of T, does it? Because I tried changing it and didn't have any luck.

Valendian

  • Jr. Member
  • **
  • Posts: 52
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #16 on: April 10, 2019, 03:38:11 am »
That's it alright R6 stores a count down, but it likely refers to frames not seconds. Leave it with me I might be able to wait for T to go negative (say -0x0120 or so)

April 13, 2019, 03:47:36 am - (Auto Merged - Double Posts are not allowed before 7 days.)
Okay got it, you can play around with the value 0x0180, this timer counts up over time

Code: [Select]
8010397C: 8e07989c lw r7,-0x6764(r16)
80103980: 00000000 nop
80103984: 28e20180 slti r2,r7,0x0180
80103988: 104000ef beq r2,r0,0x80103d48
8010398C: 3c028006 lui r2,0x8006
« Last Edit: April 13, 2019, 03:47:36 am by Valendian »

the_E_y_Es

  • Jr. Member
  • **
  • Posts: 31
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #17 on: April 13, 2019, 05:06:06 pm »
Code: [Select]
8010397C: 8e07989c lw r7,-0x6764(r16)
80103980: 00000000 nop
80103984: 28e20180 slti r2,r7,0x0180
80103988: 104000ef beq r2,r0,0x80103d48
8010398C: 3c028006 lui r2,0x8006

Fantastic. That's it really, there's nothing else I could want. And by the way, I experimented with different values and decided to keep 0x0180. I doesn't overstay its welcome and allows enough time for the music to play and the text to sink in. It's just perfect and exactly what I wanted. How did you know?

Thank you again for your time and effort. It's very appreciated. Breakthroughs like this one really motivate me to build a better mod. You'll see.

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 6893
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #18 on: May 24, 2019, 11:02:07 pm »
Isn't the MIPS weird in that it executes the instruction following the jal code before jumping?
Or is that something else?
"My watch says 30 chickens" Google, 2018

jonk

  • Sr. Member
  • ****
  • Posts: 273
    • View Profile
Re: How do I skip an operation, or a section of code?
« Reply #19 on: May 28, 2019, 01:51:32 am »
Isn't the MIPS weird in that it executes the instruction following the jal code before jumping?
Or is that something else?

I've never considered the MIPS to be weird. But perhaps it is because I worked with the MIPS R2000 back in 1985 and 1986 and visited MIPS to listen to Dr Hennessey discuss the details of their design tradeoffs (he used the Motorola 68020 as a comparison CPU die to make his points clearer.) The choice was simple. You either throw away the next instruction that has already been fetched, once the branch is decoded and executed, wasting that effort. Or else you don't throw it away and don't waste the effort. Also, adding logic needed to make those decisions adds propagation delay, which lengthens the required clock period, lowering the resulting CPU clock rate. So you pay for the waste, twice. But the more important cost is the slower clock rate because that is paid by each and every instruction that is executed.

The MIPS team (prior to forming the commercial entity "MIPS" and while still at Standford working on the MIPS project started in 1981) made the decision that this "delay slot" would be relegated to the assembler (through a tool that re-organized assembly code to fill the delay slot or insert a NOP) and compiler. In short, they designed the fastest CPU they could using the hand-me-down FAB access they had available to work on and left the issue of whether or not to stick a NOP in the delay slot as a "compiler issue." I think it was a smart choice at the time.

The result was, including some other decisions related to registers (if you read a register in an instruction directly following another instruction that modified that register, you didn't get the modified value but the prior value before modification, for example) and more, that MIPS was able to produce a CPU that could compete with the best x86 processor that Intel was making on one of the most expensive and sophisticated FABs in the world and they could compete (and beat) the x86 using FAB processes that yielded them perhaps 5% or 6% of the transistor/transmission gate equivalents. They did more, with a lot less. And it forced Intel to significantly change direction in their CPU designs (starting with the PPro creating the re-order buffer which, in effect, is a RISC processor in its own right buried deep inside.)

(I worked at Intel on the PPro, P II, and the BX chipset. And I also have written compilers.)

There are lots of fun things you can do with the delay slot. For example, a BAL instruction can set the RA register to the return address (after the delay slot.) But the instruction in the delay slot can modify the RA register to change that return address. This "feature" is particularly useful if the last statement in a conditional branch "code edge" is a function call. A not uncommon case. (I can explain that further, if interested.)
« Last Edit: May 28, 2019, 01:42:07 pm by jonk »
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me