@@ -514,42 +514,61 @@ <h2 id="architectures">Architecture-specific details</h2>
514
514
515
515
< p >
516
516
It is impractical to list all the instructions and other details for each machine.
517
- To see what instructions are defined for a given machine, say 32-bit Intel x86 ,
518
- look in the top-level header file for the corresponding linker, in this case < code > 8l </ code > .
519
- That is, the file < code > $GOROOT/ src/cmd/8l/8.out.h </ code > contains a C enumeration, called < code > as < /code > ,
520
- of the instructions and their spellings as known to the assembler and linker for that architecture.
521
- In that file you'll find a declaration that begins
517
+ To see what instructions are defined for a given machine, say ARM ,
518
+ look in the source for the < code > obj </ code > support library for
519
+ that architecture, located in the directory < code > src/cmd/internal/obj/arm < /code > .
520
+ In that directory is a file < code > a.out.go </ code > ; it contains
521
+ a long list of constants starting with < code > A </ code > , like this:
522
522
</ p >
523
523
524
524
< pre >
525
- enum as
526
- {
527
- AXXX,
528
- AAAA,
529
- AAAD,
530
- AAAM,
531
- AAAS,
532
- AADCB,
525
+ const (
526
+ AAND = obj.ABaseARM + obj.A_ARCHSPECIFIC + iota
527
+ AEOR
528
+ ASUB
529
+ ARSB
530
+ AADD
533
531
...
534
532
</ pre >
535
533
536
534
< p >
537
- Each instruction begins with a initial capital < code > A</ code > in this list, so < code > AADCB</ code >
538
- represents the < code > ADCB</ code > (add carry byte) instruction.
539
- The enumeration is in alphabetical order, plus some late additions (< code > AXXX</ code > occupies
540
- the zero slot as an invalid instruction).
541
- The sequence has nothing to do with the actual encoding of the machine instructions.
542
- Again, the linker takes care of that detail.
535
+ This is the list of instructions and their spellings as known to the assembler and linker for that architecture.
536
+ Each instruction begins with an initial capital < code > A</ code > in this list, so < code > AAND</ code >
537
+ represents the bitwise and instruction,
538
+ < code > AND</ code > (without the leading < code > A</ code > ),
539
+ and is written in assembly source as < code > AND</ code > .
540
+ The enumeration is mostly in alphabetical order.
541
+ (The architecture-independent < code > AXXX</ code > , defined in the
542
+ < code > cmd/internal/obj</ code > package,
543
+ represents an invalid instruction).
544
+ The sequence of the < code > A</ code > names has nothing to do with the actual
545
+ encoding of the machine instructions.
546
+ The < code > cmd/internal/obj</ code > package takes care of that detail.
547
+ </ p >
548
+
549
+ < p >
550
+ The instructions for both the 386 and AMD64 architectures are listed in
551
+ < code > cmd/internal/obj/x86/a.out.go</ code > .
552
+ </ p >
553
+
554
+ < p >
555
+ The architectures share syntax for common addressing modes such as
556
+ < code > (R1)</ code > (register indirect),
557
+ < code > 4(R1)</ code > (register indirect with offset), and
558
+ < code > $foo(SB)</ code > (absolute address).
559
+ The assembler also supports some (not necessarily all) addressing modes
560
+ specific to each architecture.
561
+ The sections below list these.
543
562
</ p >
544
563
545
564
< p >
546
565
One detail evident in the examples from the previous sections is that data in the instructions flows from left to right:
547
566
< code > MOVQ</ code > < code > $0,</ code > < code > CX</ code > clears < code > CX</ code > .
548
- This convention applies even on architectures where the usual mode is the opposite direction.
567
+ This rule applies even on architectures where the conventional notation uses the opposite direction.
549
568
</ p >
550
569
551
570
< p >
552
- Here follows some descriptions of key Go-specific details for the supported architectures.
571
+ Here follow some descriptions of key Go-specific details for the supported architectures.
553
572
</ p >
554
573
555
574
< h3 id ="x86 "> 32-bit Intel 386</ h3 >
@@ -558,11 +577,11 @@ <h3 id="x86">32-bit Intel 386</h3>
558
577
The runtime pointer to the < code > g</ code > structure is maintained
559
578
through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
560
579
A OS-dependent macro < code > get_tls</ code > is defined for the assembler if the source includes
561
- an architecture-dependent header file, like this :
580
+ a special header, < code > go_asm.h </ code > :
562
581
</ p >
563
582
564
583
< pre >
565
- #include "zasm_GOOS_GOARCH .h"
584
+ #include "go_asm .h"
566
585
</ pre >
567
586
568
587
< p >
@@ -575,21 +594,39 @@ <h3 id="x86">32-bit Intel 386</h3>
575
594
< pre >
576
595
get_tls(CX)
577
596
MOVL g(CX), AX // Move g into AX.
578
- MOVL g_m(AX), BX // Move g- > m into BX.
597
+ MOVL g_m(AX), BX // Move g. m into BX.
579
598
</ pre >
580
599
600
+ < p >
601
+ Addressing modes:
602
+ </ p >
603
+
604
+ < ul >
605
+
606
+ < li >
607
+ < code > (DI)(BX*2)</ code > : The location at address < code > DI</ code > plus < code > BX*2</ code > .
608
+ </ li >
609
+
610
+ < li >
611
+ < code > 64(DI)(BX*2)</ code > : The location at address < code > DI</ code > plus < code > BX*2</ code > plus 64.
612
+ These modes accept only 1, 2, 4, and 8 as scale factors.
613
+ </ li >
614
+
615
+ </ ul >
616
+
581
617
< h3 id ="amd64 "> 64-bit Intel 386 (a.k.a. amd64)</ h3 >
582
618
583
619
< p >
584
- The assembly code to access the < code > m</ code > and < code > g</ code >
585
- pointers is the same as on the 386, except it uses < code > MOVQ</ code > rather than
586
- < code > MOVL</ code > :
620
+ The two architectures behave largely the same at the assembler level.
621
+ Assembly code to access the < code > m</ code > and < code > g</ code >
622
+ pointers on the 64-bit version is the same as on the 32-bit 386,
623
+ except it uses < code > MOVQ</ code > rather than < code > MOVL</ code > :
587
624
</ p >
588
625
589
626
< pre >
590
627
get_tls(CX)
591
628
MOVQ g(CX), AX // Move g into AX.
592
- MOVQ g_m(AX), BX // Move g- > m into BX.
629
+ MOVQ g_m(AX), BX // Move g. m into BX.
593
630
</ pre >
594
631
595
632
< h3 id ="arm "> ARM</ h3 >
@@ -626,6 +663,85 @@ <h3 id="arm">ARM</h3>
626
663
For the hardware register, use < code > R13</ code > .
627
664
</ p >
628
665
666
+ < p >
667
+ Addressing modes:
668
+ </ p >
669
+
670
+ < ul >
671
+
672
+ < li >
673
+ < code > R0->16</ code >
674
+ < br >
675
+ < code > R0>>16</ code >
676
+ < br >
677
+ < code > R0<<16</ code >
678
+ < br >
679
+ < code > R0@>16</ code > :
680
+ For < code > <<</ code > , left shift < code > R0</ code > by 16 bits.
681
+ The other codes are < code > -></ code > (arithmetic right shift),
682
+ < code > >></ code > (logical right shift), and
683
+ < code > @></ code > (rotate right).
684
+ </ li >
685
+
686
+ < li >
687
+ < code > R0->R1</ code >
688
+ < br >
689
+ < code > R0>>R1</ code >
690
+ < br >
691
+ < code > R0<<R1</ code >
692
+ < br >
693
+ < code > R0@>R1</ code > :
694
+ For < code > <<</ code > , left shift < code > R0</ code > by the count in < code > R1</ code > .
695
+ The other codes are < code > -></ code > (arithmetic right shift),
696
+ < code > >></ code > (logical right shift), and
697
+ < code > @></ code > (rotate right).
698
+
699
+ </ li >
700
+
701
+ < li >
702
+ < code > [R0,g,R12-R15]</ code > : For multi-register instructions, the set comprising
703
+ < code > R0</ code > , < code > g</ code > , and < code > R12</ code > through < code > R15</ code > inclusive.
704
+ </ li >
705
+
706
+ </ ul >
707
+
708
+ < h3 id ="arm64 "> ARM64</ h3 >
709
+
710
+ < p >
711
+ TODO
712
+ </ p >
713
+
714
+ < p >
715
+ Addressing modes:
716
+ </ p >
717
+
718
+ < ul >
719
+
720
+ < li >
721
+ TODO
722
+ </ li >
723
+
724
+ </ ul >
725
+
726
+ < h3 id ="ppc64 "> Power64, a.k.a. ppc64</ h3 >
727
+
728
+ < p >
729
+ TODO
730
+ </ p >
731
+
732
+ < p >
733
+ Addressing modes:
734
+ </ p >
735
+
736
+ < ul >
737
+
738
+ < li >
739
+ < code > (R5)(R6*1)</ code > : The location at < code > R5</ code > plus < code > R6</ code > . It is a scaled
740
+ mode like on the x86, but the only scale allowed is < code > 1</ code > .
741
+ </ li >
742
+
743
+ </ ul >
744
+
629
745
< h3 id ="unsupported_opcodes "> Unsupported opcodes</ h3 >
630
746
631
747
< p >
@@ -644,11 +760,17 @@ <h3 id="unsupported_opcodes">Unsupported opcodes</h3>
644
760
// uint64 atomicload64(uint64 volatile* addr);
645
761
// so actually
646
762
// void atomicload64(uint64 *res, uint64 volatile *addr);
647
- TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
763
+ TEXT runtime·atomicload64(SB), NOSPLIT, $0-12
648
764
MOVL ptr+0(FP), AX
765
+ TESTL $7, AX
766
+ JZ 2(PC)
767
+ MOVL 0, AX // crash with nil ptr deref
649
768
LEAL ret_lo+4(FP), BX
650
- BYTE $0x0f; BYTE $0x6f; BYTE $0x00 // MOVQ (%EAX), %MM0
651
- BYTE $0x0f; BYTE $0x7f; BYTE $0x03 // MOVQ %MM0, 0(%EBX)
652
- BYTE $0x0F; BYTE $0x77 // EMMS
769
+ // MOVQ (%EAX), %MM0
770
+ BYTE $0x0f; BYTE $0x6f; BYTE $0x00
771
+ // MOVQ %MM0, 0(%EBX)
772
+ BYTE $0x0f; BYTE $0x7f; BYTE $0x03
773
+ // EMMS
774
+ BYTE $0x0F; BYTE $0x77
653
775
RET
654
776
</ pre >
0 commit comments