feat: make compatible with openperf
This commit is contained in:
parent
a7b830fedd
commit
5fee5aad38
79 changed files with 3943 additions and 274 deletions
50
Makefile
50
Makefile
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
### *Get a more readable version of this Makefile* by `make html` (requires python-markdown)
|
### *Get a more readable version of this Makefile* by `make html` (requires python-markdown)
|
||||||
html:
|
html:
|
||||||
cat Makefile | sed 's/^\([^#]\)/ \1/g' | markdown_py > Makefile.html
|
# cat Makefile | sed 's/^\([^#]\)/ \1/g' | markdown_py > Makefile.html
|
||||||
|
cat Makefile | markdown_py > Makefile.html
|
||||||
.PHONY: html
|
.PHONY: html
|
||||||
|
|
||||||
## 1. Basic Setup and Checks
|
## 1. Basic Setup and Checks
|
||||||
|
@ -66,21 +67,21 @@ LINKAGE = $(OBJS) \
|
||||||
## 3. General Compilation Flags
|
## 3. General Compilation Flags
|
||||||
|
|
||||||
### (Cross) compilers, e.g., mips-linux-gnu-g++
|
### (Cross) compilers, e.g., mips-linux-gnu-g++
|
||||||
AS = $(CROSS_COMPILE)gcc
|
CC ?= $(CROSS_COMPILE)gcc
|
||||||
CC = $(CROSS_COMPILE)gcc
|
AS := $(CC)
|
||||||
CXX = $(CROSS_COMPILE)g++
|
CXX ?= $(CROSS_COMPILE)g++
|
||||||
LD = $(CROSS_COMPILE)ld
|
LD ?= $(CROSS_COMPILE)ld
|
||||||
AR = $(CROSS_COMPILE)ar
|
AR ?= $(CROSS_COMPILE)ar
|
||||||
OBJDUMP = $(CROSS_COMPILE)objdump
|
OBJDUMP ?= $(CROSS_COMPILE)objdump
|
||||||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
OBJCOPY ?= $(CROSS_COMPILE)objcopy
|
||||||
READELF = $(CROSS_COMPILE)readelf
|
READELF ?= $(CROSS_COMPILE)readelf
|
||||||
|
|
||||||
### Compilation flags
|
### Compilation flags
|
||||||
INC_PATH += $(WORK_DIR)/include $(addsuffix /include/, $(addprefix $(AM_HOME)/, $(LIBS)))
|
INC_PATH += $(WORK_DIR)/include $(addsuffix /include/, $(addprefix $(AM_HOME)/, $(LIBS)))
|
||||||
INCFLAGS += $(addprefix -I, $(INC_PATH))
|
INCFLAGS += $(addprefix -I, $(INC_PATH))
|
||||||
|
|
||||||
ARCH_H := arch/$(ARCH).h
|
ARCH_H := arch/$(ARCH).h
|
||||||
CFLAGS += -O2 -MMD -Wall -Werror $(INCFLAGS) \
|
CFLAGS += -lm -g -O3 -MMD -Wall $(INCFLAGS) \
|
||||||
-D__ISA__=\"$(ISA)\" -D__ISA_$(shell echo $(ISA) | tr a-z A-Z)__ \
|
-D__ISA__=\"$(ISA)\" -D__ISA_$(shell echo $(ISA) | tr a-z A-Z)__ \
|
||||||
-D__ARCH__=$(ARCH) -D__ARCH_$(shell echo $(ARCH) | tr a-z A-Z | tr - _) \
|
-D__ARCH__=$(ARCH) -D__ARCH_$(shell echo $(ARCH) | tr a-z A-Z | tr - _) \
|
||||||
-D__PLATFORM__=$(PLATFORM) -D__PLATFORM_$(shell echo $(PLATFORM) | tr a-z A-Z | tr - _) \
|
-D__PLATFORM__=$(PLATFORM) -D__PLATFORM_$(shell echo $(PLATFORM) | tr a-z A-Z | tr - _) \
|
||||||
|
@ -88,14 +89,20 @@ CFLAGS += -O2 -MMD -Wall -Werror $(INCFLAGS) \
|
||||||
-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector \
|
-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector \
|
||||||
-Wno-main -U_FORTIFY_SOURCE -fvisibility=hidden
|
-Wno-main -U_FORTIFY_SOURCE -fvisibility=hidden
|
||||||
CXXFLAGS += $(CFLAGS) -ffreestanding -fno-rtti -fno-exceptions
|
CXXFLAGS += $(CFLAGS) -ffreestanding -fno-rtti -fno-exceptions
|
||||||
ASFLAGS += -MMD $(INCFLAGS)
|
ASFLAGS += $(INCFLAGS)
|
||||||
LDFLAGS += -z noexecstack $(addprefix -T, $(LDSCRIPTS))
|
LDFLAGS += -z noexecstack
|
||||||
|
|
||||||
## 4. Arch-Specific Configurations
|
## 4. Arch-Specific Configurations
|
||||||
|
|
||||||
### Paste in arch-specific configurations (e.g., from `scripts/x86_64-qemu.mk`)
|
### Paste in arch-specific configurations (e.g., from `scripts/x86_64-qemu.mk`)
|
||||||
-include $(AM_HOME)/scripts/$(ARCH).mk
|
-include $(AM_HOME)/scripts/$(ARCH).mk
|
||||||
|
|
||||||
|
### Fall back to native gcc/binutils if there is no cross compiler
|
||||||
|
ifeq ($(wildcard $(shell which $(CC))),)
|
||||||
|
$(info # $(CC) not found; fall back to default gcc and binutils)
|
||||||
|
CROSS_COMPILE := riscv64-unknown-linux-gnu-
|
||||||
|
endif
|
||||||
|
|
||||||
## 5. Compilation Rules
|
## 5. Compilation Rules
|
||||||
|
|
||||||
### Rule (compile): a single `.c` -> `.o` (gcc)
|
### Rule (compile): a single `.c` -> `.o` (gcc)
|
||||||
|
@ -123,19 +130,14 @@ $(LIBS): %:
|
||||||
@$(MAKE) -s -C $(AM_HOME)/$* archive
|
@$(MAKE) -s -C $(AM_HOME)/$* archive
|
||||||
|
|
||||||
### Rule (link): objects (`*.o`) and libraries (`*.a`) -> `IMAGE.elf`, the final ELF binary to be packed into image (ld)
|
### Rule (link): objects (`*.o`) and libraries (`*.a`) -> `IMAGE.elf`, the final ELF binary to be packed into image (ld)
|
||||||
$(IMAGE).elf: $(LINKAGE) $(LDSCRIPTS)
|
$(IMAGE).elf: $(OBJS) $(LIBS)
|
||||||
@echo \# Creating image [$(ARCH)]
|
|
||||||
@echo + LD "->" $(IMAGE_REL).elf
|
@echo + LD "->" $(IMAGE_REL).elf
|
||||||
ifneq ($(filter $(ARCH),native),)
|
@$(LD) $(LDFLAGS) -o $(IMAGE).elf --start-group $(LINKAGE) --end-group
|
||||||
@$(CXX) -o $@ -Wl,--whole-archive $(LINKAGE) -Wl,-no-whole-archive $(LDFLAGS_CXX)
|
|
||||||
else
|
|
||||||
@$(LD) $(LDFLAGS) -o $@ --start-group $(LINKAGE) --end-group
|
|
||||||
endif
|
|
||||||
|
|
||||||
### Rule (archive): objects (`*.o`) -> `ARCHIVE.a` (ar)
|
### Rule (archive): objects (`*.o`) -> `ARCHIVE.a` (ar)
|
||||||
$(ARCHIVE): $(OBJS)
|
$(ARCHIVE): $(OBJS)
|
||||||
@echo + AR "->" $(shell realpath $@ --relative-to .)
|
@echo + AR "->" $(shell realpath $@ --relative-to .)
|
||||||
@$(AR) rcs $@ $^
|
@$(AR) rcs $(ARCHIVE) $(OBJS)
|
||||||
|
|
||||||
### Rule (`#include` dependencies): paste in `.d` files generated by gcc on `-MMD`
|
### Rule (`#include` dependencies): paste in `.d` files generated by gcc on `-MMD`
|
||||||
-include $(addprefix $(DST_DIR)/, $(addsuffix .d, $(basename $(SRCS))))
|
-include $(addprefix $(DST_DIR)/, $(addsuffix .d, $(basename $(SRCS))))
|
||||||
|
@ -145,8 +147,8 @@ $(ARCHIVE): $(OBJS)
|
||||||
### Build order control
|
### Build order control
|
||||||
image: image-dep
|
image: image-dep
|
||||||
archive: $(ARCHIVE)
|
archive: $(ARCHIVE)
|
||||||
image-dep: $(LIBS) $(IMAGE).elf
|
image-dep: $(OBJS) $(LIBS)
|
||||||
.NOTPARALLEL: image-dep
|
@echo \# Creating image [$(ARCH)]
|
||||||
.PHONY: image image-dep archive run $(LIBS)
|
.PHONY: image image-dep archive run $(LIBS)
|
||||||
|
|
||||||
### Clean a single project (remove `build/`)
|
### Clean a single project (remove `build/`)
|
||||||
|
@ -158,5 +160,5 @@ clean:
|
||||||
CLEAN_ALL = $(dir $(shell find . -mindepth 2 -name Makefile))
|
CLEAN_ALL = $(dir $(shell find . -mindepth 2 -name Makefile))
|
||||||
clean-all: $(CLEAN_ALL) clean
|
clean-all: $(CLEAN_ALL) clean
|
||||||
$(CLEAN_ALL):
|
$(CLEAN_ALL):
|
||||||
-@$(MAKE) -s -C $@ clean
|
-@$(MAKE) -s -C $@ cleaear
|
||||||
.PHONY: clean-all $(CLEAN_ALL)
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define __AMDEV_H__
|
#define __AMDEV_H__
|
||||||
|
|
||||||
// **MAY SUBJECT TO CHANGE IN THE FUTURE**
|
// **MAY SUBJECT TO CHANGE IN THE FUTURE**
|
||||||
|
#include <am.h>
|
||||||
|
|
||||||
#define AM_DEVREG(id, reg, perm, ...) \
|
#define AM_DEVREG(id, reg, perm, ...) \
|
||||||
enum { AM_##reg = (id) }; \
|
enum { AM_##reg = (id) }; \
|
||||||
|
|
|
@ -11,34 +11,15 @@ struct Context {
|
||||||
uintptr_t ksp;
|
uintptr_t ksp;
|
||||||
void *vm_head;
|
void *vm_head;
|
||||||
ucontext_t uc;
|
ucontext_t uc;
|
||||||
#ifdef __x86_64__
|
|
||||||
// skip the red zone of the stack frame, see the amd64 ABI manual for details
|
// skip the red zone of the stack frame, see the amd64 ABI manual for details
|
||||||
uint8_t redzone[128];
|
uint8_t redzone[128];
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
#define GPR1 uc.uc_mcontext.gregs[REG_RDI]
|
#define GPR1 uc.uc_mcontext.gregs[REG_RDI]
|
||||||
#define GPR2 uc.uc_mcontext.gregs[REG_RSI]
|
#define GPR2 uc.uc_mcontext.gregs[REG_RSI]
|
||||||
#define GPR3 uc.uc_mcontext.gregs[REG_RDX]
|
#define GPR3 uc.uc_mcontext.gregs[REG_RDX]
|
||||||
#define GPR4 uc.uc_mcontext.gregs[REG_RCX]
|
#define GPR4 uc.uc_mcontext.gregs[REG_RCX]
|
||||||
#define GPRx uc.uc_mcontext.gregs[REG_RAX]
|
#define GPRx uc.uc_mcontext.gregs[REG_RAX]
|
||||||
#elif defined(__aarch64__)
|
|
||||||
#define GPR1 uc.uc_mcontext.regs[0]
|
|
||||||
#define GPR2 uc.uc_mcontext.regs[1]
|
|
||||||
#define GPR3 uc.uc_mcontext.regs[2]
|
|
||||||
#define GPR4 uc.uc_mcontext.regs[3]
|
|
||||||
#define GPRx uc.uc_mcontext.regs[0]
|
|
||||||
#elif defined(__riscv)
|
|
||||||
// FIXME: may be wrong
|
|
||||||
#define GPR1 uc.uc_mcontext.__gregs[REG_A0]
|
|
||||||
#define GPR2 uc.uc_mcontext.__gregs[REG_A0+1]
|
|
||||||
#define GPR3 uc.uc_mcontext.__gregs[REG_A0+2]
|
|
||||||
#define GPR4 uc.uc_mcontext.__gregs[REG_A0+3]
|
|
||||||
#define GPRx uc.uc_mcontext.__gregs[REG_A0+4]
|
|
||||||
#else
|
|
||||||
#error Unsupported architecture
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef __USE_GNU
|
#undef __USE_GNU
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef ARCH_H__
|
#ifndef ARCH_H__
|
||||||
#define ARCH_H__
|
#define ARCH_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#ifdef __riscv_e
|
#ifdef __riscv_e
|
||||||
#define NR_REGS 16
|
#define NR_REGS 16
|
||||||
#else
|
#else
|
||||||
|
@ -8,9 +9,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
// TODO: fix the order of these members to match trap.S
|
//The order of these members should match trap.S, pay attention to pdir.
|
||||||
uintptr_t mepc, mcause, gpr[NR_REGS], mstatus;
|
uintptr_t gpr[NR_REGS];
|
||||||
void *pdir;
|
uintptr_t mcause;
|
||||||
|
uintptr_t mstatus;
|
||||||
|
uintptr_t mepc;
|
||||||
|
void *pdir;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __riscv_e
|
#ifdef __riscv_e
|
||||||
|
@ -19,9 +23,9 @@ struct Context {
|
||||||
#define GPR1 gpr[17] // a7
|
#define GPR1 gpr[17] // a7
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GPR2 gpr[0]
|
#define GPR2 gpr[10] //a0
|
||||||
#define GPR3 gpr[0]
|
#define GPR3 gpr[11] //a1
|
||||||
#define GPR4 gpr[0]
|
#define GPR4 gpr[12] //a2
|
||||||
#define GPRx gpr[0]
|
#define GPRx gpr[10] //a0, return value
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@ Context* __am_irq_handle(Context *c) {
|
||||||
if (user_handler) {
|
if (user_handler) {
|
||||||
Event ev = {0};
|
Event ev = {0};
|
||||||
uintptr_t ecode = 0;
|
uintptr_t ecode = 0;
|
||||||
switch (ecode) {
|
switch (ccode) {
|
||||||
default: ev.event = EVENT_ERROR; break;
|
default: ev.event = EVENT_ERROR; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,9 @@ static void irq_handle(Context *c) {
|
||||||
c->ksp = thiscpu->ksp;
|
c->ksp = thiscpu->ksp;
|
||||||
|
|
||||||
if (thiscpu->ev.event == EVENT_ERROR) {
|
if (thiscpu->ev.event == EVENT_ERROR) {
|
||||||
printf("Unhandle signal '%s' at pc = %p, badaddr = %p, cause = 0x%x\n",
|
uintptr_t rip = c->uc.uc_mcontext.gregs[REG_RIP];
|
||||||
thiscpu->ev.msg, AM_REG_PC(&c->uc), thiscpu->ev.ref, thiscpu->ev.cause);
|
printf("Unhandle signal '%s' at rip = %p, badaddr = %p, cause = 0x%x\n",
|
||||||
|
thiscpu->ev.msg, rip, thiscpu->ev.ref, thiscpu->ev.cause);
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
c = user_handler(thiscpu->ev, c);
|
c = user_handler(thiscpu->ev, c);
|
||||||
|
@ -36,14 +37,13 @@ static void irq_handle(Context *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_stack(uintptr_t event, ucontext_t *uc) {
|
static void setup_stack(uintptr_t event, ucontext_t *uc) {
|
||||||
void *pc = (void *)AM_REG_PC(uc);
|
void *rip = (void *)uc->uc_mcontext.gregs[REG_RIP];
|
||||||
extern uint8_t _start, _etext;
|
extern uint8_t _start, _etext;
|
||||||
int trap_from_user = __am_in_userspace(pc);
|
int trap_from_user = __am_in_userspace(rip);
|
||||||
int signal_safe = IN_RANGE(pc, RANGE(&_start, &_etext)) || trap_from_user ||
|
int signal_safe = IN_RANGE(rip, RANGE(&_start, &_etext)) || trap_from_user ||
|
||||||
// Hack here: "+13" points to the instruction after syscall. This is the
|
// Hack here: "+13" points to the instruction after syscall. This is the
|
||||||
// instruction which will trigger the pending signal if interrupt is enabled.
|
// instruction which will trigger the pending signal if interrupt is enabled.
|
||||||
// FIXME: should change 13 for aarch and riscv
|
(rip == (void *)&sigprocmask + 13);
|
||||||
(pc == (void *)&sigprocmask + 13);
|
|
||||||
|
|
||||||
if (((event == EVENT_IRQ_IODEV) || (event == EVENT_IRQ_TIMER)) && !signal_safe) {
|
if (((event == EVENT_IRQ_IODEV) || (event == EVENT_IRQ_TIMER)) && !signal_safe) {
|
||||||
// Shared libraries contain code which are not reenterable.
|
// Shared libraries contain code which are not reenterable.
|
||||||
|
@ -59,17 +59,15 @@ static void setup_stack(uintptr_t event, ucontext_t *uc) {
|
||||||
if (trap_from_user) __am_pmem_unprotect();
|
if (trap_from_user) __am_pmem_unprotect();
|
||||||
|
|
||||||
// skip the instructions causing SIGSEGV for syscall
|
// skip the instructions causing SIGSEGV for syscall
|
||||||
if (event == EVENT_SYSCALL) { pc += SYSCALL_INSTR_LEN; }
|
if (event == EVENT_SYSCALL) { rip += SYSCALL_INSTR_LEN; }
|
||||||
AM_REG_PC(uc) = (uintptr_t)pc;
|
uc->uc_mcontext.gregs[REG_RIP] = (uintptr_t)rip;
|
||||||
|
|
||||||
// switch to kernel stack if we were previously in user space
|
// switch to kernel stack if we were previously in user space
|
||||||
uintptr_t sp = trap_from_user ? thiscpu->ksp : AM_REG_SP(uc);
|
uintptr_t rsp = trap_from_user ? thiscpu->ksp : uc->uc_mcontext.gregs[REG_RSP];
|
||||||
sp -= sizeof(Context);
|
rsp -= sizeof(Context);
|
||||||
#ifdef __x86_64__
|
// keep (rsp + 8) % 16 == 0 to support SSE
|
||||||
// keep (sp + 8) % 16 == 0 to support SSE
|
if ((rsp + 8) % 16 != 0) rsp -= 8;
|
||||||
if ((sp + 8) % 16 != 0) sp -= 8;
|
Context *c = (void *)rsp;
|
||||||
#endif
|
|
||||||
Context *c = (void *)sp;
|
|
||||||
|
|
||||||
// save the context on the stack
|
// save the context on the stack
|
||||||
c->uc = *uc;
|
c->uc = *uc;
|
||||||
|
@ -78,17 +76,17 @@ static void setup_stack(uintptr_t event, ucontext_t *uc) {
|
||||||
__am_get_intr_sigmask(&uc->uc_sigmask);
|
__am_get_intr_sigmask(&uc->uc_sigmask);
|
||||||
|
|
||||||
// call irq_handle after returning from the signal handler
|
// call irq_handle after returning from the signal handler
|
||||||
AM_REG_GPR1(uc) = (uintptr_t)c;
|
uc->uc_mcontext.gregs[REG_RDI] = (uintptr_t)c;
|
||||||
AM_REG_PC(uc) = (uintptr_t)irq_handle;
|
uc->uc_mcontext.gregs[REG_RIP] = (uintptr_t)irq_handle;
|
||||||
AM_REG_SP(uc) = (uintptr_t)c;
|
uc->uc_mcontext.gregs[REG_RSP] = (uintptr_t)c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iret(ucontext_t *uc) {
|
static void iret(ucontext_t *uc) {
|
||||||
Context *c = (void *)AM_REG_GPR1(uc);
|
Context *c = (void *)uc->uc_mcontext.gregs[REG_RDI];
|
||||||
// restore the context
|
// restore the context
|
||||||
*uc = c->uc;
|
*uc = c->uc;
|
||||||
thiscpu->ksp = c->ksp;
|
thiscpu->ksp = c->ksp;
|
||||||
if (__am_in_userspace((void *)AM_REG_PC(uc))) __am_pmem_protect();
|
if (__am_in_userspace((void *)uc->uc_mcontext.gregs[REG_RIP])) __am_pmem_protect();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sig_handler(int sig, siginfo_t *info, void *ucontext) {
|
static void sig_handler(int sig, siginfo_t *info, void *ucontext) {
|
||||||
|
@ -169,8 +167,8 @@ Context* kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
||||||
Context *c = (Context*)kstack.end - 1;
|
Context *c = (Context*)kstack.end - 1;
|
||||||
|
|
||||||
__am_get_example_uc(c);
|
__am_get_example_uc(c);
|
||||||
AM_REG_PC(&c->uc) = (uintptr_t)__am_kcontext_start;
|
c->uc.uc_mcontext.gregs[REG_RIP] = (uintptr_t)__am_kcontext_start;
|
||||||
AM_REG_SP(&c->uc) = (uintptr_t)kstack.end;
|
c->uc.uc_mcontext.gregs[REG_RSP] = (uintptr_t)kstack.end;
|
||||||
|
|
||||||
int ret = sigemptyset(&(c->uc.uc_sigmask)); // enable interrupt
|
int ret = sigemptyset(&(c->uc.uc_sigmask)); // enable interrupt
|
||||||
assert(ret == 0);
|
assert(ret == 0);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <klib.h>
|
#include <klib.h>
|
||||||
#include <SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
static int rfd = -1, wfd = -1;
|
static int rfd = -1, wfd = -1;
|
||||||
static volatile int count = 0;
|
static volatile int count = 0;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <fenv.h>
|
#include <fenv.h>
|
||||||
|
|
||||||
//#define MODE_800x600
|
//#define MODE_800x600
|
||||||
#define WINDOW_W 800
|
|
||||||
#define WINDOW_H 600
|
|
||||||
#ifdef MODE_800x600
|
#ifdef MODE_800x600
|
||||||
const int disp_w = WINDOW_W, disp_h = WINDOW_H;
|
# define W 800
|
||||||
|
# define H 600
|
||||||
#else
|
#else
|
||||||
const int disp_w = 400, disp_h = 300;
|
# define W 400
|
||||||
|
# define H 300
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FPS 60
|
#define FPS 60
|
||||||
|
@ -31,8 +31,13 @@ void __am_gpu_init() {
|
||||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||||
window = SDL_CreateWindow("Native Application",
|
window = SDL_CreateWindow("Native Application",
|
||||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||||
WINDOW_W, WINDOW_H, SDL_WINDOW_OPENGL);
|
#ifdef MODE_800x600
|
||||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, disp_w, disp_h, 32,
|
W, H,
|
||||||
|
#else
|
||||||
|
W * 2, H * 2,
|
||||||
|
#endif
|
||||||
|
SDL_WINDOW_OPENGL);
|
||||||
|
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32,
|
||||||
RMASK, GMASK, BMASK, AMASK);
|
RMASK, GMASK, BMASK, AMASK);
|
||||||
SDL_AddTimer(1000 / FPS, texture_sync, NULL);
|
SDL_AddTimer(1000 / FPS, texture_sync, NULL);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +45,7 @@ void __am_gpu_init() {
|
||||||
void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
|
void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
|
||||||
*cfg = (AM_GPU_CONFIG_T) {
|
*cfg = (AM_GPU_CONFIG_T) {
|
||||||
.present = true, .has_accel = false,
|
.present = true, .has_accel = false,
|
||||||
.width = disp_w, .height = disp_h,
|
.width = W, .height = H,
|
||||||
.vmemsz = 0
|
.vmemsz = 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#define KEYDOWN_MASK 0x8000
|
#define KEYDOWN_MASK 0x8000
|
||||||
|
|
||||||
|
|
|
@ -150,9 +150,7 @@ static void init_platform() {
|
||||||
|
|
||||||
// save the context template
|
// save the context template
|
||||||
save_example_context();
|
save_example_context();
|
||||||
#ifdef __x86_64__
|
|
||||||
uc_example.uc_mcontext.fpregs = NULL; // clear the FPU context
|
uc_example.uc_mcontext.fpregs = NULL; // clear the FPU context
|
||||||
#endif
|
|
||||||
__am_get_intr_sigmask(&uc_example.uc_sigmask);
|
__am_get_intr_sigmask(&uc_example.uc_sigmask);
|
||||||
|
|
||||||
// disable interrupts by default
|
// disable interrupts by default
|
||||||
|
|
|
@ -7,22 +7,6 @@
|
||||||
#include <klib.h>
|
#include <klib.h>
|
||||||
#include <klib-macros.h>
|
#include <klib-macros.h>
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
#define AM_REG_PC(uc) (uc)->uc_mcontext.gregs[REG_RIP]
|
|
||||||
#define AM_REG_SP(uc) (uc)->uc_mcontext.gregs[REG_RSP]
|
|
||||||
#define AM_REG_GPR1(uc) (uc)->uc_mcontext.gregs[REG_RDI]
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
#define AM_REG_PC(uc) (uc)->uc_mcontext.pc
|
|
||||||
#define AM_REG_SP(uc) (uc)->uc_mcontext.sp
|
|
||||||
#define AM_REG_GPR1(uc) (uc)->uc_mcontext.regs[0]
|
|
||||||
#elif defined(__riscv) && __riscv_xlen == 64
|
|
||||||
#define AM_REG_PC(uc) (uc)->uc_mcontext.__gregs[REG_PC]
|
|
||||||
#define AM_REG_SP(uc) (uc)->uc_mcontext.__gregs[REG_SP]
|
|
||||||
#define AM_REG_GPR1(uc) (uc)->uc_mcontext.__gregs[REG_A0]
|
|
||||||
#else
|
|
||||||
#error Unsupported architecture
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void __am_get_example_uc(Context *r);
|
void __am_get_example_uc(Context *r);
|
||||||
void __am_get_intr_sigmask(sigset_t *s);
|
void __am_get_intr_sigmask(sigset_t *s);
|
||||||
int __am_is_sigmask_sti(sigset_t *s);
|
int __am_is_sigmask_sti(sigset_t *s);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
.global __am_kcontext_start
|
.global __am_kcontext_start
|
||||||
__am_kcontext_start:
|
__am_kcontext_start:
|
||||||
#ifdef __x86_64__
|
|
||||||
// rdi = arg, rsi = entry
|
// rdi = arg, rsi = entry
|
||||||
|
|
||||||
// (rsp + 8) should be multiple of 16 when
|
// (rsp + 8) should be multiple of 16 when
|
||||||
|
@ -9,21 +8,3 @@ __am_kcontext_start:
|
||||||
andq $0xfffffffffffffff0, %rsp
|
andq $0xfffffffffffffff0, %rsp
|
||||||
call *%rsi
|
call *%rsi
|
||||||
call __am_panic_on_return
|
call __am_panic_on_return
|
||||||
#elif __aarch64__
|
|
||||||
// x0 = arg, x1 = entry
|
|
||||||
// (sp + 16) should be multiple of 16 when
|
|
||||||
// control is transfered to the function entry point.
|
|
||||||
// See aarch64 ABI manual for more details
|
|
||||||
// https://github.com/ARM-software/abi-aa
|
|
||||||
mov x2, sp
|
|
||||||
and sp, x2, #0xfffffffffffffff0
|
|
||||||
br x1
|
|
||||||
bl __am_panic_on_return
|
|
||||||
#elif __riscv
|
|
||||||
// See riscv ABI manual for more details
|
|
||||||
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc
|
|
||||||
addi sp, sp, -16
|
|
||||||
andi sp, sp, ~15
|
|
||||||
jalr a1
|
|
||||||
jal __am_panic_on_return
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -124,8 +124,8 @@ Context* ucontext(AddrSpace *as, Area kstack, void *entry) {
|
||||||
Context *c = (Context*)kstack.end - 1;
|
Context *c = (Context*)kstack.end - 1;
|
||||||
|
|
||||||
__am_get_example_uc(c);
|
__am_get_example_uc(c);
|
||||||
AM_REG_PC(&c->uc) = (uintptr_t)entry;
|
c->uc.uc_mcontext.gregs[REG_RIP] = (uintptr_t)entry;
|
||||||
AM_REG_SP(&c->uc) = (uintptr_t)USER_SPACE.end;
|
c->uc.uc_mcontext.gregs[REG_RSP] = (uintptr_t)USER_SPACE.end;
|
||||||
|
|
||||||
int ret = sigemptyset(&(c->uc.uc_sigmask)); // enable interrupt
|
int ret = sigemptyset(&(c->uc.uc_sigmask)); // enable interrupt
|
||||||
assert(ret == 0);
|
assert(ret == 0);
|
||||||
|
|
12
am/src/platform/dummy/audio.c
Normal file
12
am/src/platform/dummy/audio.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <am.h>
|
||||||
|
|
||||||
|
void __am_audio_init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t __am_audio_write(uintptr_t reg, void *buf, size_t size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t __am_audio_read(uintptr_t reg, void *buf, size_t size) {
|
||||||
|
return 0;
|
||||||
|
}
|
7
am/src/platform/dummy/input.c
Normal file
7
am/src/platform/dummy/input.c
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#include "amdev.h"
|
||||||
|
#include <am.h>
|
||||||
|
|
||||||
|
void __am_input_read(AM_INPUT_KEYBRD_T *kbd) {
|
||||||
|
kbd->keydown = 0;
|
||||||
|
kbd->keycode = AM_KEY_NONE;
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ Area heap = RANGE(NULL, NULL);
|
||||||
|
|
||||||
void putch(char ch) {
|
void putch(char ch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void halt(int code) {
|
void halt(int code) {
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
16
am/src/platform/dummy/video.c
Normal file
16
am/src/platform/dummy/video.c
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <am.h>
|
||||||
|
#include <amdev.h>
|
||||||
|
|
||||||
|
#define W 320
|
||||||
|
#define H 240
|
||||||
|
|
||||||
|
size_t __am_video_read(uintptr_t reg, void *buf, size_t size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t __am_video_write(uintptr_t reg, void *buf, size_t size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __am_vga_init() {
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
# define nemu_trap(code) asm volatile("mv a0, %0; ebreak" : :"r"(code))
|
# define nemu_trap(code) asm volatile("mv a0, %0; ebreak" : :"r"(code))
|
||||||
#elif defined(__ISA_LOONGARCH32R__)
|
#elif defined(__ISA_LOONGARCH32R__)
|
||||||
# define nemu_trap(code) asm volatile("move $a0, %0; break 0" : :"r"(code))
|
# define nemu_trap(code) asm volatile("move $a0, %0; break 0" : :"r"(code))
|
||||||
#else
|
#elif
|
||||||
# error unsupported ISA __ISA__
|
# error unsupported ISA __ISA__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#define MMIO_BASE 0xa0000000
|
#define MMIO_BASE 0xa0000000
|
||||||
|
|
||||||
|
|
||||||
#define SERIAL_PORT (DEVICE_BASE + 0x00003f8)
|
#define SERIAL_PORT (DEVICE_BASE + 0x00003f8)
|
||||||
#define KBD_ADDR (DEVICE_BASE + 0x0000060)
|
#define KBD_ADDR (DEVICE_BASE + 0x0000060)
|
||||||
#define RTC_ADDR (DEVICE_BASE + 0x0000048)
|
#define RTC_ADDR (DEVICE_BASE + 0x0000048)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
#include "amdev.h"
|
||||||
|
#include "riscv/riscv.h"
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <nemu.h>
|
#include <nemu.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define AUDIO_FREQ_ADDR (AUDIO_ADDR + 0x00)
|
#define AUDIO_FREQ_ADDR (AUDIO_ADDR + 0x00)
|
||||||
#define AUDIO_CHANNELS_ADDR (AUDIO_ADDR + 0x04)
|
#define AUDIO_CHANNELS_ADDR (AUDIO_ADDR + 0x04)
|
||||||
|
@ -8,19 +12,40 @@
|
||||||
#define AUDIO_INIT_ADDR (AUDIO_ADDR + 0x10)
|
#define AUDIO_INIT_ADDR (AUDIO_ADDR + 0x10)
|
||||||
#define AUDIO_COUNT_ADDR (AUDIO_ADDR + 0x14)
|
#define AUDIO_COUNT_ADDR (AUDIO_ADDR + 0x14)
|
||||||
|
|
||||||
void __am_audio_init() {
|
//We assume that this configure will never change during the execution
|
||||||
}
|
AM_AUDIO_CONFIG_T cfg_now;
|
||||||
|
int last_write = 0;
|
||||||
|
|
||||||
void __am_audio_config(AM_AUDIO_CONFIG_T *cfg) {
|
void __am_audio_config(AM_AUDIO_CONFIG_T *cfg) {
|
||||||
cfg->present = false;
|
cfg->present = true;
|
||||||
|
cfg->bufsize = inl(AUDIO_SBUF_SIZE_ADDR);
|
||||||
|
}
|
||||||
|
void __am_audio_init() {
|
||||||
|
outl(AUDIO_INIT_ADDR, 0);
|
||||||
|
__am_audio_config(&cfg_now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) {
|
void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) {
|
||||||
|
outl(AUDIO_FREQ_ADDR, ctrl->freq);
|
||||||
|
outl(AUDIO_CHANNELS_ADDR, ctrl->channels);
|
||||||
|
outl(AUDIO_SAMPLES_ADDR, ctrl->samples);
|
||||||
|
outl(AUDIO_INIT_ADDR, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __am_audio_status(AM_AUDIO_STATUS_T *stat) {
|
void __am_audio_status(AM_AUDIO_STATUS_T *stat) {
|
||||||
stat->count = 0;
|
stat->count = inl(AUDIO_COUNT_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __am_audio_play(AM_AUDIO_PLAY_T *ctl) {
|
void __am_audio_play(AM_AUDIO_PLAY_T *ctl) {
|
||||||
|
int len = ctl->buf.end - ctl->buf.start;
|
||||||
|
int count = inl(AUDIO_COUNT_ADDR);
|
||||||
|
int size = cfg_now.bufsize;
|
||||||
|
for(; count + len > size; count = inl(AUDIO_COUNT_ADDR));
|
||||||
|
for(int i = 0; i < len; i += 4) {
|
||||||
|
outl(last_write + AUDIO_SBUF_ADDR, *(uint32_t*)(ctl->buf.start + i));
|
||||||
|
last_write = (last_write + 4) % size;
|
||||||
|
}
|
||||||
|
//Should lock here, NEMU and AM may write to this addr at the same time
|
||||||
|
outl(AUDIO_COUNT_ADDR, inl(AUDIO_COUNT_ADDR) + len);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,51 @@
|
||||||
|
//#include "amdev.h"
|
||||||
|
#include "riscv/riscv.h"
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <nemu.h>
|
#include <nemu.h>
|
||||||
|
#include <klib.h>
|
||||||
|
#include <stdint.h>
|
||||||
#define SYNC_ADDR (VGACTL_ADDR + 4)
|
#define SYNC_ADDR (VGACTL_ADDR + 4)
|
||||||
|
|
||||||
void __am_gpu_init() {
|
static AM_GPU_CONFIG_T cfg_now;
|
||||||
}
|
|
||||||
|
|
||||||
void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
|
void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
|
||||||
|
uint32_t vga_ctrl_data = inl(VGACTL_ADDR);
|
||||||
|
uint16_t w = vga_ctrl_data >> 16;
|
||||||
|
uint16_t h = vga_ctrl_data & 0x0000ffff;
|
||||||
*cfg = (AM_GPU_CONFIG_T) {
|
*cfg = (AM_GPU_CONFIG_T) {
|
||||||
.present = true, .has_accel = false,
|
.present = true, .has_accel = false,
|
||||||
.width = 0, .height = 0,
|
.width = w, .height = h,
|
||||||
.vmemsz = 0
|
.vmemsz = w * h
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __am_gpu_init() {
|
||||||
|
__am_gpu_config(&cfg_now);
|
||||||
|
}
|
||||||
|
|
||||||
void __am_gpu_fbdraw(AM_GPU_FBDRAW_T *ctl) {
|
void __am_gpu_fbdraw(AM_GPU_FBDRAW_T *ctl) {
|
||||||
if (ctl->sync) {
|
|
||||||
outl(SYNC_ADDR, 1);
|
//size of block
|
||||||
}
|
int w = ctl->w, h = ctl->h;
|
||||||
|
//coordinates of the bottom-left pixel of the block
|
||||||
|
int x = ctl->x, y = ctl->y;
|
||||||
|
uint32_t pixel_idx = 0;
|
||||||
|
uint32_t pixel = 0;
|
||||||
|
uint32_t buffer_idx = y * cfg_now.width + x;
|
||||||
|
|
||||||
|
for(int i = 0; i < h; i++) {
|
||||||
|
for(int j = 0; j < w; j++) {
|
||||||
|
pixel = *((uint32_t*)ctl->pixels + pixel_idx);
|
||||||
|
outl(FB_ADDR + 4U * buffer_idx, pixel);
|
||||||
|
pixel_idx++;
|
||||||
|
buffer_idx++;
|
||||||
|
}
|
||||||
|
buffer_idx += cfg_now.width - w;
|
||||||
|
}
|
||||||
|
if (ctl->sync) {
|
||||||
|
outl(SYNC_ADDR, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __am_gpu_status(AM_GPU_STATUS_T *status) {
|
void __am_gpu_status(AM_GPU_STATUS_T *status) {
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
#include "riscv/riscv.h"
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <nemu.h>
|
#include <nemu.h>
|
||||||
|
#include <amdev.h>
|
||||||
|
|
||||||
#define KEYDOWN_MASK 0x8000
|
#define KEYDOWN_MASK 0x8000
|
||||||
|
|
||||||
void __am_input_keybrd(AM_INPUT_KEYBRD_T *kbd) {
|
void __am_input_keybrd(AM_INPUT_KEYBRD_T *kbd) {
|
||||||
kbd->keydown = 0;
|
uint32_t k = inl(KBD_ADDR);
|
||||||
kbd->keycode = AM_KEY_NONE;
|
kbd->keydown = (k & KEYDOWN_MASK ? true : false);
|
||||||
|
kbd->keycode = k & ~KEYDOWN_MASK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
|
#include "riscv/riscv.h"
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <nemu.h>
|
#include <nemu.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void __am_timer_init() {
|
void __am_timer_init() {
|
||||||
|
outl(RTC_ADDR, 0);
|
||||||
|
outl(RTC_ADDR + 4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
|
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
|
||||||
uptime->us = 0;
|
|
||||||
|
uint32_t h = inl(RTC_ADDR + 4);
|
||||||
|
uint32_t l = inl(RTC_ADDR);
|
||||||
|
uptime->us = (uint64_t)h << 32 | l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
|
void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
|
||||||
|
|
|
@ -2,10 +2,14 @@
|
||||||
#include <nemu.h>
|
#include <nemu.h>
|
||||||
|
|
||||||
extern char _heap_start;
|
extern char _heap_start;
|
||||||
|
extern void *heap_alloc_ptr;
|
||||||
int main(const char *args);
|
int main(const char *args);
|
||||||
|
|
||||||
Area heap = RANGE(&_heap_start, PMEM_END);
|
Area heap = RANGE(&_heap_start, PMEM_END);
|
||||||
static const char mainargs[MAINARGS_MAX_LEN] = MAINARGS_PLACEHOLDER; // defined in CFLAGS
|
#ifndef MAINARGS
|
||||||
|
#define MAINARGS ""
|
||||||
|
#endif
|
||||||
|
static const char mainargs[] = MAINARGS;
|
||||||
|
|
||||||
void putch(char ch) {
|
void putch(char ch) {
|
||||||
outb(SERIAL_PORT, ch);
|
outb(SERIAL_PORT, ch);
|
||||||
|
@ -19,6 +23,7 @@ void halt(int code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _trm_init() {
|
void _trm_init() {
|
||||||
|
heap_alloc_ptr = heap.start;
|
||||||
int ret = main(mainargs);
|
int ret = main(mainargs);
|
||||||
halt(ret);
|
halt(ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,19 @@ Context* __am_irq_handle(Context *c) {
|
||||||
if (user_handler) {
|
if (user_handler) {
|
||||||
Event ev = {0};
|
Event ev = {0};
|
||||||
switch (c->mcause) {
|
switch (c->mcause) {
|
||||||
|
case 11:
|
||||||
|
#ifdef __riscv_e
|
||||||
|
uint32_t call_number = c->gpr[15]; //a5
|
||||||
|
#else
|
||||||
|
uint32_t call_number = c->gpr[17]; //a7
|
||||||
|
#endif
|
||||||
|
switch(call_number) {
|
||||||
|
case -1: ev.event = EVENT_YIELD; break;
|
||||||
|
default:
|
||||||
|
ev.event = EVENT_SYSCALL; break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default: ev.event = EVENT_ERROR; break;
|
default: ev.event = EVENT_ERROR; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +30,6 @@ Context* __am_irq_handle(Context *c) {
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void __am_asm_trap(void);
|
extern void __am_asm_trap(void);
|
||||||
|
|
||||||
bool cte_init(Context*(*handler)(Event, Context*)) {
|
bool cte_init(Context*(*handler)(Event, Context*)) {
|
||||||
|
@ -31,11 +43,27 @@ bool cte_init(Context*(*handler)(Event, Context*)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
||||||
return NULL;
|
uint32_t *stack = kstack.end; //kernel stack top
|
||||||
|
stack -= 32 + 4;
|
||||||
|
for(int i = 0; i < 32; i++) {
|
||||||
|
stack[i] = 0;
|
||||||
|
}
|
||||||
|
//stack[2] = (uint32_t)((uint32_t*)kstack.start + 1024);
|
||||||
|
stack[10] = (uint32_t)arg;
|
||||||
|
stack[32] = 11; //mcause
|
||||||
|
stack[33] = 0x1800U; //mstatus
|
||||||
|
stack[34] = (uint32_t)entry; //mepc
|
||||||
|
stack[35] = 0; //addr space
|
||||||
|
//
|
||||||
|
uint32_t *begin = kstack.start;
|
||||||
|
*begin = (uint32_t)stack;
|
||||||
|
|
||||||
|
return (Context *)stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield() {
|
void yield() {
|
||||||
#ifdef __riscv_e
|
#ifdef __riscv_e
|
||||||
|
//use a5 or a7 to get system call ID
|
||||||
asm volatile("li a5, -1; ecall");
|
asm volatile("li a5, -1; ecall");
|
||||||
#else
|
#else
|
||||||
asm volatile("li a7, -1; ecall");
|
asm volatile("li a7, -1; ecall");
|
||||||
|
|
|
@ -5,6 +5,4 @@
|
||||||
_start:
|
_start:
|
||||||
mv s0, zero
|
mv s0, zero
|
||||||
la sp, _stack_pointer
|
la sp, _stack_pointer
|
||||||
call _trm_init
|
jal _trm_init
|
||||||
|
|
||||||
.size _start, . - _start
|
|
||||||
|
|
|
@ -58,14 +58,14 @@ __am_asm_trap:
|
||||||
csrw mstatus, t1
|
csrw mstatus, t1
|
||||||
|
|
||||||
mv a0, sp
|
mv a0, sp
|
||||||
call __am_irq_handle
|
jal __am_irq_handle
|
||||||
|
|
||||||
|
mv sp, a0
|
||||||
LOAD t1, OFFSET_STATUS(sp)
|
LOAD t1, OFFSET_STATUS(sp)
|
||||||
LOAD t2, OFFSET_EPC(sp)
|
LOAD t2, OFFSET_EPC(sp)
|
||||||
csrw mstatus, t1
|
csrw mstatus, t1
|
||||||
csrw mepc, t2
|
csrw mepc, t2
|
||||||
|
|
||||||
MAP(REGS, POP)
|
MAP(REGS, POP)
|
||||||
|
|
||||||
addi sp, sp, CONTEXT_SIZE
|
addi sp, sp, CONTEXT_SIZE
|
||||||
mret
|
mret
|
||||||
|
|
|
@ -8,6 +8,7 @@ Context* __am_irq_handle(Context *c) {
|
||||||
if (user_handler) {
|
if (user_handler) {
|
||||||
Event ev = {0};
|
Event ev = {0};
|
||||||
switch (c->mcause) {
|
switch (c->mcause) {
|
||||||
|
case 11: ev.event = EVENT_YIELD; break; // scause ?
|
||||||
default: ev.event = EVENT_ERROR; break;
|
default: ev.event = EVENT_ERROR; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +32,23 @@ bool cte_init(Context*(*handler)(Event, Context*)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
||||||
return NULL;
|
//Note that we use e extension here !!!!
|
||||||
|
uint32_t *stack = kstack.end; //kernel stack top
|
||||||
|
stack -= 16 + 4;
|
||||||
|
for(int i = 0; i < 16; i++) {
|
||||||
|
stack[i] = 0;
|
||||||
|
}
|
||||||
|
//stack[2] = (uint32_t)((uint32_t*)kstack.start + 1024);
|
||||||
|
stack[10] = (uint32_t)arg;
|
||||||
|
stack[16] = 11; //mcause
|
||||||
|
stack[17] = 0x1800U; //mstatus
|
||||||
|
stack[18] = (uint32_t)entry; //mepc
|
||||||
|
stack[19] = 0; //addr space
|
||||||
|
//
|
||||||
|
uint32_t *begin = kstack.start;
|
||||||
|
*begin = (uint32_t)stack;
|
||||||
|
|
||||||
|
return (Context *)stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield() {
|
void yield() {
|
||||||
|
|
|
@ -40,7 +40,7 @@ FUNC_BEGIN (__udivsi3)
|
||||||
sll a0, a0, 32
|
sll a0, a0, 32
|
||||||
sll a1, a1, 32
|
sll a1, a1, 32
|
||||||
move t0, ra
|
move t0, ra
|
||||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||||
sext.w a0, a0
|
sext.w a0, a0
|
||||||
jr t0
|
jr t0
|
||||||
FUNC_END (__udivsi3)
|
FUNC_END (__udivsi3)
|
||||||
|
@ -52,7 +52,7 @@ FUNC_BEGIN (__umodsi3)
|
||||||
srl a0, a0, 32
|
srl a0, a0, 32
|
||||||
srl a1, a1, 32
|
srl a1, a1, 32
|
||||||
move t0, ra
|
move t0, ra
|
||||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||||
sext.w a0, a1
|
sext.w a0, a1
|
||||||
jr t0
|
jr t0
|
||||||
FUNC_END (__umodsi3)
|
FUNC_END (__umodsi3)
|
||||||
|
@ -100,7 +100,7 @@ HIDDEN_DEF (__udivdi3)
|
||||||
FUNC_BEGIN (__umoddi3)
|
FUNC_BEGIN (__umoddi3)
|
||||||
/* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
|
/* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
|
||||||
move t0, ra
|
move t0, ra
|
||||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||||
move a0, a1
|
move a0, a1
|
||||||
jr t0
|
jr t0
|
||||||
FUNC_END (__umoddi3)
|
FUNC_END (__umoddi3)
|
||||||
|
@ -117,7 +117,7 @@ FUNC_END (__umoddi3)
|
||||||
neg a1, a1
|
neg a1, a1
|
||||||
.L12:
|
.L12:
|
||||||
move t0, ra
|
move t0, ra
|
||||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||||
neg a0, a0
|
neg a0, a0
|
||||||
jr t0
|
jr t0
|
||||||
FUNC_END (__divdi3)
|
FUNC_END (__divdi3)
|
||||||
|
@ -127,7 +127,7 @@ FUNC_BEGIN (__moddi3)
|
||||||
bltz a1, .L31
|
bltz a1, .L31
|
||||||
bltz a0, .L32
|
bltz a0, .L32
|
||||||
.L30:
|
.L30:
|
||||||
call HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is not negative. */
|
jal HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is not negative. */
|
||||||
move a0, a1
|
move a0, a1
|
||||||
jr t0
|
jr t0
|
||||||
.L31:
|
.L31:
|
||||||
|
@ -135,7 +135,7 @@ FUNC_BEGIN (__moddi3)
|
||||||
bgez a0, .L30
|
bgez a0, .L30
|
||||||
.L32:
|
.L32:
|
||||||
neg a0, a0
|
neg a0, a0
|
||||||
call HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is hella negative. */
|
jal HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is hella negative. */
|
||||||
neg a0, a1
|
neg a0, a1
|
||||||
jr t0
|
jr t0
|
||||||
FUNC_END (__moddi3)
|
FUNC_END (__moddi3)
|
||||||
|
|
|
@ -5,4 +5,4 @@
|
||||||
_start:
|
_start:
|
||||||
mv s0, zero
|
mv s0, zero
|
||||||
la sp, _stack_pointer
|
la sp, _stack_pointer
|
||||||
call _trm_init
|
jal _trm_init
|
||||||
|
|
|
@ -1,10 +1,21 @@
|
||||||
|
#include "amdev.h"
|
||||||
|
#include "riscv/riscv.h"
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void __am_timer_init() {
|
#define RTC_ADDR 0xa0000048
|
||||||
}
|
static uint64_t up = 0;
|
||||||
|
|
||||||
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
|
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
|
||||||
uptime->us = 0;
|
uint32_t h = inl(RTC_ADDR + 4);
|
||||||
|
uint32_t l = inl(RTC_ADDR);
|
||||||
|
uint64_t time = (uint64_t)h << 32 | l;
|
||||||
|
uptime->us = time - up;
|
||||||
|
}
|
||||||
|
void __am_timer_init() {
|
||||||
|
uint32_t h = inl(RTC_ADDR + 4);
|
||||||
|
uint32_t l = inl(RTC_ADDR);
|
||||||
|
up = (uint64_t)h << 32 | l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
|
void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ __am_asm_trap:
|
||||||
mv a0, sp
|
mv a0, sp
|
||||||
jal __am_irq_handle
|
jal __am_irq_handle
|
||||||
|
|
||||||
|
mv sp, a0
|
||||||
LOAD t1, OFFSET_STATUS(sp)
|
LOAD t1, OFFSET_STATUS(sp)
|
||||||
LOAD t2, OFFSET_EPC(sp)
|
LOAD t2, OFFSET_EPC(sp)
|
||||||
csrw mstatus, t1
|
csrw mstatus, t1
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "riscv/riscv.h"
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <klib-macros.h>
|
#include <klib-macros.h>
|
||||||
|
|
||||||
|
@ -9,13 +10,21 @@ extern char _pmem_start;
|
||||||
#define PMEM_END ((uintptr_t)&_pmem_start + PMEM_SIZE)
|
#define PMEM_END ((uintptr_t)&_pmem_start + PMEM_SIZE)
|
||||||
|
|
||||||
Area heap = RANGE(&_heap_start, PMEM_END);
|
Area heap = RANGE(&_heap_start, PMEM_END);
|
||||||
static const char mainargs[MAINARGS_MAX_LEN] = MAINARGS_PLACEHOLDER; // defined in CFLAGS
|
#ifndef MAINARGS
|
||||||
|
#define MAINARGS ""
|
||||||
|
#endif
|
||||||
|
static const char mainargs[] = MAINARGS;
|
||||||
|
|
||||||
void putch(char ch) {
|
void putch(char ch) {
|
||||||
|
#define SERIAL_PORT 0xa00003f8
|
||||||
|
outb(SERIAL_PORT, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void halt(int code) {
|
void halt(int code) {
|
||||||
while (1);
|
asm volatile("mv a0, %0; ebreak" :: "r"(code));
|
||||||
|
|
||||||
|
//can't compile without this
|
||||||
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _trm_init() {
|
void _trm_init() {
|
||||||
|
|
22
am/src/riscv/nutshell/common/ioe.c
Normal file
22
am/src/riscv/nutshell/common/ioe.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <am.h>
|
||||||
|
#include <amdev.h>
|
||||||
|
|
||||||
|
void __am_timer_init();
|
||||||
|
void __am_timer_rtc(AM_TIMER_RTC_T *);
|
||||||
|
void __am_timer_uptime(AM_TIMER_UPTIME_T *);
|
||||||
|
static void __am_timer_config(AM_TIMER_CONFIG_T *cfg) { cfg->present = true; cfg->has_rtc = true; }
|
||||||
|
bool ioe_init() {
|
||||||
|
__am_timer_init();
|
||||||
|
return 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*handler_t)(void *buf);
|
||||||
|
void ioe_read (int reg, void *buf) { ((handler_t)lut[reg])(buf); }
|
||||||
|
void ioe_write(int reg, void *buf) { ((handler_t)lut[reg])(buf); }
|
4
am/src/riscv/nutshell/common/mainargs.S
Normal file
4
am/src/riscv/nutshell/common/mainargs.S
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.section .rodata
|
||||||
|
.globl __am_mainargs
|
||||||
|
__am_mainargs:
|
||||||
|
.asciz MAINARGS
|
30
am/src/riscv/nutshell/common/timer.c
Normal file
30
am/src/riscv/nutshell/common/timer.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include <am.h>
|
||||||
|
#include <amdev.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <nutshell.h>
|
||||||
|
#include <riscv/riscv.h>
|
||||||
|
#include <klib.h>
|
||||||
|
|
||||||
|
static uint64_t boot_time = 0;
|
||||||
|
static inline uint64_t read_time(void) {
|
||||||
|
//Just host time
|
||||||
|
return ind(RTC_ADDR) * 20000; // unit: us
|
||||||
|
//return ind(RTC_ADDR); // unit: us
|
||||||
|
}
|
||||||
|
|
||||||
|
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
|
||||||
|
uptime->us = read_time() - boot_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = 2018;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __am_timer_init() {
|
||||||
|
boot_time = read_time();
|
||||||
|
}
|
28
am/src/riscv/nutshell/common/uartlite.c
Normal file
28
am/src/riscv/nutshell/common/uartlite.c
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include <riscv/riscv.h>
|
||||||
|
|
||||||
|
#define UARTLITE_MMIO 0x40600000
|
||||||
|
#define UARTLITE_RX_FIFO 0x0
|
||||||
|
#define UARTLITE_TX_FIFO 0x4
|
||||||
|
#define UARTLITE_STAT_REG 0x8
|
||||||
|
#define UARTLITE_CTRL_REG 0xc
|
||||||
|
|
||||||
|
#define UARTLITE_RST_FIFO 0x03
|
||||||
|
#define UARTLITE_TX_FULL 0x08
|
||||||
|
#define UARTLITE_RX_VALID 0x01
|
||||||
|
|
||||||
|
void __am_init_uartlite(void) {
|
||||||
|
outb(UARTLITE_MMIO + UARTLITE_CTRL_REG, UARTLITE_RST_FIFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __am_uartlite_putchar(char ch) {
|
||||||
|
if (ch == '\n') __am_uartlite_putchar('\r');
|
||||||
|
|
||||||
|
while (inb(UARTLITE_MMIO + UARTLITE_STAT_REG) & UARTLITE_TX_FULL);
|
||||||
|
outb(UARTLITE_MMIO + UARTLITE_TX_FIFO, ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __am_uartlite_getchar() {
|
||||||
|
if (inb(UARTLITE_MMIO + UARTLITE_STAT_REG) & UARTLITE_RX_VALID)
|
||||||
|
return inb(UARTLITE_MMIO + UARTLITE_RX_FIFO);
|
||||||
|
return 0;
|
||||||
|
}
|
12
am/src/riscv/nutshell/include/nutshell.h
Normal file
12
am/src/riscv/nutshell/include/nutshell.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef __NUTSHELL_H__
|
||||||
|
#define __NUTSHELL_H__
|
||||||
|
|
||||||
|
#include <klib-macros.h>
|
||||||
|
#include <riscv/riscv.h>
|
||||||
|
|
||||||
|
# define RTC_ADDR 0x3800bff8
|
||||||
|
# define SCREEN_ADDR 0x40001000
|
||||||
|
# define SYNC_ADDR 0x40001004
|
||||||
|
# define FB_ADDR 0x50000000
|
||||||
|
|
||||||
|
#endif
|
7
am/src/riscv/nutshell/isa/riscv/boot/loader64.ld
Normal file
7
am/src/riscv/nutshell/isa/riscv/boot/loader64.ld
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
pmem_base = 0x80000000;
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ram (rwxa) : ORIGIN = 0x80000000, LENGTH = 128M
|
||||||
|
}
|
||||||
|
|
||||||
|
INCLUDE "section.ld"
|
8
am/src/riscv/nutshell/isa/riscv/boot/start.S
Normal file
8
am/src/riscv/nutshell/isa/riscv/boot/start.S
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.section entry, "ax"
|
||||||
|
.globl _start
|
||||||
|
.type _start, @function
|
||||||
|
|
||||||
|
_start:
|
||||||
|
mv s0, zero
|
||||||
|
la sp, _stack_pointer
|
||||||
|
jal _trm_init
|
38
am/src/riscv/nutshell/isa/riscv/trm.c
Normal file
38
am/src/riscv/nutshell/isa/riscv/trm.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <am.h>
|
||||||
|
#include <riscv/riscv.h>
|
||||||
|
#include <klib.h>
|
||||||
|
|
||||||
|
extern char _heap_start;
|
||||||
|
extern char _pmem_end;
|
||||||
|
|
||||||
|
int main(const char *args);
|
||||||
|
void __am_init_uartlite(void);
|
||||||
|
void __am_uartlite_putchar(char ch);
|
||||||
|
|
||||||
|
Area heap = {
|
||||||
|
.start = &_heap_start,
|
||||||
|
.end = &_pmem_end,
|
||||||
|
};
|
||||||
|
|
||||||
|
void putch(char ch) {
|
||||||
|
__am_uartlite_putchar(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void halt(int code) {
|
||||||
|
printf("Before 0x0005006b\n");
|
||||||
|
__asm__ volatile("mv a0, %0; .word 0x0005006b" : :"r"(code));
|
||||||
|
|
||||||
|
// should not reach here during simulation
|
||||||
|
printf("Exit with code = %d\n", code);
|
||||||
|
|
||||||
|
// should not reach here on FPGA
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char __am_mainargs;
|
||||||
|
static const char *mainargs = &__am_mainargs;
|
||||||
|
void _trm_init() {
|
||||||
|
__am_init_uartlite();
|
||||||
|
int ret = main(mainargs);
|
||||||
|
halt(ret);
|
||||||
|
}
|
33
am/src/riscv/nutshell/ldscript/section.ld
Normal file
33
am/src/riscv/nutshell/ldscript/section.ld
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = ORIGIN(ram);
|
||||||
|
.text : {
|
||||||
|
*(entry)
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
etext = .;
|
||||||
|
_etext = .;
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
edata = .;
|
||||||
|
_data = .;
|
||||||
|
.bss : {
|
||||||
|
_bss_start = .;
|
||||||
|
*(.bss*)
|
||||||
|
*(.sbss*)
|
||||||
|
*(.scommon)
|
||||||
|
}
|
||||||
|
_stack_top = ALIGN(0x1000);
|
||||||
|
. = _stack_top + 0x8000;
|
||||||
|
_stack_pointer = .;
|
||||||
|
end = .;
|
||||||
|
_end = .;
|
||||||
|
_heap_start = ALIGN(0x1000);
|
||||||
|
_pmem_start = pmem_base;
|
||||||
|
_pmem_end = _pmem_start + LENGTH(ram);
|
||||||
|
}
|
|
@ -1,15 +1,23 @@
|
||||||
#ifndef RISCV_H__
|
#ifndef RISCV_H__
|
||||||
#define RISCV_H__
|
#define RISCV_H__
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct { uint32_t lo, hi; };
|
||||||
|
int64_t val;
|
||||||
|
} R64;
|
||||||
|
|
||||||
static inline uint8_t inb(uintptr_t addr) { return *(volatile uint8_t *)addr; }
|
static inline uint8_t inb(uintptr_t addr) { return *(volatile uint8_t *)addr; }
|
||||||
static inline uint16_t inw(uintptr_t addr) { return *(volatile uint16_t *)addr; }
|
static inline uint16_t inw(uintptr_t addr) { return *(volatile uint16_t *)addr; }
|
||||||
static inline uint32_t inl(uintptr_t addr) { return *(volatile uint32_t *)addr; }
|
static inline uint32_t inl(uintptr_t addr) { return *(volatile uint32_t *)addr; }
|
||||||
|
static inline uint64_t ind(uintptr_t addr) { return *(volatile uint64_t *)addr; }
|
||||||
|
|
||||||
static inline void outb(uintptr_t addr, uint8_t data) { *(volatile uint8_t *)addr = data; }
|
static inline void outb(uintptr_t addr, uint8_t data) { *(volatile uint8_t *)addr = data; }
|
||||||
static inline void outw(uintptr_t addr, uint16_t data) { *(volatile uint16_t *)addr = data; }
|
static inline void outw(uintptr_t addr, uint16_t data) { *(volatile uint16_t *)addr = data; }
|
||||||
static inline void outl(uintptr_t addr, uint32_t data) { *(volatile uint32_t *)addr = data; }
|
static inline void outl(uintptr_t addr, uint32_t data) { *(volatile uint32_t *)addr = data; }
|
||||||
|
static inline void outd(uintptr_t addr, uint64_t data) { *(volatile uint64_t *)addr = data; }
|
||||||
|
|
||||||
#define PTE_V 0x01
|
#define PTE_V 0x01
|
||||||
#define PTE_R 0x02
|
#define PTE_R 0x02
|
||||||
|
@ -19,9 +27,14 @@ static inline void outl(uintptr_t addr, uint32_t data) { *(volatile uint32_t *)a
|
||||||
#define PTE_A 0x40
|
#define PTE_A 0x40
|
||||||
#define PTE_D 0x80
|
#define PTE_D 0x80
|
||||||
|
|
||||||
enum { MODE_U, MODE_S, MODE_M = 3 };
|
enum { MODE_U, MODE_S, MODE_H, MODE_M};
|
||||||
|
#define MSTATUS_IE(mode) ((1 << (mode)) << 0)
|
||||||
|
#define MSTATUS_PIE(mode) ((1 << (mode)) << 4)
|
||||||
|
#define MSTATUS_MPP(mode) ((mode) << 11)
|
||||||
|
#define MSTATUS_SPP(mode) ((mode) << 8)
|
||||||
#define MSTATUS_MXR (1 << 19)
|
#define MSTATUS_MXR (1 << 19)
|
||||||
#define MSTATUS_SUM (1 << 18)
|
#define MSTATUS_SUM (1 << 18)
|
||||||
|
#define MSTATUS_MPRV (1 << 17)
|
||||||
|
|
||||||
#if __riscv_xlen == 64
|
#if __riscv_xlen == 64
|
||||||
#define MSTATUS_SXL (2ull << 34)
|
#define MSTATUS_SXL (2ull << 34)
|
||||||
|
@ -31,4 +44,12 @@ enum { MODE_U, MODE_S, MODE_M = 3 };
|
||||||
#define MSTATUS_UXL 0
|
#define MSTATUS_UXL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Address in page table entry
|
||||||
|
#define PTE_ADDR(pte) (((uintptr_t)(pte) & ~0x3ff) << 2)
|
||||||
|
|
||||||
|
#define PTW_SV32 ((ptw_config) { .ptw_level = 2, .vpn_width = 10 })
|
||||||
|
#define PTW_SV39 ((ptw_config) { .ptw_level = 3, .vpn_width = 9 })
|
||||||
|
#define PTW_SV48 ((ptw_config) { .ptw_level = 4, .vpn_width = 9 })
|
||||||
|
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
67
am/src/riscv/ysyxsoc/cte.c
Normal file
67
am/src/riscv/ysyxsoc/cte.c
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#include <am.h>
|
||||||
|
#include <riscv/riscv.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->mcause) {
|
||||||
|
case 11: ev.event = EVENT_YIELD; break; // scause ?
|
||||||
|
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) {
|
||||||
|
//Note that we use e extension here !!!!
|
||||||
|
uint32_t *stack = kstack.end; //kernel stack top
|
||||||
|
stack -= 16 + 4;
|
||||||
|
for(int i = 0; i < 16; i++) {
|
||||||
|
stack[i] = 0;
|
||||||
|
}
|
||||||
|
//stack[2] = (uint32_t)((uint32_t*)kstack.start + 1024);
|
||||||
|
stack[10] = (uint32_t)arg;
|
||||||
|
stack[16] = 11; //mcause
|
||||||
|
stack[17] = 0x1800U; //mstatus
|
||||||
|
stack[18] = (uint32_t)entry; //mepc
|
||||||
|
stack[19] = 0; //addr space
|
||||||
|
//
|
||||||
|
uint32_t *begin = kstack.start;
|
||||||
|
*begin = (uint32_t)stack;
|
||||||
|
|
||||||
|
return (Context *)stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void yield() {
|
||||||
|
#ifdef __riscv_e
|
||||||
|
asm volatile("li a5, -1; ecall");
|
||||||
|
#else
|
||||||
|
asm volatile("li a7, -1; ecall");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ienabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iset(bool enable) {
|
||||||
|
}
|
6
am/src/riscv/ysyxsoc/input.c
Normal file
6
am/src/riscv/ysyxsoc/input.c
Normal 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;
|
||||||
|
}
|
34
am/src/riscv/ysyxsoc/ioe.c
Normal file
34
am/src/riscv/ysyxsoc/ioe.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#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 *);
|
||||||
|
|
||||||
|
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; }
|
||||||
|
static void __am_uart_config(AM_INPUT_CONFIG_T *cfg) { cfg->present = false; }
|
||||||
|
|
||||||
|
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,
|
||||||
|
[AM_UART_CONFIG] = __am_uart_config,
|
||||||
|
};
|
||||||
|
|
||||||
|
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); }
|
27
am/src/riscv/ysyxsoc/libgcc/ashldi3.c
Normal file
27
am/src/riscv/ysyxsoc/libgcc/ashldi3.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#define LIBGCC2_UNITS_PER_WORD (__riscv_xlen / 8)
|
||||||
|
#include "libgcc2.h"
|
||||||
|
|
||||||
|
DWtype __ashldi3 (DWtype u, shift_count_type b)
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
return u;
|
||||||
|
|
||||||
|
const DWunion uu = {.ll = u};
|
||||||
|
const shift_count_type bm = W_TYPE_SIZE - b;
|
||||||
|
DWunion w;
|
||||||
|
|
||||||
|
if (bm <= 0)
|
||||||
|
{
|
||||||
|
w.s.low = 0;
|
||||||
|
w.s.high = (UWtype) uu.s.low << -bm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const UWtype carries = (UWtype) uu.s.low >> bm;
|
||||||
|
|
||||||
|
w.s.low = (UWtype) uu.s.low << b;
|
||||||
|
w.s.high = ((UWtype) uu.s.high << b) | carries;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.ll;
|
||||||
|
}
|
150
am/src/riscv/ysyxsoc/libgcc/div.S
Normal file
150
am/src/riscv/ysyxsoc/libgcc/div.S
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/* Integer division routines for RISC-V.
|
||||||
|
|
||||||
|
Copyright (C) 2016-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 3, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "riscv-asm.h"
|
||||||
|
|
||||||
|
.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 HIDDEN_JUMPTARGET(__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 HIDDEN_JUMPTARGET(__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)
|
||||||
|
HIDDEN_DEF (__udivdi3)
|
||||||
|
|
||||||
|
FUNC_BEGIN (__umoddi3)
|
||||||
|
/* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
|
||||||
|
move t0, ra
|
||||||
|
jal HIDDEN_JUMPTARGET(__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 HIDDEN_JUMPTARGET(__udivdi3) /* Compute __udivdi3(-a0, -a1). */
|
||||||
|
.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */
|
||||||
|
neg a1, a1
|
||||||
|
.L12:
|
||||||
|
move t0, ra
|
||||||
|
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||||
|
neg a0, a0
|
||||||
|
jr t0
|
||||||
|
FUNC_END (__divdi3)
|
||||||
|
|
||||||
|
FUNC_BEGIN (__moddi3)
|
||||||
|
move t0, ra
|
||||||
|
bltz a1, .L31
|
||||||
|
bltz a0, .L32
|
||||||
|
.L30:
|
||||||
|
jal HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is not negative. */
|
||||||
|
move a0, a1
|
||||||
|
jr t0
|
||||||
|
.L31:
|
||||||
|
neg a1, a1
|
||||||
|
bgez a0, .L30
|
||||||
|
.L32:
|
||||||
|
neg a0, a0
|
||||||
|
jal HIDDEN_JUMPTARGET(__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
|
543
am/src/riscv/ysyxsoc/libgcc/libgcc2.h
Normal file
543
am/src/riscv/ysyxsoc/libgcc/libgcc2.h
Normal file
|
@ -0,0 +1,543 @@
|
||||||
|
/* Header file for libgcc2.c. */
|
||||||
|
/* Copyright (C) 2000-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 3, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef GCC_LIBGCC2_H
|
||||||
|
#define GCC_LIBGCC2_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define MIN_UNITS_PER_WORD (__riscv_xlen / 8)
|
||||||
|
|
||||||
|
#ifndef HIDE_EXPORTS
|
||||||
|
#pragma GCC visibility push(default)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int __gcc_bcmp (const unsigned char *, const unsigned char *, size_t);
|
||||||
|
extern void __clear_cache (void *, void *);
|
||||||
|
extern void __eprintf (const char *, const char *, unsigned int, const char *)
|
||||||
|
__attribute__ ((__noreturn__));
|
||||||
|
|
||||||
|
#ifdef __LIBGCC_HAS_HF_MODE__
|
||||||
|
#define LIBGCC2_HAS_HF_MODE 1
|
||||||
|
#else
|
||||||
|
#define LIBGCC2_HAS_HF_MODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __LIBGCC_HAS_SF_MODE__
|
||||||
|
#define LIBGCC2_HAS_SF_MODE 1
|
||||||
|
#else
|
||||||
|
#define LIBGCC2_HAS_SF_MODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __LIBGCC_HAS_DF_MODE__
|
||||||
|
#define LIBGCC2_HAS_DF_MODE 1
|
||||||
|
#else
|
||||||
|
#define LIBGCC2_HAS_DF_MODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __LIBGCC_HAS_XF_MODE__
|
||||||
|
#define LIBGCC2_HAS_XF_MODE 1
|
||||||
|
#else
|
||||||
|
#define LIBGCC2_HAS_XF_MODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __LIBGCC_HAS_TF_MODE__
|
||||||
|
#define LIBGCC2_HAS_TF_MODE 1
|
||||||
|
#else
|
||||||
|
#define LIBGCC2_HAS_TF_MODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __LIBGCC_SF_MANT_DIG__
|
||||||
|
#if LIBGCC2_HAS_SF_MODE
|
||||||
|
#error __LIBGCC_SF_MANT_DIG__ not defined
|
||||||
|
#else
|
||||||
|
#define __LIBGCC_SF_MANT_DIG__ 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __LIBGCC_DF_MANT_DIG__
|
||||||
|
#if LIBGCC2_HAS_DF_MODE
|
||||||
|
#error __LIBGCC_DF_MANT_DIG__ not defined
|
||||||
|
#else
|
||||||
|
#define __LIBGCC_DF_MANT_DIG__ 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __LIBGCC_XF_MANT_DIG__
|
||||||
|
#if LIBGCC2_HAS_XF_MODE
|
||||||
|
#error __LIBGCC_XF_MANT_DIG__ not defined
|
||||||
|
#else
|
||||||
|
#define __LIBGCC_XF_MANT_DIG__ 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __LIBGCC_TF_MANT_DIG__
|
||||||
|
#if LIBGCC2_HAS_TF_MODE
|
||||||
|
#error __LIBGCC_TF_MANT_DIG__ not defined
|
||||||
|
#else
|
||||||
|
#define __LIBGCC_TF_MANT_DIG__ 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FIXME: This #ifdef probably should be removed, ie. enable the test
|
||||||
|
for mips too. */
|
||||||
|
/* Don't use IBM Extended Double TFmode for TI->SF calculations.
|
||||||
|
The conversion from long double to float suffers from double
|
||||||
|
rounding, because we convert via double. In other cases, going
|
||||||
|
through the software fp routines is much slower than the fallback. */
|
||||||
|
#ifdef __powerpc__
|
||||||
|
#define AVOID_FP_TYPE_CONVERSION(SIZE) (SIZE == 106)
|
||||||
|
#elif defined(WIDEST_HARDWARE_FP_SIZE)
|
||||||
|
#define AVOID_FP_TYPE_CONVERSION(SIZE) (SIZE > WIDEST_HARDWARE_FP_SIZE)
|
||||||
|
#else
|
||||||
|
#define AVOID_FP_TYPE_CONVERSION(SIZE) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* In the first part of this file, we are interfacing to calls generated
|
||||||
|
by the compiler itself. These calls pass values into these routines
|
||||||
|
which have very specific modes (rather than very specific types), and
|
||||||
|
these compiler-generated calls also expect any return values to have
|
||||||
|
very specific modes (rather than very specific types). Thus, we need
|
||||||
|
to avoid using regular C language type names in this part of the file
|
||||||
|
because the sizes for those types can be configured to be anything.
|
||||||
|
Instead we use the following special type names. */
|
||||||
|
|
||||||
|
typedef int QItype __attribute__ ((mode (QI)));
|
||||||
|
typedef unsigned int UQItype __attribute__ ((mode (QI)));
|
||||||
|
typedef int HItype __attribute__ ((mode (HI)));
|
||||||
|
typedef unsigned int UHItype __attribute__ ((mode (HI)));
|
||||||
|
#if MIN_UNITS_PER_WORD > 1
|
||||||
|
/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1. */
|
||||||
|
typedef int SItype __attribute__ ((mode (SI)));
|
||||||
|
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
||||||
|
#if __SIZEOF_LONG_LONG__ > 4
|
||||||
|
/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2. */
|
||||||
|
typedef int DItype __attribute__ ((mode (DI)));
|
||||||
|
typedef unsigned int UDItype __attribute__ ((mode (DI)));
|
||||||
|
#if MIN_UNITS_PER_WORD > 4
|
||||||
|
/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4. */
|
||||||
|
typedef int TItype __attribute__ ((mode (TI)));
|
||||||
|
typedef unsigned int UTItype __attribute__ ((mode (TI)));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LIBGCC2_HAS_HF_MODE
|
||||||
|
typedef float HFtype __attribute__ ((mode (HF)));
|
||||||
|
typedef _Complex float HCtype __attribute__ ((mode (HC)));
|
||||||
|
#endif
|
||||||
|
#if LIBGCC2_HAS_SF_MODE
|
||||||
|
typedef float SFtype __attribute__ ((mode (SF)));
|
||||||
|
typedef _Complex float SCtype __attribute__ ((mode (SC)));
|
||||||
|
#endif
|
||||||
|
#if LIBGCC2_HAS_DF_MODE
|
||||||
|
typedef float DFtype __attribute__ ((mode (DF)));
|
||||||
|
typedef _Complex float DCtype __attribute__ ((mode (DC)));
|
||||||
|
#endif
|
||||||
|
#if LIBGCC2_HAS_XF_MODE
|
||||||
|
typedef float XFtype __attribute__ ((mode (XF)));
|
||||||
|
typedef _Complex float XCtype __attribute__ ((mode (XC)));
|
||||||
|
#endif
|
||||||
|
#if LIBGCC2_HAS_TF_MODE
|
||||||
|
typedef float TFtype __attribute__ ((mode (TF)));
|
||||||
|
typedef _Complex float TCtype __attribute__ ((mode (TC)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int cmp_return_type; // __attribute__((mode (__libgcc_cmp_return__)));
|
||||||
|
typedef int shift_count_type; // __attribute__((mode (__libgcc_shift_count__)));
|
||||||
|
|
||||||
|
/* Make sure that we don't accidentally use any normal C language built-in
|
||||||
|
type names in the first part of this file. Instead we want to use *only*
|
||||||
|
the type names defined above. The following macro definitions insure
|
||||||
|
that if we *do* accidentally use some normal C language built-in type name,
|
||||||
|
we will get a syntax error. */
|
||||||
|
|
||||||
|
#define char bogus_type
|
||||||
|
#define short bogus_type
|
||||||
|
#define int bogus_type
|
||||||
|
#define long bogus_type
|
||||||
|
#define unsigned bogus_type
|
||||||
|
#define float bogus_type
|
||||||
|
#define double bogus_type
|
||||||
|
|
||||||
|
/* Versions prior to 3.4.4 were not taking into account the word size for
|
||||||
|
the 5 trapping arithmetic functions absv, addv, subv, mulv and negv. As
|
||||||
|
a consequence, the si and di variants were always and the only ones emitted.
|
||||||
|
To maintain backward compatibility, COMPAT_SIMODE_TRAPPING_ARITHMETIC is
|
||||||
|
defined on platforms where it makes sense to still have the si variants
|
||||||
|
emitted. As a bonus, their implementation is now correct. Note that the
|
||||||
|
same mechanism should have been implemented for the di variants, but it
|
||||||
|
turns out that no platform would define COMPAT_DIMODE_TRAPPING_ARITHMETIC
|
||||||
|
if it existed. */
|
||||||
|
|
||||||
|
#if LIBGCC2_UNITS_PER_WORD == 8
|
||||||
|
#define W_TYPE_SIZE (8 * __CHAR_BIT__)
|
||||||
|
#define Wtype DItype
|
||||||
|
#define UWtype UDItype
|
||||||
|
#define HWtype DItype
|
||||||
|
#define UHWtype UDItype
|
||||||
|
#define DWtype TItype
|
||||||
|
#define UDWtype UTItype
|
||||||
|
#ifdef LIBGCC2_GNU_PREFIX
|
||||||
|
#define __NW(a,b) __gnu_ ## a ## di ## b
|
||||||
|
#define __NDW(a,b) __gnu_ ## a ## ti ## b
|
||||||
|
#else
|
||||||
|
#define __NW(a,b) __ ## a ## di ## b
|
||||||
|
#define __NDW(a,b) __ ## a ## ti ## b
|
||||||
|
#endif
|
||||||
|
#define COMPAT_SIMODE_TRAPPING_ARITHMETIC
|
||||||
|
#elif LIBGCC2_UNITS_PER_WORD == 4
|
||||||
|
#define W_TYPE_SIZE (4 * __CHAR_BIT__)
|
||||||
|
#define Wtype SItype
|
||||||
|
#define UWtype USItype
|
||||||
|
#define HWtype SItype
|
||||||
|
#define UHWtype USItype
|
||||||
|
#define DWtype DItype
|
||||||
|
#define UDWtype UDItype
|
||||||
|
#ifdef LIBGCC2_GNU_PREFIX
|
||||||
|
#define __NW(a,b) __gnu_ ## a ## si ## b
|
||||||
|
#define __NDW(a,b) __gnu_ ## a ## di ## b
|
||||||
|
#else
|
||||||
|
#define __NW(a,b) __ ## a ## si ## b
|
||||||
|
#define __NDW(a,b) __ ## a ## di ## b
|
||||||
|
#endif
|
||||||
|
#elif LIBGCC2_UNITS_PER_WORD == 2
|
||||||
|
#define W_TYPE_SIZE (2 * __CHAR_BIT__)
|
||||||
|
#define Wtype HItype
|
||||||
|
#define UWtype UHItype
|
||||||
|
#define HWtype HItype
|
||||||
|
#define UHWtype UHItype
|
||||||
|
#define DWtype SItype
|
||||||
|
#define UDWtype USItype
|
||||||
|
#ifdef LIBGCC2_GNU_PREFIX
|
||||||
|
#define __NW(a,b) __gnu_ ## a ## hi ## b
|
||||||
|
#define __NDW(a,b) __gnu_ ## a ## si ## b
|
||||||
|
#else
|
||||||
|
#define __NW(a,b) __ ## a ## hi ## b
|
||||||
|
#define __NDW(a,b) __ ## a ## si ## b
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define W_TYPE_SIZE __CHAR_BIT__
|
||||||
|
#define Wtype QItype
|
||||||
|
#define UWtype UQItype
|
||||||
|
#define HWtype QItype
|
||||||
|
#define UHWtype UQItype
|
||||||
|
#define DWtype HItype
|
||||||
|
#define UDWtype UHItype
|
||||||
|
#ifdef LIBGCC2_GNU_PREFIX
|
||||||
|
#define __NW(a,b) __gnu_ ## a ## qi ## b
|
||||||
|
#define __NDW(a,b) __gnu_ ## a ## hi ## b
|
||||||
|
#else
|
||||||
|
#define __NW(a,b) __ ## a ## qi ## b
|
||||||
|
#define __NDW(a,b) __ ## a ## hi ## b
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LIBGCC2_GNU_PREFIX
|
||||||
|
#define __N(a) __gnu_ ## a
|
||||||
|
#else
|
||||||
|
#define __N(a) __ ## a
|
||||||
|
#endif
|
||||||
|
#define Wtype_MAX ((Wtype)(((UWtype)1 << (W_TYPE_SIZE - 1)) - 1))
|
||||||
|
#define Wtype_MIN (- Wtype_MAX - 1)
|
||||||
|
|
||||||
|
#if W_TYPE_SIZE == 8
|
||||||
|
# define Wtype_MAXp1_F 0x1p8f
|
||||||
|
#elif W_TYPE_SIZE == 16
|
||||||
|
# define Wtype_MAXp1_F 0x1p16f
|
||||||
|
#elif W_TYPE_SIZE == 32
|
||||||
|
# define Wtype_MAXp1_F 0x1p32f
|
||||||
|
#elif W_TYPE_SIZE == 64
|
||||||
|
# define Wtype_MAXp1_F 0x1p64f
|
||||||
|
#else
|
||||||
|
# error "expand the table"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __muldi3 __NDW(mul,3)
|
||||||
|
#define __divdi3 __NDW(div,3)
|
||||||
|
#define __udivdi3 __NDW(udiv,3)
|
||||||
|
#define __moddi3 __NDW(mod,3)
|
||||||
|
#define __umoddi3 __NDW(umod,3)
|
||||||
|
#define __negdi2 __NDW(neg,2)
|
||||||
|
#define __lshrdi3 __NDW(lshr,3)
|
||||||
|
#define __ashldi3 __NDW(ashl,3)
|
||||||
|
#define __ashrdi3 __NDW(ashr,3)
|
||||||
|
#define __cmpdi2 __NDW(cmp,2)
|
||||||
|
#define __ucmpdi2 __NDW(ucmp,2)
|
||||||
|
#define __divmoddi4 __NDW(divmod,4)
|
||||||
|
#define __udivmoddi4 __NDW(udivmod,4)
|
||||||
|
#define __fixunstfDI __NDW(fixunstf,)
|
||||||
|
#define __fixtfdi __NDW(fixtf,)
|
||||||
|
#define __fixunsxfDI __NDW(fixunsxf,)
|
||||||
|
#define __fixxfdi __NDW(fixxf,)
|
||||||
|
#define __fixunsdfDI __NDW(fixunsdf,)
|
||||||
|
#define __fixdfdi __NDW(fixdf,)
|
||||||
|
#define __fixunssfDI __NDW(fixunssf,)
|
||||||
|
#define __fixsfdi __NDW(fixsf,)
|
||||||
|
#define __floatdixf __NDW(float,xf)
|
||||||
|
#define __floatditf __NDW(float,tf)
|
||||||
|
#define __floatdidf __NDW(float,df)
|
||||||
|
#define __floatdisf __NDW(float,sf)
|
||||||
|
#define __floatundixf __NDW(floatun,xf)
|
||||||
|
#define __floatunditf __NDW(floatun,tf)
|
||||||
|
#define __floatundidf __NDW(floatun,df)
|
||||||
|
#define __floatundisf __NDW(floatun,sf)
|
||||||
|
#define __fixunsxfSI __NW(fixunsxf,)
|
||||||
|
#define __fixunstfSI __NW(fixunstf,)
|
||||||
|
#define __fixunsdfSI __NW(fixunsdf,)
|
||||||
|
#define __fixunssfSI __NW(fixunssf,)
|
||||||
|
|
||||||
|
#define __absvSI2 __NW(absv,2)
|
||||||
|
#define __addvSI3 __NW(addv,3)
|
||||||
|
#define __subvSI3 __NW(subv,3)
|
||||||
|
#define __mulvSI3 __NW(mulv,3)
|
||||||
|
#define __negvSI2 __NW(negv,2)
|
||||||
|
#define __absvDI2 __NDW(absv,2)
|
||||||
|
#define __addvDI3 __NDW(addv,3)
|
||||||
|
#define __subvDI3 __NDW(subv,3)
|
||||||
|
#define __mulvDI3 __NDW(mulv,3)
|
||||||
|
#define __negvDI2 __NDW(negv,2)
|
||||||
|
|
||||||
|
#define __ffsSI2 __NW(ffs,2)
|
||||||
|
#define __clzSI2 __NW(clz,2)
|
||||||
|
#define __ctzSI2 __NW(ctz,2)
|
||||||
|
#define __clrsbSI2 __NW(clrsb,2)
|
||||||
|
#define __popcountSI2 __NW(popcount,2)
|
||||||
|
#define __paritySI2 __NW(parity,2)
|
||||||
|
#define __ffsDI2 __NDW(ffs,2)
|
||||||
|
#define __clzDI2 __NDW(clz,2)
|
||||||
|
#define __ctzDI2 __NDW(ctz,2)
|
||||||
|
#define __clrsbDI2 __NDW(clrsb,2)
|
||||||
|
#define __popcountDI2 __NDW(popcount,2)
|
||||||
|
#define __parityDI2 __NDW(parity,2)
|
||||||
|
|
||||||
|
#define __clz_tab __N(clz_tab)
|
||||||
|
#define __bswapsi2 __N(bswapsi2)
|
||||||
|
#define __bswapdi2 __N(bswapdi2)
|
||||||
|
#define __udiv_w_sdiv __N(udiv_w_sdiv)
|
||||||
|
#define __clear_cache __N(clear_cache)
|
||||||
|
#define __enable_execute_stack __N(enable_execute_stack)
|
||||||
|
|
||||||
|
#ifndef __powisf2
|
||||||
|
#define __powisf2 __N(powisf2)
|
||||||
|
#endif
|
||||||
|
#ifndef __powidf2
|
||||||
|
#define __powidf2 __N(powidf2)
|
||||||
|
#endif
|
||||||
|
#ifndef __powitf2
|
||||||
|
#define __powitf2 __N(powitf2)
|
||||||
|
#endif
|
||||||
|
#ifndef __powixf2
|
||||||
|
#define __powixf2 __N(powixf2)
|
||||||
|
#endif
|
||||||
|
#ifndef __mulsc3
|
||||||
|
#define __mulsc3 __N(mulsc3)
|
||||||
|
#endif
|
||||||
|
#ifndef __muldc3
|
||||||
|
#define __muldc3 __N(muldc3)
|
||||||
|
#endif
|
||||||
|
#ifndef __mulxc3
|
||||||
|
#define __mulxc3 __N(mulxc3)
|
||||||
|
#endif
|
||||||
|
#ifndef __multc3
|
||||||
|
#define __multc3 __N(multc3)
|
||||||
|
#endif
|
||||||
|
#ifndef __divsc3
|
||||||
|
#define __divsc3 __N(divsc3)
|
||||||
|
#endif
|
||||||
|
#ifndef __divdc3
|
||||||
|
#define __divdc3 __N(divdc3)
|
||||||
|
#endif
|
||||||
|
#ifndef __divxc3
|
||||||
|
#define __divxc3 __N(divxc3)
|
||||||
|
#endif
|
||||||
|
#ifndef __divtc3
|
||||||
|
#define __divtc3 __N(divtc3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern DWtype __muldi3 (DWtype, DWtype);
|
||||||
|
extern DWtype __divdi3 (DWtype, DWtype);
|
||||||
|
extern UDWtype __udivdi3 (UDWtype, UDWtype);
|
||||||
|
extern UDWtype __umoddi3 (UDWtype, UDWtype);
|
||||||
|
extern DWtype __moddi3 (DWtype, DWtype);
|
||||||
|
extern DWtype __divmoddi4 (DWtype, DWtype, DWtype *);
|
||||||
|
|
||||||
|
/* __udivmoddi4 is static inline when building other libgcc2 portions. */
|
||||||
|
#if (!defined (L_udivdi3) && !defined (L_divdi3) && \
|
||||||
|
!defined (L_umoddi3) && !defined (L_moddi3) && \
|
||||||
|
!defined (L_divmoddi4))
|
||||||
|
extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* __negdi2 is static inline when building other libgcc2 portions. */
|
||||||
|
#if !defined(L_divdi3) && !defined(L_moddi3)
|
||||||
|
extern DWtype __negdi2 (DWtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern DWtype __lshrdi3 (DWtype, shift_count_type);
|
||||||
|
extern DWtype __ashldi3 (DWtype, shift_count_type);
|
||||||
|
extern DWtype __ashrdi3 (DWtype, shift_count_type);
|
||||||
|
|
||||||
|
/* __udiv_w_sdiv is static inline when building other libgcc2 portions. */
|
||||||
|
#if (!defined(L_udivdi3) && !defined(L_divdi3) && \
|
||||||
|
!defined(L_umoddi3) && !defined(L_moddi3))
|
||||||
|
extern UWtype __udiv_w_sdiv (UWtype *, UWtype, UWtype, UWtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern cmp_return_type __cmpdi2 (DWtype, DWtype);
|
||||||
|
extern cmp_return_type __ucmpdi2 (UDWtype, UDWtype);
|
||||||
|
|
||||||
|
#if MIN_UNITS_PER_WORD > 1
|
||||||
|
extern SItype __bswapsi2 (SItype);
|
||||||
|
#endif
|
||||||
|
#if __SIZEOF_LONG_LONG__ > 4
|
||||||
|
extern DItype __bswapdi2 (DItype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern Wtype __absvSI2 (Wtype);
|
||||||
|
extern Wtype __addvSI3 (Wtype, Wtype);
|
||||||
|
extern Wtype __subvSI3 (Wtype, Wtype);
|
||||||
|
extern Wtype __mulvSI3 (Wtype, Wtype);
|
||||||
|
extern Wtype __negvSI2 (Wtype);
|
||||||
|
extern DWtype __absvDI2 (DWtype);
|
||||||
|
extern DWtype __addvDI3 (DWtype, DWtype);
|
||||||
|
extern DWtype __subvDI3 (DWtype, DWtype);
|
||||||
|
extern DWtype __mulvDI3 (DWtype, DWtype);
|
||||||
|
extern DWtype __negvDI2 (DWtype);
|
||||||
|
|
||||||
|
#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
|
||||||
|
#define __absvsi2 __N(absvsi2)
|
||||||
|
#define __negvsi2 __N(negvsi2)
|
||||||
|
#define __addvsi3 __N(addvsi3)
|
||||||
|
#define __subvsi3 __N(subvsi3)
|
||||||
|
#define __mulvsi3 __N(mulvsi3)
|
||||||
|
|
||||||
|
extern SItype __absvsi2 (SItype);
|
||||||
|
extern SItype __addvsi3 (SItype, SItype);
|
||||||
|
extern SItype __subvsi3 (SItype, SItype);
|
||||||
|
extern SItype __mulvsi3 (SItype, SItype);
|
||||||
|
extern SItype __negvsi2 (SItype);
|
||||||
|
#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
|
||||||
|
|
||||||
|
#undef int
|
||||||
|
#if LIBGCC2_HAS_HF_MODE
|
||||||
|
extern HCtype __divhc3 (HFtype, HFtype, HFtype, HFtype);
|
||||||
|
extern HCtype __mulhc3 (HFtype, HFtype, HFtype, HFtype);
|
||||||
|
#endif
|
||||||
|
#if LIBGCC2_HAS_SF_MODE
|
||||||
|
extern DWtype __fixsfdi (SFtype);
|
||||||
|
extern SFtype __floatdisf (DWtype);
|
||||||
|
extern SFtype __floatundisf (UDWtype);
|
||||||
|
extern UWtype __fixunssfSI (SFtype);
|
||||||
|
extern UDWtype __fixunssfDI (SFtype);
|
||||||
|
extern SFtype __powisf2 (SFtype, int);
|
||||||
|
extern SCtype __divsc3 (SFtype, SFtype, SFtype, SFtype);
|
||||||
|
extern SCtype __mulsc3 (SFtype, SFtype, SFtype, SFtype);
|
||||||
|
#endif
|
||||||
|
#if LIBGCC2_HAS_DF_MODE
|
||||||
|
extern DWtype __fixdfdi (DFtype);
|
||||||
|
extern DFtype __floatdidf (DWtype);
|
||||||
|
extern DFtype __floatundidf (UDWtype);
|
||||||
|
extern UWtype __fixunsdfSI (DFtype);
|
||||||
|
extern UDWtype __fixunsdfDI (DFtype);
|
||||||
|
extern DFtype __powidf2 (DFtype, int);
|
||||||
|
extern DCtype __divdc3 (DFtype, DFtype, DFtype, DFtype);
|
||||||
|
extern DCtype __muldc3 (DFtype, DFtype, DFtype, DFtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LIBGCC2_HAS_XF_MODE
|
||||||
|
extern DWtype __fixxfdi (XFtype);
|
||||||
|
extern UDWtype __fixunsxfDI (XFtype);
|
||||||
|
extern XFtype __floatdixf (DWtype);
|
||||||
|
extern XFtype __floatundixf (UDWtype);
|
||||||
|
extern UWtype __fixunsxfSI (XFtype);
|
||||||
|
extern XFtype __powixf2 (XFtype, int);
|
||||||
|
extern XCtype __divxc3 (XFtype, XFtype, XFtype, XFtype);
|
||||||
|
extern XCtype __mulxc3 (XFtype, XFtype, XFtype, XFtype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LIBGCC2_HAS_TF_MODE
|
||||||
|
extern UDWtype __fixunstfDI (TFtype);
|
||||||
|
extern DWtype __fixtfdi (TFtype);
|
||||||
|
extern TFtype __floatditf (DWtype);
|
||||||
|
extern TFtype __floatunditf (UDWtype);
|
||||||
|
extern TFtype __powitf2 (TFtype, int);
|
||||||
|
extern TCtype __divtc3 (TFtype, TFtype, TFtype, TFtype);
|
||||||
|
extern TCtype __multc3 (TFtype, TFtype, TFtype, TFtype);
|
||||||
|
#endif
|
||||||
|
#define int bogus_type
|
||||||
|
|
||||||
|
/* DWstructs are pairs of Wtype values in the order determined by
|
||||||
|
__BYTE_ORDER__. */
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
||||||
|
struct DWstruct {Wtype high, low;};
|
||||||
|
#else
|
||||||
|
struct DWstruct {Wtype low, high;};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* We need this union to unpack/pack DImode values, since we don't have
|
||||||
|
any arithmetic yet. Incoming DImode parameters are stored into the
|
||||||
|
`ll' field, and the unpacked result is read from the struct `s'. */
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct DWstruct s;
|
||||||
|
DWtype ll;
|
||||||
|
} DWunion;
|
||||||
|
|
||||||
|
/* Defined for L_popcount_tab. Exported here because some targets may
|
||||||
|
want to use it for their own versions of the __popcount builtins. */
|
||||||
|
extern const UQItype __popcount_tab[256];
|
||||||
|
|
||||||
|
/* Defined for L_clz. Exported here because some targets may want to use
|
||||||
|
it for their own versions of the __clz builtins. It contains the bit
|
||||||
|
position of the first set bit for the numbers 0 - 255. This avoids the
|
||||||
|
need for a separate table for the __ctz builtins. */
|
||||||
|
extern const UQItype __clz_tab[256];
|
||||||
|
|
||||||
|
#include "longlong.h"
|
||||||
|
|
||||||
|
#undef int
|
||||||
|
extern int __clzDI2 (UDWtype);
|
||||||
|
extern int __clzSI2 (UWtype);
|
||||||
|
extern int __ctzSI2 (UWtype);
|
||||||
|
extern int __ctzDI2 (UDWtype);
|
||||||
|
extern int __clrsbSI2 (Wtype);
|
||||||
|
extern int __clrsbDI2 (DWtype);
|
||||||
|
extern int __ffsSI2 (UWtype);
|
||||||
|
extern int __ffsDI2 (DWtype);
|
||||||
|
extern int __popcountSI2 (UWtype);
|
||||||
|
extern int __popcountDI2 (UDWtype);
|
||||||
|
extern int __paritySI2 (UWtype);
|
||||||
|
extern int __parityDI2 (UDWtype);
|
||||||
|
#define int bogus_type
|
||||||
|
|
||||||
|
extern void __enable_execute_stack (void *);
|
||||||
|
|
||||||
|
#ifndef HIDE_EXPORTS
|
||||||
|
#pragma GCC visibility pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ! GCC_LIBGCC2_H */
|
1774
am/src/riscv/ysyxsoc/libgcc/longlong.h
Normal file
1774
am/src/riscv/ysyxsoc/libgcc/longlong.h
Normal file
File diff suppressed because it is too large
Load diff
48
am/src/riscv/ysyxsoc/libgcc/muldi3.S
Normal file
48
am/src/riscv/ysyxsoc/libgcc/muldi3.S
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/* Integer multiplication routines for RISC-V.
|
||||||
|
|
||||||
|
Copyright (C) 2016-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 3, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "riscv-asm.h"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */
|
||||||
|
# define __muldi3 __mulsi3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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)
|
86
am/src/riscv/ysyxsoc/libgcc/multi3.c
Normal file
86
am/src/riscv/ysyxsoc/libgcc/multi3.c
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/* Multiplication two double word integers for RISC-V.
|
||||||
|
|
||||||
|
Copyright (C) 2016-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 3, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
//#include "tconfig.h"
|
||||||
|
//#include "tsystem.h"
|
||||||
|
//#include "coretypes.h"
|
||||||
|
//#include "tm.h"
|
||||||
|
//#include "libgcc_tm.h"
|
||||||
|
#define LIBGCC2_UNITS_PER_WORD (__riscv_xlen / 8)
|
||||||
|
|
||||||
|
#include "libgcc2.h"
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */
|
||||||
|
# define __multi3 __muldi3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DWtype
|
||||||
|
__multi3 (DWtype u, DWtype v)
|
||||||
|
{
|
||||||
|
const DWunion uu = {.ll = u};
|
||||||
|
const DWunion vv = {.ll = v};
|
||||||
|
DWunion w;
|
||||||
|
UWtype u_low = uu.s.low;
|
||||||
|
UWtype v_low = vv.s.low;
|
||||||
|
UWtype u_low_msb;
|
||||||
|
UWtype w_low = 0;
|
||||||
|
UWtype new_w_low;
|
||||||
|
UWtype w_high = 0;
|
||||||
|
UWtype w_high_tmp = 0;
|
||||||
|
UWtype w_high_tmp2x;
|
||||||
|
UWtype carry;
|
||||||
|
|
||||||
|
/* Calculate low half part of u and v, and get a UDWtype result just like
|
||||||
|
what __umulsidi3 do. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
new_w_low = w_low + u_low;
|
||||||
|
w_high_tmp2x = w_high_tmp << 1;
|
||||||
|
w_high_tmp += w_high;
|
||||||
|
if (v_low & 1)
|
||||||
|
{
|
||||||
|
carry = new_w_low < w_low;
|
||||||
|
w_low = new_w_low;
|
||||||
|
w_high = carry + w_high_tmp;
|
||||||
|
}
|
||||||
|
u_low_msb = (u_low >> ((sizeof (UWtype) * 8) - 1));
|
||||||
|
v_low >>= 1;
|
||||||
|
u_low <<= 1;
|
||||||
|
w_high_tmp = u_low_msb | w_high_tmp2x;
|
||||||
|
}
|
||||||
|
while (v_low);
|
||||||
|
|
||||||
|
w.s.low = w_low;
|
||||||
|
w.s.high = w_high;
|
||||||
|
|
||||||
|
if (uu.s.high)
|
||||||
|
w.s.high = w.s.high + __muluw3(vv.s.low, uu.s.high);
|
||||||
|
|
||||||
|
if (vv.s.high)
|
||||||
|
w.s.high += __muluw3(uu.s.low, vv.s.high);
|
||||||
|
|
||||||
|
return w.ll;
|
||||||
|
}
|
41
am/src/riscv/ysyxsoc/libgcc/riscv-asm.h
Normal file
41
am/src/riscv/ysyxsoc/libgcc/riscv-asm.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* Copyright (C) 2017-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 3, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This file is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#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 CONCAT1(a, b) CONCAT2(a, b)
|
||||||
|
#define CONCAT2(a, b) a ## b
|
||||||
|
#define HIDDEN_JUMPTARGET(X) CONCAT1(__hidden_, X)
|
||||||
|
#define HIDDEN_DEF(X) FUNC_ALIAS(HIDDEN_JUMPTARGET(X), X); \
|
||||||
|
.hidden HIDDEN_JUMPTARGET(X)
|
5
am/src/riscv/ysyxsoc/libgcc/unused.c
Normal file
5
am/src/riscv/ysyxsoc/libgcc/unused.c
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#include <klib-macros.h>
|
||||||
|
#include <am.h>
|
||||||
|
|
||||||
|
double __muldf3 (double a, double b) { panic("Not implement"); }
|
||||||
|
long __fixdfdi (double a) { panic("Not implement"); }
|
17
am/src/riscv/ysyxsoc/mpe.c
Normal file
17
am/src/riscv/ysyxsoc/mpe.c
Normal 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/riscv/ysyxsoc/start.S
Normal file
8
am/src/riscv/ysyxsoc/start.S
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.section entry, "ax"
|
||||||
|
.globl _start
|
||||||
|
.type _start, @function
|
||||||
|
|
||||||
|
_start:
|
||||||
|
mv s0, zero
|
||||||
|
la sp, _stack_pointer
|
||||||
|
jal _trm_init
|
28
am/src/riscv/ysyxsoc/timer.c
Normal file
28
am/src/riscv/ysyxsoc/timer.c
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include "amdev.h"
|
||||||
|
#include "riscv/riscv.h"
|
||||||
|
#include <am.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define RTC_ADDR 0xa0000048
|
||||||
|
static uint64_t up = 0;
|
||||||
|
|
||||||
|
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
|
||||||
|
uint32_t h = inl(RTC_ADDR + 4);
|
||||||
|
uint32_t l = inl(RTC_ADDR);
|
||||||
|
uint64_t time = (uint64_t)h << 32 | l;
|
||||||
|
uptime->us = time - up;
|
||||||
|
}
|
||||||
|
void __am_timer_init() {
|
||||||
|
uint32_t h = inl(RTC_ADDR + 4);
|
||||||
|
uint32_t l = inl(RTC_ADDR);
|
||||||
|
up = (uint64_t)h << 32 | l;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
67
am/src/riscv/ysyxsoc/trap.S
Normal file
67
am/src/riscv/ysyxsoc/trap.S
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#define concat_temp(x, y) x ## y
|
||||||
|
#define concat(x, y) concat_temp(x, y)
|
||||||
|
#define MAP(c, f) c(f)
|
||||||
|
|
||||||
|
#if __riscv_xlen == 32
|
||||||
|
#define LOAD lw
|
||||||
|
#define STORE sw
|
||||||
|
#define XLEN 4
|
||||||
|
#else
|
||||||
|
#define LOAD ld
|
||||||
|
#define STORE sd
|
||||||
|
#define XLEN 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REGS_LO16(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)
|
||||||
|
#ifndef __riscv_e
|
||||||
|
#define REGS_HI16(f) \
|
||||||
|
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 NR_REGS 32
|
||||||
|
#else
|
||||||
|
#define REGS_HI16(f)
|
||||||
|
#define NR_REGS 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REGS(f) REGS_LO16(f) REGS_HI16(f)
|
||||||
|
|
||||||
|
#define PUSH(n) STORE concat(x, n), (n * XLEN)(sp);
|
||||||
|
#define POP(n) LOAD concat(x, n), (n * XLEN)(sp);
|
||||||
|
|
||||||
|
#define CONTEXT_SIZE ((NR_REGS + 3 + 1) * XLEN)
|
||||||
|
#define OFFSET_SP ( 2 * XLEN)
|
||||||
|
#define OFFSET_CAUSE ((NR_REGS + 0) * XLEN)
|
||||||
|
#define OFFSET_STATUS ((NR_REGS + 1) * XLEN)
|
||||||
|
#define OFFSET_EPC ((NR_REGS + 2) * XLEN)
|
||||||
|
|
||||||
|
.align 3
|
||||||
|
.globl __am_asm_trap
|
||||||
|
__am_asm_trap:
|
||||||
|
addi sp, sp, -CONTEXT_SIZE
|
||||||
|
|
||||||
|
MAP(REGS, PUSH)
|
||||||
|
|
||||||
|
csrr t0, mcause
|
||||||
|
csrr t1, mstatus
|
||||||
|
csrr t2, mepc
|
||||||
|
|
||||||
|
STORE t0, OFFSET_CAUSE(sp)
|
||||||
|
STORE t1, OFFSET_STATUS(sp)
|
||||||
|
STORE t2, OFFSET_EPC(sp)
|
||||||
|
|
||||||
|
mv a0, sp
|
||||||
|
jal __am_irq_handle
|
||||||
|
|
||||||
|
mv sp, a0
|
||||||
|
LOAD t1, OFFSET_STATUS(sp)
|
||||||
|
LOAD t2, OFFSET_EPC(sp)
|
||||||
|
csrw mstatus, t1
|
||||||
|
csrw mepc, t2
|
||||||
|
|
||||||
|
MAP(REGS, POP)
|
||||||
|
|
||||||
|
addi sp, sp, CONTEXT_SIZE
|
||||||
|
mret
|
76
am/src/riscv/ysyxsoc/trm.c
Normal file
76
am/src/riscv/ysyxsoc/trm.c
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include "riscv/riscv.h"
|
||||||
|
#include <am.h>
|
||||||
|
#include <klib-macros.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define HEAP_SIZE 0x1000
|
||||||
|
extern char _heap_start;
|
||||||
|
int main(const char *args);
|
||||||
|
|
||||||
|
Area heap = RANGE(&_heap_start, &_heap_start + HEAP_SIZE);
|
||||||
|
#ifndef MAINARGS
|
||||||
|
#define MAINARGS ""
|
||||||
|
#endif
|
||||||
|
static const char mainargs[] = MAINARGS;
|
||||||
|
|
||||||
|
void uart_16550_init(void) {
|
||||||
|
#define UART_BASE 0x10000000U
|
||||||
|
#define UART_TX 0
|
||||||
|
#define UART_DLL 0
|
||||||
|
#define UART_IER 1
|
||||||
|
#define UART_DLM 1
|
||||||
|
#define UART_FCR 2
|
||||||
|
#define UART_LCR 3
|
||||||
|
#define UART_LSR 5
|
||||||
|
//1. set the Line Control Register to the desired line control parameters.
|
||||||
|
//Set bit 7 to '1' to allow access to the Divisor Latches.
|
||||||
|
outb(UART_BASE + UART_LCR, 0b10000111);
|
||||||
|
|
||||||
|
//2. Set the Divisor Latches, MSB first, LSB next. We don't care the value at present.
|
||||||
|
#define BATE_RATE 115200
|
||||||
|
#define CLK_FREQ 3686400
|
||||||
|
uint16_t divisor = CLK_FREQ / ( 16 * BATE_RATE );
|
||||||
|
//uint16_t divisor = 20;
|
||||||
|
|
||||||
|
outb(UART_BASE + UART_DLM, divisor >> 8);
|
||||||
|
outb(UART_BASE + UART_DLL, divisor);
|
||||||
|
|
||||||
|
//3. Set the bit '7' of LCR to '0' to disable access to Divisor Latches.
|
||||||
|
outb(UART_BASE + UART_LCR, 0b00000111);
|
||||||
|
//4. Set the FIFO trigger level.
|
||||||
|
outb(UART_BASE + UART_FCR, 0b11000111);
|
||||||
|
//5. Enable desired interrupts.
|
||||||
|
outb(UART_BASE + UART_IER, 0b00000000);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void putch(char ch) {
|
||||||
|
//Check the status of the send queue before output.
|
||||||
|
while(!(inb(UART_BASE + UART_LSR) & 0b00100000));
|
||||||
|
outb(UART_BASE + UART_TX, ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void halt(int code) {
|
||||||
|
asm volatile("mv a0, %0; ebreak" :: "r"(code));
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_bss(void) {
|
||||||
|
extern char _sbss;
|
||||||
|
extern char _ebss;
|
||||||
|
memset(&_sbss, 0, &_ebss - &_sbss);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char _sdata;
|
||||||
|
extern char _data_size;
|
||||||
|
extern char _data_load_start;
|
||||||
|
|
||||||
|
void _trm_init() {
|
||||||
|
memcpy(&_sdata, &_data_load_start, (size_t)&_data_size);
|
||||||
|
clear_bss();
|
||||||
|
uart_16550_init();
|
||||||
|
int ret = main(mainargs);
|
||||||
|
halt(ret);
|
||||||
|
}
|
18
am/src/riscv/ysyxsoc/vme.c
Normal file
18
am/src/riscv/ysyxsoc/vme.c
Normal 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;
|
||||||
|
}
|
|
@ -64,29 +64,27 @@ static void load_elf32(Elf32_Ehdr *elf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_kernel(void) {
|
void load_kernel(void) {
|
||||||
union {
|
Elf32_Ehdr *elf32 = (void *)0x8000;
|
||||||
Elf32_Ehdr elf32;
|
Elf64_Ehdr *elf64 = (void *)0x8000;
|
||||||
Elf64_Ehdr elf64;
|
|
||||||
} *u = (void *)0x8000;
|
|
||||||
int is_ap = boot_record()->is_ap;
|
int is_ap = boot_record()->is_ap;
|
||||||
|
|
||||||
if (!is_ap) {
|
if (!is_ap) {
|
||||||
// load argument (string) to memory
|
// load argument (string) to memory
|
||||||
copy_from_disk((void *)MAINARG_ADDR, 1024, -1024);
|
copy_from_disk((void *)MAINARG_ADDR, 1024, -1024);
|
||||||
// load elf header to memory
|
// load elf header to memory
|
||||||
copy_from_disk(u, 4096, 0);
|
copy_from_disk(elf32, 4096, 0);
|
||||||
if (u->elf32.e_machine == EM_X86_64) {
|
if (elf32->e_machine == EM_X86_64) {
|
||||||
load_elf64(&u->elf64);
|
load_elf64(elf64);
|
||||||
} else {
|
} else {
|
||||||
load_elf32(&u->elf32);
|
load_elf32(elf32);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// everything should be loaded
|
// everything should be loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u->elf32.e_machine == EM_X86_64) {
|
if (elf32->e_machine == EM_X86_64) {
|
||||||
((void(*)())(uint32_t)(u->elf64.e_entry))();
|
((void(*)())(uint32_t)elf64->e_entry)();
|
||||||
} else {
|
} else {
|
||||||
((void(*)())(uint32_t)(u->elf32.e_entry))();
|
((void(*)())(uint32_t)elf32->e_entry)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#define KLIB_H__
|
#define KLIB_H__
|
||||||
|
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -12,43 +12,45 @@ extern "C" {
|
||||||
//#define __NATIVE_USE_KLIB__
|
//#define __NATIVE_USE_KLIB__
|
||||||
|
|
||||||
// string.h
|
// string.h
|
||||||
void *memset (void *s, int c, size_t n);
|
char *stpcpy(char *dst, const char *src);
|
||||||
void *memcpy (void *dst, const void *src, size_t n);
|
char *stpncpy(char *dst, const char *src, size_t n);
|
||||||
void *memmove (void *dst, const void *src, size_t n);
|
void *memset(void *s, int c, size_t n);
|
||||||
int memcmp (const void *s1, const void *s2, size_t n);
|
void *memcpy(void *dst, const void *src, size_t n);
|
||||||
size_t strlen (const char *s);
|
void *memmove(void *dst, const void *src, size_t n);
|
||||||
char *strcat (char *dst, const char *src);
|
int memcmp(const void *s1, const void *s2, size_t n);
|
||||||
char *strcpy (char *dst, const char *src);
|
size_t strlen(const char *s);
|
||||||
char *strncpy (char *dst, const char *src, size_t n);
|
char *strcat(char *dst, const char *src);
|
||||||
int strcmp (const char *s1, const char *s2);
|
char *strcpy(char *dst, const char *src);
|
||||||
int strncmp (const char *s1, const char *s2, size_t n);
|
char *strncpy(char *dst, const char *src, size_t n);
|
||||||
|
int strcmp(const char *s1, const char *s2);
|
||||||
|
int strncmp(const char *s1, const char *s2, size_t n);
|
||||||
|
|
||||||
// stdlib.h
|
|
||||||
void srand (unsigned int seed);
|
|
||||||
int rand (void);
|
|
||||||
void *malloc (size_t size);
|
|
||||||
void free (void *ptr);
|
|
||||||
int abs (int x);
|
|
||||||
int atoi (const char *nptr);
|
|
||||||
|
|
||||||
|
//stdlib.h
|
||||||
|
void srand(unsigned int seed);
|
||||||
|
int rand(void);
|
||||||
|
void *malloc(size_t size);
|
||||||
|
void free(void *ptr);
|
||||||
|
int abs(int x);
|
||||||
|
int atoi(const char *nptr);
|
||||||
// stdio.h
|
// stdio.h
|
||||||
int printf (const char *format, ...);
|
int printf(const char *format, ...);
|
||||||
int sprintf (char *str, const char *format, ...);
|
int sprintf(char *str, const char *format, ...);
|
||||||
int snprintf (char *str, size_t size, const char *format, ...);
|
int snprintf(char *str, size_t size, const char *format, ...);
|
||||||
int vsprintf (char *str, const char *format, va_list ap);
|
int vsprintf(char *str, const char *format, va_list ap);
|
||||||
int vsnprintf (char *str, size_t size, const char *format, va_list ap);
|
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||||
|
|
||||||
// assert.h
|
// assert.h
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define assert(ignore) ((void)0)
|
#define assert(ignore) ((void)0)
|
||||||
#else
|
#else
|
||||||
#define assert(cond) \
|
#define assert(cond) \
|
||||||
do { \
|
do { \
|
||||||
if (!(cond)) { \
|
if (!(cond)) { \
|
||||||
printf("Assertion fail at %s:%d\n", __FILE__, __LINE__); \
|
printf("Assertion fail at %s:%d\n", __FILE__, __LINE__); \
|
||||||
halt(1); \
|
halt(1); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
124
klib/src/stdio.c
124
klib/src/stdio.c
|
@ -1,28 +1,138 @@
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <klib.h>
|
|
||||||
#include <klib-macros.h>
|
#include <klib-macros.h>
|
||||||
|
#include <klib.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
|
#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
|
||||||
|
|
||||||
|
|
||||||
|
static int int2str(char *p, int v, size_t n) {
|
||||||
|
if (n == 0 || p == NULL)
|
||||||
|
return 0;
|
||||||
|
if (v == 0) {
|
||||||
|
*p = '0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (v == INT_MIN) {
|
||||||
|
return stpncpy(p, "-2147483648", n) - p;
|
||||||
|
}
|
||||||
|
const char *const s = p;
|
||||||
|
int idx = 0;
|
||||||
|
char buf[16] = {0};
|
||||||
|
|
||||||
|
int tmp = abs(v);
|
||||||
|
|
||||||
|
while (tmp != 0) {
|
||||||
|
buf[idx] = tmp % 10 + '0';
|
||||||
|
tmp /= 10;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
if(v < 0 && n > 0) {
|
||||||
|
*p = '-';
|
||||||
|
n--;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
idx--;
|
||||||
|
while (idx >= 0 && n > 0) {
|
||||||
|
*p = buf[idx];
|
||||||
|
p++;
|
||||||
|
idx--;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return p - s;
|
||||||
|
}
|
||||||
int printf(const char *fmt, ...) {
|
int printf(const char *fmt, ...) {
|
||||||
panic("Not implemented");
|
|
||||||
|
char buf[1024] = {0};
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int n = vsnprintf(buf, 1024, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
putch(buf[i]);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vsprintf(char *out, const char *fmt, va_list ap) {
|
int vsprintf(char *out, const char *fmt, va_list ap) {
|
||||||
panic("Not implemented");
|
|
||||||
|
return vsnprintf(out, -1, fmt, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sprintf(char *out, const char *fmt, ...) {
|
int sprintf(char *out, const char *fmt, ...) {
|
||||||
panic("Not implemented");
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int res = vsprintf(out, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snprintf(char *out, size_t n, const char *fmt, ...) {
|
int snprintf(char *out, size_t n, const char *fmt, ...) {
|
||||||
panic("Not implemented");
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int res = vsnprintf(out, n, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vsnprintf(char *out, size_t n, const char *fmt, va_list ap) {
|
int vsnprintf(char *out, size_t n, const char *fmt, va_list ap1) {
|
||||||
panic("Not implemented");
|
|
||||||
|
size_t count = 0;
|
||||||
|
va_list ap;
|
||||||
|
va_copy(ap, ap1);
|
||||||
|
|
||||||
|
while (count < n - 1 && *fmt != '\0') {
|
||||||
|
switch (*fmt) {
|
||||||
|
case '%': {
|
||||||
|
fmt++;
|
||||||
|
if (*fmt == '%') {
|
||||||
|
*out = *fmt;
|
||||||
|
out++;
|
||||||
|
fmt++;
|
||||||
|
count++;
|
||||||
|
} else if (*fmt == 's') {
|
||||||
|
char *p = va_arg(ap, char *);
|
||||||
|
|
||||||
|
while (count < n - 1 && *p) {
|
||||||
|
*out = *p;
|
||||||
|
out++;
|
||||||
|
count++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
|
||||||
|
} else if (*fmt == 'd') {
|
||||||
|
int v = va_arg(ap, int);
|
||||||
|
int int_num = int2str(out, v, n - 1 - count);
|
||||||
|
count += int_num;
|
||||||
|
out += int_num;
|
||||||
|
fmt++;
|
||||||
|
} else if(*fmt == 'c'){
|
||||||
|
char c = (char)va_arg(ap, int);
|
||||||
|
*out = c;
|
||||||
|
out++;
|
||||||
|
count++;
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//panic("not implemented");
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
*out = *fmt;
|
||||||
|
out++;
|
||||||
|
fmt++;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out = '\0';
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
|
#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
|
||||||
static unsigned long int next = 1;
|
static unsigned long int next = 1;
|
||||||
|
#if defined(__ISA_RISCV32__) || defined (__ISA_RISCV32E__) || defined(__ISA_RISCV64__)
|
||||||
|
void *heap_alloc_ptr = NULL;
|
||||||
|
#endif
|
||||||
int rand(void) {
|
int rand(void) {
|
||||||
// RAND_MAX assumed to be 32767
|
// RAND_MAX assumed to be 32767
|
||||||
next = next * 1103515245 + 12345;
|
next = next * 1103515245 + 12345;
|
||||||
|
@ -34,9 +36,19 @@ void *malloc(size_t size) {
|
||||||
// Therefore do not call panic() here, else it will yield a dead recursion:
|
// Therefore do not call panic() here, else it will yield a dead recursion:
|
||||||
// panic() -> putchar() -> (glibc) -> malloc() -> panic()
|
// panic() -> putchar() -> (glibc) -> malloc() -> panic()
|
||||||
#if !(defined(__ISA_NATIVE__) && defined(__NATIVE_USE_KLIB__))
|
#if !(defined(__ISA_NATIVE__) && defined(__NATIVE_USE_KLIB__))
|
||||||
panic("Not implemented");
|
|
||||||
|
#if defined (__ISA_RISCV32__) || defined (__ISA_RISCV32E__)
|
||||||
|
void *p = heap_alloc_ptr;
|
||||||
|
heap_alloc_ptr = (void*)ROUNDUP(heap_alloc_ptr + size, 4);
|
||||||
|
panic_on(!IN_RANGE(heap_alloc_ptr, heap), "Heap overflow");
|
||||||
|
return p;
|
||||||
|
#else
|
||||||
|
panic("not implemented");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(void *ptr) {
|
void free(void *ptr) {
|
||||||
|
|
|
@ -1,47 +1,155 @@
|
||||||
#include <klib.h>
|
|
||||||
#include <klib-macros.h>
|
#include <klib-macros.h>
|
||||||
|
#include <klib.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
|
#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
|
||||||
|
|
||||||
size_t strlen(const char *s) {
|
size_t strlen(const char *s) {
|
||||||
panic("Not implemented");
|
if (s == NULL)
|
||||||
|
return 0;
|
||||||
|
size_t count = 0;
|
||||||
|
while (*s != '\0') {
|
||||||
|
count++;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strcpy(char *dst, const char *src) {
|
char *strcpy(char *dst, const char *src) {
|
||||||
panic("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (src[i] != '\0') {
|
||||||
|
dst[i] = src[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[i] = '\0';
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
char *stpncpy(char *dst, const char *src, size_t n) {
|
||||||
|
|
||||||
|
for (; n != 0 && (*dst = *src); src++, dst++, n--);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
// copied from musl
|
||||||
|
char *stpcpy(char *dst, const char *src) {
|
||||||
|
|
||||||
|
for (; (*dst = *src); src++, dst++)
|
||||||
|
;
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
char *strncpy(char *dst, const char *src, size_t n) {
|
char *strncpy(char *dst, const char *src, size_t n) {
|
||||||
panic("Not implemented");
|
// If the specified size is less than or equal to the source string's length,
|
||||||
|
// strncpy doesn't not append a null terminator to the destination buffer.
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
if (src[i] != '\0')
|
||||||
|
dst[i] = src[i];
|
||||||
|
else {
|
||||||
|
while (i < n) {
|
||||||
|
dst[i] = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strcat(char *dst, const char *src) {
|
char *strcat(char *dst, const char *src) {
|
||||||
panic("Not implemented");
|
|
||||||
|
strcpy(dst + (strlen(dst)), src);
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
int strcmp(const char *s1, const char *s2) {
|
int strcmp(const char *s1, const char *s2) { return strncmp(s1, s2, -1); }
|
||||||
panic("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// refer to musl, more elegant than mine
|
||||||
int strncmp(const char *s1, const char *s2, size_t n) {
|
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||||
panic("Not implemented");
|
|
||||||
|
unsigned char *l = (void *)s1, *r = (void *)s2;
|
||||||
|
if (!n--)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (n && *l && *r && *l == *r) {
|
||||||
|
l++;
|
||||||
|
r++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return *l - *r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memset(void *s, int c, size_t n) {
|
void *memset(void *s, int c, size_t n) {
|
||||||
panic("Not implemented");
|
if (n == 0)
|
||||||
|
return s;
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
*((unsigned char *)s + i) = (unsigned char)c;
|
||||||
|
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memmove(void *dst, const void *src, size_t n) {
|
void *memmove(void *dst, const void *src, size_t n) {
|
||||||
panic("Not implemented");
|
|
||||||
|
if (dst == src)
|
||||||
|
return dst;
|
||||||
|
// A simple way to deal with overlap areas, improve in the future.
|
||||||
|
// Can I use malloc here ? Will buf area and other areas overlap? try to find
|
||||||
|
// a better way.
|
||||||
|
size_t s = (size_t)src;
|
||||||
|
size_t d = (size_t)dst;
|
||||||
|
|
||||||
|
if (s > d && (d + n - 1 >= s)) {
|
||||||
|
size_t overlap_n = d + n - s;
|
||||||
|
memcpy(dst, src, overlap_n);
|
||||||
|
memcpy((void *)(s + overlap_n), (void *)(d + overlap_n), n - overlap_n);
|
||||||
|
} else if (d > s && (s + n - 1 >= d)) {
|
||||||
|
size_t overlap_n = s + n - d;
|
||||||
|
memcpy((void *)(d + n - overlap_n), dst, overlap_n);
|
||||||
|
memcpy(dst, src, n - overlap_n);
|
||||||
|
} else {
|
||||||
|
memcpy(dst, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memcpy(void *out, const void *in, size_t n) {
|
void *memcpy(void *out, const void *in, size_t n) {
|
||||||
panic("Not implemented");
|
// Note that memcpy function require the memory areas do not overlap.
|
||||||
}
|
// Panic directly when the input is invalid to debug. It seems to violate the
|
||||||
|
// manual specifications.
|
||||||
|
if (out == in)
|
||||||
|
return out;
|
||||||
|
size_t dest = (size_t)out;
|
||||||
|
size_t src = (size_t)in;
|
||||||
|
|
||||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
if ((dest > src && src + n - 1 < dest) ||
|
||||||
panic("Not implemented");
|
(src > dest && dest + n - 1 < src)) {
|
||||||
|
while (n != 0) {
|
||||||
|
*(char *)(dest + n - 1) = *(char *)(src + n - 1);
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
const unsigned char *a = s1;
|
||||||
|
const unsigned char *b = s2;
|
||||||
|
while (n != 0) {
|
||||||
|
if (*a == *b) {
|
||||||
|
a++;
|
||||||
|
b++;
|
||||||
|
n--;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return *a - *b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
CROSS_COMPILE := riscv64-linux-gnu-
|
CROSS_COMPILE := riscv64-linux-gnu-
|
||||||
COMMON_CFLAGS := -fno-pic -march=rv64g -mcmodel=medany -mstrict-align
|
COMMON_CFLAGS := -fno-pic -march=rv64g -mcmodel=medany -mstrict-align
|
||||||
CFLAGS += $(COMMON_CFLAGS) -static
|
CFLAGS += $(COMMON_CFLAGS) -static
|
||||||
ASFLAGS += $(COMMON_CFLAGS) -O0
|
ASFLAGS += $(COMMON_CFLAGS) -O0
|
||||||
LDFLAGS += -melf64lriscv
|
LDFLAGS += -melf64lriscv -O2
|
||||||
|
|
||||||
# overwrite ARCH_H defined in $(AM_HOME)/Makefile
|
# overwrite ARCH_H defined in $(AM_HOME)/Makefile
|
||||||
ARCH_H := arch/riscv.h
|
ARCH_H := arch/riscv.h
|
||||||
|
|
7
scripts/isa/riscv64.mk
Normal file
7
scripts/isa/riscv64.mk
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is from nutshell's am
|
||||||
|
CROSS_COMPILE := riscv64-unknown-linux-gnu-
|
||||||
|
COMMON_FLAGS := -fno-pic -march=rv64g -mcmodel=medany
|
||||||
|
CFLAGS += $(COMMON_FLAGS) -static
|
||||||
|
ASFLAGS += $(COMMON_FLAGS) -O0
|
||||||
|
LDFLAGS += -melf64lriscv
|
||||||
|
ARCH_H := arch/riscv.h
|
|
@ -1,6 +1,5 @@
|
||||||
export CROSS_COMPILE := x86_64-linux-gnu-
|
export CROSS_COMPILE := x86_64-linux-gnu-
|
||||||
CFLAGS += -m32 -fno-pic -fno-omit-frame-pointer -march=i386
|
CFLAGS += -m32 -fno-pic -fno-omit-frame-pointer -march=i386
|
||||||
CFLAGS += -fcf-protection=none # remove endbr32 in Ubuntu 20.04 with a CPU newer than Comet Lake
|
CFLAGS += -fcf-protection=none # remove endbr32 in Ubuntu 20.04 with a CPU newer than Comet Lake
|
||||||
CFLAGS += --param=min-pagesize=0 # fix warning about "array subscript 0 is outside array bounds"
|
|
||||||
ASFLAGS += -m32 -fno-pic
|
ASFLAGS += -m32 -fno-pic
|
||||||
LDFLAGS += -melf_i386
|
LDFLAGS += -melf_i386
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
export CROSS_COMPILE := x86_64-linux-gnu-
|
export CROSS_COMPILE := x86_64-linux-gnu-
|
||||||
CFLAGS += -m64 -fPIC -mno-sse
|
CFLAGS += -m64 -fPIC -mno-sse
|
||||||
CFLAGS += --param=min-pagesize=0 # fix warning about "array subscript 0 is outside array bounds"
|
|
||||||
ASFLAGS += -m64 -fPIC
|
ASFLAGS += -m64 -fPIC
|
||||||
LDFLAGS += -melf_x86_64
|
LDFLAGS += -melf_x86_64
|
||||||
|
|
41
scripts/linker-soc.ld
Normal file
41
scripts/linker-soc.ld
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
ENTRY(_start)
|
||||||
|
MEMORY {
|
||||||
|
mrom : ORIGIN = 0x20000000, LENGTH = 4K
|
||||||
|
sram : ORIGIN = 0x0f000000, LENGTH = 8K
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.text : {
|
||||||
|
_stext = .;
|
||||||
|
*(entry);
|
||||||
|
*(.text*);
|
||||||
|
_etext = .;
|
||||||
|
} > mrom AT> mrom
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
_srodata = .;
|
||||||
|
*(.rodata*);
|
||||||
|
*(.srodata*);
|
||||||
|
_erodata = .;
|
||||||
|
} > mrom AT> mrom
|
||||||
|
.data : {
|
||||||
|
_sdata = .;
|
||||||
|
*(.data*);
|
||||||
|
*(.sdata*);
|
||||||
|
_edata = .; /* Note that this is VMA */
|
||||||
|
} > sram AT> mrom
|
||||||
|
_data_size = SIZEOF(.data);
|
||||||
|
_data_load_start = LOADADDR(.data);
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
_sbss = .;
|
||||||
|
*(.bss*);
|
||||||
|
*(.sbss*);
|
||||||
|
*(.scommon);
|
||||||
|
_ebss = .;
|
||||||
|
} > sram
|
||||||
|
_end = .;
|
||||||
|
_heap_start = ALIGN(0x1000);
|
||||||
|
_stack_pointer = _sram_start + _sram_limit;
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ SECTIONS {
|
||||||
*(.scommon)
|
*(.scommon)
|
||||||
}
|
}
|
||||||
_stack_top = ALIGN(0x1000);
|
_stack_top = ALIGN(0x1000);
|
||||||
. = _stack_top + 0x8000;
|
. = _stack_top + 0x10000;
|
||||||
_stack_pointer = .;
|
_stack_pointer = .;
|
||||||
end = .;
|
end = .;
|
||||||
_end = .;
|
_end = .;
|
||||||
|
|
|
@ -12,13 +12,16 @@ AM_SRCS := native/trm.c \
|
||||||
native/ioe/audio.c \
|
native/ioe/audio.c \
|
||||||
native/ioe/disk.c \
|
native/ioe/disk.c \
|
||||||
|
|
||||||
CFLAGS += -fpie $(shell sdl2-config --cflags)
|
CFLAGS += -fpie
|
||||||
ASFLAGS += -fpie -pie
|
|
||||||
comma = ,
|
comma = ,
|
||||||
LDFLAGS_CXX = $(addprefix -Wl$(comma), $(LDFLAGS)) -pie -ldl $(shell sdl2-config --libs)
|
LDFLAGS_CXX = $(addprefix -Wl$(comma), $(LDFLAGS))
|
||||||
|
|
||||||
|
image:
|
||||||
|
@echo + LD "->" $(IMAGE_REL)
|
||||||
|
@g++ -pie -o $(IMAGE) -Wl,--whole-archive $(LINKAGE) -Wl,-no-whole-archive $(LDFLAGS_CXX) -lSDL2 -ldl
|
||||||
|
|
||||||
run: image
|
run: image
|
||||||
$(IMAGE).elf
|
$(IMAGE)
|
||||||
|
|
||||||
gdb: image
|
gdb: image
|
||||||
gdb -ex "handle SIGUSR1 SIGUSR2 SIGSEGV noprint nostop" $(IMAGE).elf
|
gdb -ex "handle SIGUSR1 SIGUSR2 SIGSEGV noprint nostop" $(IMAGE)
|
||||||
|
|
|
@ -8,28 +8,23 @@ AM_SRCS := platform/nemu/trm.c \
|
||||||
platform/nemu/mpe.c
|
platform/nemu/mpe.c
|
||||||
|
|
||||||
CFLAGS += -fdata-sections -ffunction-sections
|
CFLAGS += -fdata-sections -ffunction-sections
|
||||||
CFLAGS += -I$(AM_HOME)/am/src/platform/nemu/include
|
LDFLAGS += -T $(AM_HOME)/scripts/linker.ld \
|
||||||
LDSCRIPTS += $(AM_HOME)/scripts/linker.ld
|
--defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
|
||||||
LDFLAGS += --defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
|
|
||||||
LDFLAGS += --gc-sections -e _start
|
LDFLAGS += --gc-sections -e _start
|
||||||
NEMUFLAGS += -l $(shell dirname $(IMAGE).elf)/nemu-log.txt
|
NEMUFLAGS += -b
|
||||||
|
#-l $(shell dirname $(IMAGE).elf)/nemu-log.txt
|
||||||
|
|
||||||
MAINARGS_MAX_LEN = 64
|
CFLAGS += -DMAINARGS=\"$(mainargs)\"
|
||||||
MAINARGS_PLACEHOLDER = The insert-arg rule in Makefile will insert mainargs here.
|
CFLAGS += -I$(AM_HOME)/am/src/platform/nemu/include
|
||||||
CFLAGS += -DMAINARGS_MAX_LEN=$(MAINARGS_MAX_LEN) -DMAINARGS_PLACEHOLDER=\""$(MAINARGS_PLACEHOLDER)"\"
|
.PHONY: $(AM_HOME)/am/src/platform/nemu/trm.c
|
||||||
|
|
||||||
insert-arg: image
|
image: $(IMAGE).elf
|
||||||
@python $(AM_HOME)/tools/insert-arg.py $(IMAGE).bin $(MAINARGS_MAX_LEN) "$(MAINARGS_PLACEHOLDER)" "$(mainargs)"
|
|
||||||
|
|
||||||
image: image-dep
|
|
||||||
@$(OBJDUMP) -d $(IMAGE).elf > $(IMAGE).txt
|
@$(OBJDUMP) -d $(IMAGE).elf > $(IMAGE).txt
|
||||||
@echo + OBJCOPY "->" $(IMAGE_REL).bin
|
@echo + OBJCOPY "->" $(IMAGE_REL).bin
|
||||||
@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin
|
@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin
|
||||||
|
|
||||||
run: insert-arg
|
run: image
|
||||||
$(MAKE) -C $(NEMU_HOME) ISA=$(ISA) run ARGS="$(NEMUFLAGS)" IMG=$(IMAGE).bin
|
$(MAKE) -C $(NEMU_HOME) ISA=$(ISA) run ARGS="$(NEMUFLAGS)" IMG=$(IMAGE).bin
|
||||||
|
|
||||||
gdb: insert-arg
|
gdb: image
|
||||||
$(MAKE) -C $(NEMU_HOME) ISA=$(ISA) gdb ARGS="$(NEMUFLAGS)" IMG=$(IMAGE).bin
|
$(MAKE) -C $(NEMU_HOME) ISA=$(ISA) gdb ARGS="$(NEMUFLAGS)" IMG=$(IMAGE).bin
|
||||||
|
|
||||||
.PHONY: insert-arg
|
|
||||||
|
|
|
@ -9,23 +9,22 @@ AM_SRCS := riscv/npc/start.S \
|
||||||
platform/dummy/mpe.c
|
platform/dummy/mpe.c
|
||||||
|
|
||||||
CFLAGS += -fdata-sections -ffunction-sections
|
CFLAGS += -fdata-sections -ffunction-sections
|
||||||
LDSCRIPTS += $(AM_HOME)/scripts/linker.ld
|
LDFLAGS += -T $(AM_HOME)/scripts/linker.ld \
|
||||||
LDFLAGS += --defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
|
--defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
|
||||||
LDFLAGS += --gc-sections -e _start
|
LDFLAGS += --gc-sections -e _start
|
||||||
|
CFLAGS += -DMAINARGS=\"$(mainargs)\"
|
||||||
|
.PHONY: $(AM_HOME)/am/src/riscv/npc/trm.c
|
||||||
|
|
||||||
MAINARGS_MAX_LEN = 64
|
image: $(IMAGE).elf
|
||||||
MAINARGS_PLACEHOLDER = The insert-arg rule in Makefile will insert mainargs here.
|
|
||||||
CFLAGS += -DMAINARGS_MAX_LEN=$(MAINARGS_MAX_LEN) -DMAINARGS_PLACEHOLDER=\""$(MAINARGS_PLACEHOLDER)"\"
|
|
||||||
|
|
||||||
insert-arg: image
|
|
||||||
@python $(AM_HOME)/tools/insert-arg.py $(IMAGE).bin $(MAINARGS_MAX_LEN) "$(MAINARGS_PLACEHOLDER)" "$(mainargs)"
|
|
||||||
|
|
||||||
image: image-dep
|
|
||||||
@$(OBJDUMP) -d $(IMAGE).elf > $(IMAGE).txt
|
@$(OBJDUMP) -d $(IMAGE).elf > $(IMAGE).txt
|
||||||
@echo + OBJCOPY "->" $(IMAGE_REL).bin
|
@echo + OBJCOPY "->" $(IMAGE_REL).bin
|
||||||
@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin
|
@$(OBJCOPY) -S --set-section-flags .bss=alloc,contents -O binary $(IMAGE).elf $(IMAGE).bin
|
||||||
|
|
||||||
run: insert-arg
|
ref= $(NEMU_HOME)/build/riscv32-nemu-interpreter-so
|
||||||
echo "TODO: add command here to run simulation"
|
|
||||||
|
|
||||||
.PHONY: insert-arg
|
run: image
|
||||||
|
make -f $(NPC_HOME)/scripts/sim.mk all
|
||||||
|
$(NPC_HOME)/build/npc $(IMAGE).bin $(ref)
|
||||||
|
gdb: image
|
||||||
|
make -f $(NPC_HOME)/scripts/sim.mk all
|
||||||
|
gdb --args $(NPC_HOME)/build/npc $(IMAGE).bin
|
||||||
|
|
|
@ -11,7 +11,7 @@ build-arg: image
|
||||||
|
|
||||||
BOOT_HOME := $(AM_HOME)/am/src/x86/qemu/boot
|
BOOT_HOME := $(AM_HOME)/am/src/x86/qemu/boot
|
||||||
|
|
||||||
image: image-dep
|
image: $(IMAGE).elf
|
||||||
@$(MAKE) -s -C $(BOOT_HOME)
|
@$(MAKE) -s -C $(BOOT_HOME)
|
||||||
@echo + CREATE "->" $(IMAGE_REL)
|
@echo + CREATE "->" $(IMAGE_REL)
|
||||||
@( cat $(BOOT_HOME)/bootblock.o; head -c 1024 /dev/zero; cat $(IMAGE).elf ) > $(IMAGE)
|
@( cat $(BOOT_HOME)/bootblock.o; head -c 1024 /dev/zero; cat $(IMAGE).elf ) > $(IMAGE)
|
||||||
|
|
31
scripts/platform/ysyxsoc.mk
Normal file
31
scripts/platform/ysyxsoc.mk
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
AM_SRCS := riscv/ysyxsoc/start.S \
|
||||||
|
riscv/ysyxsoc/trm.c \
|
||||||
|
riscv/ysyxsoc/ioe.c \
|
||||||
|
riscv/ysyxsoc/timer.c \
|
||||||
|
riscv/ysyxsoc/input.c \
|
||||||
|
riscv/ysyxsoc/cte.c \
|
||||||
|
riscv/ysyxsoc/trap.S \
|
||||||
|
platform/dummy/vme.c \
|
||||||
|
platform/dummy/mpe.c
|
||||||
|
|
||||||
|
CFLAGS += -fdata-sections -ffunction-sections
|
||||||
|
LDFLAGS += -T $(AM_HOME)/scripts/linker-soc.ld \
|
||||||
|
--defsym=_mrom_start=0x20000000 --defsym=_sram_start=0x0f000000 \
|
||||||
|
--defsym=_entry_offset=0x0 --defsym=_sram_limit=0x2000 #-M
|
||||||
|
LDFLAGS += --gc-sections -e _start
|
||||||
|
CFLAGS += -DMAINARGS=\"$(mainargs)\"
|
||||||
|
.PHONY: $(AM_HOME)/am/src/riscv/ysyxsoc/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
|
||||||
|
|
||||||
|
ref= $(NEMU_HOME)/riscv32-nemu-interpreter-so
|
||||||
|
|
||||||
|
run: image
|
||||||
|
make -f $(NPC_HOME)/scripts/sim.mk all
|
||||||
|
$(NPC_HOME)/build/ysyxSoCFull $(IMAGE).bin $(ref)
|
||||||
|
gdb: image
|
||||||
|
make -f $(NPC_HOME)/scripts/sim.mk all
|
||||||
|
gdb --args $(NPC_HOME)/build/npc $(IMAGE).bin
|
|
@ -1,8 +1,8 @@
|
||||||
include $(AM_HOME)/scripts/isa/riscv.mk
|
include $(AM_HOME)/scripts/isa/riscv.mk
|
||||||
include $(AM_HOME)/scripts/platform/nemu.mk
|
include $(AM_HOME)/scripts/platform/nemu.mk
|
||||||
CFLAGS += -DISA_H=\"riscv/riscv.h\"
|
CFLAGS += -DISA_H=\"riscv/riscv.h\"
|
||||||
COMMON_CFLAGS += -march=rv32im_zicsr -mabi=ilp32 # overwrite
|
COMMON_CFLAGS += -march=rv32im_zicsr -mabi=ilp32 # overwrite
|
||||||
LDFLAGS += -melf32lriscv # overwrite
|
LDFLAGS += -melf32lriscv # overwrite
|
||||||
|
|
||||||
AM_SRCS += riscv/nemu/start.S \
|
AM_SRCS += riscv/nemu/start.S \
|
||||||
riscv/nemu/cte.c \
|
riscv/nemu/cte.c \
|
||||||
|
|
10
scripts/riscv32e-ysyxsoc.mk
Normal file
10
scripts/riscv32e-ysyxsoc.mk
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
include $(AM_HOME)/scripts/isa/riscv.mk
|
||||||
|
include $(AM_HOME)/scripts/platform/ysyxsoc.mk
|
||||||
|
COMMON_CFLAGS += -march=rv32e_zicsr -mabi=ilp32e # overwrite
|
||||||
|
LDFLAGS += -melf32lriscv # overwrite
|
||||||
|
|
||||||
|
AM_SRCS += riscv/ysyxsoc/libgcc/div.S \
|
||||||
|
riscv/ysyxsoc/libgcc/muldi3.S \
|
||||||
|
riscv/ysyxsoc/libgcc/multi3.c \
|
||||||
|
riscv/ysyxsoc/libgcc/ashldi3.c \
|
||||||
|
riscv/ysyxsoc/libgcc/unused.c
|
35
scripts/riscv64-nutshell.mk
Normal file
35
scripts/riscv64-nutshell.mk
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
include $(AM_HOME)/scripts/isa/riscv.mk
|
||||||
|
|
||||||
|
AM_SRCS := riscv/nutshell/isa/riscv/boot/start.S \
|
||||||
|
riscv/nutshell/common/mainargs.S \
|
||||||
|
riscv/nutshell/isa/riscv/trm.c \
|
||||||
|
riscv/nutshell/common/uartlite.c \
|
||||||
|
riscv/nutshell/common/ioe.c \
|
||||||
|
riscv/nutshell/common/timer.c \
|
||||||
|
platform/dummy/input.c \
|
||||||
|
platform/dummy/video.c \
|
||||||
|
platform/dummy/audio.c \
|
||||||
|
platform/dummy/cte.c \
|
||||||
|
platform/dummy/vme.c \
|
||||||
|
platform/dummy/mpe.c \
|
||||||
|
|
||||||
|
COMMON_CFLAGS += -march=rv64im_zicsr -mabi=lp64 # overwrite
|
||||||
|
LDFLAGS += -melf64lriscv # overwrite
|
||||||
|
|
||||||
|
CFLAGS += -I$(AM_HOME)/am/src/riscv/nutshell/include -DISA_H=\"riscv.h\"
|
||||||
|
ASFLAGS += -DMAINARGS=\"$(mainargs)\" # for mainargs.S, modify in the future
|
||||||
|
CFLAGS += -DMAINARGS=\"$(mainargs)\" # for trm.c
|
||||||
|
.PHONY: $(AM_HOME)/am/src/riscv/nutshell/common/mainargs.S
|
||||||
|
|
||||||
|
LDFLAGS += -L $(AM_HOME)/am/src/riscv/nutshell/ldscript
|
||||||
|
LDFLAGS += -T $(AM_HOME)/am/src/riscv/nutshell/isa/riscv/boot/loader64.ld
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
run: image
|
||||||
|
$(NUTSHELL_HOME)/build/emu --no-diff -i $(abspath $(IMAGE).bin)
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ AM_SRCS := riscv/spike/trm.c \
|
||||||
platform/dummy/mpe.c \
|
platform/dummy/mpe.c \
|
||||||
|
|
||||||
CFLAGS += -fdata-sections -ffunction-sections
|
CFLAGS += -fdata-sections -ffunction-sections
|
||||||
LDSCRIPTS += $(AM_HOME)/am/src/riscv/spike/linker.ld
|
LDFLAGS += -T $(AM_HOME)/am/src/riscv/spike/linker.ld
|
||||||
LDFLAGS += --gc-sections -e _start
|
LDFLAGS += --gc-sections -e _start
|
||||||
|
|
||||||
CFLAGS += -DMAINARGS=\"$(mainargs)\"
|
CFLAGS += -DMAINARGS=\"$(mainargs)\"
|
||||||
.PHONY: $(AM_HOME)/am/src/riscv/spike/trm.c
|
.PHONY: $(AM_HOME)/am/src/riscv/spike/trm.c
|
||||||
|
|
||||||
image: image-dep
|
image: $(IMAGE).elf
|
||||||
|
|
Loading…
Add table
Reference in a new issue