Merge pull request #1 from NJU-ProjectN/riscv64-mycpu

Riscv64 mycpu
This commit is contained in:
Zihao Yu 2021-07-13 17:19:34 +08:00 committed by GitHub
commit 96f2923137
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 454 additions and 0 deletions

1
.gitignore vendored
View file

@ -16,3 +16,4 @@ _*
*~
build/
!.gitignore
.vscode

View file

@ -0,0 +1,16 @@
#ifndef ARCH_H__
#define ARCH_H__
struct Context {
// TODO: fix the order of these members to match trap.S
uintptr_t epc, cause, gpr[32], status;
};
#define GPR1 gpr[0]
#define GPR2 gpr[0]
#define GPR3 gpr[0]
#define GPR4 gpr[0]
#define GPRx gpr[0]
#endif

45
am/src/mycpu/cte.c Normal file
View file

@ -0,0 +1,45 @@
#include <am.h>
#include <klib.h>
static Context* (*user_handler)(Event, Context*) = NULL;
Context* __am_irq_handle(Context *c) {
if (user_handler) {
Event ev = {0};
switch (c->cause) {
default: ev.event = EVENT_ERROR; break;
}
c = user_handler(ev, c);
assert(c != NULL);
}
return c;
}
extern void __am_asm_trap(void);
bool cte_init(Context*(*handler)(Event, Context*)) {
// initialize exception entry
asm volatile("csrw mtvec, %0" : : "r"(__am_asm_trap));
// register event handler
user_handler = handler;
return true;
}
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
return NULL;
}
void yield() {
asm volatile("li a7, -1; ecall");
}
bool ienabled() {
return false;
}
void iset(bool enable) {
}

6
am/src/mycpu/input.c Normal file
View file

@ -0,0 +1,6 @@
#include <am.h>
void __am_input_keybrd(AM_INPUT_KEYBRD_T *kbd) {
kbd->keydown = 0;
kbd->keycode = AM_KEY_NONE;
}

33
am/src/mycpu/ioe.c Normal file
View file

@ -0,0 +1,33 @@
#include <am.h>
#include <klib-macros.h>
void __am_timer_init();
void __am_timer_rtc(AM_TIMER_RTC_T *);
void __am_timer_uptime(AM_TIMER_UPTIME_T *);
void __am_input_keybrd(AM_INPUT_KEYBRD_T *);
void __am_timer_rtc(AM_TIMER_RTC_T *);
static void __am_timer_config(AM_TIMER_CONFIG_T *cfg) { cfg->present = true; cfg->has_rtc = true; }
static void __am_input_config(AM_INPUT_CONFIG_T *cfg) { cfg->present = true; }
typedef void (*handler_t)(void *buf);
static void *lut[128] = {
[AM_TIMER_CONFIG] = __am_timer_config,
[AM_TIMER_RTC ] = __am_timer_rtc,
[AM_TIMER_UPTIME] = __am_timer_uptime,
[AM_INPUT_CONFIG] = __am_input_config,
[AM_INPUT_KEYBRD] = __am_input_keybrd,
};
static void fail(void *buf) { panic("access nonexist register"); }
bool ioe_init() {
for (int i = 0; i < LENGTH(lut); i++)
if (!lut[i]) lut[i] = fail;
__am_timer_init();
return true;
}
void ioe_read (int reg, void *buf) { ((handler_t)lut[reg])(buf); }
void ioe_write(int reg, void *buf) { ((handler_t)lut[reg])(buf); }

140
am/src/mycpu/libgcc/div.S Normal file
View file

