giant refactoring of macros

This commit is contained in:
Perry Kivolowitz 2023-01-18 17:24:12 -06:00
parent b153fad576
commit 4d41d9d9cd
5 changed files with 211 additions and 113 deletions

View file

@ -25,15 +25,26 @@ underscores to labels defined by libraries such as the CRT and certain
other symbols like `main`.
So, `main` will not be found by the linker on Apple systems and `_main`
will be an error on Linux systems. There are macros to adjust for this.
will be an error on Linux systems.
There are some exceptions such as making use of `FILE * stdin`. On
Linux this would be `stdin`. On Mac OS you would expect `_stdin` but
you'd be wrong... instead Apple uses `___stdinp`. Why? Apple.
The macros adjust for this.
There are some exceptions to the prepending rule on Apple such as making
use of `FILE * stdin`. On Linux this would be `stdin`. On Mac OS you
would expect `_stdin` but you'd be wrong... instead Apple uses
`___stdinp`. Why? Because Apple.
There is an assumption here that labels created by you do not have
prepended underscores. This can be a problem if this isn't the case. The
solution may be to add a parallel set of macros that either do prepend
or do not. This is an open question which we hope to get user input to
resolve.
## Macros of general use
These macros don't converge Apple and Linux. They're just nice to have.
First, we describe a number of macros which are the same on both Apple
and Linux. These macros don't converge Apple and Linux. They're just
nice to have.
### PUSH_P, PUSH_R, POP_P and POP_R
@ -61,97 +72,114 @@ These resolve to: `.cfi_startproc` and `.cfi_endproc` respectively.
Handy more readable macros for determining minima and maxima.
`MIN x0, x1, x2`
Signature:
resolves to:
`MIN src_a, src_b, dest`
`csel x2, x0, x1, GT` putting the minimum of `x0` and `x1` into `x2`.
The smaller of `src_a` and `src_b` is put into `dest`.
Signature:
`MAX src_a, src_b, dest`
The larger of `src_a` and `src_b` is put into `dest`.
## Loads and Stores
### GLD_PTR
Loads the address of a label and then dereferences it where, on Apple
Loads the address of a label and then *dereferences* it where, on Apple
the label is in the global space and on Linux is a relatively close
label.
Apple version:
Signature:
```text
.macro GLD_PTR xreg, label // Dereference a global *
adrp \xreg, _\label@GOTPAGE
ldr \xreg, [\xreg, _\label@GOTPAGEOFF]
.endm
GLD_PTR xreg, label
```
Linux version:
When this macro finishes, the specified x register contains what
64 bit value lives at the specified label.
### GLD_ADDR
Loads the address of the label into the specified x register. No
dereferencing takes place. On Apple machines, the label will be
found in the global space.
Signature:
```text
.macro GLD_PTR xreg, label // Dereference a global *
ldr \xreg, =\label
ldr \xreg, [\xreg]
.endm
GLD_ADDR xreg, label
```
When this macro completes, the address of the label is in the x
register.
### LLD_ADDR
Load the value of a "local" label.
Similar to `GLD_ADDR` this macro loads the address of a "local" label.
Apple version:
Signature:
```text
.macro LLD_ADDR xreg, label // Load a local address
adrp \xreg, \label@PAGE
add \xreg, \xreg, \label@PAGEOFF
.endm
LLD_ADDR xreg, label
```
Linux version:
When this macro completes, the address of the label is in the x
register.
```text
.macro LLD_ADDR xreg, label
ldr \xreg, =\label
.endm
```
### LLD_DBL
## Extern a global label
Signature:
`LLD_DBL xreg, dreg, label`
When this macro completes, a double that lives at the specified local
label will sit in the specified double register.
Note: No underscore is prepended.
See [this sample program](./double.S) for an example.
### LLD_FLT
Signature:
`LLD_FLT xreg, sreg, label`
When this macro completes, a float that lives at the specified
local label will sit in the specified single precision
register.
Note: No underscore is prepended.
See [this sample program](./float.S) for an example.
## Mark a label as global
Makes a label available externally.
Apple version:
Signature:
```text
.macro GLABEL label
.global _\label
.endm
```
`GLABEL label`
Linux version:
An underscore is prepended.
```text
.macro GLABEL label
.global \label
.endm
```
For example:
```text
GLABEL main
```
## Calling functions
## Calling CRT functions
If you create your own function without an underscore, just call it as
usual.
If you need to call a function such as those found in the C runtime
library, use in this way:
library, use this macro in this way:
```text
CRT strlen
```
`CRT strlen`
An underscore is prepended.
## Declaring `main()`
Put `MAIN` on a line by itself. Notice there is no colon.
An underscore is prepended.

