Division
This commit is contained in:
@ -220,7 +220,7 @@ static void execute_op(Hart* hart, uint32_t instruction)
|
|||||||
}
|
}
|
||||||
else if (bank == 1)
|
else if (bank == 1)
|
||||||
{
|
{
|
||||||
if ((inst.funct3 & 0x8) == 0)
|
if ((inst.funct3 & 0x4) == 0)
|
||||||
{
|
{
|
||||||
uint64_t a = hart->regs[inst.rs1];
|
uint64_t a = hart->regs[inst.rs1];
|
||||||
uint64_t b = hart->regs[inst.rs2];
|
uint64_t b = hart->regs[inst.rs2];
|
||||||
@ -241,7 +241,68 @@ static void execute_op(Hart* hart, uint32_t instruction)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(!"Unhandled M OP");
|
uint32_t a = hart->regs[inst.rs1];
|
||||||
|
uint32_t b = hart->regs[inst.rs2];
|
||||||
|
|
||||||
|
switch (inst.funct3 & 0x3)
|
||||||
|
{
|
||||||
|
case 0: // DIV
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
else if (a == 0x80000000 && b == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = 0x80000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = (uint32_t)((int32_t)a / (int32_t)b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: // DIVU
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = a / b;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: // REM
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = a;
|
||||||
|
}
|
||||||
|
else if (a == 0x80000000 && b == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = (uint32_t)((int32_t)a % (int32_t)b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: // REMU
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hart->regs[inst.rd] = a % b;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -263,6 +263,36 @@ static void test_m()
|
|||||||
|
|
||||||
execute(&hart, 0x022091b3); // mulh x3, x1, x2
|
execute(&hart, 0x022091b3); // mulh x3, x1, x2
|
||||||
assert(hart.regs[3] == 0x00000000);
|
assert(hart.regs[3] == 0x00000000);
|
||||||
|
|
||||||
|
hart.regs[1] = (uint32_t)-63;
|
||||||
|
hart.regs[2] = 4;
|
||||||
|
|
||||||
|
execute(&hart, 0x0220c1b3); // div x3, x1, x2
|
||||||
|
assert(hart.regs[3] == (uint32_t)-15);
|
||||||
|
|
||||||
|
execute(&hart, 0x0220d1b3); // divu x3, x1, x2
|
||||||
|
assert(hart.regs[3] == 0x3FFFFFF0);
|
||||||
|
|
||||||
|
execute(&hart, 0x0220e1b3); // rem x3, x1, x2
|
||||||
|
assert(hart.regs[3] == (uint32_t)-3);
|
||||||
|
|
||||||
|
execute(&hart, 0x0220f1b3); // remu x3, x1, x2
|
||||||
|
assert(hart.regs[3] == 1);
|
||||||
|
|
||||||
|
hart.regs[1] = 30;
|
||||||
|
hart.regs[2] = 0;
|
||||||
|
|
||||||
|
execute(&hart, 0x0220c1b3); // div x3, x1, x2
|
||||||
|
assert(hart.regs[3] == 0xFFFFFFFF);
|
||||||
|
|
||||||
|
execute(&hart, 0x0220d1b3); // divu x3, x1, x2
|
||||||
|
assert(hart.regs[3] == 0xFFFFFFFF);
|
||||||
|
|
||||||
|
execute(&hart, 0x0220e1b3); // rem x3, x1, x2
|
||||||
|
assert(hart.regs[3] == 30);
|
||||||
|
|
||||||
|
execute(&hart, 0x0220f1b3); // remu x3, x1, x2
|
||||||
|
assert(hart.regs[3] == 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
|
Reference in New Issue
Block a user