@@ -117,6 +117,9 @@ <h3 id="symbols">Symbols</h3>
117
117
< p >
118
118
The < code > SB</ code > pseudo-register can be thought of as the origin of memory, so the symbol < code > foo(SB)</ code >
119
119
is the name < code > foo</ code > as an address in memory.
120
+ This form is used to name global functions and data.
121
+ Adding < code > <></ code > to the name, as in < code > foo<>(SB)</ code > , makes the name
122
+ visible only in the current source file, like a top-level < code > static</ code > declaration in a C file.
120
123
</ p >
121
124
122
125
< p >
@@ -128,8 +131,11 @@ <h3 id="symbols">Symbols</h3>
128
131
When referring to a function argument this way, it is conventional to place the name
129
132
at the beginning, as in < code > first_arg+0(FP)</ code > and < code > second_arg+8(FP)</ code > .
130
133
Some of the assemblers enforce this convention, rejecting plain < code > 0(FP)</ code > and < code > 8(FP)</ code > .
131
- For assembly functions with Go prototypes, < code > go vet</ code > will check that the argument names
134
+ For assembly functions with Go prototypes, < code > go</ code > < code > vet</ code > will check that the argument names
132
135
and offsets match.
136
+ On 32-bit systems, the low and high 32 bits of a 64-bit value are distinguished by adding
137
+ a < 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 > .
138
+ If a Go prototype does not name its result, the expected assembly name is < code > ret</ code > .
133
139
</ p >
134
140
135
141
< p >
@@ -206,6 +212,8 @@ <h3 id="directives">Directives</h3>
206
212
and is called with 8 bytes of argument, which live on the caller's frame.
207
213
If < code > NOSPLIT</ code > is not specified for the < code > TEXT</ code > ,
208
214
the argument size must be provided.
215
+ For assembly functions with Go prototypes, < code > go</ code > < code > vet</ code > will check that the
216
+ argument size is correct.
209
217
</ p >
210
218
211
219
< p >
@@ -216,19 +224,20 @@ <h3 id="directives">Directives</h3>
216
224
</ p >
217
225
218
226
< p >
219
- For < code > DATA</ code > directives, the symbol is followed by a slash and the number
220
- of bytes the memory associated with the symbol occupies.
221
- The arguments are optional flags and the data itself.
222
- For instance,
223
- </ p >
227
+ Global data symbols are defined by a sequence of initializing
228
+ < code > DATA</ code > directives followed by a < code > GLOBL</ code > directive.
229
+ Each < code > DATA</ code > directive initializes a section of the
230
+ corresponding memory.
231
+ The memory not explicitly initialized is zeroed.
232
+ The general form of the < code > DATA</ code > directive is
224
233
225
234
< pre >
226
- DATA runtime·isplan9 (SB)/4, $1
235
+ DATA symbol+offset (SB)/width, value
227
236
</ pre >
228
237
229
238
< p >
230
- declares the local symbol < code > runtime·isplan9 </ code > of size 4 and value 1 .
231
- Again the symbol has the middle dot and is offset from < code > SB </ code > .
239
+ which initializes the symbol memory at the given offset and width with the given value .
240
+ The < code > DATA </ code > directives for a given symbol must be written with increasing offsets .
232
241
</ p >
233
242
234
243
< p >
@@ -237,15 +246,26 @@ <h3 id="directives">Directives</h3>
237
246
which will have initial value all zeros unless a < code > DATA</ code > directive
238
247
has initialized it.
239
248
The < code > GLOBL</ code > directive must follow any corresponding < code > DATA</ code > directives.
240
- This example
249
+ </ p >
250
+
251
+ < p >
252
+ For example,
241
253
</ p >
242
254
243
255
< pre >
244
- GLOBL runtime·tlsoffset(SB),$4
256
+ DATA divtab<>+0x00(SB)/4, $0xf4f8fcff
257
+ DATA divtab<>+0x04(SB)/4, $0xe6eaedf0
258
+ ...
259
+ DATA divtab<>+0x3c(SB)/4, $0x81828384
260
+ GLOBL divtab<>(SB), RODATA, $64
261
+
262
+ GLOBL runtime·tlsoffset(SB), NOPTR, $4
245
263
</ pre >
246
264
247
265
< p >
248
- declares < code > runtime·tlsoffset</ code > to have size 4.
266
+ declares and initializes < code > divtab<></ code > , a read-only 64-byte table of 4-byte integer values,
267
+ and declares < code > runtime·tlsoffset</ code > , a 4-byte, implicitly zeroed variable that
268
+ contains no pointers.
249
269
</ p >
250
270
251
271
< p >
@@ -299,6 +319,80 @@ <h3 id="directives">Directives</h3>
299
319
</ li >
300
320
</ ul >
301
321
322
+ < h3 id ="runtime "> Runtime Coordination</ h3 >
323
+
324
+ < p >
325
+ For garbage collection to run correctly, the runtime must know the
326
+ location of pointers in all global data and in most stack frames.
327
+ The Go compiler emits this information when compiling Go source files,
328
+ but assembly programs must define it explicitly.
329
+ </ p >
330
+
331
+ < p >
332
+ A data symbol marked with the < code > NOPTR</ code > flag (see above)
333
+ is treated as containing no pointers to runtime-allocated data.
334
+ A data symbol with the < code > RODATA</ code > flag
335
+ is allocated in read-only memory and is therefore treated
336
+ as implicitly marked < code > NOPTR</ code > .
337
+ A data symbol with a total size smaller than a pointer
338
+ is also treated as implicitly marked < code > NOPTR</ code > .
339
+ It is not possible to define a symbol containing pointers in an assembly source file;
340
+ such a symbol must be defined in a Go source file instead.
341
+ Assembly source can still refer to the symbol by name
342
+ even without < code > DATA</ code > and < code > GLOBL</ code > directives.
343
+ A good general rule of thumb is to define all non-< code > RODATA</ code >
344
+ symbols in Go instead of in assembly.
345
+ </ p >
346
+
347
+ < p >
348
+ Each function also needs annotations giving the location of
349
+ live pointers in its arguments, results, and local stack frame.
350
+ For an assembly function with no pointer results and
351
+ either no local stack frame or no function calls,
352
+ the only requirement is to define a Go prototype for the function
353
+ in a Go source file in the same package.
354
+ For more complex situations, explicit annotation is needed.
355
+ These annotations use pseudo-instructions defined in the standard
356
+ < code > #include</ code > file < code > funcdata.h</ code > .
357
+ </ p >
358
+
359
+ < p >
360
+ If a function has no arguments and no results,
361
+ the pointer information can be omitted.
362
+ This is indicated by an argument size annotation of < code > $< i > n</ i > -0</ code >
363
+ on the < code > TEXT</ code > instruction.
364
+ Otherwise, pointer information must be provided by
365
+ a Go prototype for the function in a Go source file,
366
+ even for assembly functions not called directly from Go.
367
+ (The prototype will also let < code > go</ code > < code > vet</ code > check the argument references.)
368
+ At the start of the function, the arguments are assumed
369
+ to be initialized but the results are assumed uninitialized.
370
+ If the results will hold live pointers during a call instruction,
371
+ the function should start by zeroing the results and then
372
+ executing the pseudo-instruction < code > GO_RESULTS_INITIALIZED</ code > .
373
+ This instruction records that the results are now initialized
374
+ and should be scanned during stack movement and garbage collection.
375
+ It is typically easier to arrange that assembly functions do not
376
+ return pointers or do not contain call instructions;
377
+ no assembly functions in the standard library use
378
+ < code > GO_RESULTS_INITIALIZED</ code > .
379
+ </ p >
380
+
381
+ < p >
382
+ If a function has no local stack frame,
383
+ the pointer information can be omitted.
384
+ This is indicated by a local frame size annotation of < code > $0-< i > n</ i > </ code >
385
+ on the < code > TEXT</ code > instruction.
386
+ The pointer information can also be omitted if the
387
+ function contains no call instructions.
388
+ Otherwise, the local stack frame must not contain pointers,
389
+ and the assembly must confirm this fact by executing the
390
+ pseudo-instruction < code > NO_LOCAL_POINTERS</ code > .
391
+ Because stack resizing is implemented by moving the stack,
392
+ the stack pointer may change during any function call:
393
+ even pointers to stack data must not be kept in local variables.
394
+ </ p >
395
+
302
396
< h2 id ="architectures "> Architecture-specific details</ h2 >
303
397
304
398
< p >
@@ -434,13 +528,10 @@ <h3 id="unsupported_opcodes">Unsupported opcodes</h3>
434
528
// so actually
435
529
// void atomicload64(uint64 *res, uint64 volatile *addr);
436
530
TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
437
- MOVL 4(SP), BX
438
- MOVL 8(SP), AX
439
- // MOVQ (%EAX), %MM0
440
- BYTE $0x0f; BYTE $0x6f; BYTE $0x00
441
- // MOVQ %MM0, 0(%EBX)
442
- BYTE $0x0f; BYTE $0x7f; BYTE $0x03
443
- // EMMS
444
- BYTE $0x0F; BYTE $0x77
531
+ MOVL ptr+0(FP), AX
532
+ LEAL ret_lo+4(FP), BX
533
+ BYTE $0x0f; BYTE $0x6f; BYTE $0x00 // MOVQ (%EAX), %MM0
534
+ BYTE $0x0f; BYTE $0x7f; BYTE $0x03 // MOVQ %MM0, 0(%EBX)
535
+ BYTE $0x0F; BYTE $0x77 // EMMS
445
536
RET
446
537
</ pre >
0 commit comments