PowerPC For Dummies: A simplified guide to understanding the PowerPC Instruction Set
#11
(06-25-2021, 09:34 PM)Vega Wrote: No completely wrong. All those instructions have nothing to with 'code'.

It's all cache related. For 99% of Wii codes you will never need these instructions. I wouldn't bother putting them in your simplified guide as these instructions are for more advanced work.

Yeah, I think I'll leave them off the guide for now. I mostly just put them there for the sake of wanting to have every instruction listed, even the obscure ones, but I'll come back to it in the future if I ever fully understand it.
Reply
#12
Went over your Guide again looking for any more errors:

- Bit is not a single digit within a word (its not half of a byte). A bit is a binary number (0 or 1) and a group of 4 of these binary values comprise a digit's value. It's why in the thread about rlwinm, i was putting the binary values in groups of 4. 4 bits in a digit, 8 digits in a word, so 32 bits in a word.

- Regarding your quick description of an fpr, you should add in a note that the floating value is in its 64-bit form

- Broadway does not have an 'xnor' instruction. Is it a simplified mnemonic? Is xnor instruction present in other PPC chips?

- Regarding your lis description, you should add a note that whenever lis is executed, the lower 16 bits are always set to null

An Fyi. Li is a simplified mnemonic for addi

i.e. li r1, 1 = addi r1, r0, 1 #Broadway treats r0 as literal 0 when it's used as a source register in this instruction

Lis is simplified mnemonic of addis

i.e. lis r1, 1 = addis r1, r0, 1 #r0 treated as literal 0

There are a lot more instructions (too many to list) that if r0 is the source register, its literal 0

In the Broadway manual i see nothing about bun, bnu, bdznt, bdnzf, and bdz branches. Are these present in other PPC chips? An fyi, the disassembler used in Dolphin is a generic PPC disassembler, so it will show instructions that simply don't exist in Broadway. Maybe these are simplified mnemonics not referenced in the manual?

- Your definition for NOT is incorrect. NOT is not the negative of a value. Its a simplified mnemonic for NOR'ing a register with itself

i.e. not r5, r3 = nor r5, r3, r3

Use the neg instruction instead (i.e. neg r5, r3)

Neg = Negate btw. Positive number becomes negative,negative becomes positive

- Stwu is a store word instruction but the address in the source register gets updated with the value of the previous source register's value + VALUE.

example:
r3 = 0x80000000; VALUE = 0x1500

stwu r0, 0x1500 (r3)

Before instruction was executed; r3 was 0x80000000
After instruction has executed; r3 is now 0x80001500

If you repeat the instruction again for a 2nd time, r3 is now 0x80003000, keep repeating the instruction to keep increasing r3 by 0x1500. This is why some coders use stwu/lwu in certain loops. lwzu is just the opposite of stwu ofc.

Btw, your guide is a good learning bridge as sometimes tutorials (such as mine) can be too technical at times.
Reply
#13
Thanks! Although I have a few counter questions.


1. 
So this part is actually correct?


Code:
With Update = An address will be placed into a register after execution of an instruction.

Algebric = The user specified value in an instruction will be treated as a 32 bit value.

Indexed = Calculates an address after execution of an instruction





I sent the page to one of the people who helped with the guide (and is familiar with PowerPC) to get his input, but he never responded when I sent him these, what I wrote for those are mostly assumptions, are those the actual definitions?





2. 

Code:
An Fyi. Li is a simplified mnemonic for addi

i.e. li r1, 1 = addi r1, r0, 1 #Broadway treats r0 as literal 0 when it's used as a source register in this instruction
Do you know what specific instructions treat r0 like this? I want to label them for the guide. 
(I know in the sentence below you say that there are too many to list, but what are the main ones?)




3. 

Code:
In the Broadway manual i see nothing about bun, bnu, bdznt, bdnzf, and bdz branches. Are these present in other PPC chips? An fyi, the disassembler used in Dolphin is a generic PPC disassembler, so it will show instructions that simply don't exist in Broadway. Maybe these are simplified mnemonics not referenced in the manual?

