Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h> // for stderr
- #include <stdlib.h> // for exit()
- #include "types.h"
- #include "utils.h"
- #include "riscv.h"
- void execute_rtype(Instruction, Processor *);
- void execute_itype_except_load(Instruction, Processor *);
- void execute_branch(Instruction, Processor *);
- void execute_jal(Instruction, Processor *);
- void execute_load(Instruction, Processor *, Byte *);
- void execute_store(Instruction, Processor *, Byte *);
- void execute_ecall(Processor *, Byte *);
- void execute_lui(Instruction, Processor *);
- void execute_instruction(uint32_t instruction_bits, Processor *processor,Byte *memory) {
- Instruction instruction = parse_instruction(instruction_bits);
- switch(instruction.opcode) {
- case 0x33:
- execute_rtype(instruction, processor);
- break;
- case 0x13:
- execute_itype_except_load(instruction, processor);
- break;
- case 0x73:
- execute_ecall(processor, memory);
- break;
- case 0x63:
- execute_branch(instruction, processor);
- break;
- case 0x6F:
- execute_jal(instruction, processor);
- break;
- case 0x23:
- execute_store(instruction, processor, memory);
- break;
- case 0x03:
- execute_load(instruction, processor, memory);
- break;
- case 0x37:
- execute_lui(instruction, processor);
- break;
- default: // undefined opcode
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- }
- void execute_rtype(Instruction instruction, Processor *processor) {
- sWord rs1_value, rs2_value;
- sByte msb;
- Word ones, immediate;
- sDouble rd_value, rs1_double, rs2_double;
- switch (instruction.rtype.funct3){
- case 0x0:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // Add
- processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] + processor->R[instruction.rtype.rs2];
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- //Mul
- rs1_value = processor->R[instruction.rtype.rs1];
- rs2_value = processor->R[instruction.rtype.rs2];
- rd_value = (sDouble) rs1_value * (sDouble) rs2_value;
- processor->R[instruction.rtype.rd] = (Register) (rd_value & 0xFFFFFFFF);
- processor->PC = processor->PC+4;
- break;
- case 0x20:
- //Sub
- processor->R[instruction.rtype.rd] = (Register) (processor->R[instruction.rtype.rs1] - processor->R[instruction.rtype.rs2]);
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x1:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // SLL
- processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] << processor->R[instruction.rtype.rs2];
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- // MULH
- processor->R[instruction.rtype.rd] = (((sDouble) (sWord) processor->R[instruction.rtype.rs1] * (sDouble) (sWord) processor->R[instruction.rtype.rs2]) >> 32);
- processor->PC = processor->PC+4;
- break;
- }
- break;
- case 0x2:
- // SLT
- if((sWord) processor->R[instruction.rtype.rs1] < (sWord) processor->R[instruction.rtype.rs2])
- processor->R[instruction.rtype.rd] = 1;
- else
- processor->R[instruction.rtype.rd] = 0;
- processor->PC = processor->PC+4;
- break;
- case 0x4:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // XOR
- processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] ^ processor->R[instruction.rtype.rs2];
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- // DIV
- processor->R[instruction.rtype.rd] = (Register) ((sDouble) ((sWord) processor->R[instruction.rtype.rs1]) / (sDouble) ((sWord) processor->R[instruction.rtype.rs2]));
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x5:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // SRL
- processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] >> (processor->R[instruction.rtype.rs2] & 0x1f);
- processor->PC = processor->PC+4;
- break;
- case 0x20:
- // SRA
- immediate = processor->R[instruction.rtype.rs2] & 0x1f;
- msb = processor->R[instruction.rtype.rs2];
- msb = msb >> 31;
- if ((msb & 1) & immediate != 0){
- ones = (0xFFFFFFFF) << (32 - immediate);
- processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rs1] >> (processor->R[instruction.rtype.rs2] & 0x1f);
- processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rd] | ones;
- }
- else if (immediate == 0){
- processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rs1];
- }
- else {
- processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rs1] >> (Register) (processor->R[instruction.rtype.rs2] & 0x1f);
- }
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x6:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // OR
- processor->R[instruction.rtype.rd] = (Register) (processor->R[instruction.rtype.rs1] | processor->R[instruction.rtype.rs2]);
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- // REM
- processor->R[instruction.rtype.rd] = (Register) ((sDouble) ((sWord) processor->R[instruction.rtype.rs1]) % ((sWord) processor->R[instruction.rtype.rs2]));
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x7:
- // AND
- processor->R[instruction.rtype.rd] = (Register) (processor->R[instruction.rtype.rs1] & processor->R[instruction.rtype.rs2]);
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- }
- void execute_itype_except_load(Instruction instruction, Processor *processor) {
- Word ones, check_bit, immediate;
- switch (instruction.itype.funct3) {
- case 0x0:
- // ADDI
- processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12);
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- // SLLI
- processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] << (instruction.itype.imm & 0x1F);
- processor->PC = processor->PC+4;
- break;
- case 0x2:
- // STLI
- if ((sWord) processor->R[instruction.itype.rs1] < sign_extend_number(instruction.itype.imm, 12))
- processor->R[instruction.itype.rd] = 1;
- else
- processor->R[instruction.itype.rd] = 0;
- processor->PC = processor->PC+4;
- break;
- case 0x4:
- // XORI
- processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1]^ sign_extend_number(instruction.itype.imm, 12);
- processor->PC = processor->PC+4;
- break;
- case 0x5:
- // Shift Right (You must handle both logical and arithmetic)
- immediate = instruction.itype.imm & 0x1f;
- check_bit = instruction.itype.imm >> 10;
- if (!(check_bit & 1) & (immediate != 0)) { //Logical
- processor->R[instruction.itype.rd] =
- processor->R[instruction.itype.rs1] >> immediate;
- }
- else if ((check_bit & 1) & (immediate != 0)){ //Arithmetic
- if (processor->R[instruction.itype.rs1] & 0x80000000){ //Ones shift
- ones = (0xFFFFFFFF) << (32 - immediate);
- processor->R[instruction.itype.rd] =
- processor->R[instruction.itype.rs1] >> immediate;
- processor->R[instruction.itype.rd] = processor->R[instruction.itype.rd] | ones;
- }
- else { //Zeroes shift
- processor->R[instruction.itype.rd] =
- processor->R[instruction.itype.rs1] >> immediate;
- }
- }
- else if (immediate == 0){
- processor->R[instruction.itype.rd] =
- processor->R[instruction.itype.rs1];
- }
- processor->PC = processor->PC+4;
- break;
- case 0x6:
- // ORI
- processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] | sign_extend_number(instruction.itype.imm, 12);
- processor->PC = processor->PC+4;
- break;
- case 0x7:
- // ANDI
- processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] & sign_extend_number(instruction.itype.imm, 12);
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- break;
- }
- }
- void execute_ecall(Processor *p, Byte *memory) {
- Register i;
- // syscall number is given by a0 (x10)
- // argument is given by a1
- switch(p->R[10]) {
- case 1: // print an integer
- printf("%d",p->R[11]);
- p->PC = p->PC+4;
- break;
- case 4: // print a string
- for(i=p->R[11];i<MEMORY_SPACE && load(memory,i,LENGTH_BYTE);i++) {
- printf("%c",load(memory,i,LENGTH_BYTE));
- }
- p->PC = p->PC+4;
- break;
- case 10: // exit
- printf("exiting the simulator\n");
- p->PC = p->PC+4;
- exit(0);
- break;
- case 11: // print a character
- printf("%c",p->R[11]);
- p->PC = p->PC+4;
- break;
- default: // undefined ecall
- printf("Illegal ecall number %d\n", p->R[10]);
- p->PC = p->PC+4;
- exit(-1);
- break;
- }
- }
- void execute_branch(Instruction instruction, Processor *processor) {
- sWord offset = get_branch_offset(instruction);
- switch (instruction.sbtype.funct3) {
- case 0x0:
- // BEQ
- if (processor->R[instruction.sbtype.rs1] == processor->R[instruction.sbtype.rs2]){
- processor->PC = processor->PC + offset;
- }
- else
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- // BNE
- if (processor->R[instruction.sbtype.rs1] != processor->R[instruction.sbtype.rs2]){
- processor->PC = processor->PC + offset;
- }
- else
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- }
- void execute_load(Instruction instruction, Processor *processor, Byte *memory) {
- switch (instruction.itype.funct3) {
- case 0x0:
- // LB
- processor->R[instruction.itype.rd] = (Register) sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_BYTE), 8);
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- // LH
- processor->R[instruction.itype.rd] = (Register) sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_HALF_WORD), 16);
- processor->PC = processor->PC+4;
- break;
- case 0x2:
- // LW
- processor->R[instruction.itype.rd] = load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_WORD);
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- break;
- }
- }
- void execute_store(Instruction instruction, Processor *processor, Byte *memory) {
- sWord offset;
- switch (instruction.stype.funct3) {
- case 0x0:
- // SB
- offset = get_store_offset(instruction);
- store(memory, processor->R[instruction.stype.rs1] + offset, LENGTH_BYTE, processor->R[instruction.stype.rs2]);
- processor->PC = processor->PC+4;
- break;
- case 0x1:
- // SH
- offset = get_store_offset(instruction);
- store(memory, processor->R[instruction.stype.rs1] + offset, LENGTH_HALF_WORD, processor->R[instruction.stype.rs2]);
- processor->PC = processor->PC+4;
- break;
- case 0x2:
- // SW
- offset = get_store_offset(instruction);
- store(memory, processor->R[instruction.stype.rs1] + offset, LENGTH_WORD, processor->R[instruction.stype.rs2]);
- processor->PC = processor->PC+4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- }
- void execute_jal(Instruction instruction, Processor *processor) {
- sWord offset = get_jump_offset(instruction);
- processor->R[instruction.ujtype.rd] = processor->PC + 4;
- processor->PC = processor->PC + offset;
- }
- void execute_lui(Instruction instruction, Processor *processor) {
- Word immediate = instruction.utype.imm<<12;
- processor->R[instruction.utype.rd] = immediate;
- processor->PC = processor->PC+4;
- }
- void store(Byte *memory, Address address, Alignment alignment, Word value) {
- Word intermediate;
- for (int i = 0; i < alignment; i++){
- intermediate = value >> (8*i);
- *(memory + address + i) = (Byte) (intermediate & 0xFF);
- }
- }
- Word load(Byte *memory, Address address, Alignment alignment) {
- //MEMORY is a byte pointer pointing to the memory
- //Address is where they want you to start
- //Alignment is how many bytes they want you to pull.
- //Oh and this is in Little Endian
- Word result = 0;
- for (int i = 0; i < alignment; i++)
- result += *(memory + address + i)<<(8 * i);
- return result;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement