// Copyright 2025 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package asmgenvarArchAMD64 = &Arch{Name: "amd64",WordBits: 64,WordBytes: 8,regs: []string{"BX", "SI", "DI","R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15","AX", "DX", "CX", // last to leave available for hinted allocation },op3: x86Op3,hint: x86Hint,memOK: true,subCarryIsBorrow: true,// Note: Not setting memIndex, because code generally runs faster // if we avoid the use of scaled-index memory references, // particularly in ADX instructions.options: map[Option]func(*Asm, string){OptionAltCarry: amd64JmpADX, },mov: "MOVQ",adds: "ADDQ",adcs: "ADCQ",subs: "SUBQ",sbcs: "SBBQ",lsh: "SHLQ",lshd: "SHLQ",rsh: "SHRQ",rshd: "SHRQ",and: "ANDQ",or: "ORQ",xor: "XORQ",neg: "NEGQ",lea: "LEAQ",addF: amd64Add,mulWideF: x86MulWide,addWords: "LEAQ (%[2]s)(%[1]s*8), %[3]s",jmpZero: "TESTQ %[1]s, %[1]s; JZ %[2]s",jmpNonZero: "TESTQ %[1]s, %[1]s; JNZ %[2]s",loopBottom: "SUBQ $1, %[1]s; JNZ %[2]s",loopBottomNeg: "ADDQ $1, %[1]s; JNZ %[2]s",}func amd64JmpADX( *Asm, string) { .Printf("\tCMPB ·hasADX(SB), $0; JNZ %s\n", )}func amd64Add( *Asm, , Reg, Reg, Carry) bool {if .Enabled(OptionAltCarry) {// If OptionAltCarry is enabled, the generator is emitting ADD instructions // both with and without the AltCarry flag set; the AltCarry flag means to // use ADOX. Otherwise we have to use ADCX. // Using regular ADD/ADC would smash both carry flags, // so we reject anything we can't handled with ADCX/ADOX.if &UseCarry != 0 && &(SetCarry|SmashCarry) != 0 {if &AltCarry != 0 { .op3("ADOXQ", , , ) } else { .op3("ADCXQ", , , ) }returntrue }if &(SetCarry|UseCarry) == SetCarry && .IsZero() && == {// Clearing carry flag. Caller will add EOL comment. .Printf("\tTESTQ AX, AX\n")returntrue }if != KeepCarry { .Fatalf("unsupported carry") } }returnfalse}// The x86-prefixed functions are shared with Arch386 in 386.go.func x86Op3( string) bool {// As far as a.op3 is concerned, there are no 3-op instructions. // (We print instructions like MULX ourselves.)returnfalse}func x86Hint( *Asm, Hint) string {switch {caseHintShiftCount:return"CX"caseHintMulSrc:if .Enabled(OptionAltCarry) { // using MULXreturn"DX" }return"AX"caseHintMulHi:if .Enabled(OptionAltCarry) { // using MULXreturn"" }return"DX" }return""}func x86Suffix( *Asm) string {// Note: Not using a.Arch == Arch386 to avoid init cycle.if .Arch.Name == "386" {return"L" }return"Q"}func x86MulWide( *Asm, , , , Reg) {if .Enabled(OptionAltCarry) {// Using ADCX/ADOX; use MULX to avoid clearing carry flag.if .name != "DX" {if .name != "DX" { .Fatalf("mul src1 or src2 must be DX") } = } .Printf("\tMULXQ %s, %s, %s\n", , , )return }if .name != "AX" {if .name != "AX" { .Fatalf("mulwide src1 or src2 must be AX") } = }if .name != "AX" { .Fatalf("mulwide dstlo must be AX") }if .name != "DX" { .Fatalf("mulwide dsthi must be DX") } .Printf("\tMUL%s %s\n", x86Suffix(), )}
The pages are generated with Goldsv0.7.7-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.