Reputation: 91
I just want to check my understanding of these two concepts is correct, as I have been trying to finish a project and while everything works to my expectations, it keeps narrowly failing the test cases and introducing a random value...
Basically, the objective of the project is to write out a branch instruction to console in this form:
BranchName $S, [$t, if applicable] 0xAbsoluteAddressOfBranchTargetInstruction
Edit: Clarification: I'm writing this in MIPS. The idea is I get a memory address in $a0 given to the program by my instructor's code (I write the function). The address is for the word containing a MIPS instruction. I'm to do the following:
IE:
BEQ $6, $9, 0x00100008
Firstly, is my understanding of branch calculation correct?
Secondly, could somebody tell me which bits I need to isolate to know what kind of branch I'm dealing with? I think I have them (first 6 for BEQ/BNE, first 16 with $s masked out for others) but I wanted to double check.
Oh, and finally... should I expect deviation on SPIM from running it on an Intel x86 Windows system and an Intel x86 Linux system? I'm getting a stupid glitch and I cannot seem to isolate it from my hand-worked address calculations, but it only shows up when I run the test scripts my prof gave us on Linux (.sh); running directly in spim on either OS seems to work... provided my understanding of how to do the hand calculations (as listed above) is correct.
Upvotes: 0
Views: 944
Reputation: 33601
This is prefaced by my various comments.
Here is a sample program that does the address calculation correctly. It does not do the branch instruction type decode, so you'll have to combine parts of this and your version together.
Note that it uses the mars
syscall 34 to print values in hex. This isn't available under spim
, so you may need to output in decimal using syscall 1 or write your own hex value output function [if you haven't already]
.data
msg_best: .asciiz "correct target address: "
msg_tgt: .asciiz "current target address: "
msg_nl: .asciiz "\n"
.text
.globl main
main:
la $s0,inst # pointer to branch instruction
la $s1,einst # get end of instructions
subu $s1,$s1,$s0 # get number of bytes
srl $s1,$s1,2 # get number of instruction words
la $s2,loop # the correct target address
la $a0,msg_best
move $a1,$s2
jal printaddr
loop:
move $a0,$s0
jal showme # decode and print instruction
addiu $s0,$s0,4
sub $s1,$s1,1
bnez $s1,loop # more to do? yes, loop
li $v0,10
syscall
# branch instructions to decode
inst:
bne $s0,$s1,loop
beq $s0,$s1,loop
beqz $s1,loop
bnez $s1,loop
bgtz $s1,loop
bgez $s1,loop
bltz $s1,loop
blez $s1,loop
einst:
# showme -- decode and print data about instruction
#
# NOTE: this does _not_ decode the instruction type
#
# arguments:
# a0 -- instruction address
#
# registers:
# t5 -- raw instruction word
# t4 -- branch offset
# t3 -- absolute address of branch target
showme:
subu $sp,$sp,4
sw $ra,0($sp)
lw $t5,0($a0) # get inst word
addiu $t3,$a0,4 # get PC + 4
sll $t4,$t5,16 # shift offset left
sra $t4,$t4,16 # shift offset right (sign extend)
sll $t4,$t4,2 # get byte offset
addu $t3,$t3,$t4 # add in offset
# NOTE: as a diagnostic, we could compare t3 against s2 -- it should
# always match
la $a0,msg_tgt
move $a1,$t3
jal printaddr
lw $ra,0($sp)
addu $sp,$sp,4
jr $ra
# printaddr -- print address
#
# arguments:
# a0 -- message
# a1 -- address value
printaddr:
li $v0,4
syscall
# NOTE: only mars supports this syscall
# to use spim, use a syscall number of 1, which outputs in decimal and
# then hand convert
# or write your own hex output function
move $a0,$a1
li $v0,34 # output number in hex (mars _only_)
syscall
la $a0,msg_nl
li $v0,4
syscall
jr $ra
Upvotes: 1
Reputation: 6586
The 16 bit immediate value is sign-extended to 32 bits, then shifted. I don't know if that would affect your program; but, that's the only potential "mistake" I noticed.
Upvotes: 1