func compareBounds(p *gen.Prog, indexReg reg.R, upperBound int32) {
	in.MOVi.RegImm32(&p.Text, wa.I32, RegScratch, upperBound)
	in.TEST.RegReg(&p.Text, wa.I32, indexReg, indexReg)
	in.CMOVL.RegReg(&p.Text, wa.I32, indexReg, RegScratch)  
	in.CMP.RegReg(&p.Text, wa.I32, RegScratch, indexReg)
}
compareBounds zero-extends indexReg.
package x86
import (
	"gate.computer/wag/internal/gen"
	"gate.computer/wag/internal/gen/condition"
	"gate.computer/wag/internal/gen/link"
	"gate.computer/wag/internal/gen/operand"
	"gate.computer/wag/internal/gen/reg"
	"gate.computer/wag/internal/gen/rodata"
	"gate.computer/wag/internal/gen/storage"
	"gate.computer/wag/internal/isa/x86/in"
	"gate.computer/wag/internal/isa/x86/nonabi"
	"gate.computer/wag/internal/obj"
	"gate.computer/wag/trap"
	"gate.computer/wag/wa"
	errors "golang.org/x/xerrors"
)
const (
	FuncAlignment = 16
	PadByte = 0xcc  
)
var conditionInsns = [22]in.CCInsn{
	condition.Eq:            in.InsnEq,
	condition.Ne:            in.InsnNe,
	condition.GeS:           in.InsnGeS,
	condition.GtS:           in.InsnGtS,
	condition.GeU:           in.InsnGeU,
	condition.GtU:           in.InsnGtU,
	condition.LeS:           in.InsnLeS,
	condition.LtS:           in.InsnLtS,
	condition.LeU:           in.InsnLeU,
	condition.LtU:           in.InsnLtU,
	condition.OrderedAndEq:  in.InsnEq,
	condition.OrderedAndNe:  in.InsnNe,
	condition.OrderedAndGe:  in.InsnGeU,
	condition.OrderedAndGt:  in.InsnGtU,
	condition.OrderedAndLe:  in.InsnLeU,
	condition.OrderedAndLt:  in.InsnLtU,
	condition.UnorderedOrEq: in.InsnEq,
	condition.UnorderedOrNe: in.InsnNe,
	condition.UnorderedOrGe: in.InsnGeU,
	condition.UnorderedOrGt: in.InsnGtU,
	condition.UnorderedOrLe: in.InsnLeU,
	condition.UnorderedOrLt: in.InsnLtU,
}
var suspendRewindOffsets = [2]int8{
	0: 8,   
	1: 12,  
}
var asm MacroAssembler
type MacroAssembler struct{}
func (MacroAssembler) AlignData(p *gen.Prog, alignment int) {
	pad(p, (alignment-int(p.Text.Addr))&(alignment-1))
}
func (MacroAssembler) AlignFunc(p *gen.Prog) {
	pad(p, (FuncAlignment-int(p.Text.Addr))&(FuncAlignment-1))
}
func (MacroAssembler) PadUntil(p *gen.Prog, addr int32) {
	pad(p, int(addr)-int(p.Text.Addr))
}
func pad(p *gen.Prog, length int) {
	gap := p.Text.Extend(length)
	for i := range gap {
		gap[i] = PadByte
	}
}
func (MacroAssembler) AddToStackPtrUpper32(f *gen.Func, r reg.R) {
	in.SARi.RegImm8(&f.Text, wa.I64, r, 32)  
	in.ADD.RegReg(&f.Text, wa.I64, RegStackPtr, r)
	f.Regs.Free(wa.I64, r)
}
func (MacroAssembler) DropStackValues(p *gen.Prog, n int) {
	in.LEA.RegStackDisp(&p.Text, wa.I64, RegStackPtr, int32(n*obj.Word))
}
func (MacroAssembler) Branch(p *gen.Prog, addr int32) {
	in.JMPcd.Addr32(&p.Text, addr)
}
func (MacroAssembler) BranchStub(p *gen.Prog) int32 {
	return in.JMPcd.Stub32(&p.Text)
}
func (MacroAssembler) BranchIndirect(f *gen.Func, addr reg.R) {
	in.MOV.RegReg(&f.Text, wa.I32, RegScratch, addr)
	f.Regs.Free(wa.I64, addr)
	in.ADD.RegReg(&f.Text, wa.I64, RegScratch, RegTextBase)
	in.JMPcd.Addr32(&f.Text, nonabi.TextAddrRetpoline)
}
func (MacroAssembler) BranchIf(f *gen.Func, x operand.O, labelAddr int32) (sites []int32) {
	sites = asm.BranchIfStub(f, x, true, false)
	if labelAddr != 0 {
		linker.UpdateFarBranches(f.Text.Bytes(), &link.L{Sites: sites, Addr: labelAddr})
	}
	return
}
func (MacroAssembler) BranchIfStub(f *gen.Func, x operand.O, yes, near bool) (sites []int32) {
	var cond condition.C
	if x.Storage == storage.Flags {
		cond = x.FlagsCond()
	} else {
		r, _ := getScratchReg(f, x)
		in.TEST.RegReg(&f.Text, wa.I32, r, r)
		cond = condition.Ne
		f.Regs.Free(wa.I32, r)
	}
	if !yes {
		cond = condition.Inverted[cond]
	}
	var endJumps []int32
	switch {
	case cond >= condition.MinUnorderedOrCondition:
		sites = append(sites, in.JPc.Stub(&f.Text, near))
	case cond >= condition.MinOrderedAndCondition:
		endJumps = append(endJumps, in.JPcb.Stub8(&f.Text))
	}
	sites = append(sites, conditionInsns[cond].JccOpcodeC().Stub(&f.Text, near))
	linker.UpdateNearBranches(f.Text.Bytes(), endJumps)
	return
}
func (MacroAssembler) BranchIfOutOfBounds(p *gen.Prog, indexReg reg.R, upperBound, addr int32) {
	compareBounds(p, indexReg, upperBound)
	in.JLEc.Addr(&p.Text, addr)
}
func (MacroAssembler) BranchIfOutOfBoundsStub(p *gen.Prog, indexReg reg.R, upperBound int32) int32 {
	compareBounds(p, indexReg, upperBound)
	return in.JLEc.AddrStub(&p.Text)
}