can you produce BEQL MIPS instruction with C code? - c

So I have this code snippet in C
int unit_test_case08(int a, int b)
{
int success = 1336;
if(a != b)
{
success = 1337;
}
else
{
success = -1;
}
return success;
}
Which translates in MIPS to
unit_test_case08:
addiu $sp,$sp,-24
sw $fp,20($sp)
move $fp,$sp
sw $4,24($fp)
sw $5,28($fp)
sw $6,32($fp)
li $2,1336 # 0x538
sw $2,8($fp)
lw $3,24($fp)
lw $2,28($fp)
nop
beq $3,$2,$L2
nop
li $2,1337 # 0x539
sw $2,8($fp)
b $L3
nop
$L2:
li $2,-1 # 0xffffffffffffffff
sw $2,8($fp)
$L3:
lw $2,8($fp)
move $sp,$fp
lw $fp,20($sp)
addiu $sp,$sp,24
jr $31
nop
But for my question, im trying to create some test cases for my emulator, but am finding it hard to generate some code in C that will get me BEQL instead of BEQ?
beq $3,$2,$L2
This question extends to most of the "Likelys" if possible.
I am a very new to MIPS.
I would like to learn how to code a test case in C that would translate to BEQL instead of BEQ.

Related

C to assembly MIPS-32 [duplicate]