Not a question. But look at page 523 - 526 of this pdf. There are many, many, many, many.... many.... many... branch instructions types........




4. 


Code:
example:
r3 = 0x80000000; VALUE = 0x1500
stwu r0, 0x1500 (r3)
Before instruction was executed; r3 was 0x80000000
After instruction has executed; r3 is now 0x80001500


In this context, what is r0 for? I've never really fully understood the "update" instruction types.





5.

Code:
Your definition for NOT is incorrect. NOT is not the negative of a value. Its a simplified mnemonic for NOR'ing a register with itself

Hmm, well the person I've been showing the page to told me it made values negative. But what exactly does it mean to "NOR" a value? I only know of the term of it.




6.



Code:
Regarding your quick description of an fpr, you should add in a note that the floating value is in its 64-bit form


I was going to put something like this, but on the psq description page on the smash forum I linked in another forum category here, it mentions that dolphin has a weird issue where it will display the same value twice in the fpr display in debug mode, even if it's not a double, something like that. It confused me, which means it most likely will confuse everyone else.





7.


Code:
Bit is not a single digit within a word (its not half of a byte).

What would be a better term I could put for what I labeled as a "bit" on the site?





Last Question

8. 

On the Operation Instructions Section of the site
What I put for AND and OR is actually correct? I just want to be sure, the person I've been showing the site too didn't respond about it yet.
Reply
#14
First, my bad on the xnor instruction. It's known as eqv in Broadway (.i.e. eqv rD, rA, rB)

1.  
With Update: Updates the Source Address with new value based on VALUE
Algebraic: I've never once used algebraic labeled instructions believe it or not.

Here's the definition of Load Half Word Algebraic btw (there's other algebraic instructions ofc such as sraw)
The halfword at the Effective Address is loaded in the lower 16 bits of rD. The remaining bits in rD are filled with a copy of the most significant bit of the loaded halfword. 

So if the halfword loaded of 0x8000, it will actually load as 0xFFFF8000. Cause the first bit in 0x8000 is 1. Fill every bit of 1 in the upper 16 bits is 0xFFFF.

Negative halfwords in memory take up 32-bits of space (i.e. 0xFFFFFFFD = -3). So what compilers can do to save space in memory is store negative halfwords via sth, so the lower 16 bits are stored to memory only, then the compilers can load these values later with lha to sign-extend them in the register. Example: store the halfword of 0xFFFF8000, will only store 0x8000 to memory, now load it with lha so it loads as 0xFFFF8000. Btw 0xFFFF8000 is -32768 and is the 'lowest' negative number for the 16-bit signed range

Indexed: No use of VALUE, instead another Source Register is used for the Effective Address calculation

2.
Some I know right off the bat...
addi, addis, subi, subis, addic., subic.
Every store/load instruction that is NOT lwm,stwm,lswi,stswi (i havent ever checked lswx, stswx btw). Actually I've never checked the other ones, a generic PowerPC manual I read ages ago claimed that. Btw the Broadway manual (from what ive seen) doesnt have a quick reference/list about instructions and literal 0. There is probably a small paragraph buried somewhere in the manual about it. You could go thru the pain of testing up a bunch of mock instructions with non-zero values in their source registers, and log the results.

3. A quick glance on the file shows its for PowerPC 405. Broadway is based off of PowerPC 750.

4. Its just for example. The point I was making is that the Source Register gets updated with a new value.

5. Whoever told you that is wrong. Compile a not r5, r3 instruction and a nor r5, r3, r3 instruction. It will compile as the same 32-bit code. Go on Dolphin, pause emulation, place in the value of 1 in r3. Execute a not r5, r3 instruction. r5 will equal -2 instead of -1. That's because every bit in a not instruction gets flipped.

Now redo this same example but use neg r5, r3. And r5 will then equal -1, which is obviously the negative value of positive 1.

6. Ye that's true, but even with that bug, floats are still displayed in 64 bit mode.

7. Example of a Register value 7843ABCF

