]> Cypherpunks.ru repositories - gostls13.git/blobdiff - doc/asm.html
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / doc / asm.html
index 3e03c548fd189b8c014f5fc0b443ccdad326ef39..f7787a4076ce600dbce55eef8b1dbdccdf2898c5 100644 (file)
@@ -29,7 +29,7 @@ Instead, the compiler operates on a kind of semi-abstract instruction set,
 and instruction selection occurs partly after code generation.
 The assembler works on the semi-abstract form, so
 when you see an instruction like <code>MOV</code>
-what the tool chain actually generates for that operation might
+what the toolchain actually generates for that operation might
 not be a move instruction at all, perhaps a clear or load.
 Or it might correspond exactly to the machine instruction with that name.
 In general, machine-specific operations tend to appear as themselves, while more general concepts like
@@ -57,59 +57,66 @@ func main() {
        println(3)
 }
 $ GOOS=linux GOARCH=amd64 go tool compile -S x.go        # or: go build -gcflags -S x.go
-
---- prog list "main" ---
-0000 (x.go:3) TEXT    main+0(SB),$8-0
-0001 (x.go:3) FUNCDATA $0,gcargs·0+0(SB)
-0002 (x.go:3) FUNCDATA $1,gclocals·0+0(SB)
-0003 (x.go:4) MOVQ    $3,(SP)
-0004 (x.go:4) PCDATA  $0,$8
-0005 (x.go:4) CALL    ,runtime.printint+0(SB)
-0006 (x.go:4) PCDATA  $0,$-1
-0007 (x.go:4) PCDATA  $0,$0
-0008 (x.go:4) CALL    ,runtime.printnl+0(SB)
-0009 (x.go:4) PCDATA  $0,$-1
-0010 (x.go:5) RET     ,
+"".main STEXT size=74 args=0x0 locals=0x10
+       0x0000 00000 (x.go:3)   TEXT    "".main(SB), $16-0
+       0x0000 00000 (x.go:3)   MOVQ    (TLS), CX
+       0x0009 00009 (x.go:3)   CMPQ    SP, 16(CX)
+       0x000d 00013 (x.go:3)   JLS     67
+       0x000f 00015 (x.go:3)   SUBQ    $16, SP
+       0x0013 00019 (x.go:3)   MOVQ    BP, 8(SP)
+       0x0018 00024 (x.go:3)   LEAQ    8(SP), BP
+       0x001d 00029 (x.go:3)   FUNCDATA        $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
+       0x001d 00029 (x.go:3)   FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
+       0x001d 00029 (x.go:3)   FUNCDATA        $2, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
+       0x001d 00029 (x.go:4)   PCDATA  $0, $0
+       0x001d 00029 (x.go:4)   PCDATA  $1, $0
+       0x001d 00029 (x.go:4)   CALL    runtime.printlock(SB)
+       0x0022 00034 (x.go:4)   MOVQ    $3, (SP)
+       0x002a 00042 (x.go:4)   CALL    runtime.printint(SB)
+       0x002f 00047 (x.go:4)   CALL    runtime.printnl(SB)
+       0x0034 00052 (x.go:4)   CALL    runtime.printunlock(SB)
+       0x0039 00057 (x.go:5)   MOVQ    8(SP), BP
+       0x003e 00062 (x.go:5)   ADDQ    $16, SP
+       0x0042 00066 (x.go:5)   RET
+       0x0043 00067 (x.go:5)   NOP
+       0x0043 00067 (x.go:3)   PCDATA  $1, $-1
+       0x0043 00067 (x.go:3)   PCDATA  $0, $-1
+       0x0043 00067 (x.go:3)   CALL    runtime.morestack_noctxt(SB)
+       0x0048 00072 (x.go:3)   JMP     0
 ...
 </pre>
 
 <p>
 The <code>FUNCDATA</code> and <code>PCDATA</code> directives contain information
 for use by the garbage collector; they are introduced by the compiler.
-</p> 
-
-<!-- Commenting out because the feature is gone but it's popular and may come back.
+</p>
 
 <p>
-To see what gets put in the binary after linking, add the <code>-a</code> flag to the linker:
+To see what gets put in the binary after linking, use <code>go tool objdump</code>:
 </p>
 
 <pre>
