It now runs a program
This commit is contained in:
parent
2a5423d504
commit
c5173df335
7 changed files with 133 additions and 5 deletions
16
README.txt
Normal file
16
README.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
RISC-V (rv32i) emulator in C
|
||||
This is just for me to understand how all this works, and to learn something new.
|
||||
So don't use it.
|
||||
|
||||
Example programs:
|
||||
- return.bin: returns -1094647826 (puts it to register 10)
|
||||
|
||||
To compile stuff:
|
||||
0. Get the toolchain obviously
|
||||
1. riscv32-unknown-elf-gcc -c -Oz program.c
|
||||
2. riscv32-unknown-elf-objcopy -O binary program.o program.bin
|
||||
3. program.bin is the binary file with the program, pass it as an argument
|
||||
|
||||
rv32i, ilp32 compatible toolchain for 64bit Linux: https://lfs.m724.eu/toolchain.tar.zst adaa74f263dcba430da588b1109bc3b90bd90a84c67b06213bd03a7bbacd1a2a
|
||||
Or just the stuff necessary to make a binary file: https://lfs.m724.eu/toolchainlite.tar.zst 55e79dff7ba4093dedb8151461508fc157525ad89615d49d737845af03d1643f
|
||||
Those were compiled with `./configure --prefix=$(pwd)/../toolchain --with-arch=rv32i --with-abi=ilp32` and `make`
|
BIN
programs/return.bin
Normal file
BIN
programs/return.bin
Normal file
Binary file not shown.
4
remake.sh
Executable file
4
remake.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
make clean
|
||||
make
|
||||
./build/criscv $1
|
BIN
simple.bin
BIN
simple.bin
Binary file not shown.
|
@ -60,6 +60,7 @@ int read_address_space(const AddressSpace *addressSpace, const uint32_t address,
|
|||
|
||||
} else {
|
||||
// TODO IO
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -85,6 +86,7 @@ int write_address_space(const AddressSpace *addressSpace, const uint32_t address
|
|||
}
|
||||
} else {
|
||||
// TODO IO
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -10,13 +10,15 @@ static void printBinary(int num) {
|
|||
|
||||
int execute_instruction_on_cpu(CPU *cpu, uint32_t instruction) {
|
||||
AddressSpace *addressSpace = cpu->addressSpace;
|
||||
cpu->registers[0] = 0; // x0 is always 0
|
||||
uint32_t *registers = cpu->registers;
|
||||
registers[0] = 0; // x0 is always 0
|
||||
|
||||
uint8_t opcode = instruction & 0x7F;
|
||||
uint8_t rd = instruction >> 7 & 0x1F;
|
||||
|
||||
if (opcode != 0) {
|
||||
printf("\nPC: %d\n", cpu->programCounter);
|
||||
|
||||
if (opcode != 0) {
|
||||
printf("Instruction: ");
|
||||
printBinary(instruction);
|
||||
printf("\nOpcode: 0x%X (", opcode);
|
||||
|
@ -25,6 +27,51 @@ int execute_instruction_on_cpu(CPU *cpu, uint32_t instruction) {
|
|||
printf("Dest. reg.: x%d\n", rd);
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case 0b0010011: { // OP-IMM for Integer Register-Immediate Instructions (I type)
|
||||
uint8_t funct3 = instruction >> 12 & 0x7;
|
||||
uint8_t rs1 = instruction >> 15 & 0x1F;
|
||||
uint32_t imm = (int32_t)instruction >> 20;
|
||||
|
||||
switch (funct3) {
|
||||
case 0b000: // ADDI
|
||||
registers[rd] = registers[rs1] + imm;
|
||||
break;
|
||||
default:
|
||||
// TODO other and illegal instruction
|
||||
break;
|
||||
}
|
||||
/* code */
|
||||
break;
|
||||
}
|
||||
case 0b0110111: { // LUI load upper immediate (U type)
|
||||
uint32_t imm = instruction & 0xFFFFF000;
|
||||
registers[rd] = imm;
|
||||
break;
|
||||
}
|
||||
case 0b1100111: { // JALR for unconditional jump and link register (I type)
|
||||
uint8_t funct3 = instruction >> 12 & 0x7;
|
||||
|
||||
if (funct3 != 0) {
|
||||
// TODO illegal instruction
|
||||
}
|
||||
|
||||
uint8_t rs1 = instruction >> 15 & 0x1F;
|
||||
uint32_t imm = (int32_t)instruction >> 20;
|
||||
|
||||
int result = registers[rs1] + imm;
|
||||
result &= ~1; // set LSB to 0
|
||||
|
||||
registers[rd] = cpu->programCounter + 4;
|
||||
cpu->programCounter = result - 4; // program counter is always incremented after executing instruction
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO illegal instruction
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
|
|
65
src/main.c
65
src/main.c
|
@ -1,5 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "program_loader.h"
|
||||
#include "cpu.h"
|
||||
|
@ -19,11 +21,68 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
CPU cpu = create_cpu(addressSpace);
|
||||
cpu.registers[1] = addressSpace->romSize + addressSpace->ramSize; // make jumping to x1 end the program
|
||||
|
||||
while (cpu_cycle(&cpu) != -1) {
|
||||
sleep(1);
|
||||
int code;
|
||||
while ((code = cpu_cycle(&cpu)) != -1) {
|
||||
//sleep(1);
|
||||
}
|
||||
|
||||
printf("Done");
|
||||
|
||||
printf("\n Emulator exited with code \033[1m%d\033[0m\n", code);
|
||||
printf(" Program exited with code \033[1m%d\033[0m\n\n", cpu.registers[10]);
|
||||
|
||||
int cols[8] = {0};
|
||||
int total = 0;
|
||||
|
||||
for (int col=0; col<8; col++) {
|
||||
int len;
|
||||
for (int row=0; row<4; row++) {
|
||||
int i = 8 * row + col;
|
||||
len = snprintf(NULL, 0, "%d: \033[1m0x%X\033[0m (%u)", i, cpu.registers[i], cpu.registers[i]);
|
||||
if (len > cols[col]) {
|
||||
cols[col] = len;
|
||||
}
|
||||
}
|
||||
total += len;
|
||||
}
|
||||
|
||||
printf("+");
|
||||
for (int i=0; i<8; i++) {
|
||||
for (int j=0; j<cols[i] - 6; j++) {
|
||||
printf("-");
|
||||
}
|
||||
printf("+");
|
||||
}
|
||||
|
||||
for (int i=0; i<32; i++) {
|
||||
if (i % 8 == 0) {
|
||||
printf("\n| ");
|
||||
}
|
||||
int row = i / 8;
|
||||
int col = i - row * 8;
|
||||
|
||||
int len = cols[col];
|
||||
char *entry = malloc(len);
|
||||
char *entryy = malloc(len);
|
||||
memset(entry, ' ', len);
|
||||
|
||||
int flen = snprintf(entryy, len+1, "%d: \033[1m0x%X\033[0m (%u)", i, cpu.registers[i], cpu.registers[i]);
|
||||
for (int j=0; j<flen; j++) {
|
||||
entry[j] = entryy[j];
|
||||
}
|
||||
|
||||
printf("%s | ", entry);
|
||||
}
|
||||
|
||||
printf("\n+");
|
||||
for (int i=0; i<8; i++) {
|
||||
for (int j=0; j<cols[i] - 6; j++) {
|
||||
printf("-");
|
||||
}
|
||||
printf("+");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue