diff --git a/seminaries/hello-apo/.gitingnore b/seminaries/hello-apo/.gitingnore new file mode 100644 index 0000000000000000000000000000000000000000..2fe532e90ea841795e63cbcc4314e63e6accb079 --- /dev/null +++ b/seminaries/hello-apo/.gitingnore @@ -0,0 +1,9 @@ +*.o +*.dump +*-native +*-x86 +*-riscv +*-riscv64 +*-mips +*-arm +*-aarch64 diff --git a/seminaries/hello-apo/Makefile b/seminaries/hello-apo/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a123f1fbfe048d437d4bb72ca92a83cdc13ac775 --- /dev/null +++ b/seminaries/hello-apo/Makefile @@ -0,0 +1,109 @@ +# Makefile to buidl example for different ISA targets +# Select architecture by ARCH parameter +# native, x86, riscv, riscv64, mips, arm, aarch64 + +# Specify source files of the program +SOURCES = hello-apo.c + +# Specify base name of the executable - architecture +TARGET_BASE = hello-apo + +# The actual target filename is unique for each architecture +TARGET_EXE = $(TARGET_BASE)-$(ARCH) + +all: default + +.PHONY : all default build run dump clean + +ARCH_SUPPORTED = native x86 riscv riscv64 mips arm aarch64 + +ifneq ($(MAKECMDGOALS),clean) +ifeq ($(filter $(ARCH_SUPPORTED),$(ARCH)),) + $(error ARCH parameter has to be set accepted: x86, riscv, riscv64, mips and arm) +endif +endif + +# setting specific for riscv build for native build +SOURCES-native += +LOADLIBES-native += +CC-native = gcc +OBJDUMP-native = objdump +ARCHFLAGS-native += -ggdb +RUN-native = + +# setting specific for riscv build for native build +SOURCES-x86 += +LOADLIBES-x86 += +CC-x86 = x86_64-linux-gnu-gcc +OBJDUMP-x86 = x86_64-linux-gnu-objdump +ARCHFLAGS-native += -static -ggdb +RUN-x86 = qemu-x86_64-static + +# setting specific for riscv build for QtRvSim simulator and or RISC-V Linux 32-bit run +SOURCES-riscv += sys-qtrvsim/qtrvsim_sys_stub.c sys-qtrvsim/crt0local.S +LOADLIBES-riscv += -lc -lgcc +CC-riscv = riscv64-unknown-elf-gcc +OBJDUMP-riscv = riscv64-unknown-elf-objdump +ARCHFLAGS-riscv += -mabi=ilp32 -march=rv32im -fno-lto -nostartfiles -nostdlib -static -ggdb +RUN-riscv = qemu-riscv32-static + +# setting specific for riscv64 build for QtRvSim simulator and or RISC-V Linux 64-bit run +SOURCES-riscv64 += sys-qtrvsim/qtrvsim_sys_stub.c sys-qtrvsim/crt0local.S +LOADLIBES-riscv64 += -lc -lgcc +CC-riscv64 = riscv64-unknown-elf-gcc +OBJDUMP-riscv64 = riscv64-unknown-elf-objdump +ARCHFLAGS-riscv64 += -mabi=lp64 -march=rv64imac -fno-lto -nostartfiles -nostdlib -static -ggdb +RUN-riscv64 = qemu-riscv64-static + +# setting specific for riscv64 build for QtMips simulator and or MIPS Linux run +SOURCES-mips += sys-qtmips/qtmips_sys_stub.c sys-qtmips/crt0local.S +LOADLIBES-mips += -lc -lgcc +CC-mips = mips-elf-gcc +OBJDUMP-mips = mips-elf-objdump +ARCHFLAGS-mips += -march=mips32 -fno-lto -nostartfiles -nostdlib -static -ggdb +RUN-mips = qemu-mips-static + +# setting specific for ARM 32-bit build +SOURCES-arm += +LOADLIBES-arm += +CC-arm = arm-linux-gnueabihf-gcc +OBJDUMP-arm = arm-linux-gnueabihf-objdump +ARCHFLAGS-arm += -static -ggdb +RUN-arm = qemu-arm-static + +# setting specific for ARM 64-bit build +SOURCES-aarch64 += +LOADLIBES-aarch64 += +CC-aarch64 = aarch64-linux-gnu-gcc +OBJDUMP-aarch64 = aarch64-linux-gnu-objdump +ARCHFLAGS-aarch64 += -static -ggdb +RUN-aarch64 = qemu-aarch64-static + +define compile_one_src +src := $(1) +arch := $(2) +obj := $$(basename $$(notdir $$(src)))-$$(arch).o +$$(obj) : $$(src) + $$(CC-$$(arch)) $$(ARCHFLAGS-$$(arch)) -c $$< -o $$@ +OBJS-$$(arch) := $$(OBJS-$$(arch)) $$(obj) +#$$(warning $$(src) $$(obj) $$(arch) $$(OBJS-$$(arch))) +endef + +$(foreach srci, $(SOURCES) $(SOURCES-$(ARCH)),$(eval $(call compile_one_src, $(srci), $(ARCH)))) + +$(TARGET_EXE) : $(OBJS-$(ARCH)) + $(CC-$(ARCH)) -o $@ $^ $(ARCHFLAGS-$(ARCH)) $(LOADLIBES-$(ARCH)) + +build : $(TARGET_EXE) + +run : $(TARGET_EXE) + $(RUN-$(ARCH)) ./$< + +dump: $(TARGET_EXE) + $(OBJDUMP-$(ARCH)) --source $< > $<.dump + cat $<.dump + +clean : + rm -f $(OBJS-$(ARCH)) $(foreach arch,$(ARCH_SUPPORTED),$(TARGET_BASE)-$(arch)) *.o *.dump + +default : build \ No newline at end of file diff --git a/seminaries/hello-apo/hello-apo.c b/seminaries/hello-apo/hello-apo.c new file mode 100644 index 0000000000000000000000000000000000000000..b6197a548067d21239bafdfe27f4b167d9bc4134 --- /dev/null +++ b/seminaries/hello-apo/hello-apo.c @@ -0,0 +1,25 @@ +/* Hello world example to demonstrate on multiple architectures */ + +/* + * compile, run and examine for different instruction set architectures + * build by make command where ARCH is chisen as one of + * native, x86, riscv, riscv64, mips, arm or aarch64 + * make ARCH=riscv + */ + +#include <stdio.h> + +//int var_a = 40; +//int var_b = 2; + +int main(int argc, char *argv[]) +{ + + /* + * modify program to compute and print answer + * of var_a + var_b + */ + printf("Hello APO\n"); + + return 0; +} diff --git a/seminaries/hello-apo/sys-qtmips/crt0local.S b/seminaries/hello-apo/sys-qtmips/crt0local.S new file mode 100644 index 0000000000000000000000000000000000000000..1931e765e4915b95bee4ee22ca4096795f2700e9 --- /dev/null +++ b/seminaries/hello-apo/sys-qtmips/crt0local.S @@ -0,0 +1,47 @@ +/* minimal replacement of crt0.o which is else provided by C library */ + +.globl main +.globl _start +.globl __start +.globl _heap_stack_start +.globl _heap_stack_end +.set noat +.set noreorder +.ent _start + +.text + +__start: +_start: +#if defined(__PIC__) || defined(__pic__) + bal next + nop +next: + .set noreorder + .cpload $31 + .set reorder +#else + la $gp, _gp +#endif + la $sp, _heap_stack_end + addi $a0, $zero, 0 + addi $a1, $zero, 0 + jal main + nop +quit: + addi $a0, $zero, 0 + addi $v0, $zero, 4001 /* SYS_exit */ + + syscall + +loop: break + beq $zero, $zero, loop + nop + +.end _start + +.bss + +_heap_stack_start: + .skip 0x800000 +_heap_stack_end: diff --git a/seminaries/hello-apo/sys-qtmips/qtmips_sys_stub.c b/seminaries/hello-apo/sys-qtmips/qtmips_sys_stub.c new file mode 100644 index 0000000000000000000000000000000000000000..119f5d3613816ba5783a82766f3e4a7b78e4efd8 --- /dev/null +++ b/seminaries/hello-apo/sys-qtmips/qtmips_sys_stub.c @@ -0,0 +1,436 @@ +/* Support files for GNU libc. Files in the system namespace go here. + Files in the C namespace (ie those that do not start with an + underscore) go in .c. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <stdio.h> +#include <stdarg.h> +#include <time.h> +#include <sys/time.h> +#include <sys/times.h> +#include <errno.h> +#include <reent.h> +#include "qtmips_unistd.h" + +#define UNUSED_PARAM(symbol) ((void)(symbol)) + +/* Register name - works in collusion with the linker. */ +register char * stack_ptr asm ("sp"); + + +int _read(int file, char *ptr, int len); +int +_read (int file, + char * ptr, + int len) +{ + register int __v0 asm("$v0") = __NR_read; + register int __a0 asm("$a0") = file; + register char * __a1 asm("$a1") = ptr; + register int __a2 asm("$a2") = len; + register int __a3 asm("$a3"); + __asm__ volatile ( + ".set\tnoreorder\n\t" + "syscall\n\t" + ".set reorder" + : "=r" (__v0), "=r" (__a3) + : "r" (__v0), "r" (__a0), "r" (__a1), "r"(__a2) + : ); + return __a3? -1: __v0; +} + +int _write(int file, const char *ptr, int len); +int +_write (int file, + const char * ptr, + int len) +{ + register int __v0 asm("$v0") = __NR_write; + register int __a0 asm("$a0") = file; + register const char * __a1 asm("$a1") = ptr; + register int __a2 asm("$a2") = len; + register int __a3 asm("$a3"); + __asm__ volatile ( + ".set\tnoreorder\n\t" + "syscall\n\t" + ".set reorder" + : "=r" (__v0), "=r" (__a3) + : "r" (__v0), "r" (__a0), "r" (__a1), "r"(__a2) + : ); + return __a3? -1: __v0; +} + + +int +_lseek (int file, + int pos, + int dir) +{ + UNUSED_PARAM(file); + UNUSED_PARAM(pos); + UNUSED_PARAM(dir); + + return -1; +} + +int _open(const char *path, int flags, ...); +int +_open (const char * path, + int flags, + ...) +{ + register int __v0 asm("$v0") = __NR_open; + register const char * __a0 asm("$a0") = path; + register int __a1 asm("$a1") = flags; + register int __a2 asm("$a2") = 0; + register int __a3 asm("$a3"); + + if (flags & O_CREAT) { + va_list list; + va_start(list, flags); + __a2 = va_arg(list, int); + va_end(list); + } + + __asm__ volatile ( + ".set\tnoreorder\n\t" + "syscall\n\t" + ".set reorder" + : "=r" (__v0), "=r" (__a3) + : "r" (__v0), "r" (__a0), "r" (__a1), "r"(__a2) + : ); + return __a3? -1: __v0; +} + +int _close(int file); +int +_close (int file) +{ + register int __v0 asm("$v0") = __NR_close; + register int __a0 asm("$a0") = file; + register int __a3 asm("$a3"); + __asm__ volatile ( + ".set\tnoreorder\n\t" + "syscall\n\t" + ".set reorder" + : "=r" (__v0), "=r" (__a3) + : "r" (__v0), "r" (__a0) + : ); + return __a3? -1: __v0; +} + +void _exit(int n); +void +_exit (int n) +{ + register int __v0 asm("$v0") = __NR_exit; + register int __a0 asm("$a0") = n; + + while(1) __asm__ volatile ( + ".set\tnoreorder\n\t" + "syscall\n\t" + ".set reorder" + : + : "r" (__v0), "r" (__a0) + : "a3"); +} + +void abort(void); +void abort(void) +{ + while(1) __asm__ volatile ( + ".set\tnoreorder\n\t" + "break\n\t" + ".set reorder" + : + : + : ); +} + +int _kill(int n, int m); +int +_kill (int n, int m) +{ + UNUSED_PARAM(n); + UNUSED_PARAM(m); + return -1; +} + +int _getpid(void); +int +_getpid (void) +{ + return 1; +} + + +void *_sbrk(ptrdiff_t incr); +void * +_sbrk (ptrdiff_t incr) +{ + extern char _heap_stack_start; + static char *heap_end; + char * prev_heap_end; + + incr=(incr+3) & ~3; + + if (heap_end == NULL) + heap_end = & _heap_stack_start; + + prev_heap_end = heap_end; + + if ((heap_end + incr > stack_ptr) && (&_heap_stack_start < stack_ptr)) + { + /* Some of the libstdc++-v3 tests rely upon detecting + out of memory errors, so do not abort here. */ +#if 1 + extern void abort (void); + + _write (1, "_sbrk: Heap and stack collision\n", 32); + + abort (); +#else + errno = ENOMEM; + return (caddr_t) -1; +#endif + } + + heap_end += incr; + + return /*(caddr_t)*/ prev_heap_end; +} + +int _fstat(int file, struct stat *st); +int +_fstat (int file, struct stat * st) +{ + UNUSED_PARAM(file); + UNUSED_PARAM(st); + return -1; +} + +int _stat (const char *fname, struct stat *st); +int _stat (const char *fname, struct stat *st) +{ + UNUSED_PARAM(fname); + UNUSED_PARAM(st); + return -1; +} + +int _link(const char *path1, const char *path2); +int +_link (const char *path1, + const char *path2) +{ + UNUSED_PARAM(path1); + UNUSED_PARAM(path2); + return -1; +} + +int _unlink(const char *path); +int +_unlink (const char *path) +{ + UNUSED_PARAM(path); + return -1; +} + +void _raise(void); +void +_raise (void) +{ + return; +} + +int _gettimeofday(struct timeval *tp, struct timezone *tzp); +int +_gettimeofday (struct timeval *tp, + struct timezone *tzp) +{ + + if(tp) + { + tp->tv_sec = 0; + tp->tv_usec = 0; + } + /* Return fixed data for the timezone. */ + if (tzp) + { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + + return 0; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t _times(struct tms *tp); +clock_t +_times (struct tms * tp) +{ + clock_t timeval = 0; + + if (tp) + { + tp->tms_utime = timeval; /* user time */ + tp->tms_stime = 0; /* system time */ + tp->tms_cutime = 0; /* user time, children */ + tp->tms_cstime = 0; /* system time, children */ + } + + return timeval; +}; + + +int isatty(int fd); +int +isatty (int fd) +{ + UNUSED_PARAM(fd); + return 1; +} + +int _system(const char *s); +int +_system (const char *s) +{ + UNUSED_PARAM(s); + return -1; +} + +int _rename(const char *oldpath, const char *newpath); +int +_rename (const char * oldpath, const char * newpath) +{ + UNUSED_PARAM(oldpath); + UNUSED_PARAM(newpath); + return -1; +} + +/* extern (.*) ([^ ]*) _PARAMS \(\(struct _reent \*(,*)(.*)\)\); */ +/* \1 \2 (struct _reent *\3\4) { return \2(\4);} */ + +struct _reent; + +int _close_r(struct _reent *reent, int file) +{ UNUSED_PARAM(reent); return _close(file);} +/* + int _fcntl_r(struct _reent *, int, int, int) + { return _fcntl( int, int, int);} +*/ +int _fstat_r(struct _reent *reent, int file, struct stat *st); +int _fstat_r(struct _reent *reent, int file, struct stat *st) +{ UNUSED_PARAM(reent); return _fstat(file, st);} + +int _getpid_r(struct _reent *reent); +int _getpid_r(struct _reent *reent) +{ UNUSED_PARAM(reent); return _getpid();} + +int _kill_r(struct _reent *reent, int n, int m); +int _kill_r(struct _reent *reent, int n, int m) +{ UNUSED_PARAM(reent); return _kill(n, m);} + +int _link_r(struct _reent *reent, const char *path1, const char *path2); +int _link_r(struct _reent *reent, const char *path1, const char *path2) +{ UNUSED_PARAM(reent); return _link(path1, path2);} + +_off_t _lseek_r(struct _reent *reent, int file, _off_t pos, int dir); +_off_t _lseek_r(struct _reent *reent, int file, _off_t pos, int dir) +{ UNUSED_PARAM(reent); return _lseek(file, pos, dir);} + +int _open_r(struct _reent *reent, const char *path, int flags, int opts); +int _open_r(struct _reent *reent, const char *path, int flags, int opts) +{ UNUSED_PARAM(reent); return _open(path, flags, opts);} + +_ssize_t _read_r(struct _reent *reent, int file, void *ptr, size_t len); +_ssize_t _read_r(struct _reent *reent, int file, void *ptr, size_t len) +{ UNUSED_PARAM(reent); return _read(file, ptr, len);} + +void *_sbrk_r(struct _reent *reent, ptrdiff_t incr); +void *_sbrk_r(struct _reent *reent, ptrdiff_t incr) +{ UNUSED_PARAM(reent); return _sbrk(incr);} + +int _stat_r(struct _reent *reent, const char *path, struct stat *st); +int _stat_r(struct _reent *reent, const char *path, struct stat *st) +{ UNUSED_PARAM(reent); return _stat(path, st);} + +int _unlink_r(struct _reent *reent, const char *path); +int _unlink_r(struct _reent *reent, const char *path) +{ UNUSED_PARAM(reent); return _unlink(path);} + +_ssize_t _write_r(struct _reent *reent, int file, const void *ptr, size_t len); +_ssize_t _write_r(struct _reent *reent, int file, const void *ptr, size_t len) +{ UNUSED_PARAM(reent); return _write(file, ptr, len);} + +/* FIXME: TDK added dummy functions. Need to implement. */ +int _isatty(int fd); +int _isatty(int fd) +{ + UNUSED_PARAM(fd); + return -1; +} + +int _swistat(int fd, struct stat *st); +int _swistat(int fd, struct stat *st) +{ + UNUSED_PARAM(fd); + UNUSED_PARAM(st); + return -1; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t _clock(void); +clock_t _clock(void) +{ + clock_t timeval=0; + return timeval; +} + +int _swiclose(int fh); +int _swiclose(int fh) +{ + UNUSED_PARAM(fh); + return -1; +} + +int _swiopen(const char *path, int flags); +int _swiopen(const char *path, int flags) +{ + UNUSED_PARAM(path); + UNUSED_PARAM(flags); + return -1; +} + +int _swiwrite(int fh, char *ptr, int len); +int _swiwrite(int fh, char *ptr, int len) +{ + UNUSED_PARAM(fh); + UNUSED_PARAM(ptr); + UNUSED_PARAM(len); + return -1; +} + +int _swilseek(int fd, int ptr, int dir); +int _swilseek(int fd, int ptr, int dir) +{ + UNUSED_PARAM(fd); + UNUSED_PARAM(ptr); + UNUSED_PARAM(dir); + return -1; +} + +int _swiread(int fh, char *ptr, int len); +int _swiread(int fh, char *ptr, int len) +{ + UNUSED_PARAM(fh); + UNUSED_PARAM(ptr); + UNUSED_PARAM(len); + return -1; +} + +void initialise_monitor_handles(void); +void initialise_monitor_handles(void) +{ +} diff --git a/seminaries/hello-apo/sys-qtmips/qtmips_unistd.h b/seminaries/hello-apo/sys-qtmips/qtmips_unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..e1a686967c708635189ed60a4f7bee8252a9d211 --- /dev/null +++ b/seminaries/hello-apo/sys-qtmips/qtmips_unistd.h @@ -0,0 +1,29 @@ +// ****************************************************************** +// QtMips emulator https://github.com/cvut/QtMips support filees +// +// qtmips_unistd.h - definition of the QtMips syscall numbers +// +// (C) Copyright 2019 - 2020 by Pavel Pisa +// e-mail: pisa@cmp.felk.cvut.cz +// homepage: http://cmp.felk.cvut.cz/~pisa +// license: any combination of GPL, LGPL, MPL or BSD licenses +// +// ****************************************************************** + +#ifndef QTMIPS_UNISTD_H +#define QTMIPS_UNISTD_H + +// Linux kernel compatible system calls subset + +#define __NR_exit 4001 // void exit(int status) +#define __NR_read 4003 // ssize_t read(int fd, void *buf, size_t count) +#define __NR_write 4004 // ssize_t write(int fd, const void *buf, size_t count) +#define __NR_close 4006 // int close(int fd) +#define __NR_open 4005 // int open(const char *pathname, int flags, mode_t mode) +#define __NR_brk 4045 // void * brk(void *addr) +#define __NR_truncate 4092 // int ftruncate(int fd, off_t length) +#define __NR_readv 4145 // ssize_t readv(int fd, const struct iovec *iov, int iovcnt) +#define __NR_writev 4146 // ssize_t writev(int fd, const struct iovec *iov, int iovcnt) +#define __NR_set_thread_area 4283 // int set_thread_area(unsigned long addr) + +#endif /*QTMIPS_UNISTD_H*/ diff --git a/seminaries/hello-apo/sys-qtrvsim/crt0local.S b/seminaries/hello-apo/sys-qtrvsim/crt0local.S new file mode 100644 index 0000000000000000000000000000000000000000..20017869ebfd71380908cd2aea560595e8d9b698 --- /dev/null +++ b/seminaries/hello-apo/sys-qtrvsim/crt0local.S @@ -0,0 +1,37 @@ +/* minimal replacement of crt0.o which is else provided by C library */ + +.globl main +.globl _start +.globl __start +.globl _heap_stack_start +.globl _heap_stack_end + +.option norelax + +.text + +__start: +_start: + .option push + .option norelax + la gp, __global_pointer$ + .option pop + la sp, _heap_stack_end + addi a0, zero, 0 + addi a1, zero, 0 + jal main +quit: + addi a0, zero, 0 + addi a7, zero, 93 /* SYS_exit */ + ecall + +loop: ebreak + beq zero, zero, loop + +.bss + +_heap_stack_start: + .skip 16384 +_heap_stack_end: + +.end _start diff --git a/seminaries/hello-apo/sys-qtrvsim/qtrvsim_sys_stub.c b/seminaries/hello-apo/sys-qtrvsim/qtrvsim_sys_stub.c new file mode 100644 index 0000000000000000000000000000000000000000..e56603e3a90ac37555e4c82e307ac4ffa9b749f4 --- /dev/null +++ b/seminaries/hello-apo/sys-qtrvsim/qtrvsim_sys_stub.c @@ -0,0 +1,502 @@ +/* Support files for GNU libc. Files in the system namespace go here. + Files in the C namespace (ie those that do not start with an + underscore) go in .c. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <stdio.h> +#include <stdarg.h> +#include <time.h> +#include <sys/time.h> +#include <sys/times.h> +#include <errno.h> +#include <reent.h> +#include "qtrvsim_unistd.h" + +#define UNUSED_PARAM(symbol) ((void)(symbol)) + + +/* Open flags definition for Linux kernel copied from musl-libc */ + +#define KERNEL_O_CREAT 0100 +#define KERNEL_O_EXCL 0200 +#define KERNEL_O_NOCTTY 0400 +#define KERNEL_O_TRUNC 01000 +#define KERNEL_O_APPEND 02000 +#define KERNEL_O_NONBLOCK 04000 +#define KERNEL_O_DSYNC 010000 +#define KERNEL_O_SYNC 04010000 +#define KERNEL_O_RSYNC 04010000 +#define KERNEL_O_DIRECTORY 0200000 +#define KERNEL_O_NOFOLLOW 0400000 +#define KERNEL_O_CLOEXEC 02000000 + +#define KERNEL_O_PATH 010000000 + +#define KERNEL_O_SYNC1 040000 + +#define KERNEL_O_ACCMODE (03 | KERNEL_O_PATH) +#define KERNEL_O_RDONLY 00 +#define KERNEL_O_WRONLY 01 +#define KERNEL_O_RDWR 02 + +#define TARGET_AT_FDCWD -100 + +/* Register name - works in collusion with the linker. */ +register char * stack_ptr asm ("sp"); + + +int _read(int file, char *ptr, int len); +int +_read (int file, + char * ptr, + int len) +{ + register int __a7 asm("a7") = __NR_read; + register int __a0 asm("a0") = file; + register char * __a1 asm("a1") = ptr; + register int __a2 asm("a2") = len; + __asm__ volatile ( + "ecall\n\t" + : "=r" (__a0) + : "r" (__a7), "r" (__a0), "r" (__a1), "r"(__a2) + : ); + return __a0 < 0 ? -1: __a0; +} + +int _write(int file, const char *ptr, int len); +int +_write (int file, + const char * ptr, + int len) +{ + register int __a7 asm("a7") = __NR_write; + register int __a0 asm("a0") = file; + register const char * __a1 asm("a1") = ptr; + register int __a2 asm("a2") = len; + __asm__ volatile ( + "ecall\n\t" + : "=r" (__a0) + : "r" (__a7), "r" (__a0), "r" (__a1), "r"(__a2) + : ); + return __a0 < 0 ? -1: __a0; +} + + +int +_lseek (int file, + int pos, + int dir) +{ + UNUSED_PARAM(file); + UNUSED_PARAM(pos); + UNUSED_PARAM(dir); + + return -1; +} + +int _openat(int fd, const char *path, int flags, ...); +int +_openat (int fd, const char * path, + int flags, + ...) +{ + register int __a7 asm("a7") = __NR_openat; + // use fd = -100 for normal open behaviour. Full openat not supported. + register int __a0 asm("a0") = fd; + register const char * __a1 asm("a1") = path; + register int __a2 asm("a2") = 0; + register int __a3 asm("a3"); + +#ifdef O_CREAT + if (flags & O_CREAT) + __a2 |= KERNEL_O_CREAT; +#endif +#ifdef O_EXCL + if (flags & O_EXCL) + __a2 |= KERNEL_O_EXCL; +#endif +#ifdef O_NOCTTY + if (flags & O_NOCTTY) + __a2 |= KERNEL_O_NOCTTY; +#endif +#ifdef O_TRUNC + if (flags & O_TRUNC) + __a2 |= KERNEL_O_TRUNC; +#endif +#ifdef O_APPEND + if (flags & O_APPEND) + __a2 |= KERNEL_O_APPEND; +#endif +#ifdef O_NONBLOCK + if (flags & O_NONBLOCK) + __a2 |= KERNEL_O_NONBLOCK; +#endif +#ifdef O_DSYNC + if (flags & O_DSYNC) + __a2 |= KERNEL_O_DSYNC; +#endif +#ifdef O_SYNC + if (flags & O_SYNC) + __a2 |= KERNEL_O_SYNC; +#endif +#ifdef O_RSYNC + if (flags & O_RSYNC) + __a2 |= KERNEL_O_RSYNC; +#endif +#ifdef O_DIRECTORY + if (flags & O_DIRECTORY) + __a2 |= KERNEL_O_DIRECTORY; +#endif +#ifdef O_NOFOLLOW + if (flags & O_NOFOLLOW) + __a2 |= KERNEL_O_NOFOLLOW; +#endif +#ifdef O_CLOEXEC + if (flags & O_CLOEXEC) + __a2 |= KERNEL_O_CLOEXEC; +#endif + + if (flags & O_CREAT) { + va_list list; + va_start(list, flags); + __a3 = va_arg(list, int); + va_end(list); + } + + __asm__ volatile ( + "ecall\n\t" + : "=r" (__a0) + : "r" (__a7), "r" (__a0), "r" (__a1), "r"(__a2), "r"(__a3) + : ); + return __a0 < 0 ? -1: __a0; +} + +int _close(int file); +int +_close (int file) +{ + register int __a7 asm("a7") = __NR_close; + register int __a0 asm("a0") = file; + __asm__ volatile ( + "ecall\n\t" + : "=r" (__a0) + : "r" (__a7), "r" (__a0) + : ); + return __a0 < 0 ? -1: __a0; +} + +void _exit(int n); +void +_exit (int n) +{ + register int __a7 asm("a7") = __NR_exit; + register int __a0 asm("a0") = n; + + while(1) __asm__ volatile ( + "ecall\n\t" + : + : "r" (__a7), "r" (__a0) + : ); +} + +void abort(void); +void abort(void) +{ + while(1) __asm__ volatile ( + "ebreak\n\t" + : + : + : ); +} + +int _kill(int n, int m); +int +_kill (int n, int m) +{ + UNUSED_PARAM(n); + UNUSED_PARAM(m); + return -1; +} + +int _getpid(void); +int +_getpid (void) +{ + return 1; +} + + +void *_sbrk(ptrdiff_t incr); +void * +_sbrk (ptrdiff_t incr) +{ + extern char _heap_stack_start; + static char *heap_end; + char * prev_heap_end; + + incr=(incr+3) & ~3; + + if (heap_end == NULL) + heap_end = & _heap_stack_start; + + prev_heap_end = heap_end; + + if ((heap_end + incr > stack_ptr) && (&_heap_stack_start < stack_ptr)) + { + /* Some of the libstdc++-v3 tests rely upon detecting + out of memory errors, so do not abort here. */ +#if 1 + extern void abort (void); + + _write (1, "_sbrk: Heap and stack collision\n", 32); + + abort (); +#else + errno = ENOMEM; + return (caddr_t) -1; +#endif + } + + heap_end += incr; + + return /*(caddr_t)*/ prev_heap_end; +} + +int _fstat(int file, struct stat *st); +int +_fstat (int file, struct stat * st) +{ + UNUSED_PARAM(file); + UNUSED_PARAM(st); + return -1; +} + +int _stat (const char *fname, struct stat *st); +int _stat (const char *fname, struct stat *st) +{ + UNUSED_PARAM(fname); + UNUSED_PARAM(st); + return -1; +} + +int _link(const char *path1, const char *path2); +int +_link (const char *path1, + const char *path2) +{ + UNUSED_PARAM(path1); + UNUSED_PARAM(path2); + return -1; +} + +int _unlink(const char *path); +int +_unlink (const char *path) +{ + UNUSED_PARAM(path); + return -1; +} + +void _raise(void); +void +_raise (void) +{ + return; +} + +int _gettimeofday(struct timeval *tp, struct timezone *tzp); +int +_gettimeofday (struct timeval *tp, + struct timezone *tzp) +{ + + if(tp) + { + tp->tv_sec = 0; + tp->tv_usec = 0; + } + /* Return fixed data for the timezone. */ + if (tzp) + { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + + return 0; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t _times(struct tms *tp); +clock_t +_times (struct tms * tp) +{ + clock_t timeval = 0; + + if (tp) + { + tp->tms_utime = timeval; /* user time */ + tp->tms_stime = 0; /* system time */ + tp->tms_cutime = 0; /* user time, children */ + tp->tms_cstime = 0; /* system time, children */ + } + + return timeval; +}; + + +int isatty(int fd); +int +isatty (int fd) +{ + UNUSED_PARAM(fd); + return 1; +} + +int _system(const char *s); +int +_system (const char *s) +{ + UNUSED_PARAM(s); + return -1; +} + +int _rename(const char *oldpath, const char *newpath); +int +_rename (const char * oldpath, const char * newpath) +{ + UNUSED_PARAM(oldpath); + UNUSED_PARAM(newpath); + return -1; +} + +/* extern (.*) ([^ ]*) _PARAMS \(\(struct _reent \*(,*)(.*)\)\); */ +/* \1 \2 (struct _reent *\3\4) { return \2(\4);} */ + +struct _reent; + +int _close_r(struct _reent *reent, int file) +{ UNUSED_PARAM(reent); return _close(file);} +/* + int _fcntl_r(struct _reent *, int, int, int) + { return _fcntl( int, int, int);} +*/ +int _fstat_r(struct _reent *reent, int file, struct stat *st); +int _fstat_r(struct _reent *reent, int file, struct stat *st) +{ UNUSED_PARAM(reent); return _fstat(file, st);} + +int _getpid_r(struct _reent *reent); +int _getpid_r(struct _reent *reent) +{ UNUSED_PARAM(reent); return _getpid();} + +int _kill_r(struct _reent *reent, int n, int m); +int _kill_r(struct _reent *reent, int n, int m) +{ UNUSED_PARAM(reent); return _kill(n, m);} + +int _link_r(struct _reent *reent, const char *path1, const char *path2); +int _link_r(struct _reent *reent, const char *path1, const char *path2) +{ UNUSED_PARAM(reent); return _link(path1, path2);} + +_off_t _lseek_r(struct _reent *reent, int file, _off_t pos, int dir); +_off_t _lseek_r(struct _reent *reent, int file, _off_t pos, int dir) +{ UNUSED_PARAM(reent); return _lseek(file, pos, dir);} + +int _open_r(struct _reent *reent, const char *path, int flags, int opts); +int _open_r(struct _reent *reent, const char *path, int flags, int opts) +{ UNUSED_PARAM(reent); return _openat(TARGET_AT_FDCWD, path, flags, opts);} + +int _openat_r(struct _reent *reent, int fd, const char *path, int flags, int opts); +int _openat_r(struct _reent *reent, int fd, const char *path, int flags, int opts) +{ UNUSED_PARAM(reent); return _openat(fd, path, flags, opts);} + +_ssize_t _read_r(struct _reent *reent, int file, void *ptr, size_t len); +_ssize_t _read_r(struct _reent *reent, int file, void *ptr, size_t len) +{ UNUSED_PARAM(reent); return _read(file, ptr, len);} + +void *_sbrk_r(struct _reent *reent, ptrdiff_t incr); +void *_sbrk_r(struct _reent *reent, ptrdiff_t incr) +{ UNUSED_PARAM(reent); return _sbrk(incr);} + +int _stat_r(struct _reent *reent, const char *path, struct stat *st); +int _stat_r(struct _reent *reent, const char *path, struct stat *st) +{ UNUSED_PARAM(reent); return _stat(path, st);} + +int _unlink_r(struct _reent *reent, const char *path); +int _unlink_r(struct _reent *reent, const char *path) +{ UNUSED_PARAM(reent); return _unlink(path);} + +_ssize_t _write_r(struct _reent *reent, int file, const void *ptr, size_t len); +_ssize_t _write_r(struct _reent *reent, int file, const void *ptr, size_t len) +{ UNUSED_PARAM(reent); return _write(file, ptr, len);} + +/* FIXME: TDK added dummy functions. Need to implement. */ +int _isatty(int fd); +int _isatty(int fd) +{ + UNUSED_PARAM(fd); + return -1; +} + +int _swistat(int fd, struct stat *st); +int _swistat(int fd, struct stat *st) +{ + UNUSED_PARAM(fd); + UNUSED_PARAM(st); + return -1; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t _clock(void); +clock_t _clock(void) +{ + clock_t timeval=0; + return timeval; +} + +int _swiclose(int fh); +int _swiclose(int fh) +{ + UNUSED_PARAM(fh); + return -1; +} + +int _swiopen(const char *path, int flags); +int _swiopen(const char *path, int flags) +{ + UNUSED_PARAM(path); + UNUSED_PARAM(flags); + return -1; +} + +int _swiwrite(int fh, char *ptr, int len); +int _swiwrite(int fh, char *ptr, int len) +{ + UNUSED_PARAM(fh); + UNUSED_PARAM(ptr); + UNUSED_PARAM(len); + return -1; +} + +int _swilseek(int fd, int ptr, int dir); +int _swilseek(int fd, int ptr, int dir) +{ + UNUSED_PARAM(fd); + UNUSED_PARAM(ptr); + UNUSED_PARAM(dir); + return -1; +} + +int _swiread(int fh, char *ptr, int len); +int _swiread(int fh, char *ptr, int len) +{ + UNUSED_PARAM(fh); + UNUSED_PARAM(ptr); + UNUSED_PARAM(len); + return -1; +} + +void initialise_monitor_handles(void); +void initialise_monitor_handles(void) +{ +} diff --git a/seminaries/hello-apo/sys-qtrvsim/qtrvsim_unistd.h b/seminaries/hello-apo/sys-qtrvsim/qtrvsim_unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..219d676f13d3b58ab04ddd2c005dced918a07de3 --- /dev/null +++ b/seminaries/hello-apo/sys-qtrvsim/qtrvsim_unistd.h @@ -0,0 +1,29 @@ +// ****************************************************************** +// QtRvSim emulator https://github.com/cvut/qtrvsim support filees +// +// qtrvsim_unistd.h - definition of the QtRvSim syscall numbers +// +// (C) Copyright 2019 - 2022 by Pavel Pisa +// e-mail: pisa@cmp.felk.cvut.cz +// homepage: http://cmp.felk.cvut.cz/~pisa +// license: any combination of GPL, LGPL, MPL or BSD licenses +// +// ****************************************************************** + +#ifndef QTRVSIM_UNISTD_H +#define QTRVSIM_UNISTD_H + +// Linux kernel compatible system calls subset + +#define __NR_exit 93 // void exit(int status) +#define __NR_read 63 // ssize_t read(int fd, void *buf, size_t count) +#define __NR_write 64 // ssize_t write(int fd, const void *buf, size_t count) +#define __NR_close 57 // int close(int fd) +#define __NR_openat 56 // int openat(int fd, const char *pathname, int flags, mode_t mode) + // use fd = -100 for normal open behaviour. Full openat not supported. +#define __NR_brk 214 // void * brk(void *addr) +#define __NR_ftruncate64 46 // int ftruncate64(int fd, off_t length) +#define __NR_readv 65 // ssize_t readv(int fd, const struct iovec *iov, int iovcnt) +#define __NR_writev 66 // ssize_t writev(int fd, const struct iovec *iov, int iovcnt) + +#endif /*QTRVSIM_UNISTD_H*/