Added M (Multiplication) extension

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

@ -64,18 +64,33 @@
#define FUNC7_SRAI 0x20 #define FUNC7_SRAI 0x20
/* OPCODE_ARITHLOG sub functions (func3 + func7) */ /* OPCODE_ARITHLOG sub functions (func3 + func7) */
#define FUNC3_ADD_SUB 0x0 #define FUNC3_ADD_SUB_MUL 0x0
#define FUNC7_ADD 0x0 #define FUNC7_ADD 0x0
#define FUNC7_SUB 0x20 #define FUNC7_SUB 0x20
#define FUNC3_SLL 0x1 #define FUNC3_SLL_MULH 0x1
#define FUNC3_SLT 0x2 #define FUNC7_SLL 0x0
#define FUNC3_SLTU 0x3 #define FUNC3_SLT_MULHSU 0x2
#define FUNC3_XOR 0x4 #define FUNC7_SLT 0x0
#define FUNC3_SRL_SRA 0x5 #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_SRL 0x0
#define FUNC7_SRA 0x20 #define FUNC7_SRA 0x20
#define FUNC3_OR 0x6 #define FUNC3_OR_REM 0x6
#define FUNC3_AND 0x7 #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) */ /* OPCODE_SYSTEM sub functions (func3 + imm) */
#define FUNC3_ECALL_EBREAK 0x0 #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 // To find out which operation, we must analyse func3 and func7
switch(instruction->func3) switch(instruction->func3)
{ {
case FUNC3_ADD_SUB: case FUNC3_ADD_SUB_MUL:
switch(instruction->func7) switch(instruction->func7)
{ {
case FUNC7_ADD: case FUNC7_ADD:
@ -348,41 +348,122 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
case FUNC7_SUB: case FUNC7_SUB:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] - cpu->regs.x[instruction->rs2]; cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] - cpu->regs.x[instruction->rs2];
break; break;
case FUNC7_MUL:
cpu->regs.x[instruction->rd] = (uint32_t) (cpu->regs.x[instruction->rs1] * cpu->regs.x[instruction->rs2]);
break;
default: 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); exit(EXIT_FAILURE);
break; break;
} }
break; break;
case FUNC3_SLL: case FUNC3_SLL_MULH:
// Slide Left Logical switch(instruction->func7)
uint32_t sll_value = cpu->regs.x[instruction->rs2] & 0x1F; {
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] << sll_value; 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; break;
case FUNC3_SLT: case FUNC3_SLT_MULHSU:
// Set Less Than switch(instruction->func7)
if(((int32_t) cpu->regs.x[instruction->rs1]) < ((int32_t) cpu->regs.x[instruction->rs2])) {
cpu->regs.x[instruction->rd] = 1; case FUNC7_SLT:
else // Set Less Than
cpu->regs.x[instruction->rd] = 0; 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; break;
case FUNC3_SLTIU: case FUNC3_SLTU_MULHU:
// Set Less Than Unsigned switch(instruction->func7)
if(cpu->regs.x[instruction->rs1] < cpu->regs.x[instruction->rs2]) {
cpu->regs.x[instruction->rd] = 1; case FUNC7_SLTU:
else // Set Less Than Unsigned
cpu->regs.x[instruction->rd] = 0; 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; break;
case FUNC3_XOR: case FUNC3_XOR_DIV:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] ^ cpu->regs.x[instruction->rs2]; 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; break;
case FUNC3_OR: case FUNC3_OR_REM:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] | cpu->regs.x[instruction->rs2]; 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; break;
case FUNC3_AND: case FUNC3_AND_REMU:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] & cpu->regs.x[instruction->rs2]; 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; break;
case FUNC3_SRL_SRA: case FUNC3_SRL_SRA_DIVU:
switch(instruction->func7) switch(instruction->func7)
{ {
case FUNC7_SRL: 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; uint32_t sra_value = cpu->regs.x[instruction->rs2] & 0x1F;
cpu->regs.x[instruction->rd] = ((int32_t) cpu->regs.x[instruction->rs1]) >> sra_value; cpu->regs.x[instruction->rd] = ((int32_t) cpu->regs.x[instruction->rs1]) >> sra_value;
break; break;
case FUNC7_DIVU:
cpu->regs.x[instruction->rd] = cpu->regs.x[instruction->rs1] / cpu->regs.x[instruction->rs2];
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/DIVU instruction, could not execute\n", instruction->func7);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
} }
@ -787,7 +871,7 @@ static void cpu_print_instruction(instruction_t* instruction)
// To find out which operation, we must analyse func3 and func7 // To find out which operation, we must analyse func3 and func7
switch(instruction->func3) switch(instruction->func3)
{ {
case FUNC3_ADD_SUB: case FUNC3_ADD_SUB_MUL:
switch(instruction->func7) switch(instruction->func7)
{ {
case FUNC7_ADD: case FUNC7_ADD:
@ -796,33 +880,105 @@ static void cpu_print_instruction(instruction_t* instruction)
case FUNC7_SUB: case FUNC7_SUB:
printf("sub x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); printf("sub x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break; break;
case FUNC7_MUL:
printf("mul x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default: 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;
} }
break; break;
case FUNC3_SLL: case FUNC3_SLL_MULH:
// Slide Left Logical switch(instruction->func7)
printf("sll x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); {
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; break;
case FUNC3_SLT: case FUNC3_SLT_MULHSU:
// Set Less Than switch(instruction->func7)
printf("slt x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); {
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; break;
case FUNC3_SLTIU: case FUNC3_SLTU_MULHU:
// Set Less Than Unsigned switch(instruction->func7)
printf("sltu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); {
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; break;
case FUNC3_XOR: case FUNC3_XOR_DIV:
printf("xor x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); 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; break;
case FUNC3_OR: case FUNC3_OR_REM:
printf("or x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); 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; break;
case FUNC3_AND: case FUNC3_AND_REMU:
printf("and x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); 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; break;
case FUNC3_SRL_SRA: case FUNC3_SRL_SRA_DIVU:
switch(instruction->func7) switch(instruction->func7)
{ {
case FUNC7_SRL: case FUNC7_SRL:
@ -833,15 +989,16 @@ static void cpu_print_instruction(instruction_t* instruction)
// Slide Right Arithmetical // Slide Right Arithmetical
printf("sra x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2); printf("sra x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break; break;
case FUNC7_DIVU:
printf("divu x%u, x%u, x%u\n", instruction->rd, instruction->rs1, instruction->rs2);
break;
default: default:
fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog SRL/SRA instruction\n", instruction->func7); fprintf(stderr, "Warning: Unknown func7 0x%x for arithlog SRL/SRA/DIVU instruction\n", instruction->func7);
exit(EXIT_FAILURE);
break; break;
} }
break; break;
default: default:
fprintf(stderr, "Warning: Unknown func3 0x%x for arithlog instruction\n", instruction->func3); fprintf(stderr, "Warning: Unknown func3 0x%x for arithlog instruction\n", instruction->func3);
exit(EXIT_FAILURE);
break; break;
} }
break; break;

Loading…
Cancel
Save