From 10054b2f171882480af37caf52540c6372e32fd3 Mon Sep 17 00:00:00 2001 From: Ekaitz Zarraga Date: Thu, 21 Sep 2023 15:43:50 +0200 Subject: [PATCH] riscv64: add support for tcc Adapted from -gcc but make assembly match tcc style assembly where the offsets are received as an extra input argument: sw a0, 9(t0) Becomes: sw a0, t0, 9 * lib/linux/riscv64-mes-tcc/_exit.c, lib/linux/riscv64-mes-tcc/_write.c, lib/linux/riscv64-mes-tcc/crt1.c, lib/linux/riscv64-mes-tcc/exit-42.S, lib/linux/riscv64-mes-tcc/hello-mes.S, lib/linux/riscv64-mes-tcc/syscall-internal.c, lib/linux/riscv64-mes-tcc/syscall.c: New files. --- lib/linux/riscv64-mes-tcc/_exit.c | 40 ++++ lib/linux/riscv64-mes-tcc/_write.c | 41 ++++ lib/linux/riscv64-mes-tcc/crt1.c | 58 ++++++ lib/linux/riscv64-mes-tcc/exit-42.S | 32 +++ lib/linux/riscv64-mes-tcc/hello-mes.S | 46 +++++ lib/linux/riscv64-mes-tcc/syscall-internal.c | 63 ++++++ lib/linux/riscv64-mes-tcc/syscall.c | 198 +++++++++++++++++++ 7 files changed, 478 insertions(+) create mode 100644 lib/linux/riscv64-mes-tcc/_exit.c create mode 100644 lib/linux/riscv64-mes-tcc/_write.c create mode 100644 lib/linux/riscv64-mes-tcc/crt1.c create mode 100644 lib/linux/riscv64-mes-tcc/exit-42.S create mode 100644 lib/linux/riscv64-mes-tcc/hello-mes.S create mode 100644 lib/linux/riscv64-mes-tcc/syscall-internal.c create mode 100644 lib/linux/riscv64-mes-tcc/syscall.c diff --git a/lib/linux/riscv64-mes-tcc/_exit.c b/lib/linux/riscv64-mes-tcc/_exit.c new file mode 100644 index 00000000..21c697f8 --- /dev/null +++ b/lib/linux/riscv64-mes-tcc/_exit.c @@ -0,0 +1,40 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2019,2020 Jan (janneke) Nieuwenhuizen + * Copyright © 2021 W. J. van der Laan + * Copyright © 2023 Ekaitz Zarraga + * + * This file is part of GNU Mes. + * + * GNU Mes 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 of the License, or (at + * your option) any later version. + * + * GNU Mes 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include "mes/lib-mini.h" + +#define SYS_exit 93 + +// *INDENT-OFF* +void +_exit (int code) +{ + register long __a7 asm ("a7") = SYS_exit; + register long __a0 asm ("a0") = code; + asm volatile ( + "ecall\n\t" + : // no outputs + : "r" (__a0), "r" (__a7) + ); + // not reached + _exit (0); +} diff --git a/lib/linux/riscv64-mes-tcc/_write.c b/lib/linux/riscv64-mes-tcc/_write.c new file mode 100644 index 00000000..7fed0915 --- /dev/null +++ b/lib/linux/riscv64-mes-tcc/_write.c @@ -0,0 +1,41 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2019,2020 Jan (janneke) Nieuwenhuizen + * Copyright © 2021 W. J. van der Laan + * Copyright © 2023 Ekaitz Zarraga + * + * This file is part of GNU Mes. + * + * GNU Mes 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 of the License, or (at + * your option) any later version. + * + * GNU Mes 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include "mes/lib-mini.h" + +#define SYS_write 64 + +// *INDENT-OFF* +ssize_t +_write (int filedes, void const *buffer, size_t size) +{ + register long __a7 asm ("a7") = (long) SYS_write; + register long __a0 asm ("a0") = (long) filedes; + register long __a1 asm ("a1") = (long) buffer; + register long __a2 asm ("a2") = (long) size; + asm volatile ( + "ecall\n\t" + : "+r" (__a0) + : "r" (__a7), "r" (__a1), "r" (__a2) + ); + return (ssize_t)__a0; +} diff --git a/lib/linux/riscv64-mes-tcc/crt1.c b/lib/linux/riscv64-mes-tcc/crt1.c new file mode 100644 index 00000000..0fe6c686 --- /dev/null +++ b/lib/linux/riscv64-mes-tcc/crt1.c @@ -0,0 +1,58 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2017,2018,2019,2020,2023 Jan (janneke) Nieuwenhuizen + * Copyright © 2019,2020 Danny Milosavljevic + * Copyright © 2021 W. J. van der Laan + * Copyright © 2023 Ekaitz Zarraga + * + * This file is part of GNU Mes. + * + * GNU Mes 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 of the License, or (at + * your option) any later version. + * + * GNU Mes 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include +//int main (int argc, char *argv[], char *envp[]); + +// *INDENT-OFF* +void +_start () +{ + asm ( + "lla gp, __global_pointer$\n\t" + "andi sp, sp, ~15\n\t" // make sure sp conforms to ABI alignment + ); + + // environ is &argv[argc + 1] + asm ( + "lw t0, s0, 0\n\t" + "addi t1, s0, 8\n\t" + "addi t0, t0, 1\n\t" + "slli t0, t0, 3\n\t" + "add t0, t1, t0\n\t" + + "lw a0, s0, 0\n\t" // a0 argc + "addi a1, s0, 8\n\t" // a1 argv + "mv a2, t0\n\t" // a2 envp + + "jal ra, __init_io\n\t" + "jal ra, main\n\t" + + "li a7, 93\n\t" // SYS_exit + "ecall\n\t" // exit(return value from main) + + "ebreak\n\t" + : //no outputs "" + : "r" (environ) + ); +} diff --git a/lib/linux/riscv64-mes-tcc/exit-42.S b/lib/linux/riscv64-mes-tcc/exit-42.S new file mode 100644 index 00000000..22f9149a --- /dev/null +++ b/lib/linux/riscv64-mes-tcc/exit-42.S @@ -0,0 +1,32 @@ +/* + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2021 W. J. van der Laan + * Copyright © 2023 Ekaitz Zarraga + * + * This file is part of GNU Mes. + * + * GNU Mes 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 of the License, or (at + * your option) any later version. + * + * GNU Mes 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +/** Code: */ + +SYS_exit = 93 /* Linux syscalls. */ + .globl _start /* Magic linker symbol: --entry-address. */ + + .text /* Program text. */ +_start: + li a7, SYS_exit /* System call function: exit, in a7. */ + li a0, 42 /* 1st parameter: exit status, in a0. */ + ecall /* Call system. */ + wfi /* Should not be reached. */ diff --git a/lib/linux/riscv64-mes-tcc/hello-mes.S b/lib/linux/riscv64-mes-tcc/hello-mes.S new file mode 100644 index 00000000..931b80b0 --- /dev/null +++ b/lib/linux/riscv64-mes-tcc/hello-mes.S @@ -0,0 +1,46 @@ +/* + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2021 W. J. van der Laan + * Copyright © 2023 Ekaitz Zarraga + * + * This file is part of GNU Mes. + * + * GNU Mes 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 of the License, or (at + * your option) any later version. + * + * GNU Mes 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +/** Code: */ + +SYS_exit = 93 /* Linux syscalls. */ +SYS_write = 64 +stdout = 1 /* File descriptor */ + .globl _start /* Magic linker symbol: --entry-address. */ + + .text /* Program text. */ +hello: .ascii "Hello, GNU Mes!\n" +bye: +.equ string_size, (bye - hello) + +_start: + li a7, SYS_write /* System call function: write, in a7. */ + li a0, stdout /* 1st parameter: file descriptor, in a0. */ +.equ string_offset, (hello - .) + auipc a1, 0 /* Load pc for pc-relative address */ + addi a1, a1, string_offset /* 2nd parameter: address, in a1. */ + li a2, string_size /* 3rd parameter: byte count a2. */ + ecall /* Call system. */ + + li a7, SYS_exit /* System call function: exit, in a7. */ + li a0, 0 /* 1st parameter: exit status, in a0. */ + ecall /* Call system. */ + wfi /* Should not be reached. */ diff --git a/lib/linux/riscv64-mes-tcc/syscall-internal.c b/lib/linux/riscv64-mes-tcc/syscall-internal.c new file mode 100644 index 00000000..9053e10e --- /dev/null +++ b/lib/linux/riscv64-mes-tcc/syscall-internal.c @@ -0,0 +1,63 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen + * Copyright © 2021 W. J. van der Laan + * Copyright © 2023 Ekaitz Zarraga + * + * This file is part of GNU Mes. + * + * GNU Mes 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 of the License, or (at + * your option) any later version. + * + * GNU Mes 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include + +// *INDENT-OFF* +static long +__sys_call_internal (long sys_call) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0"); + asm volatile ( + "ecall\n\t" + : "=r" (__a0) + : "r" (__a7) + ); + return __a0; +} + +static long +__sys_call2_internal (long sys_call, long one, long two) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0") = one; + register long __a1 asm ("a1") = two; + asm volatile ( + "ecall\n\t" + : "+r" (__a0) + : "r" (__a7), "r" (__a1) + ); + return __a0; +} +// *INDENT-ON* + +/* Returns < 0 on error (errno-like value from kernel), or 0 on success */ +int +__raise (int signum) +{ + long pid = __sys_call_internal (SYS_getpid); + if (pid < 0) + return pid; + else + return __sys_call2_internal (SYS_kill, pid, signum); +} diff --git a/lib/linux/riscv64-mes-tcc/syscall.c b/lib/linux/riscv64-mes-tcc/syscall.c new file mode 100644 index 00000000..e0579914 --- /dev/null +++ b/lib/linux/riscv64-mes-tcc/syscall.c @@ -0,0 +1,198 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen + * Copyright © 2021 W. J. van der Laan + * Copyright © 2023 Ekaitz Zarraga + * + * This file is part of GNU Mes. + * + * GNU Mes 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 of the License, or (at + * your option) any later version. + * + * GNU Mes 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include +#include + +// *INDENT-OFF* +long +__sys_call (long sys_call) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0"); + asm volatile ( + "ecall\n\t" + : "=r" (__a0) + : "r" (__a7) + ); + return __a0; +} + +long +__sys_call1 (long sys_call, long one) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0") = one; + asm volatile ( + "ecall\n\t" + : "+r" (__a0) + : "r" (__a7) + ); + return __a0; +} + +long +__sys_call2 (long sys_call, long one, long two) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0") = one; + register long __a1 asm ("a1") = two; + asm volatile ( + "ecall\n\t" + : "+r" (__a0) + : "r" (__a7), "r" (__a1) + ); + return __a0; +} + +long +__sys_call3 (long sys_call, long one, long two, long three) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0") = one; + register long __a1 asm ("a1") = two; + register long __a2 asm ("a2") = three; + asm volatile ( + "ecall\n\t" + : "+r" (__a0) + : "r" (__a7), "r" (__a1), "r" (__a2) + ); + return __a0; +} + +long +__sys_call4 (long sys_call, long one, long two, long three, long four) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0") = one; + register long __a1 asm ("a1") = two; + register long __a2 asm ("a2") = three; + register long __a3 asm ("a3") = four; + asm volatile ( + "ecall\n\t" + : "+r" (__a0) + : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3) + ); + return __a0; +} + +long +__sys_call5 (long sys_call, long one, long two, long three, long four, long five) +{ + register long __a7 asm ("a7") = sys_call; + register long __a0 asm ("a0") = one; + register long __a1 asm ("a1") = two; + register long __a2 asm ("a2") = three; + register long __a3 asm ("a3") = four; + register long __a4 asm ("a4") = five; + asm volatile ( + "ecall\n\t" + : "+r" (__a0) + : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3), "r" (__a4) + ); + return __a0; +} +// *INDENT-ON* + +long +_sys_call (long sys_call) +{ + long r = __sys_call (sys_call); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call1 (long sys_call, long one) +{ + long r = __sys_call1 (sys_call, one); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call2 (long sys_call, long one, long two) +{ + long r = __sys_call2 (sys_call, one, two); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call3 (long sys_call, long one, long two, long three) +{ + long r = __sys_call3 (sys_call, one, two, three); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call4 (long sys_call, long one, long two, long three, long four) +{ + long r = __sys_call4 (sys_call, one, two, three, four); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +} + +long +_sys_call5 (long sys_call, long one, long two, long three, long four, long five) +{ + long r = __sys_call5 (sys_call, one, two, three, four, five); + if (r < 0) + { + errno = -r; + r = -1; + } + else + errno = 0; + return r; +}