Logical Operations for PPC ASM
#1
Logical Operations for PPC ASM

For ASM Coders who already know the basics.



Chapter 1: Fundamentals

Logical Operation Instructions are Instructions that compute a result using Binary/Bit operation. We need to go over some basic vocab first before diving into actual Instructions.

The term "high" or "true" refers to when a Bit has a value of 1.
The term "low" or "false" refers to when a Bit has a value of 0.

The far left-hand bit of any value in a register is known as the "Sign Bit" or the "Most Significant Bit" (aka MSB). The far right-hand bit of any value in a register is known as the "Least Significant Bit" (aka LSB).

Each Bit has an assigned number that we use for easy reference, so other coders can know which bit within a register we are talking about. The MSB is bit 0. The LSB is bit 31. The bit numbers ascend as you move from left to right within a register.

The far left hand bit (first bit) is bit 0. Next bit is bit 1. Then bit 2. All the way until you hit the LSB which is bit 31. Since bit numbering ascends from left to right, this is called "Big Endian" (there's more to the term Big Endian, we're just talking about the bit numbering system).

Logical Operations are done on a bit-by-bit basis! It's important to understand this.

Let's say we have a value in r3 and we preform a logical operation instruction with the value in r27. Bit 0 of r3 will have a logical operation done in reference to bit 0 of r27. Bit 1 of r3 will have an operation done in reference to bit 1 of r27. Bit 2 of r3 will have a logical operation done in reference to bit 3 of r27, and so on and so on.

There are a maximum of 6 types of Logical Operations, they are...
  • Logical OR
  • Logical AND
  • Logical XOR
  • Logical NOR (also known as Logical Not OR)
  • Logical NAND (also known as Logical Not AND)
  • Logical XNOR (also known as Logical EQV or as Logical Not XOR)

The easiest way to understand each Logical Operation is with its corresponding truth table. A truth table is a table/list of the results of all 4 combinations of possible bit operations for a Logical Operation. Each Logical Operation has a unique truth table. They are actually not too hard to remember. You simply need to remember or, and, & xor. After that the other 3 truth tables (nor, nand, xnor respectively) are the just the the flipped versions of the original 3.



Chapter 2: Logical OR

Logical ORing is one of the most commonly used logical operations. ORing means if at least value#1 or value#2 is true, then the result is true.

Truth Table:

Code:
Bit Value rA  Bit Value rB Bit Result rD
0                0            0
0                1            1
1                0            1
1                1            1

Scaling up from binary to a hex word value, if r3 has a value of 0x00000001, and r27 has a value of 0x80000001, and these two values are OR'd together, it would produce a result of 0x80000001. Confused by this? let's break it down in binary view...

r3  - 0000 0000 0000 0000 0000 0000 0000 0001
r27 - 1000 0000 0000 0000 0000 0000 0000 0001

Remember Logical Operations are done on a per-bit basis. What occurs is this....
  • Bit 0 of r3 is Logically OR'd with Bit 0 of r27. 0 OR'd with 1 = 1.
  • Bit 1 of r3 is Logically OR'd with Bit 1 of r27. 0 OR'd with 0 = 0.
  • Bit 2 of r3 is Logically OR'd with Bit 2 of r27. 0 OR'd with 0 = 0.
  • etc... etc..
  • Bit 31 of r3 is Logically OR'd with Bit 31 or r27. 1 OR'd with 1 = 1.

Every bit in the Source Register will have the Logical Operation done with its corresponding bit in the other Source Register/Immediate Value. Okay let's look at the full result in Binary view...

1000 0000 0000 0000 0000 0000 0000 0001

Convert that to Hex and you get 0x80000001.

Broadway comes with the following Logical OR instructions:

Code:
or rD, rA, rB #rA is OR'd with rB, result placed in rD. This instruction comes with the ability to use the Record feature (free use of cmpwi rD, 0).

ori rD, rA, UIMM #rA is OR'd with 0x0000VVVV with VVVV being UIMM, the result is placed in rD.

oris rD, rA, UIMM #rA is OR'd with 0xVVVV0000 with VVVV being UIMM, the result is placed in rD.

Referring back from the beginner's Assembly Tutorial HERE, you should now have an understanding of why the usage of the lis and ori instructions are preformed to write entire 32-bit (word) values from scratch to a GPR.

You may find yourself in a scenario where you need set a bit high and not mess with the other bits in a register. Here's an example where we need load a value into a register, set its bit value high, then store the value back.

Code:
lwz rX, 0xZZZZ (rY)
oris rX, rX, 0x8000
stw rX, 0xZZZZ (rY)

Fyi: nop is a simplified mnemonic of ori r0, r0, 0x0000
Fyi: mr rD, rA is a simplified mnemonic of or rD, rA, rA #rA is logically OR'd with itself



Chapter 3: Logical AND

Another commonly used logical operation is AND. AND means if both inputs are true, then the result is true, otherwise the result is always false. Here is the Truth Table for AND~

