diff --git a/doc/asm.html b/doc/asm.html index 943347216e..771c493cc2 100644 --- a/doc/asm.html +++ b/doc/asm.html @@ -117,6 +117,9 @@ All user-defined symbols other than jump labels are written as offsets to these
The SB pseudo-register can be thought of as the origin of memory, so the symbol foo(SB)
is the name foo as an address in memory.
+This form is used to name global functions and data.
+Adding <> to the name, as in foo<>(SB), makes the name
+visible only in the current source file, like a top-level static declaration in a C file.
@@ -128,8 +131,11 @@ Thus 0(FP) is the first argument to the function,
When referring to a function argument this way, it is conventional to place the name
at the beginning, as in first_arg+0(FP) and second_arg+8(FP).
Some of the assemblers enforce this convention, rejecting plain 0(FP) and 8(FP).
-For assembly functions with Go prototypes, go vet will check that the argument names
+For assembly functions with Go prototypes, go vet will check that the argument names
and offsets match.
+On 32-bit systems, the low and high 32 bits of a 64-bit value are distinguished by adding
+a _lo or _hi suffix to the name, as in arg_lo+0(FP) or arg_hi+4(FP).
+If a Go prototype does not name its result, the expected assembly name is ret.
@@ -206,6 +212,8 @@ The frame size $24-8 states that the function has a 24-byte frame
and is called with 8 bytes of argument, which live on the caller's frame.
If NOSPLIT is not specified for the TEXT,
the argument size must be provided.
+For assembly functions with Go prototypes, go vet will check that the
+argument size is correct.
@@ -216,19 +224,20 @@ simple name profileloop.
-For DATA directives, the symbol is followed by a slash and the number
-of bytes the memory associated with the symbol occupies.
-The arguments are optional flags and the data itself.
-For instance,
-
DATA directives followed by a GLOBL directive.
+Each DATA directive initializes a section of the
+corresponding memory.
+The memory not explicitly initialized is zeroed.
+The general form of the DATA directive is
-DATA runtime·isplan9(SB)/4, $1 +DATA symbol+offset(SB)/width, value
-declares the local symbol runtime·isplan9 of size 4 and value 1.
-Again the symbol has the middle dot and is offset from SB.
+which initializes the symbol memory at the given offset and width with the given value.
+The DATA directives for a given symbol must be written with increasing offsets.
@@ -237,15 +246,26 @@ The arguments are optional flags and the size of the data being declared as a gl
which will have initial value all zeros unless a DATA directive
has initialized it.
The GLOBL directive must follow any corresponding DATA directives.
-This example
+
+For example,
-GLOBL runtime·tlsoffset(SB),$4 +DATA divtab<>+0x00(SB)/4, $0xf4f8fcff +DATA divtab<>+0x04(SB)/4, $0xe6eaedf0 +... +DATA divtab<>+0x3c(SB)/4, $0x81828384 +GLOBL divtab<>(SB), RODATA, $64 + +GLOBL runtime·tlsoffset(SB), NOPTR, $4
-declares runtime·tlsoffset to have size 4.
+declares and initializes divtab<>, a read-only 64-byte table of 4-byte integer values,
+and declares runtime·tlsoffset, a 4-byte, implicitly zeroed variable that
+contains no pointers.
@@ -299,6 +319,80 @@ This is a wrapper function and should not count as disabling recover
+
+For garbage collection to run correctly, the runtime must know the +location of pointers in all global data and in most stack frames. +The Go compiler emits this information when compiling Go source files, +but assembly programs must define it explicitly. +
+ +
+A data symbol marked with the NOPTR flag (see above)
+is treated as containing no pointers to runtime-allocated data.
+A data symbol with the RODATA flag
+is allocated in read-only memory and is therefore treated
+as implicitly marked NOPTR.
+A data symbol with a total size smaller than a pointer
+is also treated as implicitly marked NOPTR.
+It is not possible to define a symbol containing pointers in an assembly source file;
+such a symbol must be defined in a Go source file instead.
+Assembly source can still refer to the symbol by name
+even without DATA and GLOBL directives.
+A good general rule of thumb is to define all non-RODATA
+symbols in Go instead of in assembly.
+
+Each function also needs annotations giving the location of
+live pointers in its arguments, results, and local stack frame.
+For an assembly function with no pointer results and
+either no local stack frame or no function calls,
+the only requirement is to define a Go prototype for the function
+in a Go source file in the same package.
+For more complex situations, explicit annotation is needed.
+These annotations use pseudo-instructions defined in the standard
+#include file funcdata.h.
+
+If a function has no arguments and no results,
+the pointer information can be omitted.
+This is indicated by an argument size annotation of $n-0
+on the TEXT instruction.
+Otherwise, pointer information must be provided by
+a Go prototype for the function in a Go source file,
+even for assembly functions not called directly from Go.
+(The prototype will also let go vet check the argument references.)
+At the start of the function, the arguments are assumed
+to be initialized but the results are assumed uninitialized.
+If the results will hold live pointers during a call instruction,
+the function should start by zeroing the results and then
+executing the pseudo-instruction GO_RESULTS_INITIALIZED.
+This instruction records that the results are now initialized
+and should be scanned during stack movement and garbage collection.
+It is typically easier to arrange that assembly functions do not
+return pointers or do not contain call instructions;
+no assembly functions in the standard library use
+GO_RESULTS_INITIALIZED.
+
+If a function has no local stack frame,
+the pointer information can be omitted.
+This is indicated by a local frame size annotation of $0-n
+on the TEXT instruction.
+The pointer information can also be omitted if the
+function contains no call instructions.
+Otherwise, the local stack frame must not contain pointers,
+and the assembly must confirm this fact by executing the
+pseudo-instruction NO_LOCAL_POINTERS.
+Because stack resizing is implemented by moving the stack,
+the stack pointer may change during any function call:
+even pointers to stack data must not be kept in local variables.
+
@@ -434,13 +528,10 @@ Here's how the 386 runtime defines the 64-bit atomic load function. // so actually // void atomicload64(uint64 *res, uint64 volatile *addr); TEXT runtime·atomicload64(SB), NOSPLIT, $0-8 - MOVL 4(SP), BX - MOVL 8(SP), AX - // MOVQ (%EAX), %MM0 - BYTE $0x0f; BYTE $0x6f; BYTE $0x00 - // MOVQ %MM0, 0(%EBX) - BYTE $0x0f; BYTE $0x7f; BYTE $0x03 - // EMMS - BYTE $0x0F; BYTE $0x77 + MOVL ptr+0(FP), AX + LEAL ret_lo+4(FP), BX + BYTE $0x0f; BYTE $0x6f; BYTE $0x00 // MOVQ (%EAX), %MM0 + BYTE $0x0f; BYTE $0x7f; BYTE $0x03 // MOVQ %MM0, 0(%EBX) + BYTE $0x0F; BYTE $0x77 // EMMS RET diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h index a2667a4c02..d6c14fcb41 100644 --- a/src/runtime/funcdata.h +++ b/src/runtime/funcdata.h @@ -28,6 +28,9 @@ // defines the pointer map for the function's arguments. // GO_ARGS should be the first instruction in a function that uses it. // It can be omitted if there are no arguments at all. +// GO_ARGS is inserted implicitly by the linker for any function +// that also has a Go prototype and therefore is usually not necessary +// to write explicitly. #define GO_ARGS FUNCDATA $FUNCDATA_ArgsPointerMaps, go_args_stackmap(SB) // GO_RESULTS_INITIALIZED indicates that the assembly function