@ -0,0 +1,140 @@
#define FUNC_TYPE(X) .type X,@function
#define FUNC_SIZE(X) .size X,.-X
#define FUNC_BEGIN(X) \
.globl X; \
FUNC_TYPE (X); \
X:
#define FUNC_END(X) \
FUNC_SIZE(X)
#define FUNC_ALIAS(X,Y) \
.globl X; \
X = Y
#define __riscv_xlen 64
.text
.align 2
#if __riscv_xlen == 32
/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */
# define __udivdi3 __udivsi3
# define __umoddi3 __umodsi3
# define __divdi3 __divsi3
# define __moddi3 __modsi3
#else
FUNC_BEGIN (__udivsi3)
/* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t. */
sll a0, a0, 32
sll a1, a1, 32
move t0, ra
jal __udivdi3
sext.w a0, a0
jr t0
FUNC_END (__udivsi3)
FUNC_BEGIN (__umodsi3)
/* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t. */
sll a0, a0, 32
sll a1, a1, 32
srl a0, a0, 32
srl a1, a1, 32
move t0, ra
jal __udivdi3
sext.w a0, a1
jr t0
FUNC_END (__umodsi3)
FUNC_ALIAS (__modsi3, __moddi3)
FUNC_BEGIN( __divsi3)
/* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */
li t0, -1
beq a1, t0, .L20
#endif
FUNC_BEGIN (__divdi3)
bltz a0, .L10
bltz a1, .L11
/* Since the quotient is positive, fall into __udivdi3. */
FUNC_BEGIN (__udivdi3)
mv a2, a1
mv a1, a0
li a0, -1
beqz a2, .L5
li a3, 1
bgeu a2, a1, .L2
.L1:
blez a2, .L2
slli a2, a2, 1
slli a3, a3, 1
bgtu a1, a2, .L1
.L2:
li a0, 0
.L3:
bltu a1, a2, .L4
sub a1, a1, a2
or a0, a0, a3
.L4:
srli a3, a3, 1
srli a2, a2, 1
bnez a3, .L3
.L5:
ret
FUNC_END (__udivdi3)
FUNC_BEGIN (__umoddi3)
/* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
move t0, ra
jal __udivdi3
move a0, a1
jr t0
FUNC_END (__umoddi3)
/* Handle negative arguments to __divdi3. */
.L10:
neg a0, a0
/* Zero is handled as a negative so that the result will not be inverted. */
bgtz a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */
neg a1, a1
j __udivdi3 /* Compute __udivdi3(-a0, -a1). */
.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */
neg a1, a1
.L12:
move t0, ra
jal __udivdi3
neg a0, a0
jr t0
FUNC_END (__divdi3)
FUNC_BEGIN (__moddi3)
move t0, ra
bltz a1, .L31
bltz a0, .L32
.L30:
jal __udivdi3 /* The dividend is not negative. */
move a0, a1
jr t0
.L31:
neg a1, a1
bgez a0, .L30
.L32:
neg a0, a0
jal __udivdi3 /* The dividend is hella negative. */
neg a0, a1
jr t0
FUNC_END (__moddi3)
#if __riscv_xlen == 64
/* continuation of __divsi3 */
.L20:
sll t0, t0, 31
bne a0, t0, __divdi3
ret
FUNC_END (__divsi3)
#endif

View file

@ -0,0 +1,25 @@
#define FUNC_TYPE(X) .type X,@function
#define FUNC_SIZE(X) .size X,.-X
#define FUNC_BEGIN(X) \
.globl X; \
FUNC_TYPE (X); \
X:
#define FUNC_END(X) \
FUNC_SIZE(X)
FUNC_BEGIN (__muldi3)
mv a2, a0
li a0, 0
.L1:
andi a3, a1, 1
beqz a3, .L2
add a0, a0, a2
.L2:
srli a1, a1, 1
slli a2, a2, 1
bnez a1, .L1
ret
FUNC_END (__muldi3)

17
am/src/mycpu/mpe.c Normal file
View file

@ -0,0 +1,17 @@
#include <am.h>
bool mpe_init(void (*entry)()) {
return false;
}
int cpu_count() {
return 1;
}
int cpu_current() {
return 0;
}
int atomic_xchg(int *addr, int newval) {
return 0;
}

8
am/src/mycpu/start.S Normal file
View file

@ -0,0 +1,8 @@
.section entry, "ax"
.globl _start
.type _start, @function
_start:
mv s0, zero
la sp, _stack_pointer
jal _trm_init

17
am/src/mycpu/timer.c Normal file
View file

@ -0,0 +1,17 @@
#include <am.h>
void __am_timer_init() {
}
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
uptime->us = 0;
}
void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
rtc->second = 0;
rtc->minute = 0;
rtc->hour = 0;
rtc->day = 0;
rtc->month = 0;
rtc->year = 1900;
}

51
am/src/mycpu/trap.S Normal file
View file