-$ go tool 6l -a x.6        # or: go build -ldflags -a x.go
-codeblk [0x2000,0x1d059) at offset 0x1000
-002000 main.main            | (3)      TEXT    main.main+0(SB),$8
-002000 65488b0c25a0080000   | (3)      MOVQ    2208(GS),CX
-002009 483b21               | (3)      CMPQ    SP,(CX)
-00200c 7707                 | (3)      JHI     ,2015
-00200e e83da20100           | (3)      CALL    ,1c250+runtime.morestack00
-002013 ebeb                 | (3)      JMP     ,2000
-002015 4883ec08             | (3)      SUBQ    $8,SP
-002019                      | (3)      FUNCDATA        $0,main.gcargs·0+0(SB)
-002019                      | (3)      FUNCDATA        $1,main.gclocals·0+0(SB)
-002019 48c7042403000000     | (4)      MOVQ    $3,(SP)
-002021                      | (4)      PCDATA  $0,$8
-002021 e8aad20000           | (4)      CALL    ,f2d0+runtime.printint
-002026                      | (4)      PCDATA  $0,$-1
-002026                      | (4)      PCDATA  $0,$0
-002026 e865d40000           | (4)      CALL    ,f490+runtime.printnl
-00202b                      | (4)      PCDATA  $0,$-1
-00202b 4883c408             | (5)      ADDQ    $8,SP
-00202f c3                   | (5)      RET     ,
-...
+$ go build -o x.exe x.go
+$ go tool objdump -s main.main x.exe
+TEXT main.main(SB) /tmp/x.go
+  x.go:3               0x10501c0               65488b0c2530000000      MOVQ GS:0x30, CX
+  x.go:3               0x10501c9               483b6110                CMPQ 0x10(CX), SP
+  x.go:3               0x10501cd               7634                    JBE 0x1050203
+  x.go:3               0x10501cf               4883ec10                SUBQ $0x10, SP
+  x.go:3               0x10501d3               48896c2408              MOVQ BP, 0x8(SP)
+  x.go:3               0x10501d8               488d6c2408              LEAQ 0x8(SP), BP
+  x.go:4               0x10501dd               e86e45fdff              CALL runtime.printlock(SB)
+  x.go:4               0x10501e2               48c7042403000000        MOVQ $0x3, 0(SP)
+  x.go:4               0x10501ea               e8e14cfdff              CALL runtime.printint(SB)
+  x.go:4               0x10501ef               e8ec47fdff              CALL runtime.printnl(SB)
+  x.go:4               0x10501f4               e8d745fdff              CALL runtime.printunlock(SB)
+  x.go:5               0x10501f9               488b6c2408              MOVQ 0x8(SP), BP
+  x.go:5               0x10501fe               4883c410                ADDQ $0x10, SP
+  x.go:5               0x1050202               c3                      RET
+  x.go:3               0x1050203               e83882ffff              CALL runtime.morestack_noctxt(SB)
+  x.go:3               0x1050208               ebb6                    JMP main.main(SB)
 </pre>
 
--->
-
 <h3 id="constants">Constants</h3>
 
 <p>
@@ -118,8 +125,8 @@ it is a distinct program, so there are some differences.
 One is in constant evaluation.
 Constant expressions in the assembler are parsed using Go's operator
 precedence, not the C-like precedence of the original.
-Thus <code>3&amp;1<<2</code> is 4, not 0—it parses as <code>(3&amp;1)<<2</code>
-not <code>3&amp;(1<<2)</code>.
+Thus <code>3&amp;1&lt;&lt;2</code> is 4, not 0—it parses as <code>(3&amp;1)&lt;&lt;2</code>
+not <code>3&amp;(1&lt;&lt;2)</code>.
 Also, constants are always evaluated as 64-bit unsigned integers.
 Thus <code>-2</code> is not the integer value minus two,
 but the unsigned 64-bit integer with the same bit pattern.
@@ -139,7 +146,7 @@ The exact set depends on the architecture.
 <p>
 There are four predeclared symbols that refer to pseudo-registers.
 These are not real registers, but rather virtual registers maintained by
-the tool chain, such as a frame pointer.
+the toolchain, such as a frame pointer.
 The set of pseudo-registers is the same for all architectures:
 </p>
 
@@ -159,7 +166,7 @@ jumps and branches.
 </li>
 
 <li>
