Added M (Multiplication) extension

master
vhaudiquet 12 months ago
parent 89744626a7
commit 378d0fa463
  1. 31
      src/cpu/instruction.h
  2. 253
      src/cpu/rv32cpu.c

@ -64,18 +64,33 @@
#define FUNC7_SRAI 0x20
/* OPCODE_ARITHLOG sub functions (func3 + func7) */
#define FUNC3_ADD_SUB 0x0
#define FUNC3_ADD_SUB_MUL 0x0
#define FUNC7_ADD 0x0
#define FUNC7_SUB 0x20
#define FUNC3_SLL 0x1
#define FUNC3_SLT 0x2
#define FUNC3_SLTU 0x3
#define FUNC3_XOR 0x4
#define FUNC3_SRL_SRA 0x5
#define FUNC3_SLL_MULH 0x1
#define FUNC7_SLL 0x0
#define FUNC3_SLT_MULHSU 0x2
#define FUNC7_SLT 0x0
#define FUNC3_SLTU_MULHU 0x3
#define FUNC7_SLTU 0x0
#define FUNC3_XOR_DIV 0x4
#define FUNC7_XOR 0x0
#define FUNC3_SRL_SRA_DIVU 0x5
#define FUNC7_SRL 0x0
#define FUNC7_SRA 0x20
#define FUNC3_OR 0x6
#define FUNC3_AND 0x7
#define FUNC3_OR_REM 0x6
#define FUNC7_OR 0x0
#define FUNC3_AND_REMU 0x7
#define FUNC7_AND 0x0
/* RISC-V RV32 M Extension */
#define FUNC7_MUL 0x1
#define FUNC7_MULH 0x1
#define FUNC7_MULHSU 0x1
#define FUNC7_MULHU 0x1
#define FUNC7_DIV 0x1
#define FUNC7_DIVU 0x1
#define FUNC7_REM 0x1
#define FUNC7_REMU 0x1
/* OPCODE_SYSTEM sub functions (func3 + imm) */
#define FUNC3_ECALL_EBREAK 0x0

