|
|
@ -35,6 +35,8 @@ typedef struct INSTRUCTION |
|
|
|
uint8_t rs2; |
|
|
|
uint8_t rs2; |
|
|
|
} instruction_t; |
|
|
|
} instruction_t; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void cpu_print_instruction(instruction_t* instruction); |
|
|
|
|
|
|
|
|
|
|
|
void cpu_init() |
|
|
|
void cpu_init() |
|
|
|
{ |
|
|
|
{ |
|
|
|
cpu0 = malloc(sizeof(rv32_cpu_t)); |
|
|
|
cpu0 = malloc(sizeof(rv32_cpu_t)); |
|
|
@ -99,6 +101,9 @@ static void cpu_decode(raw_instruction_t raw_instruction, instruction_t* output) |
|
|
|
// Bits of rd are immediate bits 4:0
|
|
|
|
// Bits of rd are immediate bits 4:0
|
|
|
|
output->immediate |= raw_instruction.rd; |
|
|
|
output->immediate |= raw_instruction.rd; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case OPCODE_NOP: |
|
|
|
|
|
|
|
// TODO : Decode NOP instructions
|
|
|
|
|
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
fprintf(stderr, "Error: Unknown instruction opcode 0x%x, could not decode\n", raw_instruction.opcode); |
|
|
|
fprintf(stderr, "Error: Unknown instruction opcode 0x%x, could not decode\n", raw_instruction.opcode); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
exit(EXIT_FAILURE); |
|
|
@ -300,12 +305,12 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction) |
|
|
|
break; |
|
|
|
break; |
|
|
|
case FUNC3_SLLI: |
|
|
|
case FUNC3_SLLI: |
|
|
|
// Sign-extend immediate in rs2 from 5 bits to 32 bits
|
|
|
|
// Sign-extend immediate in rs2 from 5 bits to 32 bits
|
|
|
|
immediate = (cpu->regs.x[instruction->rs2] & 0x1F) | (cpu->regs.x[instruction->rs2] & 0x10 ? 0xFFFFFFE0 : 0); |
|
|
|
immediate = (instruction->rs2 & 0x1F) | (instruction->rs2 & 0x10 ? 0xFFFFFFE0 : 0); |
|
|
|
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] << immediate; |
|
|
|
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] << immediate; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case FUNC3_SRLI_SRAI: |
|
|
|
case FUNC3_SRLI_SRAI: |
|
|
|
// Sign-extend immediate in rs2 from 5 bits to 32 bits
|
|
|
|
// Sign-extend immediate in rs2 from 5 bits to 32 bits
|
|
|
|
immediate = (cpu->regs.x[instruction->rs2] & 0x1F) | (cpu->regs.x[instruction->rs2] & 0x10 ? 0xFFFFFFE0 : 0); |
|
|
|
immediate = (instruction->rs2 & 0x1F) | (instruction->rs2 & 0x10 ? 0xFFFFFFE0 : 0); |
|
|
|
// Analyse func7 to know which is it
|
|
|
|
// Analyse func7 to know which is it
|
|
|
|
switch(instruction->func7) |
|
|
|
switch(instruction->func7) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -314,10 +319,7 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction) |
|
|
|
break; |
|
|
|
break; |
|
|
|
case FUNC7_SRAI: |
|
|
|
case FUNC7_SRAI: |
|
|
|
// Arithmetic slide
|
|
|
|
// Arithmetic slide
|
|
|
|
uint32_t sign_bit = cpu->regs.x[instruction->rs1] & 0x80000000; |
|
|
|
cpu->regs.x[instruction->rd] = ((int32_t) cpu->regs.x[instruction->rs1]) >> immediate; |
|
|
|
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] >> immediate; |
|
|
|
|
|
|
|
if(sign_bit) |
|
|
|
|
|
|
|
cpu->regs.x[instruction->rd] |= ~(0xFFFFFFFF >> immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog immediate SRLI/SRAI instruction, could not execute\n", instruction->func7); |
|
|
|
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog immediate SRLI/SRAI instruction, could not execute\n", instruction->func7); |
|
|
@ -392,10 +394,7 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction) |
|
|
|
case FUNC7_SRA: |
|
|
|
case FUNC7_SRA: |
|
|
|
// Slide Right Arithmetical
|
|
|
|
// Slide Right Arithmetical
|
|
|
|
uint32_t sra_value = cpu->regs.x[instruction->rs2] & 0x1F; |
|
|
|
uint32_t sra_value = cpu->regs.x[instruction->rs2] & 0x1F; |
|
|
|
uint32_t sign_bit = cpu->regs.x[instruction->rs1] & 0x80000000; |
|
|
|
cpu->regs.x[instruction->rd] = ((int32_t) cpu->regs.x[instruction->rs1]) >> sra_value; |
|
|
|
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] >> sra_value; |
|
|
|
|
|
|
|
if(sign_bit) |
|
|
|
|
|
|
|
cpu->regs.x[instruction->rd] |= ~(0xFFFFFFFF >> sra_value); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog SRL/SRA instruction, could not execute\n", instruction->func7); |
|
|
|
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog SRL/SRA instruction, could not execute\n", instruction->func7); |
|
|
@ -413,11 +412,24 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction) |
|
|
|
case OPCODE_NOP: |
|
|
|
case OPCODE_NOP: |
|
|
|
{ |
|
|
|
{ |
|
|
|
// TODO : Implement PAUSE, FENCE, FENCE.TSO
|
|
|
|
// TODO : Implement PAUSE, FENCE, FENCE.TSO
|
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unsupported NOP instruction\n"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case OPCODE_SYSTEM: |
|
|
|
case OPCODE_SYSTEM: |
|
|
|
{ |
|
|
|
{ |
|
|
|
// TODO : Implement ECALL, EBREAK
|
|
|
|
switch(instruction->immediate) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case IMM_ECALL: |
|
|
|
|
|
|
|
fprintf(stderr, "ECALL: a7(sbi ext id) = %d, a6(sbi funct id) = %d\n", cpu->regs.a7, cpu->regs.a6); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case IMM_EBREAK: |
|
|
|
|
|
|
|
fprintf(stderr, "EBREAK\n"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "FATAL: Unknown SYSTEM instruction while executing (IMM=0x%x)\n", instruction->immediate); |
|
|
|
|
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
default: |
|
|
|
default: |
|
|
@ -444,9 +456,296 @@ void cpu_loop(rv32_cpu_t* cpu) |
|
|
|
instruction_t instruction; |
|
|
|
instruction_t instruction; |
|
|
|
cpu_decode(raw_instruction, &instruction); |
|
|
|
cpu_decode(raw_instruction, &instruction); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cpu_print_instruction(&instruction); |
|
|
|
|
|
|
|
|
|
|
|
// Execute
|
|
|
|
// Execute
|
|
|
|
cpu_execute(cpu, &instruction); |
|
|
|
cpu_execute(cpu, &instruction); |
|
|
|
|
|
|
|
|
|
|
|
cpu->pc += 4; |
|
|
|
cpu->pc += 4; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void cpu_print_instruction(instruction_t* instruction) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
switch(instruction->opcode) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case OPCODE_LUI: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Load Upper Immediate (load immediate(31:12 bits) in rd)
|
|
|
|
|
|
|
|
printf("lui x%u, 0x%x\n", instruction->rd, instruction->immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_AUIPC: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Add Upper Immediate to PC
|
|
|
|
|
|
|
|
printf("auipc x%u, 0x%x\n", instruction->rd, instruction->immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_JAL: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Jump And Link
|
|
|
|
|
|
|
|
// Sign extend immediate from 21 bits to 32 bits
|
|
|
|
|
|
|
|
uint32_t immediate = (instruction->immediate & 0x1FFFFF) | (instruction->immediate & 0x100000 ? 0xFFE00000 : 0); |
|
|
|
|
|
|
|
printf("jal x%u, 0x%x\n", instruction->rd, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_JALR: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Jump And Link Register
|
|
|
|
|
|
|
|
// Sign extend immediate from 12 bits to 32 bits
|
|
|
|
|
|
|
|
uint32_t immediate = (instruction->immediate & 0xFFF) | (instruction->immediate & 0x800 ? 0xFFFFF000 : 0); |
|
|
|
|
|
|
|
printf("jalr x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_BRANCH: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Branches ; to know which one, we must analyse func3
|
|
|
|
|
|
|
|
// Sign extend immediate from 13 bits to 32 bits
|
|
|
|
|
|
|
|
uint32_t immediate = (instruction->immediate & 0xFFF) | (instruction->immediate & 0x1000 ? 0xFFFFE000 : 0); |
|
|
|
|
|
|
|
immediate -= 4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(instruction->func3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC3_BEQ: |
|
|
|
|
|
|
|
// Branch EQual
|
|
|
|
|
|
|
|
printf("beq x%u, x%u, 0x%x\n", instruction->rs1, instruction->rs2, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_BNE: |
|
|
|
|
|
|
|
// Branch Not Equal
|
|
|
|
|
|
|
|
printf("bne x%u, x%u, 0x%x\n", instruction->rs1, instruction->rs2, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_BLT: |
|
|
|
|
|
|
|
// Branch Less Than
|
|
|
|
|
|
|
|
printf("blt x%u, x%u, %d\n", instruction->rs1, instruction->rs2, (int32_t) immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_BLTU: |
|
|
|
|
|
|
|
// Branch Less Than Unsigned
|
|
|
|
|
|
|
|
printf("bltu x%u, x%u, 0x%x\n", instruction->rs1, instruction->rs2, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_BGE: |
|
|
|
|
|
|
|
// Branch Greater Equal
|
|
|
|
|
|
|
|
printf("bge x%u, x%u, %d\n", instruction->rs1, instruction->rs2, (int32_t) immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_BGEU: |
|
|
|
|
|
|
|
// Branch Greater Equal Unsigned
|
|
|
|
|
|
|
|
printf("bgeu x%u, x%u, 0x%x\n", instruction->rs1, instruction->rs2, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func3 0x%x for branch instruction\n", instruction->func3); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_LOAD: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Loads ; to know which one, we must analyse func3
|
|
|
|
|
|
|
|
// Sign extend immediate from 12 bits to 32 bits
|
|
|
|
|
|
|
|
uint32_t immediate = (instruction->immediate & 0xFFF) | (instruction->immediate & 0x800 ? 0xFFFFF000 : 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(instruction->func3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC3_LB: |
|
|
|
|
|
|
|
printf("lb x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_LH: |
|
|
|
|
|
|
|
// Load Halfword (16-bits)
|
|
|
|
|
|
|
|
printf("lh x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_LW: |
|
|
|
|
|
|
|
// Load Word (32-bits)
|
|
|
|
|
|
|
|
printf("lw x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_LBU: |
|
|
|
|
|
|
|
// Load Byte Unsigned (8-bits)
|
|
|
|
|
|
|
|
printf("lbu x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_LHU: |
|
|
|
|
|
|
|
// Load Halfword Unsigned (16-bits)
|
|
|
|
|
|
|
|
printf("lhu x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func3 0x%x for load instruction\n", instruction->func3); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_STORE: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Store ; to know which one, we must analyse func3
|
|
|
|
|
|
|
|
// Sign extend immediate from 12 bits to 32 bits
|
|
|
|
|
|
|
|
uint32_t immediate = (instruction->immediate & 0xFFF) | (instruction->immediate & 0x800 ? 0xFFFFF000 : 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(instruction->func3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC3_SB: |
|
|
|
|
|
|
|
// Store Byte (8-bits)
|
|
|
|
|
|
|
|
printf("sb x%u, x%u, 0x%x\n", instruction->rs1, instruction->rs2, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SH: |
|
|
|
|
|
|
|
// Store Halfword (16-bits)
|
|
|
|
|
|
|
|
printf("sh x%u, x%u, 0x%x\n", instruction->rs1, instruction->rs2, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SW: |
|
|
|
|
|
|
|
// Store Word (32-bits)
|
|
|
|
|
|
|
|
printf("sw x%u, x%u, 0x%x\n", instruction->rs1, instruction->rs2, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func3 0x%x for store instruction\n", instruction->func3); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_ARITHLOG_IMM: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Arithmetic and logic instructions on immediate values
|
|
|
|
|
|
|
|
// To find out which operation, we must analyse func3
|
|
|
|
|
|
|
|
// Sign extend immediate from 12 bits to 32 bits
|
|
|
|
|
|
|
|
uint32_t immediate = (instruction->immediate & 0xFFF) | (instruction->immediate & 0x800 ? 0xFFFFF000 : 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(instruction->func3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC3_ADDI: |
|
|
|
|
|
|
|
// ADD Immediate
|
|
|
|
|
|
|
|
printf("addi x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SLTI: |
|
|
|
|
|
|
|
// Set Less Than Immediate
|
|
|
|
|
|
|
|
printf("slti x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SLTIU: |
|
|
|
|
|
|
|
printf("sltiu x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_XORI: |
|
|
|
|
|
|
|
// XOR Immediate
|
|
|
|
|
|
|
|
printf("xori x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_ORI: |
|
|
|
|
|
|
|
// OR Immediate
|
|
|
|
|
|
|
|
printf("ori x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_ANDI: |
|
|
|
|
|
|
|
// AND Immediate
|
|
|
|
|
|
|
|
printf("andi x%u, x%u, 0x%x\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SLLI: |
|
|
|
|
|
|
|
// Sign-extend immediate in rs2 from 5 bits to 32 bits
|
|
|
|
|
|
|
|
immediate = (instruction->rs2 & 0x1F) | (instruction->rs2 & 0x10 ? 0xFFFFFFE0 : 0); |
|
|
|
|
|
|
|
printf("slli x%u, x%u, %u\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SRLI_SRAI: |
|
|
|
|
|
|
|
// Sign-extend immediate in rs2 from 5 bits to 32 bits
|
|
|
|
|
|
|
|
immediate = (instruction->rs2 & 0x1F) | (instruction->rs2 & 0x10 ? 0xFFFFFFE0 : 0); |
|
|
|
|
|
|
|
// Analyse func7 to know which is it
|
|
|
|
|
|
|
|
switch(instruction->func7) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC7_SRLI: |
|
|
|
|
|
|
|
printf("srli x%u, x%u, %u\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC7_SRAI: |
|
|
|
|
|
|
|
// Arithmetic slide
|
|
|
|
|
|
|
|
printf("srai x%u, x%u, %u\n", instruction->rd, instruction->rs1, immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog immediate SRLI/SRAI instruction\n", instruction->func7); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func3 0x%x for arithlog immediate instruction, could not execute\n", instruction->func3); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_ARITHLOG: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Arithmetic and logic instructions
|
|
|
|
|
|
|
|
// To find out which operation, we must analyse func3 and func7
|
|
|
|
|
|
|
|
switch(instruction->func3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC3_ADD_SUB: |
|
|
|
|
|
|
|
switch(instruction->func7) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC7_ADD: |
|
|
|
|
|
|
|
printf("add x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC7_SUB: |
|
|
|
|
|
|
|
printf("sub x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog ADD/SUB instruction, could not execute\n", instruction->func7); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SLL: |
|
|
|
|
|
|
|
// Slide Left Logical
|
|
|
|
|
|
|
|
printf("sll x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SLT: |
|
|
|
|
|
|
|
// Set Less Than
|
|
|
|
|
|
|
|
printf("slt x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SLTIU: |
|
|
|
|
|
|
|
// Set Less Than Unsigned
|
|
|
|
|
|
|
|
printf("sltu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_XOR: |
|
|
|
|
|
|
|
printf("xor x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_OR: |
|
|
|
|
|
|
|
printf("or x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_AND: |
|
|
|
|
|
|
|
printf("and x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC3_SRL_SRA: |
|
|
|
|
|
|
|
switch(instruction->func7) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case FUNC7_SRL: |
|
|
|
|
|
|
|
// Slide Right Logical
|
|
|
|
|
|
|
|
printf("srl x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FUNC7_SRA: |
|
|
|
|
|
|
|
// Slide Right Arithmetical
|
|
|
|
|
|
|
|
printf("sra x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog SRL/SRA instruction\n", instruction->func7); |
|
|
|
|
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown func3 0x%x for arithlog instruction\n", instruction->func3); |
|
|
|
|
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_NOP: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// TODO : Implement PAUSE, FENCE, FENCE.TSO
|
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unsupported NOP instruction\n"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case OPCODE_SYSTEM: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
switch(instruction->immediate) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case IMM_ECALL: |
|
|
|
|
|
|
|
printf("ecall\n"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case IMM_EBREAK: |
|
|
|
|
|
|
|
printf("ebreak\n"); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown SYSTEM instruction (IMM=0x%x)\n", instruction->immediate); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
fprintf(stderr, "Warning: Unknown instruction opcode 0x%x while printing\n", instruction->opcode); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|