diff --git a/CMakeLists.txt b/CMakeLists.txt index e0448b1f..2d96606c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ unset(_default_abi) ## Arch-and-model -set(_all_archs arm arm64 e2k loongarch64 mips32 mips64 ppc32 ppc64 riscv64 s390x i386 x86_64 combined) +set(_all_archs alpha arm arm64 e2k loongarch64 mips32 mips64 ppc32 ppc64 riscv64 s390x i386 x86_64 combined) # Try at start to auto determine arch from CMake. if(CMAKE_SYSTEM_PROCESSOR IN_LIST _all_archs) @@ -80,7 +80,7 @@ else() endif() endif() -set(BOOST_CONTEXT_ARCHITECTURE "${_default_arch}" CACHE STRING "Boost.Context architecture (arm, arm64, e2k, loongarch64, mips32, mips64, ppc32, ppc64, riscv64, s390x, i386, x86_64, combined)") +set(BOOST_CONTEXT_ARCHITECTURE "${_default_arch}" CACHE STRING "Boost.Context architecture (alpha, arm, arm64, e2k, loongarch64, mips32, mips64, ppc32, ppc64, riscv64, s390x, i386, x86_64, combined)") set_property(CACHE BOOST_CONTEXT_ARCHITECTURE PROPERTY STRINGS ${_all_archs}) unset(_all_archs) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 3b04ce90..8c9d0f3b 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -528,6 +528,30 @@ alias asm_sources gcc ; +# ALPHA +# ALPHA/SYSV/ELF +alias asm_sources + : asm/make_alpha_sysv_elf_gas.S + asm/jump_alpha_sysv_elf_gas.S + asm/ontop_alpha_sysv_elf_gas.S + : sysv + 64 + alpha + elf + gcc + ; + +alias asm_sources + : asm/make_alpha_sysv_elf_gas.S + asm/jump_alpha_sysv_elf_gas.S + asm/ontop_alpha_sysv_elf_gas.S + : sysv + 64 + alpha + elf + clang + ; + # S390X # S390X/SYSV/ELF alias asm_sources diff --git a/doc/architectures.qbk b/doc/architectures.qbk index b17e1f22..df2dea2d 100644 --- a/doc/architectures.qbk +++ b/doc/architectures.qbk @@ -12,6 +12,7 @@ architectures: [table Supported architectures () [[Architecture] [LINUX (UNIX)] [Windows] [MacOS X] [iOS]] + [[alpha] [SYSV|ELF] [-] [-] [-]] [[arm (aarch32)] [AAPCS|ELF] [AAPCS|PE] [-] [AAPCS|MACH-O]] [[arm (aarch64)] [AAPCS|ELF] [-] [AAPCS|MACH-O] [AAPCS|MACH-O]] [[i386] [SYSV|ELF] [MS|PE] [SYSV|MACH-O] [-]] diff --git a/src/asm/jump_alpha_sysv_elf_gas.S b/src/asm/jump_alpha_sysv_elf_gas.S new file mode 100644 index 00000000..fd52df41 --- /dev/null +++ b/src/asm/jump_alpha_sysv_elf_gas.S @@ -0,0 +1,143 @@ +/* + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ +/********************************************************* + * * + * --------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | * + * --------------------------------------------------- * + * | 0x0 | 0x8 | 0x10 | 0x18 | 0x20 | * + * --------------------------------------------------- * + * | $f2 | $f3 | $f4 | $f5 | $f6 | * + * --------------------------------------------------- * + * | 5 | 6 | 7 | 8 | 9 | * + * --------------------------------------------------- * + * | 0x28 | 0x30 | 0x38 | 0x40 | 0x48 | * + * --------------------------------------------------- * + * | $f7 | $f8 | $f9 | $9 | $10 | * + * --------------------------------------------------- * + * | 10 | 11 | 12 | 13 | 14 | * + * --------------------------------------------------- * + * | 0x50 | 0x58 | 0x60 | 0x68 | 0x70 | * + * --------------------------------------------------- * + * | $11 | $12 | $13 | $14 | $15 | * + * --------------------------------------------------- * + * | 15 | 16 | 17 | 18 | 19 | * + * --------------------------------------------------- * + * | 0x78 | 0x80 | 0x88 | 0x90 | 0x98 | * + * --------------------------------------------------- * + * | $29 | $26 | PC | hidden | pad | * + * | (gp) | (ra) | | ptr | | * + * --------------------------------------------------- * + * * + ********************************************************/ + +/* The Alpha calling standard returns a 16 byte struct such as transfer_t + via a hidden pointer in $16, shifting the declared arguments to $17 and + $18. That pointer belongs to the frame that made the call, so it has to + travel with the context: each context records the pointer its own + suspending call was given, and whoever resumes it stores through it. */ + +.file "jump_alpha_sysv_elf_gas.S" +.text +.align 4 +.globl jump_fcontext +.hidden jump_fcontext +.type jump_fcontext, @function +.ent jump_fcontext +jump_fcontext: + .frame $30, 0, $26, 0 + .prologue 0 + + # reserve space for context-data on the current stack + lda $30, -0xa0($30) + + # save callee-saved floating point registers $f2 - $f9 + stt $f2, 0x00($30) + stt $f3, 0x08($30) + stt $f4, 0x10($30) + stt $f5, 0x18($30) + stt $f6, 0x20($30) + stt $f7, 0x28($30) + stt $f8, 0x30($30) + stt $f9, 0x38($30) + + # save callee-saved integer registers $9 - $15 + stq $9, 0x40($30) + stq $10, 0x48($30) + stq $11, 0x50($30) + stq $12, 0x58($30) + stq $13, 0x60($30) + stq $14, 0x68($30) + stq $15, 0x70($30) + + # save gp and return address + stq $29, 0x78($30) + stq $26, 0x80($30) + + # save the return address as the resumption PC + stq $26, 0x88($30) + + # save the hidden transfer_t pointer this call was given + stq $16, 0x90($30) + + # $1 = fcontext_t of the context we are suspending + bis $31, $30, $1 + + # switch to the stack of the context we are resuming + bis $31, $17, $30 + + # restore callee-saved floating point registers $f2 - $f9 + ldt $f2, 0x00($30) + ldt $f3, 0x08($30) + ldt $f4, 0x10($30) + ldt $f5, 0x18($30) + ldt $f6, 0x20($30) + ldt $f7, 0x28($30) + ldt $f8, 0x30($30) + ldt $f9, 0x38($30) + + # restore callee-saved integer registers $9 - $15 + ldq $9, 0x40($30) + ldq $10, 0x48($30) + ldq $11, 0x50($30) + ldq $12, 0x58($30) + ldq $13, 0x60($30) + ldq $14, 0x68($30) + ldq $15, 0x70($30) + + # restore gp and return address + ldq $29, 0x78($30) + ldq $26, 0x80($30) + + # load the resumption PC into $27; it doubles as the procedure value + # for a context-function entered for the first time, which computes + # its own gp from it + ldq $27, 0x88($30) + + # load the hidden transfer_t pointer of the resumed context + ldq $2, 0x90($30) + + # release the context-data + lda $30, 0xa0($30) + + # return transfer_t{ $1, $18 } through the hidden pointer + stq $1, 0x00($2) + stq $18, 0x08($2) + bis $31, $2, $0 + + # and pass it by value, for a context entered via make_fcontext + bis $31, $1, $16 + bis $31, $18, $17 + + # the ret hint pops the return prediction stack entry pushed by the + # bsr that called us; the resumption PC is where that call appears to + # return. A jmp hint would orphan one entry per switch. + ret $31, ($27), 0 +.end jump_fcontext +.size jump_fcontext, .-jump_fcontext + +/* Mark that we don't need executable stack. */ +.section .note.GNU-stack,"",@progbits diff --git a/src/asm/make_alpha_sysv_elf_gas.S b/src/asm/make_alpha_sysv_elf_gas.S new file mode 100644 index 00000000..2fd2eb77 --- /dev/null +++ b/src/asm/make_alpha_sysv_elf_gas.S @@ -0,0 +1,118 @@ +/* + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ +/********************************************************* + * * + * --------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | * + * --------------------------------------------------- * + * | 0x0 | 0x8 | 0x10 | 0x18 | 0x20 | * + * --------------------------------------------------- * + * | $f2 | $f3 | $f4 | $f5 | $f6 | * + * --------------------------------------------------- * + * | 5 | 6 | 7 | 8 | 9 | * + * --------------------------------------------------- * + * | 0x28 | 0x30 | 0x38 | 0x40 | 0x48 | * + * --------------------------------------------------- * + * | $f7 | $f8 | $f9 | $9 | $10 | * + * --------------------------------------------------- * + * | 10 | 11 | 12 | 13 | 14 | * + * --------------------------------------------------- * + * | 0x50 | 0x58 | 0x60 | 0x68 | 0x70 | * + * --------------------------------------------------- * + * | $11 | $12 | $13 | $14 | $15 | * + * --------------------------------------------------- * + * | 15 | 16 | 17 | 18 | 19 | * + * --------------------------------------------------- * + * | 0x78 | 0x80 | 0x88 | 0x90 | 0x98 | * + * --------------------------------------------------- * + * | $29 | $26 | PC | hidden | pad | * + * | (gp) | (ra) | | ptr | | * + * --------------------------------------------------- * + * | 20 | 21 | | | | * + * --------------------------------------------------- * + * | 0xa0 | 0xa8 | | | | * + * --------------------------------------------------- * + * | transfer_t scratch | * + * --------------------------------------------------- * + * * + ********************************************************/ + +.file "make_alpha_sysv_elf_gas.S" +.text +.align 4 +.globl make_fcontext +.hidden make_fcontext +.type make_fcontext, @function +.ent make_fcontext +make_fcontext: + .frame $30, 0, $26, 0 + ldgp $29, 0($27) + .prologue 1 + + # $16: top address of the context-stack + # $17: size of the context-stack + # $18: address of the context-function + + # shift the address in $16 down to a 16 byte boundary + bic $16, 0xF, $0 + + # reserve space for the context-data and for the transfer_t that + # jump_fcontext writes through the hidden pointer when it enters the + # context-function + lda $0, -0xc0($0) + + # the context-function is the resumption PC + stq $18, 0x88($0) + + # jump_fcontext restores gp before entering the context-function; the + # context-function computes its own, but leave a valid value here + stq $29, 0x78($0) + + # point the hidden pointer at the scratch transfer_t + lda $1, 0xa0($0) + stq $1, 0x90($0) + + # start the context with cleared callee-saved registers + stt $f31, 0x00($0) + stt $f31, 0x08($0) + stt $f31, 0x10($0) + stt $f31, 0x18($0) + stt $f31, 0x20($0) + stt $f31, 0x28($0) + stt $f31, 0x30($0) + stt $f31, 0x38($0) + stq $31, 0x40($0) + stq $31, 0x48($0) + stq $31, 0x50($0) + stq $31, 0x58($0) + stq $31, 0x60($0) + stq $31, 0x68($0) + stq $31, 0x70($0) + + # save the address of finish as the return address of the + # context-function; it is entered after the context-function returns + ldq $1, finish($29) !literal + stq $1, 0x80($0) + + # return the pointer to the context-data in $0 + ret $31, ($26), 1 + +finish: + # the context-function returned; gp is not live here, so recompute it + br $29, 1f +1: ldgp $29, 0($29) + + # exit code is zero + bis $31, $31, $16 + + # exit application + ldq $27, _exit($29) !literal + jsr $26, ($27), _exit +.end make_fcontext +.size make_fcontext, .-make_fcontext + +/* Mark that we don't need executable stack. */ +.section .note.GNU-stack,"",@progbits diff --git a/src/asm/ontop_alpha_sysv_elf_gas.S b/src/asm/ontop_alpha_sysv_elf_gas.S new file mode 100644 index 00000000..54d6f405 --- /dev/null +++ b/src/asm/ontop_alpha_sysv_elf_gas.S @@ -0,0 +1,139 @@ +/* + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ +/********************************************************* + * * + * --------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | * + * --------------------------------------------------- * + * | 0x0 | 0x8 | 0x10 | 0x18 | 0x20 | * + * --------------------------------------------------- * + * | $f2 | $f3 | $f4 | $f5 | $f6 | * + * --------------------------------------------------- * + * | 5 | 6 | 7 | 8 | 9 | * + * --------------------------------------------------- * + * | 0x28 | 0x30 | 0x38 | 0x40 | 0x48 | * + * --------------------------------------------------- * + * | $f7 | $f8 | $f9 | $9 | $10 | * + * --------------------------------------------------- * + * | 10 | 11 | 12 | 13 | 14 | * + * --------------------------------------------------- * + * | 0x50 | 0x58 | 0x60 | 0x68 | 0x70 | * + * --------------------------------------------------- * + * | $11 | $12 | $13 | $14 | $15 | * + * --------------------------------------------------- * + * | 15 | 16 | 17 | 18 | 19 | * + * --------------------------------------------------- * + * | 0x78 | 0x80 | 0x88 | 0x90 | 0x98 | * + * --------------------------------------------------- * + * | $29 | $26 | PC | hidden | pad | * + * | (gp) | (ra) | | ptr | | * + * --------------------------------------------------- * + * * + ********************************************************/ + +.file "ontop_alpha_sysv_elf_gas.S" +.text +.align 4 +.globl ontop_fcontext +.hidden ontop_fcontext +.type ontop_fcontext, @function +.ent ontop_fcontext +ontop_fcontext: + .frame $30, 0, $26, 0 + .prologue 0 + + # $16: hidden transfer_t pointer + # $17: fcontext_t to + # $18: void * vp + # $19: transfer_t (*fn)(transfer_t) + + # reserve space for context-data on the current stack + lda $30, -0xa0($30) + + # save callee-saved floating point registers $f2 - $f9 + stt $f2, 0x00($30) + stt $f3, 0x08($30) + stt $f4, 0x10($30) + stt $f5, 0x18($30) + stt $f6, 0x20($30) + stt $f7, 0x28($30) + stt $f8, 0x30($30) + stt $f9, 0x38($30) + + # save callee-saved integer registers $9 - $15 + stq $9, 0x40($30) + stq $10, 0x48($30) + stq $11, 0x50($30) + stq $12, 0x58($30) + stq $13, 0x60($30) + stq $14, 0x68($30) + stq $15, 0x70($30) + + # save gp and return address + stq $29, 0x78($30) + stq $26, 0x80($30) + + # save the return address as the resumption PC + stq $26, 0x88($30) + + # save the hidden transfer_t pointer this call was given + stq $16, 0x90($30) + + # $1 = fcontext_t of the context we are suspending + bis $31, $30, $1 + + # switch to the stack of the context we are resuming + bis $31, $17, $30 + + # restore callee-saved floating point registers $f2 - $f9 + ldt $f2, 0x00($30) + ldt $f3, 0x08($30) + ldt $f4, 0x10($30) + ldt $f5, 0x18($30) + ldt $f6, 0x20($30) + ldt $f7, 0x28($30) + ldt $f8, 0x30($30) + ldt $f9, 0x38($30) + + # restore callee-saved integer registers $9 - $15 + ldq $9, 0x40($30) + ldq $10, 0x48($30) + ldq $11, 0x50($30) + ldq $12, 0x58($30) + ldq $13, 0x60($30) + ldq $14, 0x68($30) + ldq $15, 0x70($30) + + # restore gp; the resumed context's return address becomes the return + # address of the ontop-function, so that when it returns it lands where + # the resumed context suspended + ldq $29, 0x78($30) + ldq $26, 0x80($30) + + # load the hidden transfer_t pointer of the resumed context; the + # ontop-function returns its transfer_t through it + ldq $2, 0x90($30) + + # skip the resumption PC + # release the context-data + lda $30, 0xa0($30) + + # transfer_t{ $1, $18 } is passed by value in $17/$18; $18 already + # holds vp + bis $31, $2, $16 + bis $31, $1, $17 + + # jump to the ontop-function; $27 is its procedure value. The + # ontop-function returns to the resumed context rather than to our + # caller, so the ret hint pops the entry the bsr that called us + # pushed, which would otherwise be orphaned. + bis $31, $19, $27 + ret $31, ($27), 0 +.end ontop_fcontext +.size ontop_fcontext, .-ontop_fcontext + +/* Mark that we don't need executable stack. */ +.section .note.GNU-stack,"",@progbits