Browse Source

Added rough emulation support for div/rem/mul.

eos20
Christopher Celio 14 years ago
parent
commit
d6a522404a
  1. 3
      config.h.in
  2. 641
      configure
  3. 2
      configure.ac
  4. 8
      pk/handlers.c
  5. 66
      pk/int.c
  6. 2
      pk/pk.h
  7. 2
      pk/pk.mk.in
  8. 45
      softint/divu.c
  9. 22
      softint/mul.c
  10. 38
      softint/remu.c
  11. 1
      softint/softint.ac
  12. 23
      softint/softint.h
  13. 13
      softint/softint.mk.in

3
config.h.in

@ -33,5 +33,8 @@
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
#undef SOFTFLOAT_RISCV_ENABLED
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
#undef SOFTINT_ENABLED
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS

641
configure

File diff suppressed because it is too large

2
configure.ac

@ -83,7 +83,7 @@ AX_DEFAULT_CONFIGURE_ARG([--host=riscv])
# The '*' suffix indicates an optional subproject. The '**' suffix
# indicates an optional subproject which is also the name of a group.
MCPPBS_SUBPROJECTS([ pk, softfloat, softfloat_riscv ])
MCPPBS_SUBPROJECTS([ pk, softfloat, softfloat_riscv, softint ])
#-------------------------------------------------------------------------
# MCPPBS subproject groups

8
pk/handlers.c

@ -4,7 +4,7 @@
int have_fp = 1; // initialized to 1 because it can't be in the .bss section!
int have_vector = 1;
static void handle_vector_disabled(trapframe_t* tf)
{
if (have_vector)
@ -41,6 +41,12 @@ static void handle_illegal_instruction(trapframe_t* tf)
}
#endif
if(emulate_int(tf) == 0)
{
advance_pc(tf);
return;
}
dump_tf(tf);
panic("An illegal instruction was executed!");
}

66
pk/int.c

@ -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;
}

2
pk/pk.h

@ -32,6 +32,8 @@ extern uint32_t mem_mb;
int emulate_fp(trapframe_t*);
void init_fp(trapframe_t* tf);
int emulate_int(trapframe_t*);
void printk(const char* s, ...);
void init_tf(trapframe_t*, long pc, long sp, int user64);
void pop_tf(trapframe_t*);

2
pk/pk.mk.in

@ -1,6 +1,7 @@
pk_subproject_deps = \
softfloat_riscv \
softfloat \
softint \
pk_hdrs = \
pk.h \
@ -19,6 +20,7 @@ pk_c_srcs = \
handlers.c \
frontend.c \
fp.c \
int.c \
memset.c \
strlen.c \
elf.c \

45
softint/divu.c

@ -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;
}

22
softint/mul.c

@ -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;
}

38
softint/remu.c

@ -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;
}

1
softint/softint.ac

@ -0,0 +1 @@

23
softint/softint.h

@ -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

13
softint/softint.mk.in

@ -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…
Cancel
Save