2020-12-24 07:42:56 +00:00
|
|
|
/*-*- 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 │
|
|
|
|
│ │
|
2020-12-28 01:18:44 +00:00
|
|
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
|
|
│ any purpose with or without fee is hereby granted, provided that the │
|
|
|
|
│ above copyright notice and this permission notice appear in all copies. │
|
2020-12-24 07:42:56 +00:00
|
|
|
│ │
|
2020-12-28 01:18:44 +00:00
|
|
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
|
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
|
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
|
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
|
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
|
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
|
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
|
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
2020-12-24 07:42:56 +00:00
|
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Shorthand notation for widely-acknowledged sections.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .rodata
|
|
|
|
.section .rodata,"a",@progbits
|
|
|
|
.endm
|
|
|
|
.macro .init
|
|
|
|
.section .init,"ax",@progbits
|
|
|
|
.endm
|
|
|
|
.macro .real
|
|
|
|
.section .text.real,"ax",@progbits
|
|
|
|
.endm
|
2021-02-24 04:23:19 +00:00
|
|
|
.macro .head
|
|
|
|
.section .text.head,"ax",@progbits
|
|
|
|
.endm
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .text.startup
|
|
|
|
.section .text.startup,"ax",@progbits
|
|
|
|
.endm
|
2020-08-25 11:23:25 +00:00
|
|
|
.macro .text.exit
|
|
|
|
.section .text.exit,"ax",@progbits
|
|
|
|
.endm
|
2020-06-15 14:18:57 +00:00
|
|
|
.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
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// 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
|
2020-06-15 14:18:57 +00:00
|
|
|
.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
|
2020-08-25 11:23:25 +00:00
|
|
|
.macro .tdata
|
|
|
|
.section .tdata,"awT",@progbits
|
|
|
|
.align 4
|
|
|
|
.endm
|
|
|
|
.macro .tbss
|
|
|
|
.section .tdata,"awT",@nobits
|
|
|
|
.align 4
|
|
|
|
.endm
|
2020-06-15 14:18:57 +00:00
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// 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
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .rodata.str1.1
|
|
|
|
.section .rodata.str1.1,"aSM",@progbits,1
|
|
|
|
.align 1
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Locates unreferenced code invulnerable to --gc-sections.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .keep.text
|
|
|
|
.section .keep.text,"ax",@progbits
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Flags code as only allowed for testing purposes.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .testonly
|
|
|
|
.section .test,"ax",@progbits
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Makes code runnable while code morphing.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .privileged
|
|
|
|
.section .privileged,"ax",@progbits
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Post-Initialization Read-Only (PIRO) BSS section.
|
|
|
|
// @param ss is an optional string, for control image locality
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .piro ss
|
|
|
|
.ifnb \ss
|
|
|
|
.section .piro.sort.bss.\ss,"aw",@nobits
|
|
|
|
.else
|
|
|
|
.section .piro.bss,"aw",@nobits
|
|
|
|
.endif
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Helpers for Cosmopolitan _init() amalgamation magic.
|
|
|
|
// @param name should be consistent across macros for a module
|
|
|
|
// @see libc/runtime/_init.S
|
2020-06-15 14:18:57 +00:00
|
|
|
.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
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Declares alternative implementation of function.
|
|
|
|
// @param implement e.g. tinymath_pow
|
|
|
|
// @param canonical e.g. pow
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .alias implement:req canonical:req
|
|
|
|
.equ \canonical,\implement
|
|
|
|
.weak \canonical
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Ends function definition.
|
|
|
|
// @cost saves 1-3 lines of code
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .endfn name:req bnd vis
|
|
|
|
.size \name,.-\name
|
|
|
|
.type \name,@function
|
|
|
|
.ifnb \bnd
|
|
|
|
.\bnd \name
|
|
|
|
.endif
|
|
|
|
.ifnb \vis
|
|
|
|
.\vis \name
|
|
|
|
.endif
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Ends variable definition.
|
|
|
|
// @cost saves 1-3 lines of code
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .endobj name:req bnd vis
|
|
|
|
.size \name,.-\name
|
|
|
|
.type \name,@object
|
|
|
|
.ifnb \bnd
|
|
|
|
.\bnd \name
|
|
|
|
.endif
|
|
|
|
.ifnb \vis
|
|
|
|
.\vis \name
|
|
|
|
.endif
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// LOOP Instruction Replacement.
|
|
|
|
// With its mop-Fusion Mexican equivalent.
|
|
|
|
// Thus avoiding 3x legacy pipeline slowdown.
|
2020-11-09 23:41:11 +00:00
|
|
|
.macro .loop label:req
|
2020-08-25 11:23:25 +00:00
|
|
|
.byte 0x83,0xe9,0x01 # sub $1,%ecx
|
2020-06-15 14:18:57 +00:00
|
|
|
jnz \label
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Pushes CONSTEXPR ∈ [-128,127].
|
|
|
|
// @note assembler is wrong for non-literal constexprs
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro pushb x:req
|
|
|
|
.byte 0x6a,\x
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Sign-extends CONSTEXPR ∈ [-128,127] to REGISTER.
|
|
|
|
// @cost ≥1 cycles, -2 bytes
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro pushpop constexpr:req register:req
|
|
|
|
pushb \constexpr
|
|
|
|
pop \register
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Moves REGISTER to REGISTER.
|
|
|
|
// @cost ≥1 cycles, -1 REX byte
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro movpp src:req dest:req
|
|
|
|
push \src
|
|
|
|
pop \dest
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Declares optional function.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .optfn fn:req
|
|
|
|
.globl \fn
|
|
|
|
.weak \fn
|
|
|
|
.equ \fn,missingno
|
|
|
|
.type \fn,@function
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Embeds fixed-width zero-filled string table.
|
|
|
|
// @note zero-padded ≠ nul-terminated
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .fxstr width head rest:vararg
|
|
|
|
.ifnb \head
|
|
|
|
0: .ascii "\head"
|
|
|
|
.org 0b+\width
|
|
|
|
.fxstr \width,\rest
|
|
|
|
.endif
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Embeds Fixed-Width Zero-Padded String.
|
|
|
|
// @note .fxstr is better
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .ascin str:req fieldsize:req
|
|
|
|
1347: .ascii "\str"
|
|
|
|
.org 1347b+\fieldsize,0x00
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Marks symbols as object en-masse.
|
|
|
|
// @note zero-padded ≠ nul-terminated
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .object symbol rest:vararg
|
|
|
|
.ifnb \symbol
|
|
|
|
.type \symbol,@object
|
|
|
|
.object \rest
|
|
|
|
.endif
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Pads function prologue unconditionally for runtime hooking.
|
|
|
|
// @cost ≥0.3 cycles, 5 bytes
|
|
|
|
// @see .profilable
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .hookable
|
2021-02-08 17:19:00 +00:00
|
|
|
.byte 0x0f,0x1f,0x44,0x00,0x00
|
2020-06-15 14:18:57 +00:00
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Puts initialized data in uninitialized data section.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro .bsdata name:req expr:req bnd vis
|
2021-01-10 21:30:48 +00:00
|
|
|
.section .initbss.300._init_\name,"aw",@nobits
|
2020-06-15 14:18:57 +00:00
|
|
|
\name: .quad 0
|
|
|
|
.endobj \name,\bnd,\vis
|
2021-01-10 21:30:48 +00:00
|
|
|
.previous
|
|
|
|
.section .initro.300._init_\name,"a",@progbits
|
2020-06-15 14:18:57 +00:00
|
|
|
.quad \expr
|
2021-01-10 21:30:48 +00:00
|
|
|
.previous
|
|
|
|
.section .init.300._init_\name,"ax",@progbits
|
2020-06-15 14:18:57 +00:00
|
|
|
_init_\name:
|
|
|
|
movsq
|
|
|
|
.endfn _init_\name
|
2021-01-10 21:30:48 +00:00
|
|
|
.previous
|
2020-06-15 14:18:57 +00:00
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// ICE Breakpoint.
|
|
|
|
// Modern gas forgot this but objdump knows
|
|
|
|
// @mode long,legacy,real
|
2020-07-01 02:55:47 +00:00
|
|
|
.macro icebp
|
|
|
|
.byte 0xF1
|
|
|
|
.endm
|
|
|
|
.macro int1
|
|
|
|
icebp
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Sets breakpoint for software debugger.
|
|
|
|
// @mode long,legacy,real
|
2020-06-15 14:18:57 +00:00
|
|
|
.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
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Assembles Intel Official 4-Byte NOP.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro fatnop4
|
|
|
|
.byte 0x0f,0x1f,0x40,0x00
|
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// 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.
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro yoink symbol:req
|
2021-01-10 21:30:48 +00:00
|
|
|
.section .yoink
|
2021-02-08 17:19:00 +00:00
|
|
|
nopl "\symbol"(%rip)
|
2021-01-10 21:30:48 +00:00
|
|
|
.previous
|
2020-06-15 14:18:57 +00:00
|
|
|
.endm
|
|
|
|
.macro .yoink symbol:req
|
2021-01-10 21:30:48 +00:00
|
|
|
.section .yoink
|
2021-02-08 17:19:00 +00:00
|
|
|
nopl "\symbol"(%rip)
|
2021-01-10 21:30:48 +00:00
|
|
|
.previous
|
2020-06-15 14:18:57 +00:00
|
|
|
.endm
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Calls Windows function.
|
|
|
|
//
|
|
|
|
// @param cx,dx,r8,r9,stack
|
|
|
|
// @return ax
|
|
|
|
// @clob ax,cx,dx,r8-r11
|
2020-06-15 14:18:57 +00:00
|
|
|
.macro ntcall symbol:req
|
|
|
|
sub $32,%rsp
|
|
|
|
call *\symbol(%rip)
|
|
|
|
add $32,%rsp
|
|
|
|
.endm
|
2020-10-29 11:53:20 +00:00
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
// Custom emulator instruction for bottom stack frame.
|
2020-10-29 11:53:20 +00:00
|
|
|
.macro bofram endfunc:req
|
|
|
|
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
|
|
|
|
.endm
|