Binary file not shown.

View file

@ -1,77 +1,87 @@
// Macros to permit the "same" assembly language to build on ARM64
// Linux systems as well as Apple Silicon systems.
//
// Perry Kivolowitz
// A Gentle Introduction to Assembly Language
/* Macros to permit the "same" assembly language to build on ARM64
Linux systems as well as Apple Silicon systems.
See the fuller documentation at:
https://github.com/pkivolowitz/asm_book/blob/main/macros/README.md
Perry Kivolowitz
A Gentle Introduction to Assembly Language
*/
.macro GLD_PTR xreg, label
#if defined(__APPLE__)
// Apple makes a distinction between loading something close by
// versus something global. Note the use of GOTPAGE rather then
// PAGE.
//
// Note: this macro dereferences the label getting what is at
// the label's address.
.macro GLD_PTR xreg, label // Dereference a global *
adrp \xreg, _\label@GOTPAGE
ldr \xreg, [\xreg, _\label@GOTPAGEOFF]
#else
ldr \xreg, =\label
ldr \xreg, [\xreg]
#endif
.endm
.macro GLD_ADDR xreg, label // Get a global address
#if defined(__APPLE__)
adrp \xreg, _\label@GOTPAGE
add \xreg, \xreg, _\label@GOTPAGEOFF
.endm
// This macro loads the address of a nearby label.
.macro LLD_ADDR xreg, label // Load a local address
adrp \xreg, \label@PAGE
add \xreg, \xreg, \label@PAGEOFF
.endm
.macro GLABEL label
.global _\label
.endm
.macro MAIN
_main:
.endm
.macro CRT label
bl _\label
.endm
#else // LINUX
.macro GLABEL label
.global \label
.endm
.macro MAIN
main:
.endm
.macro CRT label
bl \label
.endm
// This macro treats label as a pointer and dereferences it.
// That is, it puts into the xreg what is found at the address
// of the label.
.macro GLD_PTR xreg, label // Dereference a global *
#else
ldr \xreg, =\label
ldr \xreg, [\xreg]
#endif
.endm
// This macro loads the address of a nearby label.
.macro LLD_ADDR xreg, label
#if defined(__APPLE__)
adrp \xreg, \label@PAGE
add \xreg, \xreg, \label@PAGEOFF
#else
ldr \xreg, =\label
#endif
.endm
.macro LLD_DBL xreg, dreg, label
#if defined(__APPLE__)
adrp \xreg, \label@PAGE
add \xreg, \xreg, \label@PAGEOFF
ldur \dreg, [\xreg]
// fmov \dreg, \xreg
#else
ldr \xreg, =\label
ldur \dreg, [\xreg]
#endif
.endm
.macro LLD_FLT xreg, sreg, label
#if defined(__APPLE__)
adrp \xreg, \label@PAGE
add \xreg, \xreg, \label@PAGEOFF
ldur \sreg, [\xreg]
#else
ldr \xreg, =\label
ldur \sreg, [\xreg]
#endif
.endm
.macro GLABEL label
#if defined(__APPLE__)
.global _\label
#else
.global \label
#endif
.endm
.macro MAIN
#if defined(__APPLE__)
_main:
#else
main:
#endif
.endm
.macro CRT label
#if defined(__APPLE__)
bl _\label
#else
bl \label
#endif
.endm
.macro START_PROC // after starting label
.cfi_startproc

29
macros/double.S Normal file
View file

@ -0,0 +1,29 @@
#include "apple-linux-convergence.S"
.text
.align 2
GLABEL main
MAIN
START_PROC
PUSH_P x29, x30
mov x29, sp
LLD_ADDR x0, fmt
LLD_DBL x1, d0, dbl
#if defined(__APPLE__)
PUSH_R d0
CRT printf
add sp, sp, 16
#else
CRT printf
#endif
POP_P x29, x30
mov w0, wzr
ret
END_PROC
dbl: .double -0.55
flt: .float 0.125
fmt: .asciz "%f\n"
.end

31
macros/float.S Normal file
View file

@ -0,0 +1,31 @@
#include "apple-linux-convergence.S"
.text
.align 2
GLABEL main
MAIN
START_PROC
PUSH_P x29, x30
mov x29, sp
LLD_ADDR x0, fmt
LLD_FLT x1, s0, flt
#if defined(__APPLE__)
fcvt d0, s0
fmov x1, d0
PUSH_R x1
CRT printf
add sp, sp, 16
#else
fcvt d0, s0
CRT printf
#endif
POP_P x29, x30
mov w0, wzr
ret
END_PROC
flt: .float 0.125
fmt: .asciz "%f\n"
.end