Code:
Bit Value rA  Bit Value rB Bit Result rD
0                0            0
0                1            0
1                0            0
1                1            1

ANDing operations for Broadway:

Code:
and rD, rA, rB #rA is AND'd with rB; result in rD. Comes with a Record feature if needed.

andi. rD, rA, UIMM #rA is AND'd with 0x0000VVVV with VVVV being UIMM, the result is placed in rD. A form of this instruction withOUT the Record feature does NOT exist. The upper 16 bits of rD will always result in 0x0000!

andis. rD, rA, UIMM #rA is AND'd with 0xVVVV0000 with VVVV being UIMM, the result is placed in rD. A form of this instruction withOUT the Record feature does NOT exist. The lower 16 bits of rD will always result in 0x0000!

ANDing can be a good way to check if certain bits are high. Let's say a r19 has a value and you want to check if bit 30 is high. If not, take the branch

Code:
andi. r0, r19, 0x0002 #Temporarily use r0 to place result in.
bne- some_label

If you were wanting to check if multiple bits are all high, you will need to add in a comparison instruction. Let's redo the same example as earlier but now check if BOTH bots 30 and 31 are high. If not, take branch.

Code:
andi. r0, r19, 0x0003
cmpwi r0, 0x0003
bne- some_label

If you only cared if either one was high, then you don't need the 'cmpwi r0, 0x0003' instruction.



Chapter 4: Logical XOR

XOR aka Exclusive OR is a logical operation that is also pretty common. Logical XOR's only produce a true result when the inputs are opposite values. If both inputs are the same bit value, then the result is always false.

Truth Table of XOR:

Code:
Bit Value rA  Bit Value rB Bit Result rD
0                0            0
0                1            1
1                0            1
1                1            0

XORing operations for Broadway:

Code:
xor rD, rA, rB #rA is XOR'd with rB; result in rD. Comes with a Record feature if needed.

xori rD, rA, UIMM #rA is XOR'd with 0x0000VVVV with VVVV being UIMM, the result is placed in rD.

xoris rD, rA, UIMM #rA is XOR'd with 0xVVVV0000 with VVVV being UIMM, the result is placed in rD.

A handy trick with XOR is that it can be used to flip a bit value regardless of what the current bit value is. Let's say you are working on a code where r31 is either 0 or 1. For whatever reason, you need this value to flipped (0 to 1; 1 to 0) in your code. A beginner ASM Coder who isn't familiar with XORing might write a source like this..

Code:
#Check r31
cmpwi r31, 0

#Preset r31 to 1 before branch
li r31, 1

#Do branch. If branch is taken, r31 was originally 0 and is now 1, we're done
beq- done

#r31's original value was 1, make it 0
li r31, 0

#Done
done:

That source is frankly silly. Since r31's value (0 or 1) is determined by bit 31 alone, you can simply XOR bit 31 with the value of 1 to flip r31's value.

Code:
xori r31, r31, 0x0001 #Flip slot value. 0 = 1, 1 = 0. Place result in back in r31.

Another trick for XOR'ing is using it as a glorified bit 'subtraction' (removal) mechanism. Check out the source of this code (has logical AND, XOR, & OR) - https://mariokartwii.com/showthread.php?tid=48

What the source is doing is..
1. Checking if a button (key #1; XXXX value) was at least hit (notice the logical AND usage)
2. If so, flip that button's bit low (notice the XOR usage)
3. Make key #2 (YYYY value) button bit high (notice the OR usage)
4. End code with original/default instruction

In conclusion if you need to 'flip' a bit, logical XORing is what you need.



Chapter 5: Other Logical Operations

Broadway also comes with...
  • nor (includes Record feature)
  • nand (includes Record feature)
  • eqv #also known as xnor but you must use the operand eqv in the compiler (includes Record feature)

Logical NOR is the exact opposite of OR. So if any ORing result would be 0, then NOR's result would be 1 and vice versa.

Truth Table of NOR

Code:
Bit Value rA  Bit Value rB Bit Result rD
0                0            1
0                1            0
1                0            0
1                1            0

If you logically NOR a value with itself, you will actually just flip every bit to it's opposite value. This is known as a logical NOT. You can use the simplified mnemonic 'not' to preform this type of operation.

Code:
not rD, rA #same this as nor rD, rA, rA

Logical NAND is the opposite of AND.

Truth Table of NAND

Code:
Bit Value rA  Bit Value rB Bit Result rD
0                0            1
0                1            1
1                0            1
1                1            0

Truth Table of EQV aka XNOR (Exclusive NOR); it's the opposite of XOR.

Code:
Bit Value rA  Bit Value rB Bit Result rD
0                0            1
0                1            0
1                0            0
1                1            1



Chapter 6: Conclusion

Understanding logical operation instructions is a must if you are working on a code that has a value in a register that uses bits to represent something such as a characters, levels, maps, items, etc. Happy coding!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)