The MIPS assembly code generated by mips-gcc almost, but doesn't quite, run on the Mars MIPS simulator. For example:
The compiler generates "j $31" instead of "jr $31"
The compiler puts .align directives in the text segment, which Mars does not allow.
In addition, the generated assembly is not quite set up so that it will start and stop properly (i.e., no sycall 10 at the end).
These problems are all appear to be easily fixable with a simply script; but, before I re-invent the wheel, I was wondering:
(1) Are there any gcc flags that will make some of these problems go away?
(2) Does anybody know of an existing program that will fix up the mips-gcc output so that it will run on Mars?
(FWIW, I see the same behavior on both gcc 3.3.6 and 4.6.1.)
Are there any gcc flags that will make some of these problems go away?
Short answer is no. Mars uses custom system calls and is very different in calling conventions.
Does anybody know of an existing program that will fix up the mips-gcc output so that it will run on Mars?
I don't know of any automated way to convert it. You can do it only manually. I have done it actually.
Roughly, these are the steps I followed:
0. Use GobBolt compiler explorer to get a beatified raw assembly of your code. They don't use specific gcc options to get this beatified view according to this, so I'm not mentioning any gcc command, but you can set up a local copy of it.
Replace all the syscalls and their calling conventions according to this : https://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html
Replace/add the required segment labels (such as .text, .data etc.) along with their required data.
If you have a main function (label) add j main after .text.
(4. Optionally, you can rename the registers to be more readable because as Peter Cordes mentioned in the comments, gcc for mips doesn't support the argument -mregnames)
This is an example I made, it lacks main cause it was intended as a library :
C code :
#include <stdio.h>
#include <stdlib.h>
typedef struct node Node;
struct node {
int data;
struct node *left;
struct node *right;
};
Node *new_node (int data) {
Node *ret = malloc (sizeof (Node)); ret->left = NULL;
ret->data = data;
ret->left = NULL;
ret->right = NULL;
return ret; }
void link (Node *parent, Node *left, Node *right) {
parent->left = left;
parent->right = right;
}
int depth (Node *root) {
if (root == NULL) {
return -1;
}
int left = depth (root->left);
int right = depth (root->right);
return 1 + (left > right? left : right);
}
int even_level_max (Node *root, int level) {
if (root == NULL) {
return 0x80000000;
}
int left = even_level_max(root->left, level + 1);
int right = even_level_max (root->right, level + 1);
int greater = (left > right) ? left : right;
if (level % 2 == 0) {
return (greater > root->data)? greater : root->data;
} else {
return greater;
}
}
Godbolt code :
new_node:
addiu $sp,$sp,-40
sw $31,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $4,40($fp)
li $4,12 # 0xc
jal malloc
nop
sw $2,24($fp)
lw $2,24($fp)
nop
sw $0,4($2)
lw $2,24($fp)
lw $3,40($fp)
nop
sw $3,0($2)
lw $2,24($fp)
nop
sw $0,4($2)
lw $2,24($fp)
nop
sw $0,8($2)
lw $2,24($fp)
move $sp,$fp
lw $31,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $31
nop
link:
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
sw $4,8($fp)
sw $5,12($fp)
sw $6,16($fp)
lw $2,8($fp)
lw $3,12($fp)
nop
sw $3,4($2)
lw $2,8($fp)
lw $3,16($fp)
nop
sw $3,8($2)
nop
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
jr $31
nop
depth:
addiu $sp,$sp,-40
sw $31,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $4,40($fp)
lw $2,40($fp)
nop
bne $2,$0,$L5
nop
li $2,-1 # 0xffffffffffffffff
b $L6
nop
$L5:
lw $2,40($fp)
nop
lw $2,4($2)
nop
move $4,$2
jal depth
nop
sw $2,24($fp)
lw $2,40($fp)
nop
lw $2,8($2)
nop
move $4,$2
jal depth
nop
sw $2,28($fp)
lw $3,24($fp)
lw $2,28($fp)
nop
slt $4,$2,$3
beq $4,$0,$L7
nop
move $2,$3
$L7:
addiu $2,$2,1
$L6:
move $sp,$fp
lw $31,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $31
nop
even_level_max:
addiu $sp,$sp,-48
sw $31,44($sp)
sw $fp,40($sp)
move $fp,$sp
sw $4,48($fp)
sw $5,52($fp)
lw $2,48($fp)
nop
bne $2,$0,$L9
nop
li $2,-2147483648 # 0xffffffff80000000
b $L10
nop
$L9:
lw $2,48($fp)
nop
lw $3,4($2)
lw $2,52($fp)
nop
addiu $2,$2,1
move $5,$2
move $4,$3
jal even_level_max
nop
sw $2,24($fp)
lw $2,48($fp)
nop
lw $3,8($2)
lw $2,52($fp)
nop
addiu $2,$2,1
move $5,$2
move $4,$3
jal even_level_max
nop
sw $2,28($fp)
lw $3,24($fp)
lw $2,28($fp)
nop
slt $4,$2,$3
beq $4,$0,$L11
nop
move $2,$3
$L11:
sw $2,32($fp)
lw $2,52($fp)
nop
andi $2,$2,0x1
bne $2,$0,$L12
nop
lw $2,48($fp)
nop
lw $3,0($2)
lw $2,32($fp)
nop
slt $4,$2,$3
beq $4,$0,$L10
nop
move $2,$3
b $L10
nop
$L12:
lw $2,32($fp)
$L10:
move $sp,$fp
lw $31,44($sp)
lw $fp,40($sp)
addiu $sp,$sp,48
jr $31
nop
Converted Mars code :
# Registers:
# a : store results
# t : temporaries
# s : saved
# k : kernel
.text:
j main
new_node: #Node *new_node (int data)
# prologue
addiu $sp,$sp,-40
sw $ra,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $a0,40($fp) # fp[40] = data
li $v0, 9
li $a0, 12
syscall
sw $v0,24($fp) # fp[24] = sbrk ( sizeof (Node = 12) )
lw $v0,24($fp)
lw $v1,40($fp) # data = fp[40]
sw $v1,0($v0) # ret[0] = data;
lw $v0,24($fp)
sw $zero,4($v0) # ret[4] = NULL;
lw $v0,24($fp)
sw $zero,8($v0) # ret[8] = NULL;
# epilogue
lw $v0,24($fp)
move $sp,$fp
lw $ra,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $ra
nop
link: # int depth (Node *root)
# prologue
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
#store arguments
sw $a0,8($fp)
sw $a1,12($fp)
sw $a2,16($fp)
#parent -> left = left;
lw $v0,8($fp)
lw $v1,12($fp)
sw $v1,4($v0)
sw $a1,4($a0)
# parent -> right = right
lw $v0,8($fp)
lw $v1,16($fp)
sw $v1,8($v0)
sw $a2,8($a0)
# epilogue
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
jr $ra
nop
depth: # int depth (Node *root)
# prologue
addiu $sp,$sp,-40
sw $ra,36($sp)
sw $fp,32($sp)
move $fp,$sp
sw $a0,40($fp) # fp[40] = root
lw $v0,40($fp)
bne $v0,$zero,L5
li $v0,-1
b L6 #if (root == NULL) return -1;
L5:
lw $v0,40($fp)
lw $v0,4($v0)
move $a0,$v0 # a0 = root -> left
jal depth # depth(a0)
sw $v0,24($fp) # fp[24] = depth(a0)
lw $v0,40($fp)
lw $v0,8($v0)
move $a0,$v0 # a0 = root -> right
jal depth # depth(a0)
sw $v0,28($fp) # fp[28] = depth(a0)
lw $v1,24($fp) # v0 = right
lw $v0,28($fp) # v1 = left
slt $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
beq $a0,$zero,L7
move $v0,$v1 # executed when v1 > v0
L7:
addiu $v0,$v0,1 # executed when v0 < v1
L6:
# epilogue
move $sp,$fp
lw $ra,36($sp)
lw $fp,32($sp)
addiu $sp,$sp,40
jr $ra
even_level_max:
# prologue
addiu $sp,$sp,-48
sw $ra,44($sp)
sw $fp,40($sp)
move $fp,$sp
sw $a0,48($fp) # fp[48] = root
sw $a1,52($fp) # fp[52] = level
lw $v0,48($fp)
bne $v0,$zero,L9
li $v0, 0x80000000
b L10 # if (root == NULL) return 0x80000000;
L9: # root != NULL
lw $v0,48($fp)
lw $v1,4($v0) # v1 = root -> left
lw $v0,52($fp)
addiu $v0,$v0,1 # v0 = level + 1
move $a1,$v0
move $a0,$v1
jal even_level_max
sw $v0,24($fp) # fp[24] = left = even_level_max(root -> left, level +1)
lw $v0,48($fp)
lw $v1,8($v0) # v1 = root -> right
lw $v0,52($fp)
addiu $v0,$v0,1 # v0 = level + 1
move $a1,$v0
move $a0,$v1
jal even_level_max
sw $v0,28($fp) # fp[28] = right = even_level_max(root -> right, level + 1)
lw $v1,24($fp) # v1 = right
lw $v0,28($fp) # v0 = left
slt $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
beq $a0,$zero,L11
move $v0,$v1
L11:
sw $v0,32($fp) # fp[32] = greater
lw $v0,52($fp) # v0 = level
andi $v0,$v0,0x1 # v0 & 1
bne $v0,$zero,L12
lw $v0,48($fp) # v0 = root
lw $v1,0($v0) # v1 = data
lw $v0,32($fp) # v0 = greater
slt $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
beq $a0,$zero,L10 # return greater
move $v0,$v1 # v0 = data
b L10 # return data
L12:
lw $v0,32($fp) # return greater
L10:
# epilogue
move $sp,$fp
lw $ra,44($sp)
lw $fp,40($sp)
addiu $sp,$sp,48
jr $ra

Translate a loop in C with arrays to MIPS by using the stack

I have a doubt on one exercise that my professor did during a seminar. It's basically a translation from C to MIPS. The C code is as follows:
void subr1(char *a, int v[]) {
int i;
char c[12];
for (i=11; i >= 0; i--) {
v[i] = subr2(c[i], *a);
}
}
And the translation of my professor was the following (I've written comments about what each instruction does and what I don't understand):
addiu $sp,$sp,-28 #Activation block
sw $ra, 24($sp) #Space for $ra (4 bytes)
sw $s0, 20($sp) #Space for *a (32-bit address = 4 bytes)
sw $s1, 16($sp) #Space for c (Q1: Shouldn't this be 12 bytes? c is an array of 12 chars = 12*1Byte=12Bytes)
sw $s2 12($sp) #Space for i (4 bytes)
(Q2: Why is he stopping at 12? Doesn't he need to save space for int v[]?)
move $s0,$a0 #Save 'a' in stack
move $s1,$a1 #Save 'c' in stack
li $s2, 11 #i=11
For:
blt $s2, $zero, End #if i<0, then go to 'End'
addu $t0, $s2, $sp (Q3: I'm not sure, but I think he's trying to access v[i] by summing $sp and 'i'. Can you do that, without initialising any register at the beginning like we did for $s0 and $s1?)
lb $a0, 0($t0) #$a0 = v[i] (Q4: Isn't this wrong? It should access c[i], not v[i])
lb $a1, 0($s0) #$a1 = *a
jal sub2 #Jump to sub2
sll $t1, $s2, 2 #$t1 = 4*i
addu $t1,$t1,$sp #$t1 = 4*i + $sp (By this, I guess he's accessing v[i])
sw $v0,0($t1) #v[i] = $v0 (returned value from sub2)
addiu $s2, $s2, -1 #i--
b For
end:
#Close the activation block
lw $s2,12($sp)
lw $s1,16($sp)
lw $s0,20($sp)
lw $ra,24($sp)
addiu $sp,$sp,28
jr $ra #Jump to register address
Could somebody help me?
Thank you in advance.

C-code to assembly [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I was trying to convert C code to MIPS assembly. Here's a snippet. The problem is that i'm not too sure if i am going along the right track. I'm hoping, someone could help.
This was the original question:
void swap(int v[], int k, int j) {
int temp;
temp = v[k];
v[k] = v[j];
v[j] = temp;
}
and this is how far i have got:
swap:
addi $sp, $sp, -4
sw $s0, 0($sp)
add $s0, $zero, $zero
L1: add $t1, $s0, $a1
lb $t2, 0($t1)
add $t3, $s0, $a0
sb $t2, 0($t3)
beq $t2, $zero, L2
addi $s0, $s0, 1
j L1
L2: lw $s0, 0($sp)
addi $sp, $sp, 4
jr $ra
Alright this is as far as i have got. Am i doing this right or am i completely lost it!?
break it down and then implement it
v, k and j come in as registers we assume.
you need to build the address v+(k<<2) and v+(j<<2) You can use scratch registers, I assume you can trash the k and j incoming registers too since you wont need them anymore.
k = k << 2;
k = k + v
j = j << 2;
j = j + v
temp0 = load(k)
temp1 = load(j)
store(k) = temp1
store(j) = temp0
and you should be able to convert that to asm, can re-arrange some of the instructions and have it still work.
Edit, I will let you figure it out, but I didnt cheat and compile first. But found that gcc produced the same basic sequence of instructions. Two shifts, two adds two loads, then two stores.
Here's a free online tool that converts c code to assembly.
Here is the converted code:
addiu $sp,$sp,-24
$LCFI0:
sw $fp,20($sp)
$LCFI1:
move $fp,$sp
movz $31,$31,$0
$LCFI2:
sw $4,24($fp)
sw $5,28($fp)
sw $6,32($fp)
lw $2,28($fp)
nop
sll $2,$2,2
lw $3,24($fp)
nop
addu $2,$3,$2
lw $2,0($2)
nop
sw $2,8($fp)
lw $2,28($fp)
nop
sll $2,$2,2
lw $3,24($fp)
nop
addu $2,$3,$2
lw $3,32($fp)
nop
sll $3,$3,2
lw $4,24($fp)
nop
addu $3,$4,$3
lw $3,0($3)
nop
sw $3,0($2)
lw $2,32($fp)
nop
sll $2,$2,2
lw $3,24($fp)
nop
addu $2,$3,$2
lw $3,8($fp)
nop
sw $3,0($2)
move $sp,$fp
lw $fp,20($sp)
addiu $sp,$sp,24
j $31
nop

how to read array in MIPS

This is code in C language:
while(a<10){
M[a] = a + b;
a++; }
How to rewrite it in assembly language in Mips and don't use pseudo instructions.
M is array of 32bit elements. a in register $s0, b in $s1, $s2 is base address of M array.
And my code it:
addi $s3, $zero, 10
LOOP: add $st1, $s0, $s1
add $t2, $s2, $s0
sw $t1, 0($s2)
addi $s0, $s0, 1
bne $s0, $s3, LOOP
but i think it has problem.
Thank you very much.
If I take this C program and compile it to MIPS assembly:
int main() {
int b = 10;
int a = 20;
int M[20];
while(a<10){
M[a] = a + b;
a++; }
}
Then with my toolchain the MIPS assembly becomes:
.file 1 "Cprogram.c"
# -G value = 8, Cpu = 3000, ISA = 1
# GNU C version cygnus-2.7.2-970404 (mips-mips-ecoff) compiled by GNU C version cygnus-2.7.2-970404.
# options passed: -msoft-float
# options enabled: -fpeephole -ffunction-cse -fkeep-static-consts
# -fpcc-struct-return -fcommon -fverbose-asm -fgnu-linker -msoft-float
# -meb -mcpu=3000
gcc2_compiled.:
__gnu_compiled_c:
.text
.align 2
.globl main
.ent main
main:
.frame $fp,112,$31 # vars= 88, regs= 2/0, args= 16, extra= 0
.mask 0xc0000000,-4
.fmask 0x00000000,0
subu $sp,$sp,112
sw $31,108($sp)
sw $fp,104($sp)
move $fp,$sp
jal __main
li $2,10 # 0x0000000a
sw $2,16($fp)
li $2,20 # 0x00000014
sw $2,20($fp)
$L2:
lw $2,20($fp)
slt $3,$2,10
bne $3,$0,$L4
j $L3
$L4:
lw $2,20($fp)
move $3,$2
sll $2,$3,2
addu $4,$fp,16
addu $3,$2,$4
addu $2,$3,8
lw $3,20($fp)
lw $4,16($fp)
addu $3,$3,$4
sw $3,0($2)
lw $2,20($fp)
addu $3,$2,1
sw $3,20($fp)
j $L2
$L3:
$L1:
move $sp,$fp # sp not trusted here
lw $31,108($sp)
lw $fp,104($sp)
addu $sp,$sp,112
j $31
.end main

how to transform array from C to mips

I have code C :
for (i=0; i<98; i++) {
C[i] = A[i+1] - B[i+2] * A[1];
}
first address of array A,B,C are A000h,B000h,C000h
and i transform to mips
addi $a0,$zero,A000h
addi $a1,$zero,B000h
addi $a2,$zero,C000h
li $t0,1
li $t1,98
loop:
addi $a0,0
addi $t2,$a0,4
addi $a1,8
addi $a2,0
lw $t3,0($a0)
lw $t4,4($t2)
lw $t5,8($a1)
mult $t5,$t5,$t3
sub $t6,$t4,$t5
sw $t6,0($a2)
addi $t0,1
bne $t0,$t1,loop
plz check it,thank
You can compile C to MIPS assembly and look at the output if it helps. The following C:
int main ()
{
int i;
int A[99], B[99], C[99];
for (i=0; i<98; i++) {
C[i] = A[i+1] - B[i+2] * A[1];
}
}
compiles with my compiler to this MIPS code
.file 1 "loop.c"
# -G value = 8, Cpu = 3000, ISA = 1
# GNU C version cygnus-2.7.2-970404 (mips-mips-ecoff) compiled by GNU C version cygnus-2.7.2-970404.
# options passed: -msoft-float
# options enabled: -fpeephole -ffunction-cse -fkeep-static-consts
# -fpcc-struct-return -fcommon -fverbose-asm -fgnu-linker -msoft-float
# -meb -mcpu=3000
gcc2_compiled.:
__gnu_compiled_c:
.text
.align 2
.globl main
.ent main
main:
.frame $fp,1232,$31 # vars= 1208, regs= 2/0, args= 16, extra= 0
.mask 0xc0000000,-4
.fmask 0x00000000,0
subu $sp,$sp,1232
sw $31,1228($sp)
sw $fp,1224($sp)
move $fp,$sp
jal __main
sw $0,16($fp)
$L2:
lw $2,16($fp)
slt $3,$2,98
bne $3,$0,$L5
j $L3
$L5:
lw $2,16($fp)
move $3,$2
sll $2,$3,2
addu $4,$fp,16
addu $3,$2,$4
addu $2,$3,808
addu $3,$fp,28
lw $4,16($fp)
move $5,$4
sll $4,$5,2
addu $3,$3,$4
addu $4,$fp,432
lw $5,16($fp)
move $6,$5
sll $5,$6,2
addu $4,$4,$5
lw $5,0($4)
lw $4,28($fp)
mult $5,$4
lw $3,0($3)
mflo $7
subu $4,$3,$7
sw $4,0($2)
$L4:
lw $2,16($fp)
addu $3,$2,1
sw $3,16($fp)
j $L2
$L3:
$L1:
move $sp,$fp # sp not trusted here
lw $31,1228($sp)
lw $fp,1224($sp)
addu $sp,$sp,1232
j $31
.end main

Resources