Let's focus on the digit 7. A 4-bit binary combination of 0111 created that digit 7. Change that binary combination to let's say 1001 and that digit is now 9 so the word value is now 9843ABCF.

8. The definitions are not technically sound if that makes sense. There's other purposes for the use of OR and AND.

--

"Check if a register holds a 32-Bit value"

I would rename this as this can mean checking if anything is present in the upper 16 bits of a register.

Rename it to something like "Executing a comparison on a register with a value exceeding the 16-bit signed range"

Scruffy's example on discord is right, he just typo'd on the subis instruction.

Code:
subis r0, r1, 0xFFFFFFFE #Same thing as addis r0, r1, 2; take the upper 16 bits of your 32 bit value in r1, shift them in the lower 16 bits and then sign extend it, that's the value you will use for the subis instruction. 0xFFFE --> 0xFFFFFFFE

cmplwi r0, 0x5645 #Now check the result of the subis instruction with the lower 16 bits of your 32 bit value

Btw this actually won't work for your example on the site since your 32 bit value originated from r0. Because if you do something like subis r3, r0, 0xFFFFFFFE, it will just set r3 to 0x00020000 (subis rD, r0, VALUE is lis rD, VALUE). Then the cmplwi r3, 0x5645 instruction won't execute correctly.

You would need to add on a mr instruction to solve this issue. But then at the point you took 3 instructions to do everything, which means lis and ori would have also worked.

Also, don't use r1 for examples unless its for stack related stuff, as r1 is specifically designed to be the stack pointer in PPC.
Reply
#15
Thanks!
Believe it or not though, I still have a few more questions lol.

1. 
Code:
The halfword at the Effective Address is loaded in the lower 16 bits of rD. The remaining bits in rD are filled with a copy of the most significant bit of the loaded halfword.

What does "the most significant bit" mean?


2. 
Code:
Indexed: No use of VALUE, instead another Source Register is used for the Effective Address calculation

What would "With Update And Indexed" mean in this case? like with lwzux


3. 
Code:
Btw the Broadway manual (from what ive seen)

What manual are you reading? I've seen about 20 different ones at this point and they all have mostly different definitions for instructions, is there a "main" one?


4.

Code:
The definitions are not technically sound if that makes sense. There's other purposes for the use of OR and AND.

I referenced this thread when I wrote part of this, did I misunderstand what you wrote?

4.5
Code:
That's because every bit in a not instruction gets flipped.

Specifically, the person who told me about the not instruction said that it flips the value in a register, I just thought that meant making it negative.


5. 

Code:
"Check if a register holds a 32-Bit value"

I would rename this as this can mean checking if anything is present in the upper 16 bits of a register.

Rename it to something like "Executing a comparison on a register with a value exceeding the 16-bit signed range"

Not a question but I just wanted to say, Yeah, you're right. Although I'm leaving it as it is because I'm trying to get too technical on the page so that slow learners (like myself) don't get too confused by the terms.


6. 
Code:
Btw this actually won't work for your example on the site since your 32 bit value originated from r0

Also, don't use r1 for examples unless its for stack related stuff, as r1 is specifically designed to be the stack pointer in PPC.

Also not a question, just wanted to clarify. I'm using r0 and r1 for example purposes, I got a bit of a headache when I was trying to learn some of the instructions at first because of the register ranges (ex: r4, r22, r11) etc. I've just found it easier to use r0 and r1 as examples.

Thanks for taking the time to answer all of these btw. Most people would've gotten annoyed by the amount of questions I ask.
Reply
#16
(06-27-2021, 10:23 PM)JimmyKazakhstan Wrote: Thanks for taking the time to answer all of these btw. Most people would've gotten annoyed by the amount of questions I ask.

No worries at all. I like teaching people this stuff as long as they are truly willing to learn and put in the work

1.
The first bit of a value is its most significant bit. It's also known as bit 0. Some PPC manuals may refer to bit 0 as the 'sign' bit as that is the bit alone that determines whether or not a value is negative as long as that particular instruction treats its values as signed to begin with.