-<code>SP</code>: Stack pointer: top of stack.
+<code>SP</code>: Stack pointer: the highest address within the local stack frame.
 </li>
 
 </ul>
@@ -209,7 +216,7 @@ If a Go prototype does not name its result, the expected assembly name is <code>
 The <code>SP</code> pseudo-register is a virtual stack pointer
 used to refer to frame-local variables and the arguments being
 prepared for function calls.
-It points to the top of the local stack frame, so references should use negative offsets
+It points to the highest address within the local stack frame, so references should use negative offsets
 in the range [−framesize, 0):
 <code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.
 </p>
@@ -266,7 +273,7 @@ that assembly programming is a fraught endeavor.
 </p>
 
 <p>
-In Go object files and binaries, the full name of a symbol is the 
+In Go object files and binaries, the full name of a symbol is the
 package path followed by a period and the symbol name:
 <code>fmt.Printf</code> or <code>math/rand.Int</code>.
 Because the assembler's parser treats period and slash as punctuation,
@@ -402,7 +409,7 @@ The linker will choose one of the duplicates to use.
 (For <code>TEXT</code> items.)
 Don't insert the preamble to check if the stack must be split.
 The frame for the routine, plus anything it calls, must fit in the
-spare space at the top of the stack segment.
+spare space remaining in the current stack segment.
 Used to protect routines such as the stack splitting code itself.
 </li>
 <li>
@@ -430,8 +437,84 @@ This is a wrapper function and should not count as disabling <code>recover</code
 (For <code>TEXT</code> items.)
 This function is a closure so it uses its incoming context register.
 </li>
+<li>
+<code>LOCAL</code> = 128
+<br>
+This symbol is local to the dynamic shared object.
+</li>
+<li>
+<code>TLSBSS</code> = 256
+<br>
+(For <code>DATA</code> and <code>GLOBL</code> items.)
+Put this data in thread local storage.
+</li>
+<li>
+<code>NOFRAME</code> = 512
+<br>
+(For <code>TEXT</code> items.)
+Do not insert instructions to allocate a stack frame and save/restore the return
+address, even if this is not a leaf function.
+Only valid on functions that declare a frame size of 0.
+</li>
+<li>
+<code>TOPFRAME</code> = 2048
+<br>
+(For <code>TEXT</code> items.)
+Function is the outermost frame of the call stack. Traceback should stop at this function.
+</li>
 </ul>
 
+<h3 id="data-offsets">Interacting with Go types and constants</h3>
+
+<p>
+If a package has any .s files, then <code>go build</code> will direct
+the compiler to emit a special header called <code>go_asm.h</code>,
+which the .s files can then <code>#include</code>.
+The file contains symbolic <code>#define</code> constants for the
+offsets of Go struct fields, the sizes of Go struct types, and most
+Go <code>const</code> declarations defined in the current package.
+Go assembly should avoid making assumptions about the layout of Go
+types and instead use these constants.
+This improves the readability of assembly code, and keeps it robust to
+changes in data layout either in the Go type definitions or in the
+layout rules used by the Go compiler.
+</p>
+
+<p>
+Constants are of the form <code>const_<i>name</i></code>.
+For example, given the Go declaration <code>const bufSize =
+1024</code>, assembly code can refer to the value of this constant
+as <code>const_bufSize</code>.
+</p>
+
+<p>
+Field offsets are of the form <code><i>type</i>_<i>field</i></code>.
+Struct sizes are of the form <code><i>type</i>__size</code>.
+For example, consider the following Go definition:
+</p>
+
+<pre>
+type reader struct {
+       buf [bufSize]byte
+       r   int
+}
+</pre>
+
+<p>
+Assembly can refer to the size of this struct
+as <code>reader__size</code> and the offsets of the two fields
+as <code>reader_buf</code> and <code>reader_r</code>.
+Hence, if register <code>R1</code> contains a pointer to
+a <code>reader</code>, assembly can reference the <code>r</code> field
+as <code>reader_r(R1)</code>.
+</p>
+
+<p>
+If any of these <code>#define</code> names are ambiguous (for example,
+a struct with a <code>_size</code> field), <code>#include
+"go_asm.h"</code> will fail with a "redefinition of macro" error.
+</p>
+
 <h3 id="runtime">Runtime Coordination</h3>
 
 <p>