@ -0,0 +1,51 @@
#define concat_temp(x, y) x ## y
#define concat(x, y) concat_temp(x, y)
#define MAP(c, f) c(f)
#define REGS(f) \
f( 1) f( 3) f( 4) f( 5) f( 6) f( 7) f( 8) f( 9) \
f(10) f(11) f(12) f(13) f(14) f(15) f(16) f(17) f(18) f(19) \
f(20) f(21) f(22) f(23) f(24) f(25) f(26) f(27) f(28) f(29) \
f(30) f(31)
#define PUSH(n) sd concat(x, n), (n * 8)(sp);
#define POP(n) ld concat(x, n), (n * 8)(sp);
#define CONTEXT_SIZE ((32 + 3) * 8)
#define OFFSET_SP ( 2 * 8)
#define OFFSET_CAUSE (32 * 8)
#define OFFSET_STATUS (33 * 8)
#define OFFSET_EPC (34 * 8)
.globl __am_asm_trap
__am_asm_trap:
addi sp, sp, -CONTEXT_SIZE
MAP(REGS, PUSH)
mv t0, sp
addi t0, t0, CONTEXT_SIZE
sd t0, OFFSET_SP(sp)
csrr t0, mcause
csrr t1, mstatus
csrr t2, mepc
sd t0, OFFSET_CAUSE(sp)
sd t1, OFFSET_STATUS(sp)
sd t2, OFFSET_EPC(sp)
mv a0, sp
jal __am_irq_handle
ld t1, OFFSET_STATUS(sp)
ld t2, OFFSET_EPC(sp)
csrw mstatus, t1
csrw mepc, t2
MAP(REGS, POP)
addi sp, sp, CONTEXT_SIZE
mret

27
am/src/mycpu/trm.c Normal file
View file

@ -0,0 +1,27 @@
#include <am.h>
#include <klib-macros.h>
extern char _heap_start;
int main(const char *args);
extern char _pmem_start;
#define PMEM_SIZE (128 * 1024 * 1024)
#define PMEM_END ((uintptr_t)&_pmem_start + PMEM_SIZE)
Area heap = RANGE(&_heap_start, PMEM_END);
#ifndef MAINARGS
#define MAINARGS ""
#endif
static const char mainargs[] = MAINARGS;
void putch(char ch) {
}
void halt(int code) {
while (1);
}
void _trm_init() {
int ret = main(mainargs);
halt(ret);
}

18
am/src/mycpu/vme.c Normal file
View file

@ -0,0 +1,18 @@
#include <am.h>
bool vme_init(void* (*pgalloc_f)(int), void (*pgfree_f)(void*)) {
return false;
}
void protect(AddrSpace *as) {
}
void unprotect(AddrSpace *as) {
}
void map(AddrSpace *as, void *va, void *pa, int prot) {
}
Context *ucontext(AddrSpace *as, Area kstack, void *entry) {
return NULL;
}

View file

@ -705,3 +705,25 @@ COMPILER_RT_ABI si_int __ctzsi2(si_int a) {
// }
return r + ((2 - (x >> 1)) & -((x & 1) == 0));
}
typedef int si_int;
typedef long long di_int;
typedef unsigned su_int;
#define CHAR_BIT __CHAR_BIT__
si_int __ctzdi2(di_int a) {
dwords x;
x.all = a;
const si_int f = -(x.s.low == 0);
return __ctzsi2((x.s.high & f) | (x.s.low & ~f)) +
(f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
}
si_int __clzdi2(di_int a) {
dwords x;
x.all = a;
const si_int f = -(x.s.high == 0);
return __clzsi2((x.s.high & ~f) | (x.s.low & f)) +
(f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
}

28
scripts/riscv64-mycpu.mk Normal file
View file

@ -0,0 +1,28 @@
CROSS_COMPILE := riscv64-linux-gnu-
COMMON_FLAGS := -fno-pic -march=rv64ifd -mcmodel=medany
CFLAGS += $(COMMON_FLAGS) -static
ASFLAGS += $(COMMON_FLAGS) -O0
LDFLAGS += -melf64lriscv
AM_SRCS := mycpu/start.S \
mycpu/trm.c \
mycpu/libgcc/muldi3.S \
mycpu/libgcc/div.S \
mycpu/ioe.c \
mycpu/timer.c \
mycpu/input.c \
mycpu/cte.c \
mycpu/trap.S \
mycpu/vme.c \
mycpu/mpe.c
CFLAGS += -fdata-sections -ffunction-sections
LDFLAGS += -T $(AM_HOME)/scripts/platform/nemu.ld --defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
LDFLAGS += --gc-sections -e _start
CFLAGS += -DMAINARGS=\"$(mainargs)\"
.PHONY: $(AM_HOME)/am/src/mycpu/trm.c
image: $(IMAGE).elf
@$(OBJDUMP) -d $(IMAGE).elf > $(IMAGE).txt
@echo + OBJCOPY "->" $(IMAGE_REL).bin
@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin