13 changed files with 605 additions and 261 deletions
File diff suppressed because it is too large
@ -0,0 +1,66 @@ |
|||
#include "pk.h" |
|||
#include "pcr.h" |
|||
|
|||
|
|||
#include "softint.h" |
|||
#include "riscv-opc.h" |
|||
#include <stdint.h> |
|||
|
|||
#define noisy 0 |
|||
|
|||
|
|||
int emulate_int(trapframe_t* tf) |
|||
{ |
|||
if(noisy) |
|||
printk("Int emulation at pc %lx, insn %x\n",tf->epc,(uint32_t)tf->insn); |
|||
|
|||
#define RS1 ((tf->insn >> 22) & 0x1F) |
|||
#define RS2 ((tf->insn >> 17) & 0x1F) |
|||
#define RD ((tf->insn >> 27) & 0x1F) |
|||
|
|||
// #define XRS1 (tf->gpr[RS1])
|
|||
// #define XRS2 (tf->gpr[RS2])
|
|||
#define XRD (tf->gpr[RD]) |
|||
|
|||
unsigned long xrs1 = tf->gpr[RS1]; |
|||
unsigned long xrs2 = tf->gpr[RS2]; |
|||
|
|||
#define IS_INSN(x) ((tf->insn & MASK_ ## x) == MATCH_ ## x) |
|||
|
|||
if(IS_INSN(DIV)) |
|||
{ |
|||
if(noisy) |
|||
printk("emulating div\n"); |
|||
XRD = softint_divu(xrs1, xrs2); |
|||
} |
|||
else if(IS_INSN(DIVU)) |
|||
{ |
|||
if(noisy) |
|||
printk("emulating divu\n"); |
|||
XRD = softint_divu( xrs1, xrs2); |
|||
} |
|||
else if(IS_INSN(MUL)) |
|||
{ |
|||
if(noisy) |
|||
printk("emulating mul\n"); |
|||
XRD = softint_mul(xrs1, xrs2); |
|||
} |
|||
else if(IS_INSN(REM)) |
|||
{ |
|||
if(noisy) |
|||
printk("emulating rem\n"); |
|||
XRD = softint_remu(xrs1, xrs2); |
|||
} |
|||
else if(IS_INSN(REMU)) |
|||
{ |
|||
if(noisy) |
|||
printk("emulating remu\n"); |
|||
XRD = softint_remu(xrs1, xrs2); |
|||
} |
|||
else |
|||
return -1; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,45 @@ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
long |
|||
softint_divu( long rs1, long rs2 ) |
|||
{ |
|||
// only designed to work for mabi=32
|
|||
// quotient = dividend / divisor + remainder
|
|||
unsigned long long dividend = rs1; |
|||
unsigned long long divisor = rs2; |
|||
|
|||
|
|||
if (divisor == 0) return -1; |
|||
|
|||
unsigned long long temp_dividend = dividend; |
|||
unsigned long long temp_divisor = divisor; |
|||
|
|||
unsigned long long quotient = 0; |
|||
|
|||
|
|||
for (int i=0; i <= 32; i++) |
|||
{ |
|||
unsigned long long temp_quotient = 1; |
|||
|
|||
if (temp_divisor == temp_dividend) { quotient += 1; break;} |
|||
else if (temp_dividend < temp_divisor) { quotient += 0; break; } |
|||
|
|||
while (temp_divisor <= temp_dividend && temp_quotient != 0) |
|||
{ |
|||
temp_divisor = temp_divisor << 1; |
|||
temp_quotient = temp_quotient << 1; |
|||
} |
|||
|
|||
temp_divisor = temp_divisor >> 1; |
|||
temp_quotient = temp_quotient >> 1; |
|||
|
|||
|
|||
temp_dividend = temp_dividend - temp_divisor; |
|||
temp_divisor = divisor; |
|||
quotient += temp_quotient; |
|||
} |
|||
|
|||
return (long) quotient; |
|||
} |
|||
|
|||
@ -0,0 +1,22 @@ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
long softint_mul( long x, long y ) |
|||
{ |
|||
|
|||
int i; |
|||
long result = 0; |
|||
|
|||
for (i = 0; i < sizeof(long); i++) { |
|||
if ((x & 0x1) == 1) |
|||
result = result + y; |
|||
|
|||
x = x >> 1; |
|||
y = y << 1; |
|||
} |
|||
|
|||
return result; |
|||
|
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,38 @@ |
|||
|
|||
#include <stdint.h> |
|||
|
|||
long |
|||
softint_remu( long rs1, long rs2 ) |
|||
{ |
|||
// only designed to work for mabi=32
|
|||
// quotient = dividend / divisor + remainder
|
|||
|
|||
unsigned long long dividend = rs1; |
|||
unsigned long long divisor = rs2; |
|||
|
|||
if (divisor == 0) { return dividend; } |
|||
|
|||
long long temp_dividend = dividend; |
|||
long long temp_divisor = divisor; |
|||
|
|||
for (int i=0; i <= 32; i++) |
|||
{ |
|||
if (temp_divisor == temp_dividend) { return 0; } |
|||
else if (temp_dividend < temp_divisor) { return (long) temp_dividend; } |
|||
|
|||
|
|||
while (temp_divisor <= temp_dividend && temp_divisor != 0) |
|||
{ |
|||
temp_divisor = temp_divisor << 1; |
|||
} |
|||
|
|||
temp_divisor = temp_divisor >> 1; |
|||
|
|||
|
|||
temp_dividend = temp_dividend - temp_divisor; |
|||
temp_divisor = divisor; |
|||
} |
|||
|
|||
return (long) temp_dividend; |
|||
} |
|||
|
|||
@ -0,0 +1 @@ |
|||
|
|||
@ -0,0 +1,23 @@ |
|||
|
|||
#ifndef softint_h |
|||
#define softint_h |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
|
|||
/*----------------------------------------------------------------------------
|
|||
| Integer Operations. |
|||
*----------------------------------------------------------------------------*/ |
|||
|
|||
long softint_divu( long, long ); |
|||
long softint_remu( long, long ); |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
|||
|
|||
@ -0,0 +1,13 @@ |
|||
softint_subproject_deps = |
|||
|
|||
softint_hdrs = \
|
|||
softint.h \
|
|||
|
|||
softint_c_srcs = \
|
|||
divu.c \
|
|||
mul.c \
|
|||
remu.c \
|
|||
|
|||
softint_test_srcs = |
|||
|
|||
softint_install_prog_srcs = |
|||
Loading…
Reference in new issue