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