diff --git a/macros/README.md b/macros/README.md index 2b02cb7..f25eef3 100644 --- a/macros/README.md +++ b/macros/README.md @@ -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. diff --git a/macros/README.pdf b/macros/README.pdf index 494c0b1..63d58f6 100644 Binary files a/macros/README.pdf and b/macros/README.pdf differ diff --git a/macros/apple-linux-convergence.S b/macros/apple-linux-convergence.S index f77a9da..aae5135 100644 --- a/macros/apple-linux-convergence.S +++ b/macros/apple-linux-convergence.S @@ -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 diff --git a/macros/double.S b/macros/double.S new file mode 100644 index 0000000..8c772c4 --- /dev/null +++ b/macros/double.S @@ -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 diff --git a/macros/float.S b/macros/float.S new file mode 100644 index 0000000..6f79f40 --- /dev/null +++ b/macros/float.S @@ -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