@@ -485,7 +568,7 @@ even for assembly functions not called directly from Go.
 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 
+the function should start by zeroing the results and then
 executing the pseudo-instruction <code>GO_RESULTS_INITIALIZED</code>.
 This instruction records that the results are now initialized
 and should be scanned during stack movement and garbage collection.
@@ -503,7 +586,7 @@ on the <code>TEXT</code> 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 
+and the assembly must confirm this fact by executing the
 pseudo-instruction <code>NO_LOCAL_POINTERS</code>.
 Because stack resizing is implemented by moving the stack,
 the stack pointer may change during any function call:
@@ -583,27 +666,30 @@ Here follow some descriptions of key Go-specific details for the supported archi
 <p>
 The runtime pointer to the <code>g</code> structure is maintained
 through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
-A OS-dependent macro <code>get_tls</code> is defined for the assembler if the source includes
-a special header, <code>go_asm.h</code>:
+In the runtime package, assembly code can include <code>go_tls.h</code>, which defines
+an OS- and architecture-dependent macro <code>get_tls</code> for accessing this register.
+The <code>get_tls</code> macro takes one argument, which is the register to load the
+<code>g</code> pointer into.
 </p>
 
-<pre>
-#include "go_asm.h"
-</pre>
-
 <p>
-Within the runtime, the <code>get_tls</code> macro loads its argument register
-with a pointer to the <code>g</code> pointer, and the <code>g</code> struct
-contains the <code>m</code> pointer.
-The sequence to load <code>g</code> and <code>m</code> using <code>CX</code> looks like this:
+For example, the sequence to load <code>g</code> and <code>m</code>
+using <code>CX</code> looks like this:
 </p>
 
 <pre>
+#include "go_tls.h"
+#include "go_asm.h"
+...
 get_tls(CX)
 MOVL   g(CX), AX     // Move g into AX.
 MOVL   g_m(AX), BX   // Move g.m into BX.
 </pre>
 
+<p>
+The <code>get_tls</code> macro is also defined on <a href="#amd64">amd64</a>.
+</p>
+
 <p>
 Addressing modes:
 </p>
@@ -645,6 +731,13 @@ MOVQ       g(CX), AX     // Move g into AX.
 MOVQ   g_m(AX), BX   // Move g.m into BX.
 </pre>
 
+<p>
+Register <code>BP</code> is callee-save.
+The assembler automatically inserts <code>BP</code> save/restore when frame size is larger than zero.
+Using <code>BP</code> as a general purpose register is allowed,
+however it can interfere with sampling-based profiling.
+</p>
+
 <h3 id="arm">ARM</h3>
 
 <p>
@@ -735,7 +828,11 @@ The other codes are <code>-&gt;</code> (arithmetic right shift),
 <h3 id="arm64">ARM64</h3>
 
 <p>
-The ARM64 port is in an experimental state.
+<code>R18</code> is the "platform register", reserved on the Apple platform.
+To prevent accidental misuse, the register is named <code>R18_PLATFORM</code>.
+<code>R27</code> and <code>R28</code> are reserved by the compiler and linker.
+<code>R29</code> is the frame pointer.
+<code>R30</code> is the link register.
 </p>
 
 <p>
@@ -752,34 +849,71 @@ Addressing modes:
 <ul>
 
 <li>
-<code>(R5, R6)</code>: Register pair for <code>LDP</code>/<code>STP</code>.
+<code>R0-&gt;16</code>
+<br>
+<code>R0&gt;&gt;16</code>
+<br>
+<code>R0&lt;&lt;16</code>
+<br>
+<code>R0@&gt;16</code>:
+These are the same as on the 32-bit ARM.
 </li>
 
-</ul>
-
-<h3 id="ppc64">64-bit PowerPC, a.k.a. ppc64</h3>
+<li>
+<code>$(8&lt;&lt;12)</code>:
+Left shift the immediate value <code>8</code> by <code>12</code> bits.
+</li>
 
-<p>
-The 64-bit PowerPC port is in an experimental state.
-</p>
+<li>
+<code>8(R0)</code>:
+Add the value of <code>R0</code> and <code>8</code>.
+</li>
 
-<p>
-Addressing modes:
-</p>
+<li>
+<code>(R2)(R0)</code>:
+The location at <code>R0</code> plus <code>R2</code>.
+</li>
 
