Fix branch signextend + offset

master
vhaudiquet 1 year ago
parent 24ca9532d4
commit 57dfd9cb76
  1. 17
      src/cpu/rv32cpu.c

@ -150,7 +150,7 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
{ {
// Branches ; to know which one, we must analyse func3 // Branches ; to know which one, we must analyse func3
// Sign extend immediate from 13 bits to 32 bits // Sign extend immediate from 13 bits to 32 bits
uint32_t immediate = (instruction->immediate & 0xFFF) | (instruction->immediate & 0x1000 ? 0xFFFFE000 : 0); uint32_t immediate = (instruction->immediate & 0x1FFF) | (instruction->immediate & 0x1000 ? 0xFFFFE000 : 0);
immediate -= 4; immediate -= 4;
switch(instruction->func3) switch(instruction->func3)
@ -158,32 +158,32 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
case FUNC3_BEQ: case FUNC3_BEQ:
// Branch EQual // Branch EQual
if(cpu->regs.x[instruction->rs1] == cpu->regs.x[instruction->rs2]) if(cpu->regs.x[instruction->rs1] == cpu->regs.x[instruction->rs2])
cpu->pc = immediate; cpu->pc += immediate;
break; break;
case FUNC3_BNE: case FUNC3_BNE:
// Branch Not Equal // Branch Not Equal
if(cpu->regs.x[instruction->rs1] != cpu->regs.x[instruction->rs2]) if(cpu->regs.x[instruction->rs1] != cpu->regs.x[instruction->rs2])
cpu->pc = immediate; cpu->pc += immediate;
break; break;
case FUNC3_BLT: case FUNC3_BLT:
// Branch Less Than // Branch Less Than
if(((int32_t) cpu->regs.x[instruction->rs1]) < ((int32_t) cpu->regs.x[instruction->rs2])) if(((int32_t) cpu->regs.x[instruction->rs1]) < ((int32_t) cpu->regs.x[instruction->rs2]))
cpu->pc = immediate; cpu->pc += immediate;
break; break;
case FUNC3_BLTU: case FUNC3_BLTU:
// Branch Less Than Unsigned // Branch Less Than Unsigned
if(cpu->regs.x[instruction->rs1] < cpu->regs.x[instruction->rs2]) if(cpu->regs.x[instruction->rs1] < cpu->regs.x[instruction->rs2])
cpu->pc = immediate; cpu->pc += immediate;
break; break;
case FUNC3_BGE: case FUNC3_BGE:
// Branch Greater Equal // Branch Greater Equal
if(((int32_t) cpu->regs.x[instruction->rs1]) >= ((int32_t) cpu->regs.x[instruction->rs2])) if(((int32_t) cpu->regs.x[instruction->rs1]) >= ((int32_t) cpu->regs.x[instruction->rs2]))
cpu->pc = immediate; cpu->pc += immediate;
break; break;
case FUNC3_BGEU: case FUNC3_BGEU:
// Branch Greater Equal Unsigned // Branch Greater Equal Unsigned
if(cpu->regs.x[instruction->rs1] >= cpu->regs.x[instruction->rs2]) if(cpu->regs.x[instruction->rs1] >= cpu->regs.x[instruction->rs2])
cpu->pc = immediate; cpu->pc += immediate;
break; break;
default: default:
fprintf(stderr, "FATAL: Unknown func3 0x%x for branch instruction, could not execute\n", instruction->func3); fprintf(stderr, "FATAL: Unknown func3 0x%x for branch instruction, could not execute\n", instruction->func3);
@ -621,8 +621,7 @@ static void cpu_print_instruction(instruction_t* instruction)
{ {
// Branches ; to know which one, we must analyse func3 // Branches ; to know which one, we must analyse func3
// Sign extend immediate from 13 bits to 32 bits // Sign extend immediate from 13 bits to 32 bits
uint32_t immediate = (instruction->immediate & 0xFFF) | (instruction->immediate & 0x1000 ? 0xFFFFE000 : 0); uint32_t immediate = (instruction->immediate & 0x1FFF) | (instruction->immediate & 0x1000 ? 0xFFFFE000 : 0);
immediate -= 4;
switch(instruction->func3) switch(instruction->func3)
{ {

Loading…
Cancel
Save