# Lab2: RISC-V RV32I[MA] emulator with ELF support: Power Function
###### tags: `RISC-V`
Choosing power function from [曾紹銘](https://hackmd.io/o1yeSGzDQO2LmbKXEoBC_g?view).
## Rewrite in C language
```cpp=
void _start(){
volatile char* tx = (volatile char*) 0x40002000;
int base = 3;
int exp = 5;
int result = 1;
while(exp > 0){
if(exp & 0x1)
result *= base;
exp >>= 1;
base *= base;
}
int out = result;
*tx = out;
}
```
## Comparing different optimization and manual in GNU Toolchain
### execute the elf file
The result in integer is not convert to char, so the output format is wrong.
I was shocked by the counts of instruction.
- produced by gcc with -O3
```bash
$ riscv-none-embed-gcc -march=rv32i -mabi=ilp32 -O3 -nostdlib -o pow power.c
$ ./emu-rv32i pow
�
>>> Execution time: 19543 ns
>>> Instruction count: 5 (IPS=255846)
>>> Jumps: 1 (20.00%) - 0 forwards, 1 backwards
>>> Branching T=0 (-nan%) F=0 (-nan%)
```
- produced by gcc with -Os
I encountered some errors, but they have not been resolved.
```bash
$ riscv-none-embed-gcc -march=rv32i -mabi=ilp32 -Os -nostdlib -o pow power.c
/home/ccs100203/riscv-none-embed-gcc/8.2.0-3.1/bin/../lib/gcc/riscv-none-embed/8.2.0/../../../../riscv-none-embed/bin/ld: /tmp/ccjM40Oy.o: in function `.L3':
power.c:(.text+0x38): undefined reference to `__mulsi3'
/home/ccs100203/riscv-none-embed-gcc/8.2.0-3.1/bin/../lib/gcc/riscv-none-embed/8.2.0/../../../../riscv-none-embed/bin/ld: /tmp/ccjM40Oy.o: in function `.L2':
power.c:(.text+0x4c): undefined reference to `__mulsi3'
collect2: error: ld returned 1 exit status
```
### objdump
```bash
$ riscv-none-embed-objdump -d pow
```
The optimization of gcc was amazing, the code size was greatly compressed.
- produced by gcc with -O3
```
pow: file format elf32-littleriscv
Disassembly of section .text:
00010054 <_start>:
10054: 400027b7 lui a5,0x40002
10058: ff300713 li a4,-13
1005c: 00e78023 sb a4,0(a5) # 40002000 <__global_pointer$+0x3fff079c>
10060: 00008067 ret
```
- produced by manual
```
.data
x: .word 3
y: .word 5 # unsigned
str1: .string " ^ "
str2: .string " = "
.text
main:
lw s0, x # Set s0 equal to the parameter x
lw s1, y # Set s1 equal to the parameter y
mv a0, s0 # Set arguments
mv a1, s1
jal power # return the result a0
mv s2, a0 # Set s2 equal to the result
j print
power:
addi sp, sp, -12
sw ra, 0(sp)
sw s0, 4(sp)
sw s1, 8(sp)
mv s0, a0 # s0 -> parameter x
mv s1, a1 # s1 -> parameter y
li s2, 1 # s2 -> res, init = 1
loop:
bge x0, s1, Ret # if (0 >= y) break
andi t0, s1, 0x1 # t0 -> y & 0x1
li t1, 0x1 # t1 -> 0x1
li ra, 0x54 # Set ra equal to srli s1, s1, 1
beq t0, t1, odd # y is odd
srli s1, s1, 1 # y_u >> 1, y /= 2
mul s0, s0, s0 # x = x * x
j loop # goto loop
odd:
mul s2, s2, s0 # res = res * x
jr ra # goto srli s1, s1, 1
Ret:
mv a0, s2 # Set return reg a0
lw ra, 0(sp) # Restore ra
lw s0, 4(sp) # Restore s0
lw s1, 8(sp) # Restore s1
addi sp, sp, 12 # Free space on the stack for the 3 words
jr ra # Return to the caller
print:
mv t0, a0 # Set tmp equal to a0
mv a0, s0 # prepare to print x
li a7, 1 # print int
ecall
la a0, str1 # prepare to print string ^
li a7, 4 # print string
ecall
mv a0, s1 # prepare to print y
li a7, 1 # print int
ecall
la a0, str2 # prepare to print string =
li a7, 4 # print string
ecall
mv a0, s2 # prepare to print result
li a7, 1 # print int
ecall
```
### readeif
```bash
$ riscv-none-embed-readelf -h pow
```
- produced by gcc with -O3
```
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: RISC-V
Version: 0x1
Entry point address: 0x10054
Start of program headers: 52 (bytes into file)
Start of section headers: 480 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 40 (bytes)
Number of section headers: 6
Section header string table index: 5
```
### size
```bash
$ riscv-none-embed-size pow
```
- produced by gcc with -O3
```
text data bss dec hex filename
16 0 0 16 10 pow
```