ASM Branch backwards

Started by live2play, October 07, 2010, 04:52:17 AM

Previous topic - Next topic

live2play

I know that I can perform a "b 0x08" to skip the next instruction, but how do I branch to a previous instruction using "b"?

dcx2

#1
Use a negative branch displacement operand.  Branching to the previous instruction would be b -4.  The exact hex value depends on what type of branch you're doing.  EDIT: the reason is because negative values are sign extended; positive values get "filled" with 0's, while negative values get "filled" with 1's.  That's why -4 turns into so many F's.

For an unconditional branch, you have 26 bits for the branch displacement operand.  That means 0x3FFFFFC.  http://pds.twi.tudelft.nl/vakken/in1200/labcourse/instruction-set/b.html

For a conditional branch, 16 bits.  0xFFFC.  http://pds.twi.tudelft.nl/vakken/in1200/labcourse/instruction-set/bc.html

Remember that instructions must be word-aligned.  That means the two LSBs, 30 and 31, will always be 0.  They are therefore used to specify absolute/relative (30) and link (31) bits.  So I kinda lied...you really only have 24/14 bits that you can actually use.  But you get the full range anyway due to alignment.

---

In practice, if you're using an assembler and branch labels, you don't even notice.  This is from my SMG2 teleportation code.  It's a loop; the bdnz+ will dec the CTR register and branch to TOP_OF_LOOP if CTR is not 0.

TOP_OF_LOOP:
lfsu f1,4(r31)
lfsu f2,4(r12)
fnmsubs f1,f0,f1,f2   # f1 = coords – (scale * orientation)
stfs f1,0(r12)
bdnz+ TOP_OF_LOOP

EDIT2:

You may be asking what the + and - after the branch mean.  Those are hints for the conditional branch.  If you look at the datasheet for bc above, you will see the BO operand.  One of the bits in the BO operand is y.  The y bit is a hint that tells the CPU whether or not the branch will usually be taken.  + means "this branch will probably be taken" and - means "probably not taken".  The PPC is allowed to use this bit to improve performance, although that may or may not be true for the chip in the Wii.

In general, branches backwards are assumed to be loops and therefore usually taken, and have a + associated with them.  Branches forward are assumed not taken and get a -.

live2play

#2
As always, very informative.  Thanks!

EDIT:  Will ASMWiiRD handle labels (TOP_OF_LOOP:)?

Romaap

Quote from: live2play on October 07, 2010, 05:57:23 AM
As always, very informative.  Thanks!

EDIT:  Will ASMWiiRD handle labels (TOP_OF_LOOP:)?
Nope, but Hawkeye2777 made this awesome app called PyiiASMH which can do the same as ASMWiiRD but more. (like labels)

dcx2

Mathew_Wi once posted that ASMWiiRD can do labels.  I never got it to work, though.

PyiiASMH does branch labels and comments.

Deathwolf

#5
lol this works by ASM to WiiRD?

btw I thought bdnz+ will write 40000000...?
lolz

matt123337

The heck, I said that it did, not Mathew_Wi :S

dcx2

My bad, matt123337's post is the one I was thinking of, although I think Mathew_Wi also told me at one point.

bdnz+ will decrement the CTR register and branch if the result is not equal to zero.

Deathwolf

so you can write floatings with those instructions?

3F800000 = lis r28,0
40000000 = bdnzf- 0,0x
42000000 = bdnz- 0x
lolz

dcx2

What you are saying makes no sense.  bdnz- 0 does not *write* 42000000.

Computers use 1's and 0's to represent things.  The computer does not "see" the assembly code bdnz- 0.  The computer "sees" the machine code 42000000.  But it's difficult for humans to read machine code.  So we use a disassembler to turn 42000000 into bdnz- 0.

The fact that 0x42000000 is also a floating point value = 32.0 is irrelevant.  0x42000000 is also the integer 1,107,296,256.

Deathwolf

write value 42000000 at address 80123456

42000000 = bdnz- 0x80123456
lolz