feat: make compatible with openperf
This commit is contained in:
parent
a7b830fedd
commit
5fee5aad38
79 changed files with 3943 additions and 274 deletions
|
@ -2,6 +2,7 @@
|
|||
#define __AMDEV_H__
|
||||
|
||||
// **MAY SUBJECT TO CHANGE IN THE FUTURE**
|
||||
#include <am.h>
|
||||
|
||||
#define AM_DEVREG(id, reg, perm, ...) \
|
||||
enum { AM_##reg = (id) }; \
|
||||
|
|
|
@ -11,34 +11,15 @@ struct Context {
|
|||
uintptr_t ksp;
|
||||
void *vm_head;
|
||||
ucontext_t uc;
|
||||
#ifdef __x86_64__
|
||||
// skip the red zone of the stack frame, see the amd64 ABI manual for details
|
||||
uint8_t redzone[128];
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define GPR1 uc.uc_mcontext.gregs[REG_RDI]
|
||||
#define GPR2 uc.uc_mcontext.gregs[REG_RSI]
|
||||
#define GPR3 uc.uc_mcontext.gregs[REG_RDX]
|
||||
#define GPR4 uc.uc_mcontext.gregs[REG_RCX]
|
||||
#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
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef ARCH_H__
|
||||
#define ARCH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef __riscv_e
|
||||
#define NR_REGS 16
|
||||
#else
|
||||
|
@ -8,9 +9,12 @@
|
|||
#endif
|
||||
|
||||
struct Context {
|
||||
// TODO: fix the order of these members to match trap.S
|
||||
uintptr_t mepc, mcause, gpr[NR_REGS], mstatus;
|
||||
void *pdir;
|
||||
//The order of these members should match trap.S, pay attention to pdir.
|
||||
uintptr_t gpr[NR_REGS];
|
||||
uintptr_t mcause;
|
||||
uintptr_t mstatus;
|
||||
uintptr_t mepc;
|
||||
void *pdir;
|
||||
};
|
||||
|
||||
#ifdef __riscv_e
|
||||
|
@ -19,9 +23,9 @@ struct Context {
|
|||
#define GPR1 gpr[17] // a7
|
||||
#endif
|
||||
|
||||
#define GPR2 gpr[0]
|
||||
#define GPR3 gpr[0]
|
||||
#define GPR4 gpr[0]
|
||||
#define GPRx gpr[0]
|
||||
#define GPR2 gpr[10] //a0
|
||||
#define GPR3 gpr[11] //a1
|
||||
#define GPR4 gpr[12] //a2
|
||||
#define GPRx gpr[10] //a0, return value
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,7 @@ Context* __am_irq_handle(Context *c) {
|
|||
if (user_handler) {
|
||||
Event ev = {0};
|
||||
uintptr_t ecode = 0;
|
||||
switch (ecode) {
|
||||
switch (ccode) {
|
||||
default: ev.event = EVENT_ERROR; break;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,9 @@ static void irq_handle(Context *c) {
|
|||
c->ksp = thiscpu->ksp;
|
||||
|
||||
if (thiscpu->ev.event == EVENT_ERROR) {
|
||||
printf("Unhandle signal '%s' at pc = %p, badaddr = %p, cause = 0x%x\n",
|
||||
thiscpu->ev.msg, AM_REG_PC(&c->uc), thiscpu->ev.ref, thiscpu->ev.cause);
|
||||
uintptr_t rip = c->uc.uc_mcontext.gregs[REG_RIP];
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
void *pc = (void *)AM_REG_PC(uc);
|
||||
void *rip = (void *)uc->uc_mcontext.gregs[REG_RIP];
|
||||
extern uint8_t _start, _etext;
|
||||
int trap_from_user = __am_in_userspace(pc);
|
||||
int signal_safe = IN_RANGE(pc, RANGE(&_start, &_etext)) || trap_from_user ||
|
||||
int trap_from_user = __am_in_userspace(rip);
|
||||
int signal_safe = IN_RANGE(rip, RANGE(&_start, &_etext)) || trap_from_user ||
|
||||
// Hack here: "+13" points to the instruction after syscall. This is the
|
||||
// instruction which will trigger the pending signal if interrupt is enabled.
|
||||
// FIXME: should change 13 for aarch and riscv
|
||||
(pc == (void *)&sigprocmask + 13);
|
||||
(rip == (void *)&sigprocmask + 13);
|
||||
|
||||
if (((event == EVENT_IRQ_IODEV) || (event == EVENT_IRQ_TIMER)) && !signal_safe) {
|
||||
// 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();
|
||||
|
||||
// skip the instructions causing SIGSEGV for syscall
|
||||
if (event == EVENT_SYSCALL) { pc += SYSCALL_INSTR_LEN; }
|
||||
AM_REG_PC(uc) = (uintptr_t)pc;
|
||||
if (event == EVENT_SYSCALL) { rip += SYSCALL_INSTR_LEN; }
|
||||
uc->uc_mcontext.gregs[REG_RIP] = (uintptr_t)rip;
|
||||
|
||||
// switch to kernel stack if we were previously in user space
|
||||
uintptr_t sp = trap_from_user ? thiscpu->ksp : AM_REG_SP(uc);
|
||||
sp -= sizeof(Context);
|
||||
#ifdef __x86_64__
|
||||
// keep (sp + 8) % 16 == 0 to support SSE
|
||||
if ((sp + 8) % 16 != 0) sp -= 8;
|
||||
#endif
|
||||
Context *c = (void *)sp;
|
||||
uintptr_t rsp = trap_from_user ? thiscpu->ksp : uc->uc_mcontext.gregs[REG_RSP];
|
||||
rsp -= sizeof(Context);
|
||||
// keep (rsp + 8) % 16 == 0 to support SSE
|
||||
if ((rsp + 8) % 16 != 0) rsp -= 8;
|
||||
Context *c = (void *)rsp;
|
||||
|
||||
// save the context on the stack
|
||||
c->uc = *uc;
|
||||
|
@ -78,17 +76,17 @@ static void setup_stack(uintptr_t event, ucontext_t *uc) {
|
|||
__am_get_intr_sigmask(&uc->uc_sigmask);
|
||||
|
||||
// call irq_handle after returning from the signal handler
|
||||
AM_REG_GPR1(uc) = (uintptr_t)c;
|
||||
AM_REG_PC(uc) = (uintptr_t)irq_handle;
|
||||
AM_REG_SP(uc) = (uintptr_t)c;
|
||||
uc->uc_mcontext.gregs[REG_RDI] = (uintptr_t)c;
|
||||
uc->uc_mcontext.gregs[REG_RIP] = (uintptr_t)irq_handle;
|
||||
uc->uc_mcontext.gregs[REG_RSP] = (uintptr_t)c;
|
||||
}
|
||||
|
||||
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
|
||||
*uc = c->uc;
|
||||
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) {
|
||||
|
@ -169,8 +167,8 @@ Context* kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
|||
Context *c = (Context*)kstack.end - 1;
|
||||
|
||||
__am_get_example_uc(c);
|
||||
AM_REG_PC(&c->uc) = (uintptr_t)__am_kcontext_start;
|
||||
AM_REG_SP(&c->uc) = (uintptr_t)kstack.end;
|
||||
c->uc.uc_mcontext.gregs[REG_RIP] = (uintptr_t)__am_kcontext_start;
|
||||
c->uc.uc_mcontext.gregs[REG_RSP] = (uintptr_t)kstack.end;
|
||||
|
||||
int ret = sigemptyset(&(c->uc.uc_sigmask)); // enable interrupt
|
||||
assert(ret == 0);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <klib.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
static int rfd = -1, wfd = -1;
|
||||
static volatile int count = 0;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#include <am.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <fenv.h>
|
||||
|
||||
//#define MODE_800x600
|
||||
#define WINDOW_W 800
|
||||
#define WINDOW_H 600
|
||||
#ifdef MODE_800x600
|
||||
const int disp_w = WINDOW_W, disp_h = WINDOW_H;
|
||||
# define W 800
|
||||
# define H 600
|
||||
#else
|
||||
const int disp_w = 400, disp_h = 300;
|
||||
# define W 400
|
||||
# define H 300
|
||||
#endif
|
||||
|
||||
#define FPS 60
|
||||
|
@ -31,8 +31,13 @@ void __am_gpu_init() {
|
|||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||
window = SDL_CreateWindow("Native Application",
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
WINDOW_W, WINDOW_H, SDL_WINDOW_OPENGL);
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, disp_w, disp_h, 32,
|
||||
#ifdef MODE_800x600
|
||||
W, H,
|
||||
#else
|
||||
W * 2, H * 2,
|
||||
#endif
|
||||
SDL_WINDOW_OPENGL);
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32,
|
||||
RMASK, GMASK, BMASK, AMASK);
|
||||
SDL_AddTimer(1000 / FPS, texture_sync, NULL);
|
||||
}
|
||||
|
@ -40,7 +45,7 @@ void __am_gpu_init() {
|
|||
void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
|
||||
*cfg = (AM_GPU_CONFIG_T) {
|
||||
.present = true, .has_accel = false,
|
||||
.width = disp_w, .height = disp_h,
|
||||
.width = W, .height = H,
|
||||
.vmemsz = 0
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <am.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#define KEYDOWN_MASK 0x8000
|
||||
|
||||
|
|
|
@ -150,9 +150,7 @@ static void init_platform() {
|
|||
|
||||
// save the context template
|
||||
save_example_context();
|
||||
#ifdef __x86_64__
|
||||
uc_example.uc_mcontext.fpregs = NULL; // clear the FPU context
|
||||
#endif
|
||||
__am_get_intr_sigmask(&uc_example.uc_sigmask);
|
||||
|
||||
// disable interrupts by default
|
||||
|
|
|
@ -7,22 +7,6 @@
|
|||
#include <klib.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_intr_sigmask(sigset_t *s);
|
||||
int __am_is_sigmask_sti(sigset_t *s);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
.global __am_kcontext_start
|
||||
__am_kcontext_start:
|
||||
#ifdef __x86_64__
|
||||
// rdi = arg, rsi = entry
|
||||
|
||||
// (rsp + 8) should be multiple of 16 when
|
||||
|
@ -9,21 +8,3 @@ __am_kcontext_start:
|
|||
andq $0xfffffffffffffff0, %rsp
|
||||
call *%rsi
|
||||
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;
|
||||
|
||||
__am_get_example_uc(c);
|
||||
AM_REG_PC(&c->uc) = (uintptr_t)entry;
|
||||
AM_REG_SP(&c->uc) = (uintptr_t)USER_SPACE.end;
|
||||
c->uc.uc_mcontext.gregs[REG_RIP] = (uintptr_t)entry;
|
||||
c->uc.uc_mcontext.gregs[REG_RSP] = (uintptr_t)USER_SPACE.end;
|
||||
|
||||
int ret = sigemptyset(&(c->uc.uc_sigmask)); // enable interrupt
|
||||
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 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))
|
||||
#elif defined(__ISA_LOONGARCH32R__)
|
||||
# define nemu_trap(code) asm volatile("move $a0, %0; break 0" : :"r"(code))
|
||||
#else
|
||||
#elif
|
||||
# error unsupported ISA __ISA__
|
||||
#endif
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
|||
|
||||
#define MMIO_BASE 0xa0000000
|
||||
|
||||
|
||||
#define SERIAL_PORT (DEVICE_BASE + 0x00003f8)
|
||||
#define KBD_ADDR (DEVICE_BASE + 0x0000060)
|
||||
#define RTC_ADDR (DEVICE_BASE + 0x0000048)
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include "amdev.h"
|
||||
#include "riscv/riscv.h"
|
||||
#include <am.h>
|
||||
#include <nemu.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define AUDIO_FREQ_ADDR (AUDIO_ADDR + 0x00)
|
||||
#define AUDIO_CHANNELS_ADDR (AUDIO_ADDR + 0x04)
|
||||
|
@ -8,19 +12,40 @@
|
|||
#define AUDIO_INIT_ADDR (AUDIO_ADDR + 0x10)
|
||||
#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) {
|
||||
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) {
|
||||
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) {
|
||||
stat->count = 0;
|
||||
stat->count = inl(AUDIO_COUNT_ADDR);
|
||||
}
|
||||
|
||||
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 <nemu.h>
|
||||
|
||||
#include <klib.h>
|
||||
#include <stdint.h>
|
||||
#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) {
|
||||
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) {
|
||||
.present = true, .has_accel = false,
|
||||
.width = 0, .height = 0,
|
||||
.vmemsz = 0
|
||||
.width = w, .height = h,
|
||||
.vmemsz = w * h
|
||||
};
|
||||
}
|
||||
|
||||
void __am_gpu_init() {
|
||||
__am_gpu_config(&cfg_now);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#include "riscv/riscv.h"
|
||||
#include <am.h>
|
||||
#include <nemu.h>
|
||||
#include <amdev.h>
|
||||
|
||||
#define KEYDOWN_MASK 0x8000
|
||||
|
||||
void __am_input_keybrd(AM_INPUT_KEYBRD_T *kbd) {
|
||||
kbd->keydown = 0;
|
||||
kbd->keycode = AM_KEY_NONE;
|
||||
uint32_t k = inl(KBD_ADDR);
|
||||
kbd->keydown = (k & KEYDOWN_MASK ? true : false);
|
||||
kbd->keycode = k & ~KEYDOWN_MASK;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
#include "riscv/riscv.h"
|
||||
#include <am.h>
|
||||
#include <nemu.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void __am_timer_init() {
|
||||
outl(RTC_ADDR, 0);
|
||||
outl(RTC_ADDR + 4, 0);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
#include <nemu.h>
|
||||
|
||||
extern char _heap_start;
|
||||
extern void *heap_alloc_ptr;
|
||||
int main(const char *args);
|
||||
|
||||
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) {
|
||||
outb(SERIAL_PORT, ch);
|
||||
|
@ -19,6 +23,7 @@ void halt(int code) {
|
|||
}
|
||||
|
||||
void _trm_init() {
|
||||
heap_alloc_ptr = heap.start;
|
||||
int ret = main(mainargs);
|
||||
halt(ret);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,19 @@ Context* __am_irq_handle(Context *c) {
|
|||
if (user_handler) {
|
||||
Event ev = {0};
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -17,7 +30,6 @@ Context* __am_irq_handle(Context *c) {
|
|||
|
||||
return c;
|
||||
}
|
||||
|
||||
extern void __am_asm_trap(void);
|
||||
|
||||
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) {
|
||||
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() {
|
||||
#ifdef __riscv_e
|
||||
//use a5 or a7 to get system call ID
|
||||
asm volatile("li a5, -1; ecall");
|
||||
#else
|
||||
asm volatile("li a7, -1; ecall");
|
||||
|
|
|
@ -5,6 +5,4 @@
|
|||
_start:
|
||||
mv s0, zero
|
||||
la sp, _stack_pointer
|
||||
call _trm_init
|
||||
|
||||
.size _start, . - _start
|
||||
jal _trm_init
|
||||
|
|
|
@ -58,14 +58,14 @@ __am_asm_trap:
|
|||
csrw mstatus, t1
|
||||
|
||||
mv a0, sp
|
||||
call __am_irq_handle
|
||||
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
|
||||
|
|
|
@ -8,6 +8,7 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -31,7 +32,23 @@ bool cte_init(Context*(*handler)(Event, Context*)) {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -40,7 +40,7 @@ FUNC_BEGIN (__udivsi3)
|
|||
sll a0, a0, 32
|
||||
sll a1, a1, 32
|
||||
move t0, ra
|
||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
||||
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||
sext.w a0, a0
|
||||
jr t0
|
||||
FUNC_END (__udivsi3)
|
||||
|
@ -52,7 +52,7 @@ FUNC_BEGIN (__umodsi3)
|
|||
srl a0, a0, 32
|
||||
srl a1, a1, 32
|
||||
move t0, ra
|
||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
||||
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||
sext.w a0, a1
|
||||
jr t0
|
||||
FUNC_END (__umodsi3)
|
||||
|
@ -100,7 +100,7 @@ HIDDEN_DEF (__udivdi3)
|
|||
FUNC_BEGIN (__umoddi3)
|
||||
/* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
|
||||
move t0, ra
|
||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
||||
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||
move a0, a1
|
||||
jr t0
|
||||
FUNC_END (__umoddi3)
|
||||
|
@ -117,7 +117,7 @@ FUNC_END (__umoddi3)
|
|||
neg a1, a1
|
||||
.L12:
|
||||
move t0, ra
|
||||
call HIDDEN_JUMPTARGET(__udivdi3)
|
||||
jal HIDDEN_JUMPTARGET(__udivdi3)
|
||||
neg a0, a0
|
||||
jr t0
|
||||
FUNC_END (__divdi3)
|
||||
|
@ -127,7 +127,7 @@ FUNC_BEGIN (__moddi3)
|
|||
bltz a1, .L31
|
||||
bltz a0, .L32
|
||||
.L30:
|
||||
call HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is not negative. */
|
||||
jal HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is not negative. */
|
||||
move a0, a1
|
||||
jr t0
|
||||
.L31:
|
||||
|
@ -135,7 +135,7 @@ FUNC_BEGIN (__moddi3)
|
|||
bgez a0, .L30
|
||||
.L32:
|
||||
neg a0, a0
|
||||
call HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is hella negative. */
|
||||
jal HIDDEN_JUMPTARGET(__udivdi3) /* The dividend is hella negative. */
|
||||
neg a0, a1
|
||||
jr t0
|
||||
FUNC_END (__moddi3)
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
_start:
|
||||
mv s0, zero
|
||||
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 <stdint.h>
|
||||
|
||||
void __am_timer_init() {
|
||||
}
|
||||
#define RTC_ADDR 0xa0000048
|
||||
static uint64_t up = 0;
|
||||
|
||||
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) {
|
||||
|
|
|
@ -55,6 +55,7 @@ __am_asm_trap:
|
|||
mv a0, sp
|
||||
jal __am_irq_handle
|
||||
|
||||
mv sp, a0
|
||||
LOAD t1, OFFSET_STATUS(sp)
|
||||
LOAD t2, OFFSET_EPC(sp)
|
||||
csrw mstatus, t1
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "riscv/riscv.h"
|
||||
#include <am.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
|
@ -9,13 +10,21 @@ extern char _pmem_start;
|
|||
#define PMEM_END ((uintptr_t)&_pmem_start + PMEM_SIZE)
|
||||
|
||||
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) {
|
||||
#define SERIAL_PORT 0xa00003f8
|
||||
outb(SERIAL_PORT, ch);
|
||||
}
|
||||
|
||||
void halt(int code) {
|
||||
while (1);
|
||||
asm volatile("mv a0, %0; ebreak" :: "r"(code));
|
||||
|
||||
//can't compile without this
|
||||
while (1);
|
||||
}
|
||||
|
||||
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__
|
||||
#define RISCV_H__
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#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 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 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 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 outd(uintptr_t addr, uint64_t data) { *(volatile uint64_t *)addr = data; }
|
||||
|
||||
#define PTE_V 0x01
|
||||
#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_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_SUM (1 << 18)
|
||||
#define MSTATUS_MPRV (1 << 17)
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define MSTATUS_SXL (2ull << 34)
|
||||
|
@ -31,4 +44,12 @@ enum { MODE_U, MODE_S, MODE_M = 3 };
|
|||
#define MSTATUS_UXL 0
|
||||
#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
|
||||
|
|
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) {
|
||||
union {
|
||||
Elf32_Ehdr elf32;
|
||||
Elf64_Ehdr elf64;
|
||||
} *u = (void *)0x8000;
|
||||
Elf32_Ehdr *elf32 = (void *)0x8000;
|
||||
Elf64_Ehdr *elf64 = (void *)0x8000;
|
||||
int is_ap = boot_record()->is_ap;
|
||||
|
||||
if (!is_ap) {
|
||||
// load argument (string) to memory
|
||||
copy_from_disk((void *)MAINARG_ADDR, 1024, -1024);
|
||||
// load elf header to memory
|
||||
copy_from_disk(u, 4096, 0);
|
||||
if (u->elf32.e_machine == EM_X86_64) {
|
||||
load_elf64(&u->elf64);
|
||||
copy_from_disk(elf32, 4096, 0);
|
||||
if (elf32->e_machine == EM_X86_64) {
|
||||
load_elf64(elf64);
|
||||
} else {
|
||||
load_elf32(&u->elf32);
|
||||
load_elf32(elf32);
|
||||
}
|
||||
} else {
|
||||
// everything should be loaded
|
||||
}
|
||||
|
||||
if (u->elf32.e_machine == EM_X86_64) {
|
||||
((void(*)())(uint32_t)(u->elf64.e_entry))();
|
||||
if (elf32->e_machine == EM_X86_64) {
|
||||
((void(*)())(uint32_t)elf64->e_entry)();
|
||||
} else {
|
||||
((void(*)())(uint32_t)(u->elf32.e_entry))();
|
||||
((void(*)())(uint32_t)elf32->e_entry)();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue