cosmopolitan/libc/macros.inc

333 lines
8.5 KiB
PHP

/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
│ This program 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; version 2 of the License. │
│ │
│ This program 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 this program; if not, write to the Free Software │
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
/ Shorthand notation for widely-acknowledged sections.
.macro .rodata
.section .rodata,"a",@progbits
.endm
.macro .init
.section .init,"ax",@progbits
.endm
.macro .real
.section .text.real,"ax",@progbits
.endm
.macro .text.startup
.section .text.startup,"ax",@progbits
.endm
.macro .text.exit
.section .text.exit,"ax",@progbits
.endm
.macro .firstclass
.section .text.hot,"ax",@progbits
.endm
.macro .text.unlikely
.section .text.unlikely,"ax",@progbits
.endm
.macro .text.likely
.section .text.hot,"ax",@progbits
.endm
.macro .text.modernity
.section .text.modernity,"ax",@progbits
.align 16
.endm
.macro .text.antiquity
.section .text.antiquity,"ax",@progbits
.endm
.macro .text.hot
.section .text.hot,"ax",@progbits
.endm
.macro .preinit_array
.section .preinit_array,"a",@init_array
.endm
.macro .init_array
.section .init_array,"a",@init_array
.endm
.macro .text.windows
.section .text.windows,"ax",@progbits
.endm
/ Mergeable numeric constant sections.
/
/ @note linker de-dupes item/values across whole compile
/ @note therefore item/values are reordered w.r.t. link order
/ @note therefore no section relative addressing
.macro .rodata.cst4
.section .rodata.cst4,"aM",@progbits,4
.align 4
.endm
.macro .rodata.cst8
.section .rodata.cst8,"aM",@progbits,8
.align 8
.endm
.macro .rodata.cst16
.section .rodata.cst16,"aM",@progbits,16
.align 16
.endm
.macro .rodata.cst32
.section .rodata.cst32,"aM",@progbits,32
.align 32
.endm
.macro .rodata.cst64
.section .rodata.cst64,"aM",@progbits,64
.align 64
.endm
.macro .tdata
.section .tdata,"awT",@progbits
.align 4
.endm
.macro .tbss
.section .tdata,"awT",@nobits
.align 4
.endm
/ Mergeable NUL-terminated UTF-8 string constant section.
/
/ @note linker de-dupes C strings here across whole compile
/ @note therefore item/values are reordered w.r.t. link order
/ @note therefore no section relative addressing
.macro .rodata.str1.1
.section .rodata.str1.1,"aSM",@progbits,1
.align 1
.endm
/ Locates unreferenced code invulnerable to --gc-sections.
.macro .keep.text
.section .keep.text,"ax",@progbits
.endm
/ Flags code as only allowed for testing purposes.
.macro .testonly
.section .test,"ax",@progbits
.endm
/ Makes code runnable while code morphing.
.macro .privileged
.section .privileged,"ax",@progbits
.endm
/ Post-Initialization Read-Only (PIRO) BSS section.
/ @param ss is an optional string, for control image locality
.macro .piro ss
.ifnb \ss
.section .piro.sort.bss.\ss,"aw",@nobits
.else
.section .piro.bss,"aw",@nobits
.endif
.endm
/ Helpers for Cosmopolitan _init() amalgamation magic.
/ @param name should be consistent across macros for a module
/ @see libc/runtime/_init.S
.macro .initro number:req name:req
.section .initro.\number\().\name,"a",@progbits
.align 8
.endm
.macro .initbss number:req name:req
.section .piro.bss.init.2.\number\().\name,"aw",@nobits
.align 8
.endm
.macro .init.start number:req name:req
.section .init.\number\().\name,"ax",@progbits
\name:
.endm
.macro .init.end number:req name:req bnd=globl vis
.endfn \name,\bnd,\vis
.previous
.endm
/ Declares alternative implementation of function.
/ @param implement e.g. tinymath_pow
/ @param canonical e.g. pow
.macro .alias implement:req canonical:req
.equ \canonical,\implement
.weak \canonical
.endm
/ Ends function definition.
/ @cost saves 1-3 lines of code
.macro .endfn name:req bnd vis
.size \name,.-\name
.type \name,@function
.ifnb \bnd
.\bnd \name
.endif
.ifnb \vis
.\vis \name
.endif
.endm
/ Ends variable definition.
/ @cost saves 1-3 lines of code
.macro .endobj name:req bnd vis
.size \name,.-\name
.type \name,@object
.ifnb \bnd
.\bnd \name
.endif
.ifnb \vis
.\vis \name
.endif
.endm
/ Custom emulator instruction for bottom stack frame.
.macro bofram endfunc:req
.byte 0x0f,0x1f,0x45,\endfunc-. # nopl disp8(%rbp)
.endm
/ Overrides LOOP instruction.
/ With its mop-Fusion Mexican equivalent.
/ Thus avoiding 3x legacy pipeline slowdown.
.macro loop label:req
.byte 0x83,0xe9,0x01 # sub $1,%ecx
jnz \label
.endm
/ Pushes CONSTEXPR [-128,127].
/ @note assembler is wrong for non-literal constexprs
.macro pushb x:req
.byte 0x6a,\x
.endm
/ Sign-extends CONSTEXPR [-128,127] to REGISTER.
/ @cost ≥1 cycles, -2 bytes
.macro pushpop constexpr:req register:req
pushb \constexpr
pop \register
.endm
/ Moves REGISTER to REGISTER.
/ @cost ≥1 cycles, -1 REX byte
.macro movpp src:req dest:req
push \src
pop \dest
.endm
/ Declares optional function.
.macro .optfn fn:req
.globl \fn
.weak \fn
.equ \fn,missingno
.type \fn,@function
.endm
/ Embeds fixed-width zero-filled string table.
/ @note zero-padded nul-terminated
.macro .fxstr width head rest:vararg
.ifnb \head
0: .ascii "\head"
.org 0b+\width
.fxstr \width,\rest
.endif
.endm
/ Embeds Fixed-Width Zero-Padded String.
/ @note .fxstr is better
.macro .ascin str:req fieldsize:req
1347: .ascii "\str"
.org 1347b+\fieldsize,0x00
.endm
/ Marks symbols as object en-masse.
/ @note zero-padded nul-terminated
.macro .object symbol rest:vararg
.ifnb \symbol
.type \symbol,@object
.object \rest
.endif
.endm
/ Pads function prologue unconditionally for runtime hooking.
/ @cost ≥0.3 cycles, 5 bytes
/ @see .profilable
.macro .hookable
/ nopl 0x00(%rax,%rax,1)
83457: .byte 0x0f,0x1f,0x44,0x00,0x00
.pushsection __mcount_loc,"a",@progbits
.quad 83457b
.popsection
.endm
/ Puts initialized data in uninitialized data section.
.macro .bsdata name:req expr:req bnd vis
.pushsection .initbss.300._init_\name,"aw",@nobits
\name: .quad 0
.endobj \name,\bnd,\vis
.popsection
.pushsection .initro.300._init_\name,"a",@progbits
.quad \expr
.popsection
.pushsection .init.300._init_\name,"ax",@progbits
_init_\name:
movsq
.endfn _init_\name
.popsection
.endm
/ ICE Breakpoint.
/ Modern gas forgot this but objdump knows
/ @mode long,legacy,real
.macro icebp
.byte 0xF1
.endm
.macro int1
icebp
.endm
/ Sets breakpoint for software debugger.
/ @mode long,legacy,real
.macro .softicebp
.byte 0x53 # push bx
.byte 0x87,0xdb # xchg bx,bx (bochs breakpoint)
.byte 0x5b # pop bx
.byte 0x66,0x90 # xchg ax,ax (microsoft breakpoint)
int3 # gdb breakpoint
.endm
/ Assembles Intel Official 4-Byte NOP.
.macro fatnop4
.byte 0x0f,0x1f,0x40,0x00
.endm
/ Pulls unrelated module into linkage.
/
/ In order for this technique to work with --gc-sections, another
/ module somewhere might want to weakly reference whats yoinked.
.macro yoink symbol:req
.pushsection .yoink
nop "\symbol"
.popsection
.endm
.macro .yoink symbol:req
.pushsection .yoink
nop "\symbol"
.popsection
.endm
/ Calls Windows function.
/
/ @param cx,dx,r8,r9,stack
/ @return ax
/ @clob ax,cx,dx,r8-r11
.macro ntcall symbol:req
sub $32,%rsp
call *\symbol(%rip)
add $32,%rsp
.endm