BO
operand of the conditional branch (controlling the mode) can be used,
in addition to specifying how to test condition register bits, to
decrement and test the count register. There are two operations you can
do with the count register:
- decrement the count register and branch if it becomes zero
- decrement the count register and branch if it becomes nonzero
In the extended mnemonics, the count register semantics are specified by adding either
dz
or dnz
immediately after the b
.
Any additional condition or instruction modifier is added after that.
So, to have a loop repeat 100 times, you would load the count register
with the number 100, and use bdnz
to control the loop. Here is how the code would look:
Listing 6. Counter-controlled loop example
#The count register has to be loaded through a general-purpose register #Load register 31 with the number 100 li 31, 100 #Move it to the count register mtctr 31 #Loop start address loop_start: ###loop body goes here### #Decrement count register and branch if it becomes nonzero bdnz loop_start #Code after loop goes here
Listing 7. Count register combined branch example
#The count register has to be loaded through a general-purpose register #Load register 31 with the number 100 li 31, 100 #Move it to the count register mtctr 31 #Loop start address loop_start: ###loop body goes here### #Check for early exit condition (reg 24 == reg 28) cmpd 24, 28 #Decrement and branch if not zero, and also test for early exit condition bdnzf eq, loop_start #Code after loop goes here
Putting it together
Now we will put this information to practical use.The first program will be a rewrite of the maximum value program we entered in the first article, and rewrite it according to what we have learned. The first version used a register to hold the current address being read from, and the code used indirect addressing to load the value. What this program will do is use an indexed-indirect addressing mode, with a register for the base address and a register for the index. In addition, rather than the index starting at zero and going forward, the index will count from the end to the beginning in order to save an extra compare instruction. The decrement can implicitly set the condition register (as opposed to an explicit compare with zero), which can then be used by a conditional branch instruction. Here is the new version (enter as
max_enhanced.s
):
Listing 8. Maximum value program enhanced version
###PROGRAM DATA### .data .align 3 value_list: .quad 23, 50, 95, 96, 37, 85 value_list_end: #Compute a constant holding the size of the list .equ value_list_size, value_list_end - value_list ###ENTRY POINT DECLARATION### .section .opd, "aw" .global _start .align 3 _start: .quad ._start, .TOC.@tocbase, 0 ###CODE### ._start: .equ DATA_SIZE, 8 #REGISTER USAGE #Register 3 -- current maximum #Register 4 -- list address #Register 5 -- current index #Register 6 -- current value #Register 7 -- size of data (negative) #Load the address of the list ld 4, value_list@got(2) #Register 7 has data size (negative) li 7, -DATA_SIZE #Load the size of the list li 5, value_list_size #Set the "current maximum" to 0 li 3, 0 loop: #Decrement index to the next value; set status register (in cr0) add. 5, 5, 7 #Load value (X-Form - add register 4 + register 5 for final address) ldx 6, 4, 5 #Unsigned comparison of current value to current maximum (use cr2) cmpld cr2, 6, 3 #If the current one is greater, set it (sets the link register) btl 4*cr2+gt, set_new_maximum #Loop unless the last index decrement resulted in zero bf eq, loop #AFTER THE LOOP -- exit li 0, 1 sc set_new_maximum: mr 3, 6 blr (return using the link register)
as -a64 max_enhanced.s -o max_enhanced.o ld -melf64ppc max_enhanced.o -o max_enhanced ./max_enhanced
Note that using the link register in the call to
set_new_maximum
is not strictly necessary. It would have worked just as well to set
the return address explicitly rather than using the link register.
However, this gives a good example of link register usage.
No comments:
Post a Comment