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) {
- switch (instruction.rtype.funct3){
- case 0x0:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // Add
- int add1 = processor->R[instruction.rtype.rs1];
- int add2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = add1 + add2;
- processor->PC += 4;
- break;
- case 0x1:
- // Mul
- int mul1 = processor->R[instruction.rtype.rs1];
- int mul2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = mul1 * mul2;
- processor->PC += 4;
- break;
- case 0x20:
- // Sub
- int sub1 = processor->R[instruction.rtype.rs1];
- int sub2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = sub1 - sub2;
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x1:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // SLL
- int sll1 = processor->R[instruction.rtype.rs1];
- int sll2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = sll1 << sll2;
- processor->PC += 4;
- break;
- case 0x1:
- // MULH
- int mulh1 = processor->R[instruction.rtype.rs1];
- int mulh2 = processor->R[instruction.rtype.rs2];
- int result = mulh1 * mulh2;
- processor->R[instruction.rtype.rd] = result >> 32;
- processor->PC += 4;
- break;
- }
- break;
- case 0x2:
- // SLT
- int slt1 = processor->R[instruction.rtype.rs1];
- int slt2 = processor->R[instruction.rtype.rs2];
- if (slt1 < slt2) {
- processor->R[instruction.rtype.rd] = 1;
- } else {
- processor->R[instruction.rtype.rd] = 0;
- }
- processor->PC += 4;
- break;
- case 0x4:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // XOR
- int xor1 = processor->R[instruction.rtype.rs1];
- int xor2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = xor1 ^ xor2;
- processor->PC += 4;
- break;
- case 0x1:
- // DIV
- int div1 = processor->R[instruction.rtype.rs1];
- int div2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = div1 / div2;
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x5:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // SRL
- int srl1 = processor->R[instruction.rtype.rs1];
- int srl2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = srl1 >> srl2;
- processor->PC += 4;
- break;
- case 0x20:
- // SRA
- int sra1 = processor->R[instruction.rtype.rs1];
- int sra2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = sra1 >> sra2;
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x6:
- switch (instruction.rtype.funct7) {
- case 0x0:
- // OR
- int or1 = processor->R[instruction.rtype.rs1];
- int or2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = or1 | or2;
- processor->PC += 4;
- break;
- case 0x1:
- // REM
- int rem1 = processor->R[instruction.rtype.rs1];
- int rem2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = rem1 % rem2;
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- break;
- case 0x7:
- // AND
- int and1 = processor->R[instruction.rtype.rs1];
- int and2 = processor->R[instruction.rtype.rs2];
- processor->R[instruction.rtype.rd] = and1 | and2;
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- }
- void execute_itype_except_load(Instruction instruction, Processor *processor) {
- int shiftOp;
- switch (instruction.itype.funct3) {
- case 0x0:
- // ADDI
- int addi1 = processor->R[instruction.itype.rs1];
- int addi2 = sign_extend_number(instruction.itype.imm, 12);
- processor->R[instruction.itype.rd] = addi1 + addi2;
- processor->PC += 4;
- break;
- case 0x1:
- // SLLI
- int slli1 = processor->R[instruction.itype.rs1];
- int slli2 = instruction.itype.imm;
- processor->R[instruction.itype.rd] = slli1 << slli2;
- processor->PC += 4;
- break;
- case 0x2:
- // STLI
- int stli1 = processor->R[instruction.itype.rs1];
- int stli2 = sign_extend_number(instruction.itype.imm, 12);
- if (stli1 < stli2) {
- processor->R[instruction.itype.rd] = 1;
- } else {
- processor->R[instruction.itype.rd] = 0;
- }
- processor->PC += 4;
- break;
- case 0x4:
- // XORI
- int xori1 = processor->R[instruction.itype.rs1];
- int xori2 = sign_extend_number(instruction.itype.imm, 12);
- processor->R[instruction.itype.rd] = xori1 ^ xori2;
- processor->PC += 4;
- break;
- case 0x5:
- // Shift Right (You must handle both logical and arithmetic)
- switch (instruction.itype.imm >> 5) {
- case 0x00:
- int srli1 = processor->R[instruction.itype.rs1];
- int srli2 = instruction.itype.imm;
- processor->R[instruction.itype.rd] = srli1 >> srli2;
- processor->PC += 4;
- break;
- case 0x20:
- int srai1 = processor->R[instruction.itype.rs1];
- int srai2 = instruction.itype.imm;
- processor->R[instruction.itype.rd] = srai1 >> srai2;
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- break;
- }
- case 0x6:
- // ORI
- int ori1 = processor->R[instruction.itype.rs1];
- int ori2 = sign_extend_number(instruction.itype.imm, 12);
- processor->R[instruction.itype.rd] = ori1 | ori2;
- processor->PC += 4;
- break;
- case 0x7:
- // ANDI
- int andi1 = processor->R[instruction.itype.rs1];
- int andi2 = sign_extend_number(instruction.itype.imm, 12);
- processor->R[instruction.itype.rd] = andi1 & andi2;
- 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 += 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 += 4;
- break;
- case 10: // exit
- printf("exiting the simulator\n");
- p->PC += 4;
- exit(0);
- break;
- case 11: // print a character
- printf("%c",p->R[11]);
- p->PC += 4;
- break;
- default: // undefined ecall
- printf("Illegal ecall number %d\n", p->R[10]);
- exit(-1);
- break;
- }
- }
- void execute_branch(Instruction instruction, Processor *processor) {
- switch (instruction.sbtype.funct3) {
- case 0x0:
- // BEQ
- int brn0 = processor->PC + sign_extend_number(get_branch_offset(instruction), 13);
- int eq10 = processor->R[instruction.sbtype.rs1];
- int eq20 = processor->R[instruction.sbtype.rs2];
- if (eq10 == eq20) {
- processor->PC = brn0;
- } else {
- processor->PC += 4;
- }
- break;
- case 0x1:
- // BNE
- int brn1 = processor->PC + sign_extend_number(get_branch_offset(instruction), 13);
- int eq11 = processor->R[instruction.sbtype.rs1];
- int eq21 = processor->R[instruction.sbtype.rs2];
- if (eq11 != eq21) {
- processor->PC = brn1;
- } else {
- 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] = load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_BYTE);
- //processor->R[instruction.itype.rd] = sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + instruction.itype.imm, LENGTH_BYTE), 8);
- processor->PC += 4;
- break;
- case 0x1:
- // LH
- processor->R[instruction.itype.rd] = load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_HALF_WORD);
- //processor->R[instruction.itype.rd] = sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + instruction.itype.imm, LENGTH_HALF_WORD), 16);
- 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->R[instruction.itype.rd] = sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + instruction.itype.imm, LENGTH_WORD), 32);
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- break;
- }
- }
- void execute_store(Instruction instruction, Processor *processor, Byte *memory) {
- switch (instruction.stype.funct3) {
- case 0x0:
- // SB
- store(memory, processor->R[instruction.stype.rs1] + sign_extend_number(get_store_offset(instruction), 12), LENGTH_BYTE, processor->R[instruction.stype.rs2]);
- processor->PC += 4;
- break;
- case 0x1:
- // SH
- store(memory, processor->R[instruction.stype.rs1] + sign_extend_number(get_store_offset(instruction), 12), LENGTH_HALF_WORD, processor->R[instruction.stype.rs2]);
- processor->PC += 4;
- break;
- case 0x2:
- // SW
- store(memory, processor->R[instruction.stype.rs1] + sign_extend_number(get_store_offset(instruction), 12), LENGTH_WORD, processor->R[instruction.stype.rs2]);
- processor->PC += 4;
- break;
- default:
- handle_invalid_instruction(instruction);
- exit(-1);
- break;
- }
- }
- void execute_jal(Instruction instruction, Processor *processor) {
- /* YOUR CODE HERE */
- int nextPC = processor->PC + get_jump_offset(instruction);
- processor->R[instruction.ujtype.rd] = processor->PC + 4;
- processor->PC = nextPC;
- }
- void execute_lui(Instruction instruction, Processor *processor) {
- /* YOUR CODE HERE */
- int imm = sign_extend_number(instruction.utype.imm, 32) << 12;
- processor->R[instruction.utype.rd] = imm;
- processor->PC += 4;
- }
- void store(Byte *memory, Address address, Alignment alignment, Word value) {
- /* YOUR CODE HERE */
- if (alignment == LENGTH_WORD)
- *(uint32_t*)(memory + address) = (uint32_t) value;
- else if (alignment == LENGTH_HALF_WORD)
- *(uint16_t*)(memory + address) = (uint16_t) value;
- else if (alignment == LENGTH_BYTE)
- *(uint8_t*)(memory + address) = (uint8_t) value;
- }
- Word load(Byte *memory, Address address, Alignment alignment) {
- /* YOUR CODE HERE */
- if(((address==0)|((address+alignment)<1) | ((address+alignment)>=MEMORY_SPACE))){exit(-1);}
- if((alignment==LENGTH_HALF_WORD && (address %2 !=0))){exit(-1);}
- if((alignment==LENGTH_WORD && (address % 4 !=0))){exit(-1);}
- switch(alignment){
- case LENGTH_BYTE:
- return *(Byte*) (memory+address);
- case LENGTH_HALF_WORD:
- return *(Half*) (memory+address);
- default:
- return *(Word*) (memory+address);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement