From d8eebae3512d2c16485779d066583eac4ade8eca Mon Sep 17 00:00:00 2001 From: sunway_fw Date: Tue, 18 Feb 2025 15:21:39 +0800 Subject: [PATCH 4/5] sw64: Add auxiliary files To support a new architecture we need to provide a few helper functions for memory, cache, timer, etc support. Signed-off-by: sunway_fw --- grub-core/kern/efi/mm.c | 2 +- grub-core/kern/sw64/cache.c | 63 +++ grub-core/kern/sw64/cache_flush.S | 44 ++ grub-core/kern/sw64/dl_helper.c | 71 +++ grub-core/kern/sw64/efi/callwrap.S | 261 +++++++++++ grub-core/kern/sw64/efi/init.c | 75 ++++ grub-core/lib/sw64/divide.S | 677 +++++++++++++++++++++++++++++ grub-core/lib/sw64/setjmp.S | 75 ++++ include/grub/efi/efi.h | 2 +- include/grub/sw64/divide.h | 11 + include/grub/sw64/efi/memory.h | 7 + include/grub/sw64/efi/time.h | 23 + include/grub/sw64/io.h | 62 +++ include/grub/sw64/jmpbuf-offsets.h | 35 ++ include/grub/sw64/kernel.h | 25 ++ include/grub/sw64/pal.h | 49 +++ include/grub/sw64/regdef.h | 44 ++ include/grub/sw64/setjmp.h | 28 ++ include/grub/sw64/time.h | 28 ++ include/grub/sw64/types.h | 32 ++ 20 files changed, 1612 insertions(+), 2 deletions(-) create mode 100644 grub-core/kern/sw64/cache.c create mode 100644 grub-core/kern/sw64/cache_flush.S create mode 100644 grub-core/kern/sw64/dl_helper.c create mode 100644 grub-core/kern/sw64/efi/callwrap.S create mode 100644 grub-core/kern/sw64/efi/init.c create mode 100644 grub-core/lib/sw64/divide.S create mode 100644 grub-core/lib/sw64/setjmp.S create mode 100644 include/grub/sw64/divide.h create mode 100644 include/grub/sw64/efi/memory.h create mode 100644 include/grub/sw64/efi/time.h create mode 100644 include/grub/sw64/io.h create mode 100644 include/grub/sw64/jmpbuf-offsets.h create mode 100644 include/grub/sw64/kernel.h create mode 100644 include/grub/sw64/pal.h create mode 100644 include/grub/sw64/regdef.h create mode 100644 include/grub/sw64/setjmp.h create mode 100644 include/grub/sw64/time.h create mode 100644 include/grub/sw64/types.h diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c index afad55e..f956331 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c @@ -720,7 +720,7 @@ grub_efi_mm_init (void) } #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) || \ - defined (__loongarch__) + defined (__loongarch__) || defined (__sw_64__) grub_err_t grub_efi_get_ram_base(grub_addr_t *base_addr) { diff --git a/grub-core/kern/sw64/cache.c b/grub-core/kern/sw64/cache.c new file mode 100644 index 0000000..9278dda --- /dev/null +++ b/grub-core/kern/sw64/cache.c @@ -0,0 +1,63 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +static grub_int64_t dlinesz; +static grub_int64_t ilinesz; + +/* Prototypes for asm functions. */ +void grub_arch_clean_dcache_range (grub_addr_t beg, grub_addr_t end, + grub_size_t line_size); +void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end, + grub_size_t line_size); + +static void +probe_caches (void) +{ + /* TODO */ + dlinesz = 128; + ilinesz = 128; +} + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + grub_size_t start, end, max_align; + + if (dlinesz == 0) + probe_caches(); + if (dlinesz == 0) + grub_fatal ("Unknown cache line size!"); + + max_align = dlinesz > ilinesz ? dlinesz : ilinesz; + + start = ALIGN_DOWN ((grub_size_t) address, max_align); + end = ALIGN_UP ((grub_size_t) address + len, max_align); + + grub_arch_clean_dcache_range (start, end, dlinesz); + grub_arch_invalidate_icache_range (start, end, ilinesz); +} + +void +grub_arch_sync_dma_caches (volatile void *address __attribute__((unused)), + grub_size_t len __attribute__((unused))) +{ + /* DMA incoherent devices not supported yet */ +} diff --git a/grub-core/kern/sw64/cache_flush.S b/grub-core/kern/sw64/cache_flush.S new file mode 100644 index 0000000..dde3e5c --- /dev/null +++ b/grub-core/kern/sw64/cache_flush.S @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "cache_flush.S" + .text + +/* + * Simple cache maintenance functions + */ + +/* + * a0 - *beg (inclusive) + * a1 - *end (exclusive) + * a2 - line size +*/ +FUNCTION(grub_arch_clean_dcache_range) + /* TODO */ + ret + +/* + * a0 - *beg (inclusive) + * a1 - *end (exclusive) + * a2 - line size + */ +FUNCTION(grub_arch_invalidate_icache_range) + memb + ret diff --git a/grub-core/kern/sw64/dl_helper.c b/grub-core/kern/sw64/dl_helper.c new file mode 100644 index 0000000..8680c9a --- /dev/null +++ b/grub-core/kern/sw64/dl_helper.c @@ -0,0 +1,71 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2005,2007,2009 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wcast-align" + +grub_err_t +grub_sw64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got) +{ + const Elf64_Ehdr *e = ehdr; + grub_size_t cntt = 0, cntg = 0;; + const Elf64_Shdr *s; + unsigned i; + + *tramp = 0; + *got = 0; + + /* Find a symbol table. */ + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); + i < grub_le_to_cpu16 (e->e_shnum); + i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) + if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) + break; + + if (i == grub_le_to_cpu16 (e->e_shnum)) + return GRUB_ERR_NONE; + + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); + i < grub_le_to_cpu16 (e->e_shnum); + i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) + if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA) + { + Elf64_Rela *rel, *max; + + for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)), + max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize); + rel < max; rel++) + switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info))) + { + case R_SW64_LITERAL: + cntg++; + break; + } + } + *tramp = cntt; + *got = cntg * sizeof (grub_uint64_t); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/sw64/efi/callwrap.S b/grub-core/kern/sw64/efi/callwrap.S new file mode 100644 index 0000000..13ee13d --- /dev/null +++ b/grub-core/kern/sw64/efi/callwrap.S @@ -0,0 +1,261 @@ + .file "callwrap.S" + .text + .align 4 + .globl sw_efi_wrap_0 + .globl sw_efi_wrap_1 + .globl sw_efi_wrap_2 + .globl sw_efi_wrap_3 + .globl sw_efi_wrap_4 + .globl sw_efi_wrap_5 + .globl sw_efi_wrap_6 + .globl sw_efi_wrap_7 + .globl sw_efi_wrap_10 + + .ent sw_efi_wrap_0 +sw_efi_wrap_0: + + ldi $30,-32($30) + stl $26,0($30) + stl $15,8($30) + mov $30,$15 + .prologue 1 + stl $16,16($15) + ldl $27,16($15) + call $26,($27),0 + #ldi $29,0($29) !gpdisp!29 + mov $15,$30 + ldl $26,0($30) + ldl $15,8($30) + ldi $30,32($30) + ret $31,($26),1 + + .end sw_efi_wrap_0 + + .ent sw_efi_wrap_1 +sw_efi_wrap_1: + + ldi $30,-32($30) + stl $26,0($30) + stl $15,8($30) + mov $30,$15 + .prologue 1 + stl $16,16($15) + stl $17,24($15) + ldl $27,16($15) + ldl $16,24($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!31 + #ldi $29,0($29) !gpdisp!31 + mov $15,$30 + ldl $26,0($30) + ldl $15,8($30) + ldi $30,32($30) + ret $31,($26),1 + .end sw_efi_wrap_1 + + .ent sw_efi_wrap_2 +sw_efi_wrap_2: + ldi $30,-48($30) + stl $26,0($30) + stl $15,8($30) + mov $30,$15 + .prologue 1 + stl $16,16($15) + stl $17,24($15) + stl $18,32($15) + ldl $27,16($15) + ldl $16,24($15) + ldl $17,32($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!33 + #ldi $29,0($29) !gpdisp!33 + mov $15,$30 + ldl $26,0($30) + ldl $15,8($30) + ldi $30,48($30) + ret $31,($26),1 + .end sw_efi_wrap_2 + + .ent sw_efi_wrap_3 +sw_efi_wrap_3: + ldi $30,-48($30) + stl $26,0($30) + stl $15,8($30) + mov $30,$15 + .prologue 1 + stl $16,16($15) + stl $17,24($15) + stl $18,32($15) + stl $19,40($15) + ldl $27,16($15) + ldl $16,24($15) + ldl $17,32($15) + ldl $18,40($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!35 + #ldi $29,0($29) !gpdisp!35 + mov $15,$30 + ldl $26,0($30) + ldl $15,8($30) + ldi $30,48($30) + ret $31,($26),1 + .end sw_efi_wrap_3 + + .ent sw_efi_wrap_4 +sw_efi_wrap_4: + ldi $30,-64($30) + stl $26,0($30) + stl $15,8($30) + mov $30,$15 + .prologue 1 + stl $16,16($15) + stl $17,24($15) + stl $18,32($15) + stl $19,40($15) + stl $20,48($15) + ldl $27,16($15) + ldl $16,24($15) + ldl $17,32($15) + ldl $18,40($15) + ldl $19,48($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!37 + #ldi $29,0($29) !gpdisp!37 + mov $15,$30 + ldl $26,0($30) + ldl $15,8($30) + ldi $30,64($30) + ret $31,($26),1 + .end sw_efi_wrap_4 + + .ent sw_efi_wrap_5 +sw_efi_wrap_5: + ldi $30,-64($30) + stl $26,0($30) + stl $15,8($30) + mov $30,$15 + .prologue 1 + stl $16,16($15) + stl $17,24($15) + stl $18,32($15) + stl $19,40($15) + stl $20,48($15) + stl $21,56($15) + ldl $27,16($15) + ldl $16,24($15) + ldl $17,32($15) + ldl $18,40($15) + ldl $19,48($15) + ldl $20,56($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!39 + #ldi $29,0($29) !gpdisp!39 + mov $15,$30 + ldl $26,0($30) + ldl $15,8($30) + ldi $30,64($30) + ret $31,($26),1 + .end sw_efi_wrap_5 + + + .ent sw_efi_wrap_6 +sw_efi_wrap_6: + ldi $30,-64($30) + stl $26,0($30) + stl $15,8($30) + mov $30,$15 + .prologue 1 + stl $16,16($15) + stl $17,24($15) + stl $18,32($15) + stl $19,40($15) + stl $20,48($15) + stl $21,56($15) + ldl $27,16($15) + ldl $16,24($15) + ldl $17,32($15) + ldl $18,40($15) + ldl $19,48($15) + ldl $20,56($15) + ldl $21,64($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!41 + #ldi $29,0($29) !gpdisp!41 + mov $15,$30 + ldl $26,0($30) + ldl $15,8($30) + ldi $30,64($30) + ret $31,($26),1 + .end sw_efi_wrap_6 + + .ent sw_efi_wrap_7 +sw_efi_wrap_7: + ldi $30,-80($30) + stl $26,16($30) + stl $15,24($30) + mov $30,$15 + .prologue 1 + stl $16,32($15) + stl $17,40($15) + stl $18,48($15) + stl $19,56($15) + stl $20,64($15) + stl $21,72($15) + ldl $1,88($15) + stl $1,0($30) + ldl $27,32($15) + ldl $16,40($15) + ldl $17,48($15) + ldl $18,56($15) + ldl $19,64($15) + ldl $20,72($15) + ldl $21,80($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!43 + #ldi $29,0($29) !gpdisp!43 + mov $15,$30 + ldl $26,16($30) + ldl $15,24($30) + ldi $30,80($30) + ret $31,($26),1 + .end sw_efi_wrap_7 + + + .ent sw_efi_wrap_10 +sw_efi_wrap_10: + ldi $30,-96($30) + stl $26,32($30) + stl $15,40($30) + mov $30,$15 + .prologue 1 + stl $16,48($15) + stl $17,56($15) + stl $18,64($15) + stl $19,72($15) + stl $20,80($15) + stl $21,88($15) + ldl $1,104($15) + stl $1,0($30) + ldl $1,112($15) + stl $1,8($30) + ldl $1,120($15) + stl $1,16($30) + ldl $1,128($15) + stl $1,24($30) + ldl $27,48($15) + ldl $16,56($15) + ldl $17,64($15) + ldl $18,72($15) + ldl $19,80($15) + ldl $20,88($15) + ldl $21,96($15) + call $26,($27),0 + #ldih $29,0($26) !gpdisp!45 + #ldi $29,0($29) !gpdisp!45 + mov $15,$30 + ldl $26,32($30) + ldl $15,40($30) + ldi $30,96($30) + ret $31,($26),1 + + .end sw_efi_wrap_10 diff --git a/grub-core/kern/sw64/efi/init.c b/grub-core/kern/sw64/efi/init.c new file mode 100644 index 0000000..d647106 --- /dev/null +++ b/grub-core/kern/sw64/efi/init.c @@ -0,0 +1,75 @@ +/* init.c - initialize a riscv-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +grub_uint64_t cycle_freq; + +static grub_uint64_t +rpcc(void) +{ + grub_uint64_t result; + + asm volatile ("rtc %0" : "=r"(result)); + + return result; +} + +static grub_uint64_t +grub_efi_get_time_ms(void) +{ + cycle_freq = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; + + return rpcc() * 1000 / cycle_freq; +} + +static void +grub_print_info (void) +{ + grub_printf ("GNU %s %s\n", PACKAGE_NAME, PACKAGE_VERSION); + grub_printf ("CPU freq: %ld Mhz\n", cpuid(GET_CPU_FREQ, 0)); + grub_printf ("Build Time: %s %s\n", __DATE__, __TIME__); +} + +void +grub_machine_init (void) +{ + grub_efi_init (); + grub_print_info (); + grub_install_get_time_ms (grub_efi_get_time_ms); +} + +void +grub_machine_fini (int flags) +{ + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + + grub_efi_fini (); + + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) + grub_efi_memory_fini (); +} diff --git a/grub-core/lib/sw64/divide.S b/grub-core/lib/sw64/divide.S new file mode 100644 index 0000000..980aba6 --- /dev/null +++ b/grub-core/lib/sw64/divide.S @@ -0,0 +1,677 @@ +/* + * divide.S + * + * (C) 1995 Linus Torvalds + * + * Alpha division.. + */ + +/* + * The alpha chip doesn't provide hardware division, so we have to do it + * by hand. The compiler expects the functions + * + * __divqu: 64-bit unsigned long divide + * __remqu: 64-bit unsigned long remainder + * __divqs/__remqs: signed 64-bit + * __divlu/__remlu: unsigned 32-bit + * __divls/__remls: signed 32-bit + * + * These are not normal C functions: instead of the normal + * calling sequence, these expect their arguments in registers + * $24 and $25, and return the result in $27. Register $28 may + * be clobbered (assemembly temporary), anything else must be saved. + * + * In short: painful. + * + * This is a rather simple bit-at-a-time algorithm: it's very good + * at dividing random 64-bit numembers, but the more usual case where + * the divisor is small is handled better by the DEC algorithm + * using lookup tables. This uses much less memory, though, and is + * nicer on the cache.. Besides, I don't know the copyright status + * of the DEC code. + */ + +/* + * My temporaries: + * $0 - current bit + * $1 - shifted divisor + * $2 - modulus/quotient + * + * $23 - return address + * $24 - dividend + * $25 - divisor + * + * $27 - quotient/modulus + * $28 - compare status + */ + +#define halt .long 0 + +/* + * Select function type and registers + */ +#define mask $0 +#define divisor $1 +#define compare $28 +#define tmp1 $3 +#define tmp2 $4 + +#define DIV +#define INTSIZE + +#undef DIV_ONLY +#undef MOD_ONLY +#undef func +#undef modulus +#undef quotient +#undef GETSIGN +#undef STACK +#undef ufunction +#undef sfunction +#undef LONGIFY +#undef SLONGIFY + +#ifdef DIV +#define DIV_ONLY(x,y...) x,##y +#define MOD_ONLY(x,y...) +#define func(x) __div##x +#define modulus $2 +#define quotient $27 +#define GETSIGN(x) xor $24,$25,x +#define STACK 48 +#else +#define DIV_ONLY(x,y...) +#define MOD_ONLY(x,y...) x,##y +#define func(x) __rem##x +#define modulus $27 +#define quotient $2 +#define GETSIGN(x) bis $24,$24,x +#define STACK 32 +#endif + +/* + * For 32-bit operations, we need to extend to 64-bit + */ +#ifdef INTSIZE +#define ufunction func(wu) +#define sfunction func(w) +#define LONGIFY(x) zapnot x,15,x +/* define SLONGIFY(x) addw x,0,x */ +#define SLONGIFY(x) +#else +#define ufunction func(lu) +#define sfunction func(l) +#define LONGIFY(x) +#define SLONGIFY(x) +#endif + +.set noat +.align 3 +.globl ufunction +.ent ufunction +ufunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + +7: stl $1, 0($30) + bis $25,$25,divisor + stl $2, 8($30) + bis $24,$24,modulus + stl $0,16($30) + bis $31,$31,quotient + LONGIFY(divisor) + stl tmp1,24($30) + LONGIFY(modulus) + bis $31,1,mask + DIV_ONLY(stl tmp2,32($30)) + beq divisor, 9f /* div by zero */ + +#ifdef INTSIZE + /* + * shift divisor left, using 3-bit shifts for + * 32-bit divides as we can't overflow. Three-bit + * shifts will result in looping three times less + * here, but can result in two loops more later. + * Thus using a large shift isn't worth it (and + * s8add pairs better than a sll..) + */ +1: cmpult divisor,modulus,compare + s8addl divisor,$31,divisor + s8addl mask,$31,mask + bne compare,1b +#else +1: cmpult divisor,modulus,compare + blt divisor, 2f + addl divisor,divisor,divisor + addl mask,mask,mask + bne compare,1b + nop +#endif + + /* ok, start to go right again.. */ +2: DIV_ONLY(addl quotient,mask,tmp2) + srl mask,1,mask + cmpule divisor,modulus,compare + subl modulus,divisor,tmp1 + DIV_ONLY(selne compare,tmp2,quotient,quotient) + srl divisor,1,divisor + selne compare,tmp1,modulus,modulus + bne mask,2b + +9: ldl $1, 0($30) + ldl $2, 8($30) + ldl $0,16($30) + ldl tmp1,24($30) + DIV_ONLY(ldl tmp2,32($30)) + addl $30,STACK,$30 + ret $31,($23),1 + .end ufunction + +/* + * Uhh.. Ugly signed division. I'd rather not have it at all, but + * it's needed in some circumstances. There are different ways to + * handle this, really. This does: + * -a / b = a / -b = -(a / b) + * -a % b = -(a % b) + * a % -b = a % b + * which is probably not the best solution, but at least should + * have the property that (x/y)*y + (x%y) = x. + */ +.align 3 +.globl sfunction +.ent sfunction +sfunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + bis $24,$25,$28 + SLONGIFY($28) + bge $28,7b + stl $24,0($30) + subl $31,$24,$28 + stl $25,8($30) + sellt $24,$28,$24,$24 /* abs($24) */ + stl $23,16($30) + subl $31,$25,$28 + stl tmp1,24($30) + sellt $25,$28,$25,$25 /* abs($25) */ + nop + bsr $23,ufunction + ldl $24,0($30) + ldl $25,8($30) + GETSIGN($28) + subl $31,$27,tmp1 + SLONGIFY($28) + ldl $23,16($30) + sellt $28,tmp1,$27,$27 + ldl tmp1,24($30) + addl $30,STACK,$30 + ret $31,($23),1 + .end sfunction + +/*rem 32 */ + +#undef DIV_ONLY +#undef MOD_ONLY +#undef func +#undef modulus +#undef quotient +#undef GETSIGN +#undef STACK +#undef ufunction +#undef sfunction +#undef LONGIFY +#undef SLONGIFY + + +#undef DIV + + +#ifdef DIV +#define DIV_ONLY(x,y...) x,##y +#define MOD_ONLY(x,y...) +#define func(x) __div##x +#define modulus $2 +#define quotient $27 +#define GETSIGN(x) xor $24,$25,x +#define STACK 48 +#else +#define DIV_ONLY(x,y...) +#define MOD_ONLY(x,y...) x,##y +#define func(x) __rem##x +#define modulus $27 +#define quotient $2 +#define GETSIGN(x) bis $24,$24,x +#define STACK 32 +#endif + +/* + * For 32-bit operations, we need to extend to 64-bit + */ +#ifdef INTSIZE +#define ufunction func(wu) +#define sfunction func(w) +#define LONGIFY(x) zapnot x,15,x +#define SLONGIFY(x) +#else +#define ufunction func(lu) +#define sfunction func(l) +#define LONGIFY(x) +#define SLONGIFY(x) +#endif + +.align 3 +.globl ufunction +.ent ufunction +ufunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + +7: stl $1, 0($30) + bis $25,$25,divisor + stl $2, 8($30) + bis $24,$24,modulus + stl $0,16($30) + bis $31,$31,quotient + LONGIFY(divisor) + stl tmp1,24($30) + LONGIFY(modulus) + bis $31,1,mask + DIV_ONLY(stl tmp2,32($30)) + beq divisor, 9f /* div by zero */ + +#ifdef INTSIZE + /* + * shift divisor left, using 3-bit shifts for + * 32-bit divides as we can't overflow. Three-bit + * shifts will result in looping three times less + * here, but can result in two loops more later. + * Thus using a large shift isn't worth it (and + * s8add pairs better than a sll..) + */ +1: cmpult divisor,modulus,compare + s8addl divisor,$31,divisor + s8addl mask,$31,mask + bne compare,1b +#else +1: cmpult divisor,modulus,compare + blt divisor, 2f + addl divisor,divisor,divisor + addl mask,mask,mask + bne compare,1b + nop +#endif + + /* ok, start to go right again.. */ +2: DIV_ONLY(addl quotient,mask,tmp2) + srl mask,1,mask + cmpule divisor,modulus,compare + subl modulus,divisor,tmp1 + DIV_ONLY(selne compare,tmp2,quotient,quotient) + srl divisor,1,divisor + selne compare,tmp1,modulus,modulus + bne mask,2b + +9: ldl $1, 0($30) + ldl $2, 8($30) + ldl $0,16($30) + ldl tmp1,24($30) + DIV_ONLY(ldl tmp2,32($30)) + addl $30,STACK,$30 + ret $31,($23),1 + .end ufunction + +/* + * Uhh.. Ugly signed division. I'd rather not have it at all, but + * it's needed in some circumstances. There are different ways to + * handle this, really. This does: + * -a / b = a / -b = -(a / b) + * -a % b = -(a % b) + * a % -b = a % b + * which is probably not the best solution, but at least should + * have the property that (x/y)*y + (x%y) = x. + */ +.align 3 +.globl sfunction +.ent sfunction +sfunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + bis $24,$25,$28 + SLONGIFY($28) + bge $28,7b + stl $24,0($30) + subl $31,$24,$28 + stl $25,8($30) + sellt $24,$28,$24,$24 /* abs($24) */ + stl $23,16($30) + subl $31,$25,$28 + stl tmp1,24($30) + sellt $25,$28,$25,$25 /* abs($25) */ + nop + bsr $23,ufunction + ldl $24,0($30) + ldl $25,8($30) + GETSIGN($28) + subl $31,$27,tmp1 + SLONGIFY($28) + ldl $23,16($30) + sellt $28,tmp1,$27,$27 + ldl tmp1,24($30) + addl $30,STACK,$30 + ret $31,($23),1 + .end sfunction + +/*div 64*/ + +#undef DIV_ONLY +#undef MOD_ONLY +#undef func +#undef modulus +#undef quotient +#undef GETSIGN +#undef STACK +#undef ufunction +#undef sfunction +#undef LONGIFY +#undef SLONGIFY + + +#define DIV +#undef INTSIZE + +#ifdef DIV +#define DIV_ONLY(x,y...) x,##y +#define MOD_ONLY(x,y...) +#define func(x) __div##x +#define modulus $2 +#define quotient $27 +#define GETSIGN(x) xor $24,$25,x +#define STACK 48 +#else +#define DIV_ONLY(x,y...) +#define MOD_ONLY(x,y...) x,##y +#define func(x) __rem##x +#define modulus $27 +#define quotient $2 +#define GETSIGN(x) bis $24,$24,x +#define STACK 32 +#endif + +/* + * For 32-bit operations, we need to extend to 64-bit + */ +#ifdef INTSIZE +#define ufunction func(wu) +#define sfunction func(w) +#define LONGIFY(x) zapnot x,15,x +#define SLONGIFY(x) +#else +#define ufunction func(lu) +#define sfunction func(l) +#define LONGIFY(x) +#define SLONGIFY(x) +#endif + +.align 3 +.globl ufunction +.ent ufunction +ufunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + +7: stl $1, 0($30) + bis $25,$25,divisor + stl $2, 8($30) + bis $24,$24,modulus + stl $0,16($30) + bis $31,$31,quotient + LONGIFY(divisor) + stl tmp1,24($30) + LONGIFY(modulus) + bis $31,1,mask + DIV_ONLY(stl tmp2,32($30)) + beq divisor, 9f /* div by zero */ + +#ifdef INTSIZE + /* + * shift divisor left, using 3-bit shifts for + * 32-bit divides as we can't overflow. Three-bit + * shifts will result in looping three times less + * here, but can result in two loops more later. + * Thus using a large shift isn't worth it (and + * s8add pairs better than a sll..) + */ +1: cmpult divisor,modulus,compare + s8addl divisor,$31,divisor + s8addl mask,$31,mask + bne compare,1b +#else +1: cmpult divisor,modulus,compare + blt divisor, 2f + addl divisor,divisor,divisor + addl mask,mask,mask + bne compare,1b + nop +#endif + + /* ok, start to go right again.. */ +2: DIV_ONLY(addl quotient,mask,tmp2) + srl mask,1,mask + cmpule divisor,modulus,compare + subl modulus,divisor,tmp1 + DIV_ONLY(selne compare,tmp2,quotient,quotient) + srl divisor,1,divisor + selne compare,tmp1,modulus,modulus + bne mask,2b + +9: ldl $1, 0($30) + ldl $2, 8($30) + ldl $0,16($30) + ldl tmp1,24($30) + DIV_ONLY(ldl tmp2,32($30)) + addl $30,STACK,$30 + ret $31,($23),1 + .end ufunction + +/* + * Uhh.. Ugly signed division. I'd rather not have it at all, but + * it's needed in some circumstances. There are different ways to + * handle this, really. This does: + * -a / b = a / -b = -(a / b) + * -a % b = -(a % b) + * a % -b = a % b + * which is probably not the best solution, but at least should + * have the property that (x/y)*y + (x%y) = x. + */ +.align 3 +.globl sfunction +.ent sfunction +sfunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + bis $24,$25,$28 + SLONGIFY($28) + bge $28,7b + stl $24,0($30) + subl $31,$24,$28 + stl $25,8($30) + sellt $24,$28,$24,$24 /* abs($24) */ + stl $23,16($30) + subl $31,$25,$28 + stl tmp1,24($30) + sellt $25,$28,$25,$25 /* abs($25) */ + nop + bsr $23,ufunction + ldl $24,0($30) + ldl $25,8($30) + GETSIGN($28) + subl $31,$27,tmp1 + SLONGIFY($28) + ldl $23,16($30) + sellt $28,tmp1,$27,$27 + ldl tmp1,24($30) + addl $30,STACK,$30 + ret $31,($23),1 + .end sfunction + + +/*rem 64*/ + +#undef DIV_ONLY +#undef MOD_ONLY +#undef func +#undef modulus +#undef quotient +#undef GETSIGN +#undef STACK +#undef ufunction +#undef sfunction +#undef LONGIFY +#undef SLONGIFY + + +#undef DIV + +#ifdef DIV +#define DIV_ONLY(x,y...) x,##y +#define MOD_ONLY(x,y...) +#define func(x) __div##x +#define modulus $2 +#define quotient $27 +#define GETSIGN(x) xor $24,$25,x +#define STACK 48 +#else +#define DIV_ONLY(x,y...) +#define MOD_ONLY(x,y...) x,##y +#define func(x) __rem##x +#define modulus $27 +#define quotient $2 +#define GETSIGN(x) bis $24,$24,x +#define STACK 32 +#endif + +/* + * For 32-bit operations, we need to extend to 64-bit + */ +#ifdef INTSIZE +#define ufunction func(wu) +#define sfunction func(w) +#define LONGIFY(x) zapnot x,15,x +#define SLONGIFY(x) +#else +#define ufunction func(lu) +#define sfunction func(l) +#define LONGIFY(x) +#define SLONGIFY(x) +#endif + + +.align 3 +.globl ufunction +.ent ufunction +ufunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + +7: stl $1, 0($30) + bis $25,$25,divisor + stl $2, 8($30) + bis $24,$24,modulus + stl $0,16($30) + bis $31,$31,quotient + LONGIFY(divisor) + stl tmp1,24($30) + LONGIFY(modulus) + bis $31,1,mask + DIV_ONLY(stl tmp2,32($30)) + beq divisor, 9f /* div by zero */ + +#ifdef INTSIZE + /* + * shift divisor left, using 3-bit shifts for + * 32-bit divides as we can't overflow. Three-bit + * shifts will result in looping three times less + * here, but can result in two loops more later. + * Thus using a large shift isn't worth it (and + * s8add pairs better than a sll..) + */ +1: cmpult divisor,modulus,compare + s8addl divisor,$31,divisor + s8addl mask,$31,mask + bne compare,1b +#else +1: cmpult divisor,modulus,compare + blt divisor, 2f + addl divisor,divisor,divisor + addl mask,mask,mask + bne compare,1b + nop +#endif + + /* ok, start to go right again.. */ +2: DIV_ONLY(addl quotient,mask,tmp2) + srl mask,1,mask + cmpule divisor,modulus,compare + subl modulus,divisor,tmp1 + DIV_ONLY(selne compare,tmp2,quotient,quotient) + srl divisor,1,divisor + selne compare,tmp1,modulus,modulus + bne mask,2b + +9: ldl $1, 0($30) + ldl $2, 8($30) + ldl $0,16($30) + ldl tmp1,24($30) + DIV_ONLY(ldl tmp2,32($30)) + addl $30,STACK,$30 + ret $31,($23),1 + .end ufunction + +/* + * Uhh.. Ugly signed division. I'd rather not have it at all, but + * it's needed in some circumstances. There are different ways to + * handle this, really. This does: + * -a / b = a / -b = -(a / b) + * -a % b = -(a % b) + * a % -b = a % b + * which is probably not the best solution, but at least should + * have the property that (x/y)*y + (x%y) = x. + */ +.align 3 +.globl sfunction +.ent sfunction +sfunction: + subl $30,STACK,$30 + .frame $30,STACK,$23 + .prologue 0 + bis $24,$25,$28 + SLONGIFY($28) + bge $28,7b + stl $24,0($30) + subl $31,$24,$28 + stl $25,8($30) + sellt $24,$28,$24,$24 /* abs($24) */ + stl $23,16($30) + subl $31,$25,$28 + stl tmp1,24($30) + sellt $25,$28,$25,$25 /* abs($25) */ + nop + bsr $23,ufunction + ldl $24,0($30) + ldl $25,8($30) + GETSIGN($28) + subl $31,$27,tmp1 + SLONGIFY($28) + ldl $23,16($30) + sellt $28,tmp1,$27,$27 + ldl tmp1,24($30) + addl $30,STACK,$30 + ret $31,($23),1 + .end sfunction diff --git a/grub-core/lib/sw64/setjmp.S b/grub-core/lib/sw64/setjmp.S new file mode 100644 index 0000000..7e84d6a --- /dev/null +++ b/grub-core/lib/sw64/setjmp.S @@ -0,0 +1,75 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv2+" + +FUNCTION(grub_setjmp) + ldgp gp, 0(pv) +#define FRAME 0 + .frame sp, FRAME, ra, 0 + + stl s0, JB_S0*8(a0) + stl s1, JB_S1*8(a0) + stl s2, JB_S2*8(a0) + stl s3, JB_S3*8(a0) + stl s4, JB_S4*8(a0) + stl s5, JB_S5*8(a0) + stl ra, JB_PC*8(a0) + addl sp, FRAME, t1 + stl t1, JB_SP*8(a0) + stl fp, JB_FP*8(a0) + fstd $f2, JB_F2*8(a0) + fstd $f3, JB_F3*8(a0) + fstd $f4, JB_F4*8(a0) + fstd $f5, JB_F5*8(a0) + fstd $f6, JB_F6*8(a0) + fstd $f7, JB_F7*8(a0) + fstd $f8, JB_F8*8(a0) + fstd $f9, JB_F9*8(a0) + ldi a0, 0($31) + ret + +FUNCTION(grub_longjmp) + mov a1, v0 + ldl s0, JB_S0*8(a0) + ldl s1, JB_S1*8(a0) + ldl s2, JB_S2*8(a0) + ldl s3, JB_S3*8(a0) + ldl s4, JB_S4*8(a0) + ldl s5, JB_S5*8(a0) + ldl ra, JB_PC*8(a0) + ldl fp, JB_FP*8(a0) + ldl t0, JB_SP*8(a0) + fldd $f2, JB_F2*8(a0) + fldd $f3, JB_F3*8(a0) + fldd $f4, JB_F4*8(a0) + fldd $f5, JB_F5*8(a0) + fldd $f6, JB_F6*8(a0) + fldd $f7, JB_F7*8(a0) + fldd $f8, JB_F8*8(a0) + fldd $f9, JB_F9*8(a0) + seleq v0, 1, v0, v0 + mov t0, sp + ret diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index 87aa1ce..0ef9a18 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -125,7 +125,7 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, void * EXPORT_FUNC (grub_efi_find_configuration_table) (const grub_guid_t *target_guid); -#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__) +#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__) || defined (__sw_64__) void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); #endif diff --git a/include/grub/sw64/divide.h b/include/grub/sw64/divide.h new file mode 100644 index 0000000..a6c8eae --- /dev/null +++ b/include/grub/sw64/divide.h @@ -0,0 +1,11 @@ +#ifndef __DIVIDE_H__ +#define __DIVIDE_H__ +void EXPORT_FUNC(__divw) (void); +void EXPORT_FUNC(__remw) (void); +void EXPORT_FUNC(__divl) (void); +void EXPORT_FUNC(__reml) (void); +void EXPORT_FUNC(__divwu) (void); +void EXPORT_FUNC(__remwu) (void); +void EXPORT_FUNC(__divlu) (void); +void EXPORT_FUNC(__remlu) (void); +#endif diff --git a/include/grub/sw64/efi/memory.h b/include/grub/sw64/efi/memory.h new file mode 100644 index 0000000..b869f46 --- /dev/null +++ b/include/grub/sw64/efi/memory.h @@ -0,0 +1,7 @@ +#ifndef GRUB_MEMORY_CPU_HEADER +#include + +#define GRUB_EFI_MAX_USABLE_ADDRESS 0xFFF000003FFFFFFFULL +#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS + +#endif /* ! GRUB_MEMORY_CPU_HEADER */ diff --git a/include/grub/sw64/efi/time.h b/include/grub/sw64/efi/time.h new file mode 100644 index 0000000..897ce9c --- /dev/null +++ b/include/grub/sw64/efi/time.h @@ -0,0 +1,23 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ +#ifndef GRUB_MACHINE_TIME_HEADER +#define GRUB_MACHINE_TIME_HEADER 1 + +#include + +#endif /* ! GRUB_MACHINE_TIME_HEADER */ diff --git a/include/grub/sw64/io.h b/include/grub/sw64/io.h new file mode 100644 index 0000000..dee76bd --- /dev/null +++ b/include/grub/sw64/io.h @@ -0,0 +1,62 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_IO_H +#define GRUB_IO_H 1 + +#include + +typedef grub_addr_t grub_port_t; + +static __inline unsigned char +grub_inb (grub_port_t port) +{ + return *(volatile grub_uint8_t *) port; +} + +static __inline unsigned short int +grub_inw (grub_port_t port) +{ + return *(volatile grub_uint16_t *) port; +} + +static __inline unsigned int +grub_inl (grub_port_t port) +{ + return *(volatile grub_uint32_t *) port; +} + +static __inline void +grub_outb (unsigned char value, grub_port_t port) +{ + *(volatile grub_uint8_t *) port = value; +} + +static __inline void +grub_outw (unsigned short int value, grub_port_t port) +{ + *(volatile grub_uint16_t *) port = value; +} + +static __inline void +grub_outl (unsigned int value, grub_port_t port) +{ + *(volatile grub_uint32_t *) port = value; +} + +#endif /* _SYS_IO_H */ diff --git a/include/grub/sw64/jmpbuf-offsets.h b/include/grub/sw64/jmpbuf-offsets.h new file mode 100644 index 0000000..86e8da2 --- /dev/null +++ b/include/grub/sw64/jmpbuf-offsets.h @@ -0,0 +1,35 @@ +/* Private macros for accessing __jmp_buf contents. Alpha version. + Copyright (C) 2006-2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#define JB_S0 0 +#define JB_S1 1 +#define JB_S2 2 +#define JB_S3 3 +#define JB_S4 4 +#define JB_S5 5 +#define JB_PC 6 +#define JB_FP 7 +#define JB_SP 8 +#define JB_F2 9 +#define JB_F3 10 +#define JB_F4 11 +#define JB_F5 12 +#define JB_F6 13 +#define JB_F7 14 +#define JB_F8 15 +#define JB_F9 16 diff --git a/include/grub/sw64/kernel.h b/include/grub/sw64/kernel.h new file mode 100644 index 0000000..c5496a0 --- /dev/null +++ b/include/grub/sw64/kernel.h @@ -0,0 +1,25 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_CPU_KERNEL_HEADER +#define GRUB_CPU_KERNEL_HEADER 1 + +#define GRUB_MOD_ALIGN 0x1 +#define GRUB_MOD_GAP 0x0 + +#endif /* ! GRUB_CPU_KERNEL_HEADER */ diff --git a/include/grub/sw64/pal.h b/include/grub/sw64/pal.h new file mode 100644 index 0000000..274f07d --- /dev/null +++ b/include/grub/sw64/pal.h @@ -0,0 +1,49 @@ +#ifndef __SW64_PAL_H +#define __SW64_PAL_H + +#define HMC_cpuid 0x03 +#define HMC_ret 0x1A +#define HMC_swpipl 0x35 + +#define GET_CPU_FREQ 4 + +#define __CALL_HMC_W1(NAME, TYPE0) \ +static inline void NAME(TYPE0 arg0) \ +{ \ + register TYPE0 __r16 __asm__("$16") = arg0; \ + __asm__ __volatile__ ("sys_call %1 # "#NAME \ + : "=r"(__r16) \ + : "i"(HMC_ ## NAME), "0"(__r16) \ + : "$1", "$22", "$23", "$24", "$25"); \ +} + +#define __CALL_HMC_RW1(NAME, RTYPE, TYPE0) \ +static inline RTYPE NAME(TYPE0 arg0) \ +{ \ + register RTYPE __r0 __asm__("$0"); \ + register TYPE0 __r16 __asm__("$16") = arg0; \ + __asm__ __volatile__ ("sys_call %2 # "#NAME \ + : "=r"(__r16), "=r"(__r0) \ + : "i"(HMC_ ## NAME), "0"(__r16) \ + : "$1", "$22", "$23", "$24", "$25"); \ + return __r0; \ +} + +#define __CALL_HMC_RW2(NAME, RTYPE, TYPE0, TYPE1) \ +static inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1) \ +{ \ + register RTYPE __r0 __asm__("$0"); \ + register TYPE0 __r16 __asm__("$16") = arg0; \ + register TYPE1 __r17 __asm__("$17") = arg1; \ + __asm__ __volatile__ ("sys_call %3 # "#NAME \ + : "=r"(__r16), "=r"(__r17), "=r"(__r0) \ + : "i"(HMC_ ## NAME), "0"(__r16), "1"(__r17) \ + : "$1", "$22", "$23", "$24", "$25"); \ + return __r0; \ +} + +__CALL_HMC_W1(ret, unsigned long); +__CALL_HMC_RW1(swpipl, unsigned long, unsigned long); +__CALL_HMC_RW2(cpuid, unsigned long, unsigned long, unsigned long); + +#endif /* __SW_64_HMC_H */ diff --git a/include/grub/sw64/regdef.h b/include/grub/sw64/regdef.h new file mode 100644 index 0000000..b30eb77 --- /dev/null +++ b/include/grub/sw64/regdef.h @@ -0,0 +1,44 @@ +#ifndef __sw_regdef_h__ +#define __sw_regdef_h__ + +#define v0 $0 /* function return value */ + +#define t0 $1 /* temporary registers (caller-saved) */ +#define t1 $2 +#define t2 $3 +#define t3 $4 +#define t4 $5 +#define t5 $6 +#define t6 $7 +#define t7 $8 + +#define s0 $9 /* saved-registers (callee-saved registers) */ +#define s1 $10 +#define s2 $11 +#define s3 $12 +#define s4 $13 +#define s5 $14 +#define s6 $15 +#define fp s6 /* frame-pointer (s6 in frame-less procedures) */ + +#define a0 $16 /* argument registers (caller-saved) */ +#define a1 $17 +#define a2 $18 +#define a3 $19 +#define a4 $20 +#define a5 $21 + +#define t8 $22 /* more temps (caller-saved) */ +#define t9 $23 +#define t10 $24 +#define t11 $25 +#define ra $26 /* return address register */ +#define t12 $27 + +#define pv t12 /* procedure-variable register */ +#define AT $at /* assembler temporary */ +#define gp $29 /* global pointer */ +#define sp $30 /* stack pointer */ +#define zero $31 /* reads as zero, writes are noops */ + +#endif /* __sw_64_regdef_h__ */ diff --git a/include/grub/sw64/setjmp.h b/include/grub/sw64/setjmp.h new file mode 100644 index 0000000..a71c9c5 --- /dev/null +++ b/include/grub/sw64/setjmp.h @@ -0,0 +1,28 @@ +/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version. + Copyright (C) 1999, 2000, 2008 Free Software Foundation, Inc. + Contributed by David Mosberger-Tang . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* User code must not depend on the internal representation of jmp_buf. */ + +#define _JBLEN 70 + +/* the __jmp_buf element type should be __float80 per ABI... */ +typedef long grub_jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */ + +int grub_setjmp (grub_jmp_buf env); +void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); diff --git a/include/grub/sw64/time.h b/include/grub/sw64/time.h new file mode 100644 index 0000000..03ee79f --- /dev/null +++ b/include/grub/sw64/time.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007, 2008 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef KERNEL_CPU_TIME_HEADER +#define KERNEL_CPU_TIME_HEADER 1 + +static __inline void +grub_cpu_idle (void) +{ + /* FIXME: not implemented */ +} + +#endif /* ! KERNEL_CPU_TIME_HEADER */ diff --git a/include/grub/sw64/types.h b/include/grub/sw64/types.h new file mode 100644 index 0000000..91a546d --- /dev/null +++ b/include/grub/sw64/types.h @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB 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. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_TYPES_CPU_HEADER +#define GRUB_TYPES_CPU_HEADER 1 + +/* The size of void *. */ +#define GRUB_TARGET_SIZEOF_VOID_P 8 + +/* The size of long. */ +#define GRUB_TARGET_SIZEOF_LONG 8 + +/* ia64 is little-endian (usually). */ +#undef GRUB_TARGET_WORDS_BIGENDIAN + + +#endif /* ! GRUB_TYPES_CPU_HEADER */ -- 2.33.0