78 lines
2.2 KiB
C
78 lines
2.2 KiB
C
#include "cpu.h"
|
|
#include <stdio.h>
|
|
|
|
static void printBinary(int num) {
|
|
if (num > 1) {
|
|
printBinary(num / 2);
|
|
}
|
|
printf("%d", num % 2);
|
|
}
|
|
|
|
int execute_instruction_on_cpu(CPU *cpu, uint32_t instruction) {
|
|
AddressSpace *addressSpace = cpu->addressSpace;
|
|
uint32_t *registers = cpu->registers;
|
|
registers[0] = 0; // x0 is always 0
|
|
|
|
uint8_t opcode = instruction & 0x7F;
|
|
uint8_t rd = instruction >> 7 & 0x1F;
|
|
|
|
printf("\nPC: %d\n", cpu->programCounter);
|
|
|
|
if (opcode != 0) {
|
|
printf("Instruction: ");
|
|
printBinary(instruction);
|
|
printf("\nOpcode: 0x%X (", opcode);
|
|
printBinary(opcode);
|
|
printf(")\n");
|
|
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;
|
|
}
|