diff --git a/doc/asm.html b/doc/asm.html index b283efde61..76aecad54c 100644 --- a/doc/asm.html +++ b/doc/asm.html @@ -514,42 +514,61 @@ even pointers to stack data must not be kept in local variables.
It is impractical to list all the instructions and other details for each machine.
-To see what instructions are defined for a given machine, say 32-bit Intel x86,
-look in the top-level header file for the corresponding linker, in this case 8l
.
-That is, the file $GOROOT/src/cmd/8l/8.out.h
contains a C enumeration, called as
,
-of the instructions and their spellings as known to the assembler and linker for that architecture.
-In that file you'll find a declaration that begins
+To see what instructions are defined for a given machine, say ARM,
+look in the source for the obj
support library for
+that architecture, located in the directory src/cmd/internal/obj/arm
.
+In that directory is a file a.out.go
; it contains
+a long list of constants starting with A
, like this:
-enum as -{ - AXXX, - AAAA, - AAAD, - AAAM, - AAAS, - AADCB, +const ( + AAND = obj.ABaseARM + obj.A_ARCHSPECIFIC + iota + AEOR + ASUB + ARSB + AADD ...
-Each instruction begins with a initial capital A
in this list, so AADCB
-represents the ADCB
(add carry byte) instruction.
-The enumeration is in alphabetical order, plus some late additions (AXXX
occupies
-the zero slot as an invalid instruction).
-The sequence has nothing to do with the actual encoding of the machine instructions.
-Again, the linker takes care of that detail.
+This is the list of instructions and their spellings as known to the assembler and linker for that architecture.
+Each instruction begins with an initial capital A
in this list, so AAND
+represents the bitwise and instruction,
+AND
(without the leading A
),
+and is written in assembly source as AND
.
+The enumeration is mostly in alphabetical order.
+(The architecture-independent AXXX
, defined in the
+cmd/internal/obj
package,
+represents an invalid instruction).
+The sequence of the A
names has nothing to do with the actual
+encoding of the machine instructions.
+The cmd/internal/obj
package takes care of that detail.
+
+The instructions for both the 386 and AMD64 architectures are listed in
+cmd/internal/obj/x86/a.out.go
.
+
+The architectures share syntax for common addressing modes such as
+(R1)
(register indirect),
+4(R1)
(register indirect with offset), and
+$foo(SB)
(absolute address).
+The assembler also supports some (not necessarily all) addressing modes
+specific to each architecture.
+The sections below list these.
One detail evident in the examples from the previous sections is that data in the instructions flows from left to right:
MOVQ
$0,
CX
clears CX
.
-This convention applies even on architectures where the usual mode is the opposite direction.
+This rule applies even on architectures where the conventional notation uses the opposite direction.
-Here follows some descriptions of key Go-specific details for the supported architectures. +Here follow some descriptions of key Go-specific details for the supported architectures.
g
structure is maintained
through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
A OS-dependent macro get_tls
is defined for the assembler if the source includes
-an architecture-dependent header file, like this:
+a special header, go_asm.h
:
-#include "zasm_GOOS_GOARCH.h" +#include "go_asm.h"
@@ -575,21 +594,39 @@ The sequence to load g
and m
using CX
loo
get_tls(CX) MOVL g(CX), AX // Move g into AX. -MOVL g_m(AX), BX // Move g->m into BX. +MOVL g_m(AX), BX // Move g.m into BX.+
+Addressing modes: +
+ +(DI)(BX*2)
: The location at address DI
plus BX*2
.
+64(DI)(BX*2)
: The location at address DI
plus BX*2
plus 64.
+These modes accept only 1, 2, 4, and 8 as scale factors.
+
-The assembly code to access the m
and g
-pointers is the same as on the 386, except it uses MOVQ
rather than
-MOVL
:
+The two architectures behave largely the same at the assembler level.
+Assembly code to access the m
and g
+pointers on the 64-bit version is the same as on the 32-bit 386,
+except it uses MOVQ
rather than MOVL
:
get_tls(CX) MOVQ g(CX), AX // Move g into AX. -MOVQ g_m(AX), BX // Move g->m into BX. +MOVQ g_m(AX), BX // Move g.m into BX.
SP
always refers to the virtual stack pointer described ea
For the hardware register, use R13
.
++Addressing modes: +
+ +R0->16
+R0>>16
+R0<<16
+R0@>16
:
+For <<
, left shift R0
by 16 bits.
+The other codes are ->
(arithmetic right shift),
+>>
(logical right shift), and
+@>
(rotate right).
+R0->R1
+R0>>R1
+R0<<R1
+R0@>R1
:
+For <<
, left shift R0
by the count in R1
.
+The other codes are ->
(arithmetic right shift),
+>>
(logical right shift), and
+@>
(rotate right).
+
+[R0,g,R12-R15]
: For multi-register instructions, the set comprising
+R0
, g
, and R12
through R15
inclusive.
++TODO +
+ ++Addressing modes: +
+ ++TODO +
+ ++Addressing modes: +
+ +(R5)(R6*1)
: The location at R5
plus R6
. It is a scaled
+mode like on the x86, but the only scale allowed is 1
.
+@@ -644,11 +760,17 @@ Here's how the 386 runtime defines the 64-bit atomic load function. // uint64 atomicload64(uint64 volatile* addr); // so actually // void atomicload64(uint64 *res, uint64 volatile *addr); -TEXT runtime·atomicload64(SB), NOSPLIT, $0-8 +TEXT runtime·atomicload64(SB), NOSPLIT, $0-12 MOVL ptr+0(FP), AX + TESTL $7, AX + JZ 2(PC) + MOVL 0, AX // crash with nil ptr deref 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 + // MOVQ (%EAX), %MM0 + BYTE $0x0f; BYTE $0x6f; BYTE $0x00 + // MOVQ %MM0, 0(%EBX) + BYTE $0x0f; BYTE $0x7f; BYTE $0x03 + // EMMS + BYTE $0x0F; BYTE $0x77 RET