code
All checks were successful
/ deploy (push) Successful in 1m22s

This commit is contained in:
Minecon724 2024-10-23 20:53:01 +02:00
parent b320dfa4cd
commit 94c4c16727
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
6 changed files with 89 additions and 16 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
.vscode/ .vscode/
build/ build/
programs/tests/

View file

@ -1,4 +1,4 @@
RISC-V (rv32i) emulator in C \ RISC-V (rv32mi) emulator in C \
This is just for me to understand how all this works, and to learn something new. \ This is just for me to understand how all this works, and to learn something new. \
So don't use it. So don't use it.

View file

@ -40,11 +40,16 @@ static inline int process_elf(Elf *elf, CPU *cpu) {
return 1; return 1;
} }
/*uint32_t pretextSize = 0;
uint8_t *pretext;
uint32_t textSize = 0; uint32_t textSize = 0;
uint8_t *text; uint8_t *text;
uint32_t rodataSize = 0; uint32_t rodataSize = 0;
uint8_t *rodata; uint8_t *rodata;*/
uint32_t written = 0;
while ((scn = elf_nextscn(elf, scn)) != NULL) { while ((scn = elf_nextscn(elf, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) != &shdr) { if (gelf_getshdr(scn, &shdr) != &shdr) {
@ -54,9 +59,9 @@ static inline int process_elf(Elf *elf, CPU *cpu) {
char *sectionName = elf_strptr(elf, shdrstrndx, shdr.sh_name); char *sectionName = elf_strptr(elf, shdrstrndx, shdr.sh_name);
Elf_Data *data = elf_getdata(scn, NULL); Elf_Data *sectionData = elf_getdata(scn, NULL);
if (data == NULL || data->d_size == 0) { if (sectionData == NULL || sectionData->d_size == 0) {
fprintf(stderr, "elf_getdata() failed: %s\n", elf_errmsg(-1)); fprintf(stderr, "elf_getdata() failed: %s\n", elf_errmsg(-1));
continue; continue;
} }
@ -64,19 +69,49 @@ static inline int process_elf(Elf *elf, CPU *cpu) {
if (shdr.sh_type == SHT_RISCV_ATTRIBUTES) { if (shdr.sh_type == SHT_RISCV_ATTRIBUTES) {
// TODO this is highly fragile // TODO this is highly fragile
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc
char *content = (char *)data->d_buf; char *content = (char *)sectionData->d_buf;
content += 19; // first 17 chars are subsection headers, and I have to +2 to make strcmp match content += 19; // first 17 chars are subsection headers, and I have to +2 to make strcmp match
if (strcmp(content, "rv32i2p1") == 0) { if (strcmp(content, "rv32i2p1") == 0) {
warnedArch = 1; warnedArch = 1;
} }
} else if (strcmp(sectionName, ".text.init") == 0) {
uint8_t *data = (uint8_t *)sectionData->d_buf;
uint32_t dataLength = sectionData->d_size;
if (written + dataLength > addressSpace->romSize) {
fprintf(stderr, "Section %s has %d bytes, already written %d bytes, and doesn't fit in ROM of capacity %d bytes\n", sectionName, dataLength, written, addressSpace->romSize);
return 1;
}
printf("Copying %d bytes from %s\n", dataLength, sectionName);
memcpy(addressSpace->rom + written, data, dataLength);
written += dataLength;
} else if (strcmp(sectionName, ".text") == 0) { } else if (strcmp(sectionName, ".text") == 0) {
text = (uint8_t *)data->d_buf; uint8_t *data = (uint8_t *)sectionData->d_buf;
textSize = data->d_size; uint32_t dataLength = sectionData->d_size;
if (written + dataLength > addressSpace->romSize) {
fprintf(stderr, "Section %s has %d bytes, already written %d bytes, and doesn't fit in ROM of capacity %d bytes\n", sectionName, dataLength, written, addressSpace->romSize);
return 1;
}
printf("Copying %d bytes from %s\n", dataLength, sectionName);
memcpy(addressSpace->rom + written, data, dataLength);
written += dataLength;
} else if (strcmp(sectionName, ".rodata") == 0) { } else if (strcmp(sectionName, ".rodata") == 0) {
rodata = (uint8_t *)data->d_buf; uint8_t *data = (uint8_t *)sectionData->d_buf;
rodataSize = data->d_size; uint32_t dataLength = sectionData->d_size;
if (written + dataLength > addressSpace->romSize) {
fprintf(stderr, "Section %s has %d bytes, already written %d bytes, and doesn't fit in ROM of capacity %d bytes\n", sectionName, dataLength, written, addressSpace->romSize);
return 1;
}
printf("Copying %d bytes from %s\n", dataLength, sectionName);
memcpy(addressSpace->rom + written, data, dataLength);
written += dataLength;
} else { } else {
printf("Unrecognized section: %s (%ub)\n", sectionName, (uint32_t)data->d_size); printf("Unrecognized section: %s (%ub)\n", sectionName, (uint32_t)sectionData->d_size);
} }
} }
@ -84,6 +119,15 @@ static inline int process_elf(Elf *elf, CPU *cpu) {
printf("I couldn't verify whether the ELF was compiled for the correct instruction set!\n"); printf("I couldn't verify whether the ELF was compiled for the correct instruction set!\n");
} }
/*if (pretextSize > 0) {
if (textSize > addressSpace->romSize) {
fprintf(stderr, "Code has %d bytes, and doesn't fit in ROM of capacity %d bytes\n", textSize, addressSpace->romSize);
return 1;
}
memcpy(addressSpace->rom, text, textSize);
}
if (textSize > 0) { if (textSize > 0) {
if (textSize > addressSpace->romSize) { if (textSize > addressSpace->romSize) {
fprintf(stderr, "Code has %d bytes, and doesn't fit in ROM of capacity %d bytes\n", textSize, addressSpace->romSize); fprintf(stderr, "Code has %d bytes, and doesn't fit in ROM of capacity %d bytes\n", textSize, addressSpace->romSize);
@ -91,7 +135,7 @@ static inline int process_elf(Elf *elf, CPU *cpu) {
} }
memcpy(addressSpace->rom, text, textSize); memcpy(addressSpace->rom, text, textSize);
} else { } else if (pretextSize == 0) {
fprintf(stderr, "There's no code\n"); fprintf(stderr, "There's no code\n");
return 1; return 1;
} }
@ -104,11 +148,15 @@ static inline int process_elf(Elf *elf, CPU *cpu) {
} }
memcpy(addressSpace->rom + textSize, rodata, rodataSize); memcpy(addressSpace->rom + textSize, rodata, rodataSize);
} }*/
printf("Loaded from ELF | Code: %d bytes (%d insts) | ROdata: %d bytes \n", textSize, textSize / 4, rodataSize); //printf("Loaded from ELF | Code: %d bytes (%d insts) | ROdata: %d bytes \n", textSize, textSize / 4, rodataSize);
printf("Loaded %d bytes from ELF\n", written);
cpu->programCounter = ehdr.e_entry; cpu->programCounter = ehdr.e_entry;
if (cpu->programCounter == 0x80000000) { // TODO not
cpu->programCounter = 0x0;
}
return 0; return 0;
} }

View file

@ -277,6 +277,29 @@ int execute_instruction_on_cpu(CPU *cpu, uint32_t instruction) { // TODO conside
break; break;
} }
case 0b1110011: {// SYSTEM (I type) instructions are used to access system functionality that might require privileged access, here only ECALL and EBREAK
uint8_t funct3 = instruction >> 12 & 0x7;
uint32_t rs1 = instruction >> 15 & 0x1F;
uint32_t func12 = instruction >> 20 & 0xFFF;
if (funct3 != 0 || rd != 0 || rs1 != 0) {
fprintf(stderr, "For SYSTEM instructions, funct3, rd and rs1 must be 0, but are 0x%X, 0x%X and 0x%X. Zicsr is not supported.", funct3, rd, rs1);
return 2;
}
if (func12 == 0) { // ECALL
printf("--- ECALL ---");
// TODO do something
} else if (func12 == 1) { // EBREAK
printf("--- EBREAK---");
// TODO do something
} else {
fprintf(stderr, "Invalid SYSTEM func12: 0x%X", func12);
return 2;
}
break;
}
default: { default: {
// TODO illegal instruction, proper error handling // TODO illegal instruction, proper error handling
fprintf(stderr, "Unrecognized opcode: 0x%X", opcode); fprintf(stderr, "Unrecognized opcode: 0x%X", opcode);

View file

@ -14,7 +14,7 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
AddressSpace *addressSpace = create_address_space(512, 512); AddressSpace *addressSpace = create_address_space(2048, 512);
printf("Address space: %dB ROM, %dB RAM\n", addressSpace->romSize, addressSpace->ramSize); printf("Address space: %dB ROM, %dB RAM\n", addressSpace->romSize, addressSpace->ramSize);
CPU cpu = create_cpu(addressSpace); CPU cpu = create_cpu(addressSpace);
@ -23,7 +23,6 @@ int main(int argc, char *argv[]) {
int lres = load_to_rom(argv[1], addressSpace); int lres = load_to_rom(argv[1], addressSpace);
if (lres == -1) { if (lres == -1) {
printf("Loading a binary file is deprecated. Please use an ELF.\n");
lres = load_elf_to_cpu_and_rom(argv[1], &cpu); lres = load_elf_to_cpu_and_rom(argv[1], &cpu);
} }

View file

@ -26,6 +26,8 @@ int load_to_rom(const char filename[], AddressSpace *addressSpace) {
return -1; return -1;
} }
printf("Loading a binary file is deprecated. Please use an ELF.\n");
// size_t is not used because a program can't be larger than the 32bit address space // size_t is not used because a program can't be larger than the 32bit address space
int romSize = addressSpace->romSize; int romSize = addressSpace->romSize;
int bytesRead = fread(addressSpace->rom, 1, romSize, file); int bytesRead = fread(addressSpace->rom, 1, romSize, file);