Download Class 11.2 Set Instructions and more Branch Instructions

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Class 11.2
Set Instructions and more Branch Instructions.
Set Instructions
This chapter describes two additional branch instructions and several conditional set instructions.
Set instructions set a register to 1 or 0 depending on whether a condition is true or false.
These new instructions help you to implement loops and branches.
Branch on Less than Zero,
Branch on Greater than Zero
MIPS has several ways to implement relational operators. Here are two more branch instructions.
These instructions compare the contents of a register to zero. The register's contents is assumed
to be in two's complement representation.
bltz
s,label
bgez
s,label
#
#
#
#
#
#
Branch if the two's comp. integer
in register s is < 0
A branch delay slot follows the instruction.
Branch if the two's comp. integer
in register s is >= 0
A branch delay slot follows the instruction.
The first instruction branches if the integer is strictly less than zero. The other branches if the
integer is greater than or equal to zero.
Both of these instructions are followed by a branch delay slot. This means that
the instruction in that slot will always execute, and the branch (if it happens)
will not happen until after that instruction finishes.
Set on Less Than
The set instructions are used to implement relational operators. However, they do not in
themselves alter the flow of control. They set a register to 1 or 0 to show the relation between two
values. The slt instruction is used with two's complement integers:
slt
d,s,t
#
#
#
#
#
#
#
$s and $t contain
two's comp. integers
if ( $s < $t )
d <-- 1
else
d <-- 0
1
The sltu instruction is used with unsigned integers:
sltu
d,s,t
#
#
#
#
#
#
#
$s and $t contain
unsigned integers
if ( $s < $t )
d <-- 1
else
d <-- 0
These instructions be used with character data. If the characters to be compared are loaded in
the low-order byte of two registers, and the rest of the bits are zero, either instruction could be
used.
Set on Less Than Immediate
The other two set instructions compare an operand register with an immediate value in the
instruction. There is a version for two's complement:
slti
d,s,imm
#
#
#
#
#
#
#
$s and imm contain
two's comp. integers
if ( $s < imm )
d <-- 1
else
d <-- 0
And a version for unsigned integers:
sltiu
d,s,imm
#
#
#
#
#
#
#
$s and imm contain
unsigned integers
if ( $s < imm )
d <-- 1
else
d <-- 0
How is the 16-bit immediate field extended to 32 bits for the comparison?


slti: by sign extension.
sltiu: by zero extension.
2
Temperature Range Tester
Say that you are writing a control program for a robot spray painter. The allowed temperature
range for the paint is 30 degrees to 55 degrees Celsius. The device driver for the temperature
sensor puts the temperature in register $2.
Your program will test if the unsigned integer in register $2 is in range. If it is in range, register $3
is set to 1, otherwise to 0.
The flowchart for the program is at right. The trick of setting a
flag to a default value in advance of the test is common.
The range test is in two parts. The first part (in this program)
tests if temp is less than or equal to 55. However, the machine
instruction is "set on less than". If temp is out of range a branch
is taken to out. The branch is followed by a no-op for the
branch delay.
The immediate operand used in the set instruction is changed
to 56 to implement "less than or equal". Notice that the
assembly language uses decimal numbers for temperatures.
This is fine. The assembler translates the decimal
representation of the source file into the correct bit pattern for
the machine instruction.
The next part of the program tests if temp is less than 30. Be
careful with the branch instruction so that it branches for the
correct condition.
Here is the complete program, suitable to copy to a file and to run with SPIM. When you run it, set
the PC to 0x400000 (as usual) and also use the set value menu to set R2 to a temperature. Run
the program with different temperatures and check that $3 is set correctly.
3
##
##
##
##
##
##
##
##
##
tempRange.asm
Check that
30 <= temp <= 55
Set flag to 1 if in range, to 0 if out of range
Registers:
$2 --- temperature
$3 --- in/out range indicator flag
$8 --- scratch
.text
.globl
main
# Set range indicator to 1
main:
ori
$3,$0,1
# Test
#
set to 1
30 <= temp <= 55
sltiu
$8,$2,56
beq
$8,$0,out
sll
$0,$0,0
#
#
#
$8=1 if temp <= 55
0? out of range
delay
sltiu
beq
sll
#
#
#
$8=1 if temp < 30
0? in range
delay
$8,$2,30
$8,$0,cont
$0,$0,0
# Out of Range: set range indicator to 0
out:
ori
$3,$0,0
# clear to 0
cont:
sll
## End of file
$0,$0,0
#
target for the jump
Delay Slot Bug
The program can be made slightly shorter by removing the no-op instruction filling the first delay
slot. The instruction following it (the sltiu) will always execute, sometimes uselessly, but never
will do damage.
The second no-op, however, is essential. If it is missing, the next instruction, the ori sets the flag
to zero regardless of the branch instruction. This is a common bug, and can be very frustrating
because sometimes the result is correct.
4
Counting Loop
A common program loop is controlled by an integer that counts up from an initial value to an
upper limit. Such a loop is called a counting loop. The integer is called a loop control variable.
Loops are implemented with the conditional branch, jump, and conditional set instructions.
A loop has three parts that must be correct:
1. The counter must be initialized.
2. The test must end the loop on the correct count.
3. The counter must be increased.
It is easy to get these wrong in a high-level programming language. It is
remarkably easy to get them wrong in assembly language.
Usually you want a top-driven loop such as the one at right, where the
test is performed at the top before control enters the loop body. Be clear
about the loop you want before you program it, because assembly
language allows any sort of weird loop.
Here is the loop in C. It is intended to execute 10 times starting at zero.
int j;
j = 0;
while ( j < 10 )
{
. . .
j++ ;
}
Here is an assembly version of the counting loop:
#
# branch delay slots filled
#
init:
ori
$8,$0,0
# count = 0
test:
sltiu
beq
sll
$9,$8,10
$9,$0,endLp
$0,$0,0
# count < 10
# end loop if count >= 10
# delay
# do stuff
endLp:
addiu
j
sll
$8,$8,1
test
$0,$0,0
# count++ ;
sll
$0,$0,0
# branch target
# delay
5
The no-op at endLp is not filling a branch delay slot. It is there for convenience in running the
program with SPIM.
We could modify the program to compute the sum of the integers 0 through 9.
The loop is already correct for the problem. Computing the sum is done by adding just two
statements:
## sumint.asm
##
## Sum of integers 0 .. 9
##
## Registers:
## $8 --- loop control
## $9 --- scratch
## $10 --- sum
init:
test:
endLp:
ori
ori
sltiu
beq
sll
$10,$0,0
$8,$0,0
$9,$8,10
$9,$0,endLp
$0,$0,0
#
#
#
#
#
sum = 0
count = 0
count < 10
end loop if count >= 10
delay
addu
$10,$10,$8
# sum += count
addiu
j
sll
$8,$8,1
test
$0,$0,0
# count++ ;
sll
$0,$0,0
# jump target
# delay
In the Settings menu of SPIM set Bare Machine ON, Allow Pseudo Instructions OFF, Load Trap
File OFF, Delayed Branches ON, Delayed Loads ON.
Run the programs by setting the value of the PC to 0x400000 and then single stepping (pushing
F10) or by multiple stepping (push F11 and enter a number of steps). Observing the results in the
SPIM window.
6