i.e. 0x80000000 = negative, bit 0 (sign bit) has the value of 1. Binary value of 1000 makes the hex digit 8.

The final bit of a value is the least significant bit. Also known as bit 31.

---

2. Update and Indexed is simply the combination of both.

Let's break down a simple stwx instruction first

Example:
stwx r3, r4, r5

r3 = 0x00000001
r4 = 0x00002000
r5 = 0x80000000

Instead of having a 16-bit Immediate VALUE being used to calculate the address of where the store will be done at in memory (VALUE + Source Register), that calculation is done with two source registers being added together.

r4 + r5 = 0x80002000 #This is the address in memory where the word value of r3 (0x00000001) will be stored at after the instruction has executed.

Now let's break down a stwu instruction, just as a refresher
stwu r3, 0x2000 (r5)

Using same values for r3 and r5 as before, for the first time this instruction is executed 0x2000 is added to r5 to calculate the address where r3's word value is stored to, so it stores to 0x80002000. However after that store occurs, r5 gets incremented by 0x2000 to 0x80002000. If you execute the instruction a 2nd time you are now adding 0x2000 to 0x80002000 so r3's word will store at 0x80004000. Every time you execute this instruction r5 keeps increasing by 0x2000.

Ok now finally going to a stwux instruction
stwux r3, r4, r5

r3 = 0x00000001
r4 = 0x80000000
r5 = 0x00002000

In any update+indexed storing/loading instruction; the register that gets incremented with the new value is the 1st source register (the middle register, NOT the far right register)

Anyway, first time this instruction executes, take r4 +r5, so r3's word stores at 0x80002000. Then r4's value gets incremented by r5's value. So if you execute this instruction a 2nd time, r4 is now 0x80002000 when you add it with r5, you get 0x80004000. Thus r3's word value now stores at 0x80004000. r4's value keeps incrementing by r5's value every time the instruction gets executed

The only reason you would need a stwux/lwux type instruction is the amount you wanna keep increasing exceeds the 16-bit signed limit (0xFFFF8000 thru 0x7FFF)

--

3.
Google something like "pokeacer Broadway Manual" and you will be able to find the actual Broadway manual, I can't host it on this site for obvious reasons

---

4.
That's just one clever usage for OR'ing. There's many other purposes for OR.

---

6.
Just be careful using examples of r0, because of the literal 0 rule in certain instructions. Stick to r3 thru r12; r14 thru r31 for example purposes. r1 is the sp (stack pointer), r2 is rtoc (register table of contents) and r13 is used as a global type of pointer which should never be modified that points to a small region of important data.
Reply
#17
Thanks again!


Code:
No worries at all. I like teaching people this stuff as long as they are truly willing to learn and put in the work

Yeah this is me, I'm more than willing to learn things if I'm able to understand enough of it. Would you mind in the future if I ask you more questions about certain instructions before I add them on the guide here?

Anyways I have 2 final questions.


1. 
Code:
2. Update and Indexed is simply the combination of both.

Let's break down a simple stwx instruction first
Thanks for this example, but would you mind making one for lwzx/lwzxu? I want to try and learn the "Load" instruction types before the store ones.


2.
This isn't on the guide, but it's a question I have.
Apparently there's an instruction called "blrl" (Branch to Link Register + Link). Do you know anything about how this instruction works? Or would I ever need to use it in a code? I'm just wondering about it.
Reply
#18
I don't mind at all.


1. Loads are just the opposite of stores. Stores copy a value from a register to a spot in memory, while loads copy a value from a spot in memory to a register. The same basic rules of stwx/stwu/stwux apply to the load versions as well.

2. It's just like bctrl except you jump to the address in the LR instead of the CTR. Then executing a blr later will have you jump back where you left off.
Reply
#19
so blrl is the following?
 


blrl
Branch To Link Register And Link
Your code will jump to the address that you put in the Link Register, the function that gets jumped to will be ran until a blr statement is reached, once it gets reached, The code will jump back to the blrl instruction and execute the next instruction down.
 
 

Reply
#20
Yes.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)