Source File
arch.go
Belonging Package
math/big/internal/asmgen
// 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 asmgenimport ()// Note: Exported fields and methods are expected to be used// by function generators (like the ones in add.go and so on).// Unexported fields and methods should not be.// An Arch defines how to generate assembly for a specific architecture.type Arch struct {Name string // name of architectureBuild string // build tagWordBits int // length of word in bits (32 or 64)WordBytes int // length of word in bytes (4 or 8)CarrySafeLoop bool // whether loops preserve carry flag across iterations// Registers.regs []string // usable general registers, in allocation orderreg0 string // dedicated zero registerregCarry string // dedicated carry register, for systems with no hardware carry bitsregAltCarry string // dedicated secondary carry register, for systems with no hardware carry bitsregTmp string // dedicated temporary register// regShift indicates that the architecture supports// using REG1>>REG2 and REG1<<REG2 as the first source// operand in an arithmetic instruction. (32-bit ARM does this.)regShift bool// setup is called to emit any per-architecture function prologue,// immediately after the TEXT line has been emitted.// If setup is nil, it is taken to be a no-op.setup func(*Func)// hint returns the register to use for a given hint.// Returning an empty string indicates no preference.// If hint is nil, it is considered to return an empty string.hint func(*Asm, Hint) string// op3 reports whether the named opcode accepts 3 operands// (true on most instructions on most systems, but not true of x86 instructions).// The assembler unconditionally turns op x,z,z into op x,z.// If op3 returns false, then the assembler will turn op x,y,z into mov y,z; op x,z.// If op3 is nil, then all opcodes are assumed to accept 3 operands.op3 func(name string) bool// memOK indicates that arithmetic instructions can use memory references (like on x86)memOK bool// maxColumns is the default maximum number of vector columns// to process in a single [Pipe.Loop] block.// 0 means unlimited.// [Pipe.SetMaxColumns] overrides this.maxColumns int// Instruction names.mov string // move (word-sized)add string // add with no carry involvementadds string // add, setting but not using carryadc string // add, using but not setting carryadcs string // add, setting and using carrysub string // sub with no carry involvementsubs string // sub, setting but not using carrysbc string // sub, using but not setting carrysbcs string // sub, setting and using carrymul string // multiplymulhi string // multiply producing high bitslsh string // left shiftlshd string // double-width left shiftrsh string // right shiftrshd string // double-width right shiftand string // bitwise andor string // bitwise orxor string // bitwise xorneg string // negatersb string // reverse subtractsltu string // set less-than unsigned (dst = src2 < src1), for carry-less systemssgtu string // set greater-than unsigned (dst = src2 > src1), for carry-less systemslea string // load effective address// addF and subF implement a.Add and a.Sub// on systems where the situation is more complicated than// the six basic instructions (add, adds, adcs, sub, subs, sbcs).// They return a boolean indicating whether the operation was handled.addF func(a *Asm, src1, src2, dst Reg, carry Carry) boolsubF func(a *Asm, src1, src2, dst Reg, carry Carry) bool// mulF and mulWideF implement Mul and MulWide.// They call Fatalf if the operation is unsupported.// An architecture can set the mul field instead of mulF.// mulWide is optional, but otherwise mulhi should be set.mulWideF func(a *Asm, src1, src2, dstlo, dsthi Reg)// addWords is a printf format taking src1, src2, dst// and sets dst = WordBytes*src1+src2.// It may modify the carry flag.addWords string// subCarryIsBorrow is true when the actual processor carry bit used in subtraction// is really a “borrow” bit, meaning 1 means borrow and 0 means no borrow.// In contrast, most systems (except x86) use a carry bit with the opposite// meaning: 0 means a borrow happened, and 1 means it didn't.subCarryIsBorrow bool// Jump instruction printf formats.// jmpZero and jmpNonZero are printf formats taking src, label// and jump to label if src is zero / non-zero.jmpZero stringjmpNonZero string// loopTop is a printf format taking src, label that should// jump to label if src is zero, or else set up for a loop.// If loopTop is not set, jmpZero is used.loopTop string// loopBottom is a printf format taking dst, label that should// decrement dst and then jump to label if src is non-zero.// If loopBottom is not set, a subtraction is used followed by// use of jmpNonZero.loopBottom string// loopBottomNeg is like loopBottom but used in negative-index// loops, which only happen memIndex is also set (only on 386).// It increments dst instead of decrementing it.loopBottomNeg string// Indexed memory access.// If set, memIndex returns a memory reference for a mov instruction// addressing off(ptr)(ix*WordBytes).// Using memIndex costs an extra register but allows the end-of-loop// to do a single increment/decrement instead of advancing two or three pointers.// This is particularly important on 386.memIndex func(a *Asm, off int, ix Reg, ptr RegPtr) Reg// Incrementing/decrementing memory access.// loadIncN loads memory at ptr into regs, incrementing ptr by WordBytes after each reg.// loadDecN loads memory at ptr into regs, decrementing ptr by WordBytes before each reg.// storeIncN and storeDecN are the same, but storing from regs instead of loading into regs.// If missing, the assembler accesses memory and advances pointers using separate instructions.loadIncN func(a *Asm, ptr RegPtr, regs []Reg)loadDecN func(a *Asm, ptr RegPtr, regs []Reg)storeIncN func(a *Asm, ptr RegPtr, regs []Reg)storeDecN func(a *Asm, ptr RegPtr, regs []Reg)// options is a map from optional CPU features to functions that test for them.// The test function should jump to label if the feature is available.options map[Option]func(a *Asm, label string)}// HasShiftWide reports whether the Arch has working LshWide/RshWide instructions.// If not, calling them will panic.func ( *Arch) () bool {return .lshd != ""}// A Hint is a hint about what a register will be used for,// so that an appropriate one can be selected.type Hint uintconst (HintNone Hint = iotaHintShiftCount // shift count (CX on x86)HintMulSrc // mul source operand (AX on x86)HintMulHi // wide mul high output (DX on x86)HintMemOK // a memory reference is okayHintCarry // carry flagHintAltCarry // secondary carry flag)// A Reg is an allocated register or other assembly operand.// (For example, a constant might have name "$123"// and a memory reference might have name "0(R8)".)type Reg struct{ name string }// IsImm reports whether r is an immediate value.func ( Reg) () bool { return strings.HasPrefix(.name, "$") }// IsMem reports whether r is a memory value.func ( Reg) () bool { return strings.HasSuffix(.name, ")") }// String returns the assembly syntax for r.func ( Reg) () string { return .name }// Valid reports whether is valid, meaning r is not the zero value of Reg (a register with no name).func ( Reg) () bool { return .name != "" }// A RegPtr is like a Reg but expected to hold a pointer.// The separate Go type helps keeps pointers and scalars separate and avoid mistakes;// it is okay to convert to Reg as needed to use specific routines.type RegPtr struct{ name string }// String returns the assembly syntax for r.func ( RegPtr) () string { return .name }// Valid reports whether is valid, meaning r is not the zero value of RegPtr (a register with no name).func ( RegPtr) () bool { return .name != "" }// mem returns a memory reference to off bytes from the pointer r.func ( *RegPtr) ( int) Reg { return Reg{fmt.Sprintf("%d(%s)", , )} }// A Carry is a flag field explaining how an instruction sets and uses the carry flags.// Different operations expect different sets of bits.// Add and Sub expect: UseCarry or 0, SetCarry, KeepCarry, or SmashCarry; and AltCarry or 0.// ClearCarry, SaveCarry, and ConvertCarry expect: AddCarry or SubCarry; and AltCarry or 0.type Carry uintconst (SetCarry Carry = 1 << iota // sets carryUseCarry // uses carryKeepCarry // must preserve carrySmashCarry // can modify carry or not, whatever is easiestAltCarry // use the secondary carry flagAddCarry // use add carry flag semantics (for ClearCarry, ConvertCarry)SubCarry // use sub carry flag semantics (for ClearCarry, ConvertCarry))// An Option denotes an optional CPU feature that can be tested at runtime.type Option intconst (_ Option = iota// OptionAltCarry checks whether there is an add instruction// that uses a secondary carry flag, so that two different sums// can be accumulated in parallel with independent carry flags.// Some architectures (MIPS, Loong64, RISC-V) provide this// functionality natively, indicated by asm.Carry().Valid() being true.OptionAltCarry)
![]() |
The pages are generated with Golds v0.7.9-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. |