@ -339,7 +339,7 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
// To find out which operation, we must analyse func3 and func7
switch(instruction->func3)
{
case FUNC3_ADD_SUB:
case FUNC3_ADD_SUB_MUL:
switch(instruction->func7)
{
case FUNC7_ADD:
@ -348,41 +348,122 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
case FUNC7_SUB:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] - cpu->regs.x[instruction->rs2];
break;
case FUNC7_MUL:
cpu->regs.x[instruction->rd] = (uint32_t) (cpu->regs.x[instruction->rs1] * cpu->regs.x[instruction->rs2]);
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog ADD/SUB instruction, could not execute\n", instruction->func7);
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog ADD/SUB/MUL instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
break;
case FUNC3_SLL:
// Slide Left Logical
uint32_t sll_value = cpu->regs.x[instruction->rs2] & 0x1F;
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] << sll_value;
case FUNC3_SLL_MULH:
switch(instruction->func7)
{
case FUNC7_SLL:
// Slide Left Logical
uint32_t sll_value = cpu->regs.x[instruction->rs2] & 0x1F;
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] << sll_value;
break;
case FUNC7_MULH:
// MULtiplication High (32 high bits) (signed * signed)
uint64_t mulh_result = (uint64_t) (((int64_t) cpu->regs.x[instruction->rs1]) * ((int64_t) cpu->regs.x[instruction->rs2]));
cpu->regs.x[instruction->rd] = (uint32_t) (mulh_result >> 32);
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog SLL/MULH instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
break;
case FUNC3_SLT:
// Set Less Than
if(((int32_t) cpu->regs.x[instruction->rs1]) < ((int32_t) cpu->regs.x[instruction->rs2]))
cpu->regs.x[instruction->rd] = 1;
else
cpu->regs.x[instruction->rd] = 0;
case FUNC3_SLT_MULHSU:
switch(instruction->func7)
{
case FUNC7_SLT:
// Set Less Than
if(((int32_t) cpu->regs.x[instruction->rs1]) < ((int32_t) cpu->regs.x[instruction->rs2]))
cpu->regs.x[instruction->rd] = 1;
else
cpu->regs.x[instruction->rd] = 0;
break;
case FUNC7_MULHSU:
// MULtiplication High (32 high bits) (signed * unsigned)
uint64_t mulhsu_result = (uint64_t) (((int64_t) cpu->regs.x[instruction->rs1]) * ((uint64_t) cpu->regs.x[instruction->rs2]));
cpu->regs.x[instruction->rd] = (uint32_t) (mulhsu_result >> 32);
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog SLL/MULH instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
break;
case FUNC3_SLTIU:
// Set Less Than Unsigned
if(cpu->regs.x[instruction->rs1] < cpu->regs.x[instruction->rs2])
cpu->regs.x[instruction->rd] = 1;
else
cpu->regs.x[instruction->rd] = 0;
case FUNC3_SLTU_MULHU:
switch(instruction->func7)
{
case FUNC7_SLTU:
// Set Less Than Unsigned
if(cpu->regs.x[instruction->rs1] < cpu->regs.x[instruction->rs2])
cpu->regs.x[instruction->rd] = 1;
else
cpu->regs.x[instruction->rd] = 0;
break;
case FUNC7_MULHU:
// MULtiplication High (32 high bits) (unsigned * unsigned)
uint64_t mulhu_result = (((uint64_t) cpu->regs.x[instruction->rs1]) * ((uint64_t) cpu->regs.x[instruction->rs2]));
cpu->regs.x[instruction->rd] = (uint32_t) (mulhu_result >> 32);
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog SLTU/MULHU instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
break;
case FUNC3_XOR:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] ^ cpu->regs.x[instruction->rs2];
case FUNC3_XOR_DIV:
switch(instruction->func7)
{
case FUNC7_XOR:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] ^ cpu->regs.x[instruction->rs2];
break;
case FUNC7_DIV:
cpu->regs.x[instruction->rd] = ((int32_t) cpu->regs.x[instruction->rs1]) / ((int32_t) cpu->regs.x[instruction->rs2]);
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog XOR/DIV instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
break;
case FUNC3_OR:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] | cpu->regs.x[instruction->rs2];
case FUNC3_OR_REM:
switch(instruction->func7)
{
case FUNC7_OR:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] | cpu->regs.x[instruction->rs2];
break;
case FUNC7_REM:
cpu->regs.x[instruction->rd] = ((int32_t) cpu->regs.x[instruction->rs1]) % ((int32_t) cpu->regs.x[instruction->rs2]);
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog OR/REM instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
break;
case FUNC3_AND:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] & cpu->regs.x[instruction->rs2];
case FUNC3_AND_REMU:
switch(instruction->func7)
{
case FUNC7_AND:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] & cpu->regs.x[instruction->rs2];
break;
case FUNC7_REMU:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] % cpu->regs.x[instruction->rs2];
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for arithlog AND/REMU instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
break;
case FUNC3_SRL_SRA:
case FUNC3_SRL_SRA_DIVU:
switch(instruction->func7)
{
case FUNC7_SRL:
@ -395,8 +476,11 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
uint32_t sra_value = cpu->regs.x[instruction->rs2] & 0x1F;
cpu->regs.x[instruction->rd] = ((int32_t) cpu->regs.x[instruction->rs1]) >> sra_value;
break;
case FUNC7_DIVU:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] / cpu->regs.x[instruction->rs2];
break;
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/DIVU instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE);
break;
}
@ -579,7 +663,7 @@ void cpu_loop(rv32_cpu_t* cpu)
// Execute
cpu_execute(cpu, &instruction);
// Reset value of zero, in case instruction tried to modify
cpu->regs.zero = 0;
@ -787,7 +871,7 @@ static void cpu_print_instruction(instruction_t* instruction)
// To find out which operation, we must analyse func3 and func7
switch(instruction->func3)
{
case FUNC3_ADD_SUB:
case FUNC3_ADD_SUB_MUL:
switch(instruction->func7)
{
case FUNC7_ADD:
@ -796,33 +880,105 @@ static void cpu_print_instruction(instruction_t* instruction)
case FUNC7_SUB:
printf("sub x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_MUL:
printf("mul 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);
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog ADD/SUB/MUL instruction\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);
case FUNC3_SLL_MULH:
switch(instruction->func7)
{
case FUNC7_SLL:
// Slide Left Logical
printf("sll x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_MULH:
// MULtiplication High (32 high bits) (signed * signed)
printf("mulh x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default:
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog SLL/MULH instruction\n", instruction->func7);
break;
}
break;
case FUNC3_SLT:
// Set Less Than
printf("slt x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
case FUNC3_SLT_MULHSU:
switch(instruction->func7)
{
case FUNC7_SLT:
// Set Less Than
printf("slt x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_MULHSU:
// MULtiplication High (32 high bits) (signed * unsigned)
printf("mulhsu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default:
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog SLL/MULH instruction\n", instruction->func7);
break;
}
break;
case FUNC3_SLTIU:
// Set Less Than Unsigned
printf("sltu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
case FUNC3_SLTU_MULHU:
switch(instruction->func7)
{
case FUNC7_SLTU:
// Set Less Than Unsigned
printf("sltu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_MULHU:
// MULtiplication High (32 high bits) (unsigned * unsigned)
printf("mulhu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default:
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog SLTU/MULHU instruction\n", instruction->func7);
break;
}
break;
case FUNC3_XOR:
printf("xor x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
case FUNC3_XOR_DIV:
switch(instruction->func7)
{
case FUNC7_XOR:
printf("xor x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_DIV:
printf("div x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default:
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog XOR/DIV instruction\n", instruction->func7);
break;
}
break;
case FUNC3_OR:
printf("or x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
case FUNC3_OR_REM:
switch(instruction->func7)
{
case FUNC7_OR:
printf("or x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_REM:
printf("rem x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default:
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog OR/REM instruction\n", instruction->func7);
break;
}
break;
case FUNC3_AND:
printf("and x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
case FUNC3_AND_REMU:
switch(instruction->func7)
{
case FUNC7_AND:
printf("and x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_REMU:
printf("remu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default:
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog AND/REMU instruction\n", instruction->func7);
break;
}
break;
case FUNC3_SRL_SRA:
case FUNC3_SRL_SRA_DIVU:
switch(instruction->func7)
{
case FUNC7_SRL:
@ -833,15 +989,16 @@ static void cpu_print_instruction(instruction_t* instruction)
// Slide Right Arithmetical
printf("sra x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
case FUNC7_DIVU:
printf("divu 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);
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog SRL/SRA/DIVU instruction\n", instruction->func7);
break;
}
break;
default:
fprintf(stderr, "Warning: Unknown func3 0x%x for arithlog instruction\n", instruction->func3);
exit(EXIT_FAILURE);
break;
}
break;

Loading…
Cancel
Save