C to MIPS translation: decoder

-1

We're given the following code in C and asked to translate it into MIPS. We don't need to handle lo and hi; they're stored for us in $a0 and $a1:

void decode_request(unsigned long int request, int* array) {

   // lo and hi are already stored for us in $a0 and $a1
  unsigned lo = (unsigned)((request << 32) >> 32);
  unsigned hi = (unsigned)(request >> 32);

  for (int i = 0; i < 6; ++i) {
    array[i] = lo & 0x0000001f;
    lo = lo >> 5;
 }
  unsigned upper_three_bits = (hi << 2) & 0x0000001f;
  array[6] = upper_three_bits | lo;
  hi = hi >> 3;

  for (int i = 7; i < 11; ++i) {
    array[i] = hi & 0x0000001f;
    hi = hi >> 5;
  }

This is my attempt of it:

.globl decode_request
decode_request:
    li      $t0, 0      # int i = 0;

first_loop:
    bge $t0, 6, after_first_loop    # branch if greater than or equal to 6
    mul $t0, $t0, 4 # account for ints; storage size = word
    and $t1, $a0, 0x0000001f # lo & 0x0000001f;
    sw $t1, 4($t1) # array[i] = lo & 0x0000001f;
    srl $t2, $a0, 5 # lo >> 5;
    sw $t2, 0($t2) # lo = lo >> 5;
    add $t0, $t0, 1 # ++i
    j first_loop # jump back to top of loop

after_first_loop:
    sll $t3, $a1, 2 # (hi << 2)
    and $t3, $t3, 0x0000001f # & 0x0000001f
    mul $t3, $t3, 4 # account for ints; storage size = word
    sw $t3, 0($t3) # store back into memory
    or $t4, $t3, $a0 # array[6] = upper_three_bits | lo;
    sw $t4, 24($t4) # store back into memory; use 24 since int = 4 bytes and we have offset of 6
    srl $a1, $a1, 3 # hi >> 3;
    sw $a1, 0($a1) # hi = hi >> 3;

second_loop:
    li $t5, 7 # int i = 7;
    bge $t0, 11, end    # branch if greater than or equal to 11
    mul $t5, $t5, 4  # account for ints; storage size = word
    and $t6, $a1, 0x0000001f # hi & 0x0000001f
    sw $t6, 4($t6) # array[i] = hi & 0x0000001f;
    srl $t7, $a0, 5 # hi >> 5;
    sw $t7, 0($t7) # lo = lo >> 5;
    add $t5, $t5, 1 # ++i
    j second_loop # jump back to top of second_loop
end:
    jr  $ra

Any ideas as to where I could be going wrong, or possibly other approaches?

Thank you!

c
mips
code-translation
asked on Stack Overflow Feb 27, 2019 by Mark T.

2 Answers

1

I have corrected the first part of your code. And 80% of instructions where incorrect syntactically. This is something that the asm should have told you. And many, many logical errors. One of the main is that you need to manage addresses of the array elements.

decode_request:
    li      $t0, 0      # int i = 0;
### we assume $t4=@array and $t5=array[i]

    add $t5, $t4, zero  ## t5=&array[0]
first_loop:
### bge is bge reg1, reg2, offset. Cant use an immediate
### slti does a compare and then a branch is possible
    sltiu $t1, $t0, 6                  # i<6 ?
    beq $t0, zero, after_first_loop    # false ? goto end first loop
### i=i*4??? what is it supposed to do?
####mul $t0, $t0, 4 # account for ints; storage size = word
### and $t1, $a0, 0x0000001f ... should be andi
    andi $t1, $a0, 0x0000001f # lo & 0x0000001f;
### not sw $t1, 4($t1) which does not make sense
### array[i] is $t5 and data to store is $t1
    sw $t1, 0($t5) # array[i] = lo & 0x0000001f;
    srl $t2, $a0, 5 # lo >> 5;
### why do you want to store lo? Just keep it is register $t2.
### And your store is anyway incorrect. Should be sw $t2,0($t6) 
####                           where $t6 is the address of lo
##    sw $t2, 0($t2) # lo = lo >> 5;
### add add $t0 ... should be addi
    addi $t0, $t0, 1 # ++i
#### and you must increment array address
    addi $t5, $t5, 4 # $t5++ -> $t5==array[i+1]
    j first_loop # jump back to top of loop

Now try to correct the rest of your program. Errors in the asm should be explicit.

answered on Stack Overflow Feb 28, 2019 by Alain Merigot
0

I've used Alain's corrections to try and do the second loop

loop_two:
# these loops go from 0-5 and then from 7-10
# since t5 has been incremented each time, $t5 = array[5]
# have to add 8 to get $t5 = array[7]
# do this in between_loops
slti $t7, $t6, 11              # i < 11 ?
beq $t6, zero, end                       # if false, done with loop, go to end

# loop body goes here
andi $t6, $a1, 0x0000001f        # hi & 0x0000001f
# array[i] is $t5 and data to store is $t6
sw $t6, 0($t5)                               # array[i] = hi & 0x0000001f;
srl $t7, $a0, 5                              # hi >> 5;
add $t6, $t6, 1                                 # ++i
addi $t5, $t5, 4                                # increment array address, $t5++ -> $t5==array[i+1]
j loop_two

This assumes that the code below was declared in decode_request

li $t6, 7   # t3 is our second counter (int i = 7)
answered on Stack Overflow Feb 28, 2019 by user611988

User contributions licensed under CC BY-SA 3.0