-<ul>
+<li>
+<code>R0.UXTB</code>
+<br>
+<code>R0.UXTB&lt;&lt;imm</code>:
+<code>UXTB</code>: extract an 8-bit value from the low-order bits of <code>R0</code> and zero-extend it to the size of <code>R0</code>.
+<code>R0.UXTB&lt;&lt;imm</code>: left shift the result of <code>R0.UXTB</code> by <code>imm</code> bits.
+The <code>imm</code> value can be 0, 1, 2, 3, or 4.
+The other extensions include <code>UXTH</code> (16-bit), <code>UXTW</code> (32-bit), and <code>UXTX</code> (64-bit).
+</li>
 
 <li>
-<code>(R5)(R6*1)</code>: The location at <code>R5</code> plus <code>R6</code>. It is a scaled
-mode as on the x86, but the only scale allowed is <code>1</code>.
+<code>R0.SXTB</code>
+<br>
+<code>R0.SXTB&lt;&lt;imm</code>:
+<code>SXTB</code>: extract an 8-bit value from the low-order bits of <code>R0</code> and sign-extend it to the size of <code>R0</code>.
+<code>R0.SXTB&lt;&lt;imm</code>: left shift the result of <code>R0.SXTB</code> by <code>imm</code> bits.
+The <code>imm</code> value can be 0, 1, 2, 3, or 4.
+The other extensions include <code>SXTH</code> (16-bit), <code>SXTW</code> (32-bit), and <code>SXTX</code> (64-bit).
 </li>
 
 <li>
-<code>(R5+R6)</code>: Alias for (R5)(R6*1)
+<code>(R5, R6)</code>: Register pair for <code>LDAXP</code>/<code>LDP</code>/<code>LDXP</code>/<code>STLXP</code>/<code>STP</code>/<code>STP</code>.
 </li>
 
 </ul>
 
+<p>
+Reference: <a href="/pkg/cmd/internal/obj/arm64">Go ARM64 Assembly Instructions Reference Manual</a>
+</p>
+
+<h3 id="ppc64">PPC64</h3>
+
+<p>
+This assembler is used by GOARCH values ppc64 and ppc64le.
+</p>
+
+<p>
+Reference: <a href="/pkg/cmd/internal/obj/ppc64">Go PPC64 Assembly Instructions Reference Manual</a>
+</p>
+
 <h3 id="s390x">IBM z/Architecture, a.k.a. s390x</h3>
 
 <p>
@@ -838,6 +972,56 @@ It is a scaled mode as on the x86, but the only scale allowed is <code>1</code>.
 
 </ul>
 
+<h3 id="mips">MIPS, MIPS64</h3>
+
+<p>
+General purpose registers are named <code>R0</code> through <code>R31</code>,
+floating point registers are <code>F0</code> through <code>F31</code>.
+</p>
+
+<p>
+<code>R30</code> is reserved to point to <code>g</code>.
+<code>R23</code> is used as a temporary register.
+</p>
+
+<p>
+In a <code>TEXT</code> directive, the frame size <code>$-4</code> for MIPS or
+<code>$-8</code> for MIPS64 instructs the linker not to save <code>LR</code>.
+</p>
+
+<p>
+<code>SP</code> refers to the virtual stack pointer.
+For the hardware register, use <code>R29</code>.
+</p>
+
+<p>
+Addressing modes:
+</p>
+
+<ul>
+
+<li>
+<code>16(R1)</code>: The location at <code>R1</code> plus 16.
+</li>
+
+<li>
+<code>(R1)</code>: Alias for <code>0(R1)</code>.
+</li>
+
+</ul>
+
+<p>
+The value of <code>GOMIPS</code> environment variable (<code>hardfloat</code> or
+<code>softfloat</code>) is made available to assembly code by predefining either
+<code>GOMIPS_hardfloat</code> or <code>GOMIPS_softfloat</code>.
+</p>
+
+<p>
+The value of <code>GOMIPS64</code> environment variable (<code>hardfloat</code> or
+<code>softfloat</code>) is made available to assembly code by predefining either
+<code>GOMIPS64_hardfloat</code> or <code>GOMIPS64_softfloat</code>.
+</p>
+
 <h3 id="unsupported_opcodes">Unsupported opcodes</h3>
 
 <p>