blob: 43382fc96be5b7c860cfd68a988a7388baa7c660 [file] [log] [blame]
Rob Pike2fbcb082013-11-12 20:04:22 -08001<!--{
2 "Title": "A Quick Guide to Go's Assembler",
Russ Coxa664b492013-11-13 21:29:34 -05003 "Path": "/doc/asm"
Rob Pike2fbcb082013-11-12 20:04:22 -08004}-->
5
6<h2 id="introduction">A Quick Guide to Go's Assembler</h2>
7
8<p>
9This document is a quick outline of the unusual form of assembly language used by the <code>gc</code>
10suite of Go compilers (<code>6g</code>, <code>8g</code>, etc.).
Rob Pikeedebe102014-04-15 16:27:48 -070011The document is not comprehensive.
12</p>
13
14<p>
15The assembler is based on the input to the Plan 9 assemblers, which is documented in detail
Rob Pike2fbcb082013-11-12 20:04:22 -080016<a href="http://plan9.bell-labs.com/sys/doc/asm.html">on the Plan 9 site</a>.
17If you plan to write assembly language, you should read that document although much of it is Plan 9-specific.
18This document provides a summary of the syntax and
19describes the peculiarities that apply when writing assembly code to interact with Go.
20</p>
21
22<p>
23The most important thing to know about Go's assembler is that it is not a direct representation of the underlying machine.
24Some of the details map precisely to the machine, but some do not.
25This is because the compiler suite (see
26<a href="http://plan9.bell-labs.com/sys/doc/compiler.html">this description</a>)
27needs no assembler pass in the usual pipeline.
28Instead, the compiler emits a kind of incompletely defined instruction set, in binary form, which the linker
29then completes.
30In particular, the linker does instruction selection, so when you see an instruction like <code>MOV</code>
31what the linker actually generates for that operation might not be a move instruction at all, perhaps a clear or load.
32Or it might correspond exactly to the machine instruction with that name.
33In general, machine-specific operations tend to appear as themselves, while more general concepts like
34memory move and subroutine call and return are more abstract.
35The details vary with architecture, and we apologize for the imprecision; the situation is not well-defined.
36</p>
37
38<p>
39The assembler program is a way to generate that intermediate, incompletely defined instruction sequence
40as input for the linker.
41If you want to see what the instructions look like in assembly for a given architecture, say amd64, there
42are many examples in the sources of the standard library, in packages such as
43<a href="/pkg/runtime/"><code>runtime</code></a> and
44<a href="/pkg/math/big/"><code>math/big</code></a>.
45You can also examine what the compiler emits as assembly code:
46</p>
47
48<pre>
49$ cat x.go
50package main
51
52func main() {
53 println(3)
54}
55$ go tool 6g -S x.go # or: go build -gcflags -S x.go
56
57--- prog list "main" ---
580000 (x.go:3) TEXT main+0(SB),$8-0
590001 (x.go:3) FUNCDATA $0,gcargs·0+0(SB)
600002 (x.go:3) FUNCDATA $1,gclocals·0+0(SB)
610003 (x.go:4) MOVQ $3,(SP)
620004 (x.go:4) PCDATA $0,$8
630005 (x.go:4) CALL ,runtime.printint+0(SB)
640006 (x.go:4) PCDATA $0,$-1
650007 (x.go:4) PCDATA $0,$0
660008 (x.go:4) CALL ,runtime.printnl+0(SB)
670009 (x.go:4) PCDATA $0,$-1
680010 (x.go:5) RET ,
69...
70</pre>
71
72<p>
73The <code>FUNCDATA</code> and <code>PCDATA</code> directives contain information
74for use by the garbage collector; they are introduced by the compiler.
75</p>
76
Rob Pikeedebe102014-04-15 16:27:48 -070077<!-- Commenting out because the feature is gone but it's popular and may come back.
78
Rob Pike2fbcb082013-11-12 20:04:22 -080079<p>
80To see what gets put in the binary after linking, add the <code>-a</code> flag to the linker:
81</p>
82
83<pre>
84$ go tool 6l -a x.6 # or: go build -ldflags -a x.go
85codeblk [0x2000,0x1d059) at offset 0x1000
86002000 main.main | (3) TEXT main.main+0(SB),$8
87002000 65488b0c25a0080000 | (3) MOVQ 2208(GS),CX
88002009 483b21 | (3) CMPQ SP,(CX)
8900200c 7707 | (3) JHI ,2015
9000200e e83da20100 | (3) CALL ,1c250+runtime.morestack00
91002013 ebeb | (3) JMP ,2000
92002015 4883ec08 | (3) SUBQ $8,SP
93002019 | (3) FUNCDATA $0,main.gcargs·0+0(SB)
94002019 | (3) FUNCDATA $1,main.gclocals·0+0(SB)
95002019 48c7042403000000 | (4) MOVQ $3,(SP)
96002021 | (4) PCDATA $0,$8
97002021 e8aad20000 | (4) CALL ,f2d0+runtime.printint
98002026 | (4) PCDATA $0,$-1
99002026 | (4) PCDATA $0,$0
100002026 e865d40000 | (4) CALL ,f490+runtime.printnl
10100202b | (4) PCDATA $0,$-1
10200202b 4883c408 | (5) ADDQ $8,SP
10300202f c3 | (5) RET ,
104...
105</pre>
106
Rob Pikeedebe102014-04-15 16:27:48 -0700107-->
Rob Pike2fbcb082013-11-12 20:04:22 -0800108
109<h3 id="symbols">Symbols</h3>
110
111<p>
112Some symbols, such as <code>PC</code>, <code>R0</code> and <code>SP</code>, are predeclared and refer to registers.
113There are two other predeclared symbols, <code>SB</code> (static base) and <code>FP</code> (frame pointer).
114All user-defined symbols other than jump labels are written as offsets to these pseudo-registers.
115</p>
116
117<p>
118The <code>SB</code> pseudo-register can be thought of as the origin of memory, so the symbol <code>foo(SB)</code>
119is the name <code>foo</code> as an address in memory.
Russ Cox202bf8d2014-10-28 15:51:06 -0400120This form is used to name global functions and data.
121Adding <code>&lt;&gt;</code> to the name, as in <code>foo&lt;&gt;(SB)</code>, makes the name
122visible only in the current source file, like a top-level <code>static</code> declaration in a C file.
Rob Pike2fbcb082013-11-12 20:04:22 -0800123</p>
124
125<p>
Russ Coxa664b492013-11-13 21:29:34 -0500126The <code>FP</code> pseudo-register is a virtual frame pointer
127used to refer to function arguments.
Rob Pike2fbcb082013-11-12 20:04:22 -0800128The compilers maintain a virtual frame pointer and refer to the arguments on the stack as offsets from that pseudo-register.
129Thus <code>0(FP)</code> is the first argument to the function,
130<code>8(FP)</code> is the second (on a 64-bit machine), and so on.
Russ Coxa664b492013-11-13 21:29:34 -0500131When referring to a function argument this way, it is conventional to place the name
132at the beginning, as in <code>first_arg+0(FP)</code> and <code>second_arg+8(FP)</code>.
133Some of the assemblers enforce this convention, rejecting plain <code>0(FP)</code> and <code>8(FP)</code>.
Russ Cox202bf8d2014-10-28 15:51:06 -0400134For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the argument names
Russ Coxa664b492013-11-13 21:29:34 -0500135and offsets match.
Russ Cox202bf8d2014-10-28 15:51:06 -0400136On 32-bit systems, the low and high 32 bits of a 64-bit value are distinguished by adding
137a <code>_lo</code> or <code>_hi</code> suffix to the name, as in <code>arg_lo+0(FP)</code> or <code>arg_hi+4(FP)</code>.
138If a Go prototype does not name its result, the expected assembly name is <code>ret</code>.
Russ Coxa664b492013-11-13 21:29:34 -0500139</p>
140
141<p>
142The <code>SP</code> pseudo-register is a virtual stack pointer
143used to refer to frame-local variables and the arguments being
144prepared for function calls.
145It points to the top of the local stack frame, so references should use negative offsets
146in the range [−framesize, 0):
147<code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.
148On architectures with a real register named <code>SP</code>, the name prefix distinguishes
149references to the virtual stack pointer from references to the architectural <code>SP</code> register.
150That is, <code>x-8(SP)</code> and <code>-8(SP)</code> are different memory locations:
151the first refers to the virtual stack pointer pseudo-register, while the second refers to the
152hardware's <code>SP</code> register.
Rob Pike2fbcb082013-11-12 20:04:22 -0800153</p>
154
155<p>
156Instructions, registers, and assembler directives are always in UPPER CASE to remind you
157that assembly programming is a fraught endeavor.
Russ Cox89f185f2014-06-26 11:54:39 -0400158(Exception: the <code>g</code> register renaming on ARM.)
Rob Pike2fbcb082013-11-12 20:04:22 -0800159</p>
160
161<p>
162In Go object files and binaries, the full name of a symbol is the
163package path followed by a period and the symbol name:
164<code>fmt.Printf</code> or <code>math/rand.Int</code>.
165Because the assembler's parser treats period and slash as punctuation,
166those strings cannot be used directly as identifier names.
167Instead, the assembler allows the middle dot character U+00B7
168and the division slash U+2215 in identifiers and rewrites them to
169plain period and slash.
170Within an assembler source file, the symbols above are written as
171<code>fmt·Printf</code> and <code>math∕rand·Int</code>.
172The assembly listings generated by the compilers when using the <code>-S</code> flag
173show the period and slash directly instead of the Unicode replacements
174required by the assemblers.
175</p>
176
177<p>
178Most hand-written assembly files do not include the full package path
179in symbol names, because the linker inserts the package path of the current
180object file at the beginning of any name starting with a period:
181in an assembly source file within the math/rand package implementation,
182the package's Int function can be referred to as <code>·Int</code>.
183This convention avoids the need to hard-code a package's import path in its
184own source code, making it easier to move the code from one location to another.
185</p>
186
187<h3 id="directives">Directives</h3>
188
189<p>
190The assembler uses various directives to bind text and data to symbol names.
191For example, here is a simple complete function definition. The <code>TEXT</code>
192directive declares the symbol <code>runtime·profileloop</code> and the instructions
193that follow form the body of the function.
194The last instruction in a <code>TEXT</code> block must be some sort of jump, usually a <code>RET</code> (pseudo-)instruction.
195(If it's not, the linker will append a jump-to-itself instruction; there is no fallthrough in <code>TEXTs</code>.)
196After the symbol, the arguments are flags (see below)
197and the frame size, a constant (but see below):
198</p>
199
200<pre>
201TEXT runtime·profileloop(SB),NOSPLIT,$8
202 MOVQ $runtime·profileloop1(SB), CX
203 MOVQ CX, 0(SP)
204 CALL runtime·externalthreadhandler(SB)
205 RET
206</pre>
207
208<p>
209In the general case, the frame size is followed by an argument size, separated by a minus sign.
Brad Fitzpatrick66075342014-04-27 07:40:48 -0700210(It's not a subtraction, just idiosyncratic syntax.)
Rob Pike2fbcb082013-11-12 20:04:22 -0800211The frame size <code>$24-8</code> states that the function has a 24-byte frame
212and is called with 8 bytes of argument, which live on the caller's frame.
213If <code>NOSPLIT</code> is not specified for the <code>TEXT</code>,
214the argument size must be provided.
Russ Cox202bf8d2014-10-28 15:51:06 -0400215For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the
216argument size is correct.
Rob Pike2fbcb082013-11-12 20:04:22 -0800217</p>
218
219<p>
220Note that the symbol name uses a middle dot to separate the components and is specified as an offset from the
221static base pseudo-register <code>SB</code>.
222This function would be called from Go source for package <code>runtime</code> using the
223simple name <code>profileloop</code>.
224</p>
225
226<p>
Russ Cox202bf8d2014-10-28 15:51:06 -0400227Global data symbols are defined by a sequence of initializing
228<code>DATA</code> directives followed by a <code>GLOBL</code> directive.
229Each <code>DATA</code> directive initializes a section of the
230corresponding memory.
231The memory not explicitly initialized is zeroed.
232The general form of the <code>DATA</code> directive is
Rob Pike2fbcb082013-11-12 20:04:22 -0800233
234<pre>
Russ Cox202bf8d2014-10-28 15:51:06 -0400235DATA symbol+offset(SB)/width, value
Rob Pike2fbcb082013-11-12 20:04:22 -0800236</pre>
237
238<p>
Russ Cox202bf8d2014-10-28 15:51:06 -0400239which initializes the symbol memory at the given offset and width with the given value.
240The <code>DATA</code> directives for a given symbol must be written with increasing offsets.
Rob Pike2fbcb082013-11-12 20:04:22 -0800241</p>
242
243<p>
244The <code>GLOBL</code> directive declares a symbol to be global.
245The arguments are optional flags and the size of the data being declared as a global,
246which will have initial value all zeros unless a <code>DATA</code> directive
247has initialized it.
248The <code>GLOBL</code> directive must follow any corresponding <code>DATA</code> directives.
Russ Cox202bf8d2014-10-28 15:51:06 -0400249</p>
250
251<p>
252For example,
Rob Pike2fbcb082013-11-12 20:04:22 -0800253</p>
254
255<pre>
Russ Cox202bf8d2014-10-28 15:51:06 -0400256DATA divtab&lt;&gt;+0x00(SB)/4, $0xf4f8fcff
257DATA divtab&lt;&gt;+0x04(SB)/4, $0xe6eaedf0
258...
259DATA divtab&lt;&gt;+0x3c(SB)/4, $0x81828384
260GLOBL divtab&lt;&gt;(SB), RODATA, $64
261
262GLOBL runtime·tlsoffset(SB), NOPTR, $4
Rob Pike2fbcb082013-11-12 20:04:22 -0800263</pre>
264
265<p>
Russ Cox202bf8d2014-10-28 15:51:06 -0400266declares and initializes <code>divtab&lt;&gt;</code>, a read-only 64-byte table of 4-byte integer values,
267and declares <code>runtime·tlsoffset</code>, a 4-byte, implicitly zeroed variable that
268contains no pointers.
Rob Pike2fbcb082013-11-12 20:04:22 -0800269</p>
270
271<p>
272There may be one or two arguments to the directives.
273If there are two, the first is a bit mask of flags,
274which can be written as numeric expressions, added or or-ed together,
275or can be set symbolically for easier absorption by a human.
Rob Pike8bca1482014-08-12 17:04:45 -0700276Their values, defined in the standard <code>#include</code> file <code>textflag.h</code>, are:
Rob Pike2fbcb082013-11-12 20:04:22 -0800277</p>
278
279<ul>
280<li>
281<code>NOPROF</code> = 1
282<br>
283(For <code>TEXT</code> items.)
284Don't profile the marked function. This flag is deprecated.
285</li>
286<li>
287<code>DUPOK</code> = 2
288<br>
289It is legal to have multiple instances of this symbol in a single binary.
290The linker will choose one of the duplicates to use.
291</li>
292<li>
293<code>NOSPLIT</code> = 4
294<br>
295(For <code>TEXT</code> items.)
296Don't insert the preamble to check if the stack must be split.
297The frame for the routine, plus anything it calls, must fit in the
298spare space at the top of the stack segment.
299Used to protect routines such as the stack splitting code itself.
300</li>
301<li>
302<code>RODATA</code> = 8
303<br>
304(For <code>DATA</code> and <code>GLOBL</code> items.)
305Put this data in a read-only section.
306</li>
307<li>
308<code>NOPTR</code> = 16
309<br>
310(For <code>DATA</code> and <code>GLOBL</code> items.)
311This data contains no pointers and therefore does not need to be
312scanned by the garbage collector.
313</li>
314<li>
315<code>WRAPPER</code> = 32
316<br>
317(For <code>TEXT</code> items.)
318This is a wrapper function and should not count as disabling <code>recover</code>.
319</li>
320</ul>
321
Russ Cox202bf8d2014-10-28 15:51:06 -0400322<h3 id="runtime">Runtime Coordination</h3>
323
324<p>
325For garbage collection to run correctly, the runtime must know the
326location of pointers in all global data and in most stack frames.
327The Go compiler emits this information when compiling Go source files,
328but assembly programs must define it explicitly.
329</p>
330
331<p>
332A data symbol marked with the <code>NOPTR</code> flag (see above)
333is treated as containing no pointers to runtime-allocated data.
334A data symbol with the <code>RODATA</code> flag
335is allocated in read-only memory and is therefore treated
336as implicitly marked <code>NOPTR</code>.
337A data symbol with a total size smaller than a pointer
338is also treated as implicitly marked <code>NOPTR</code>.
339It is not possible to define a symbol containing pointers in an assembly source file;
340such a symbol must be defined in a Go source file instead.
341Assembly source can still refer to the symbol by name
342even without <code>DATA</code> and <code>GLOBL</code> directives.
343A good general rule of thumb is to define all non-<code>RODATA</code>
344symbols in Go instead of in assembly.
345</p>
346
347<p>
348Each function also needs annotations giving the location of
349live pointers in its arguments, results, and local stack frame.
350For an assembly function with no pointer results and
351either no local stack frame or no function calls,
352the only requirement is to define a Go prototype for the function
Shenghou Ma7aa68752015-01-08 21:43:47 -0500353in a Go source file in the same package. The name of the assembly
354function must not contain the package name component (for example,
355function <code>Syscall</code> in package <code>syscall</code> should
356use the name <code>·Syscall</code> instead of the equivalent name
357<code>syscall·Syscall</code> in its <code>TEXT</code> directive).
Russ Cox202bf8d2014-10-28 15:51:06 -0400358For more complex situations, explicit annotation is needed.
359These annotations use pseudo-instructions defined in the standard
360<code>#include</code> file <code>funcdata.h</code>.
361</p>
362
363<p>
364If a function has no arguments and no results,
365the pointer information can be omitted.
366This is indicated by an argument size annotation of <code>$<i>n</i>-0</code>
367on the <code>TEXT</code> instruction.
368Otherwise, pointer information must be provided by
369a Go prototype for the function in a Go source file,
370even for assembly functions not called directly from Go.
371(The prototype will also let <code>go</code> <code>vet</code> check the argument references.)
372At the start of the function, the arguments are assumed
373to be initialized but the results are assumed uninitialized.
374If the results will hold live pointers during a call instruction,
375the function should start by zeroing the results and then
376executing the pseudo-instruction <code>GO_RESULTS_INITIALIZED</code>.
377This instruction records that the results are now initialized
378and should be scanned during stack movement and garbage collection.
379It is typically easier to arrange that assembly functions do not
380return pointers or do not contain call instructions;
381no assembly functions in the standard library use
382<code>GO_RESULTS_INITIALIZED</code>.
383</p>
384
385<p>
386If a function has no local stack frame,
387the pointer information can be omitted.
388This is indicated by a local frame size annotation of <code>$0-<i>n</i></code>
389on the <code>TEXT</code> instruction.
390The pointer information can also be omitted if the
391function contains no call instructions.
392Otherwise, the local stack frame must not contain pointers,
393and the assembly must confirm this fact by executing the
394pseudo-instruction <code>NO_LOCAL_POINTERS</code>.
395Because stack resizing is implemented by moving the stack,
396the stack pointer may change during any function call:
397even pointers to stack data must not be kept in local variables.
398</p>
399
Rob Pike2fbcb082013-11-12 20:04:22 -0800400<h2 id="architectures">Architecture-specific details</h2>
401
402<p>
403It is impractical to list all the instructions and other details for each machine.
404To see what instructions are defined for a given machine, say 32-bit Intel x86,
405look in the top-level header file for the corresponding linker, in this case <code>8l</code>.
406That is, the file <code>$GOROOT/src/cmd/8l/8.out.h</code> contains a C enumeration, called <code>as</code>,
407of the instructions and their spellings as known to the assembler and linker for that architecture.
408In that file you'll find a declaration that begins
409</p>
410
411<pre>
412enum as
413{
414 AXXX,
415 AAAA,
416 AAAD,
417 AAAM,
418 AAAS,
419 AADCB,
420 ...
421</pre>
422
423<p>
424Each instruction begins with a initial capital <code>A</code> in this list, so <code>AADCB</code>
425represents the <code>ADCB</code> (add carry byte) instruction.
426The enumeration is in alphabetical order, plus some late additions (<code>AXXX</code> occupies
427the zero slot as an invalid instruction).
428The sequence has nothing to do with the actual encoding of the machine instructions.
429Again, the linker takes care of that detail.
430</p>
431
432<p>
433One detail evident in the examples from the previous sections is that data in the instructions flows from left to right:
434<code>MOVQ</code> <code>$0,</code> <code>CX</code> clears <code>CX</code>.
435This convention applies even on architectures where the usual mode is the opposite direction.
436</p>
437
438<p>
439Here follows some descriptions of key Go-specific details for the supported architectures.
440</p>
441
442<h3 id="x86">32-bit Intel 386</h3>
443
444<p>
Russ Cox89f185f2014-06-26 11:54:39 -0400445The runtime pointer to the <code>g</code> structure is maintained
Rob Pike2fbcb082013-11-12 20:04:22 -0800446through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
447A OS-dependent macro <code>get_tls</code> is defined for the assembler if the source includes
448an architecture-dependent header file, like this:
449</p>
450
451<pre>
452#include "zasm_GOOS_GOARCH.h"
453</pre>
454
455<p>
456Within the runtime, the <code>get_tls</code> macro loads its argument register
Russ Cox89f185f2014-06-26 11:54:39 -0400457with a pointer to the <code>g</code> pointer, and the <code>g</code> struct
458contains the <code>m</code> pointer.
Rob Pike2fbcb082013-11-12 20:04:22 -0800459The sequence to load <code>g</code> and <code>m</code> using <code>CX</code> looks like this:
460</p>
461
462<pre>
463get_tls(CX)
Russ Cox89f185f2014-06-26 11:54:39 -0400464MOVL g(CX), AX // Move g into AX.
465MOVL g_m(AX), BX // Move g->m into BX.
Rob Pike2fbcb082013-11-12 20:04:22 -0800466</pre>
467
468<h3 id="amd64">64-bit Intel 386 (a.k.a. amd64)</h3>
469
470<p>
471The assembly code to access the <code>m</code> and <code>g</code>
472pointers is the same as on the 386, except it uses <code>MOVQ</code> rather than
473<code>MOVL</code>:
474</p>
475
476<pre>
477get_tls(CX)
Russ Cox89f185f2014-06-26 11:54:39 -0400478MOVQ g(CX), AX // Move g into AX.
479MOVQ g_m(AX), BX // Move g->m into BX.
Rob Pike2fbcb082013-11-12 20:04:22 -0800480</pre>
481
482<h3 id="arm">ARM</h3>
483
484<p>
Russ Cox89f185f2014-06-26 11:54:39 -0400485The registers <code>R10</code> and <code>R11</code>
Russ Coxa664b492013-11-13 21:29:34 -0500486are reserved by the compiler and linker.
487</p>
488
489<p>
Russ Cox89f185f2014-06-26 11:54:39 -0400490<code>R10</code> points to the <code>g</code> (goroutine) structure.
491Within assembler source code, this pointer must be referred to as <code>g</code>;
492the name <code>R10</code> is not recognized.
Russ Coxa664b492013-11-13 21:29:34 -0500493</p>
494
495<p>
496To make it easier for people and compilers to write assembly, the ARM linker
497allows general addressing forms and pseudo-operations like <code>DIV</code> or <code>MOD</code>
498that may not be expressible using a single hardware instruction.
499It implements these forms as multiple instructions, often using the <code>R11</code> register
500to hold temporary values.
501Hand-written assembly can use <code>R11</code>, but doing so requires
502being sure that the linker is not also using it to implement any of the other
503instructions in the function.
Rob Pike2fbcb082013-11-12 20:04:22 -0800504</p>
505
506<p>
507When defining a <code>TEXT</code>, specifying frame size <code>$-4</code>
508tells the linker that this is a leaf function that does not need to save <code>LR</code> on entry.
509</p>
510
Russ Coxa664b492013-11-13 21:29:34 -0500511<p>
512The name <code>SP</code> always refers to the virtual stack pointer described earlier.
513For the hardware register, use <code>R13</code>.
514</p>
Rob Pike2fbcb082013-11-12 20:04:22 -0800515
516<h3 id="unsupported_opcodes">Unsupported opcodes</h3>
517
518<p>
519The assemblers are designed to support the compiler so not all hardware instructions
520are defined for all architectures: if the compiler doesn't generate it, it might not be there.
521If you need to use a missing instruction, there are two ways to proceed.
522One is to update the assembler to support that instruction, which is straightforward
523but only worthwhile if it's likely the instruction will be used again.
524Instead, for simple one-off cases, it's possible to use the <code>BYTE</code>
525and <code>WORD</code> directives
526to lay down explicit data into the instruction stream within a <code>TEXT</code>.
527Here's how the 386 runtime defines the 64-bit atomic load function.
528</p>
529
530<pre>
531// uint64 atomicload64(uint64 volatile* addr);
532// so actually
533// void atomicload64(uint64 *res, uint64 volatile *addr);
534TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
Russ Cox202bf8d2014-10-28 15:51:06 -0400535 MOVL ptr+0(FP), AX
536 LEAL ret_lo+4(FP), BX
537 BYTE $0x0f; BYTE $0x6f; BYTE $0x00 // MOVQ (%EAX), %MM0
538 BYTE $0x0f; BYTE $0x7f; BYTE $0x03 // MOVQ %MM0, 0(%EBX)
539 BYTE $0x0F; BYTE $0x77 // EMMS
Rob Pike2fbcb082013-11-12 20:04:22 -0800540 RET
541</pre>