Commit 818eff03 authored by Russ Cox's avatar Russ Cox

cmd/internal/obj/i386: delete

Now unused.

Change-Id: I0ba27e58721ad66cc3068346d6d31ba0ac37ad64
Reviewed-on: https://go-review.googlesource.com/6893Reviewed-by: default avatarRob Pike <r@golang.org>
Reviewed-by: default avatarMinux Ma <minux@golang.org>
parent 2897d6de
// Inferno utils/8c/8.out.h
// http://code.google.com/p/inferno-os/source/browse/utils/8c/8.out.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package i386
import "cmd/internal/obj"
const (
AAAA = obj.ABase386 + obj.A_ARCHSPECIFIC + iota
AAAD
AAAM
AAAS
AADCB
AADCL
AADCW
AADDB
AADDL
AADDW
AADJSP
AANDB
AANDL
AANDW
AARPL
ABOUNDL
ABOUNDW
ABSFL
ABSFW
ABSRL
ABSRW
ABTL
ABTW
ABTCL
ABTCW
ABTRL
ABTRW
ABTSL
ABTSW
ABYTE
ACLC
ACLD
ACLI
ACLTS
ACMC
ACMPB
ACMPL
ACMPW
ACMPSB
ACMPSL
ACMPSW
ADAA
ADAS
ADECB
ADECL
ADECW
ADIVB
ADIVL
ADIVW
AENTER
AHLT
AIDIVB
AIDIVL
AIDIVW
AIMULB
AIMULL
AIMULW
AINB
AINL
AINW
AINCB
AINCL
AINCW
AINSB
AINSL
AINSW
AINT
AINTO
AIRETL
AIRETW
AJCC
AJCS
AJCXZL
AJCXZW
AJEQ
AJGE
AJGT
AJHI
AJLE
AJLS
AJLT
AJMI
AJNE
AJOC
AJOS
AJPC
AJPL
AJPS
ALAHF
ALARL
ALARW
ALEAL
ALEAW
ALEAVEL
ALEAVEW
ALOCK
ALODSB
ALODSL
ALODSW
ALONG
ALOOP
ALOOPEQ
ALOOPNE
ALSLL
ALSLW
AMOVB
AMOVL
AMOVW
AMOVQ
AMOVBLSX
AMOVBLZX
AMOVBWSX
AMOVBWZX
AMOVWLSX
AMOVWLZX
AMOVSB
AMOVSL
AMOVSW
AMULB
AMULL
AMULW
ANEGB
ANEGL
ANEGW
ANOTB
ANOTL
ANOTW
AORB
AORL
AORW
AOUTB
AOUTL
AOUTW
AOUTSB
AOUTSL
AOUTSW
APAUSE
APOPAL
APOPAW
APOPFL
APOPFW
APOPL
APOPW
APUSHAL
APUSHAW
APUSHFL
APUSHFW
APUSHL
APUSHW
ARCLB
ARCLL
ARCLW
ARCRB
ARCRL
ARCRW
AREP
AREPN
AROLB
AROLL
AROLW
ARORB
ARORL
ARORW
ASAHF
ASALB
ASALL
ASALW
ASARB
ASARL
ASARW
ASBBB
ASBBL
ASBBW
ASCASB
ASCASL
ASCASW
ASETCC
ASETCS
ASETEQ
ASETGE
ASETGT
ASETHI
ASETLE
ASETLS
ASETLT
ASETMI
ASETNE
ASETOC
ASETOS
ASETPC
ASETPL
ASETPS
ACDQ
ACWD
ASHLB
ASHLL
ASHLW
ASHRB
ASHRL
ASHRW
ASTC
ASTD
ASTI
ASTOSB
ASTOSL
ASTOSW
ASUBB
ASUBL
ASUBW
ASYSCALL
ATESTB
ATESTL
ATESTW
AVERR
AVERW
AWAIT
AWORD
AXCHGB
AXCHGL
AXCHGW
AXLAT
AXORB
AXORL
AXORW
AFMOVB
AFMOVBP
AFMOVD
AFMOVDP
AFMOVF
AFMOVFP
AFMOVL
AFMOVLP
AFMOVV
AFMOVVP
AFMOVW
AFMOVWP
AFMOVX
AFMOVXP
AFCOMB
AFCOMBP
AFCOMD
AFCOMDP
AFCOMDPP
AFCOMF
AFCOMFP
AFCOMI
AFCOMIP
AFCOML
AFCOMLP
AFCOMW
AFCOMWP
AFUCOM
AFUCOMI
AFUCOMIP
AFUCOMP
AFUCOMPP
AFADDDP
AFADDW
AFADDL
AFADDF
AFADDD
AFMULDP
AFMULW
AFMULL
AFMULF
AFMULD
AFSUBDP
AFSUBW
AFSUBL
AFSUBF
AFSUBD
AFSUBRDP
AFSUBRW
AFSUBRL
AFSUBRF
AFSUBRD
AFDIVDP
AFDIVW
AFDIVL
AFDIVF
AFDIVD
AFDIVRDP
AFDIVRW
AFDIVRL
AFDIVRF
AFDIVRD
AFXCHD
AFFREE
AFLDCW
AFLDENV
AFRSTOR
AFSAVE
AFSTCW
AFSTENV
AFSTSW
AF2XM1
AFABS
AFCHS
AFCLEX
AFCOS
AFDECSTP
AFINCSTP
AFINIT
AFLD1
AFLDL2E
AFLDL2T
AFLDLG2
AFLDLN2
AFLDPI
AFLDZ
AFNOP
AFPATAN
AFPREM
AFPREM1
AFPTAN
AFRNDINT
AFSCALE
AFSIN
AFSINCOS
AFSQRT
AFTST
AFXAM
AFXTRACT
AFYL2X
AFYL2XP1
ACMPXCHGB
ACMPXCHGL
ACMPXCHGW
ACMPXCHG8B
ACPUID
ARDTSC
AXADDB
AXADDL
AXADDW
ACMOVLCC
ACMOVLCS
ACMOVLEQ
ACMOVLGE
ACMOVLGT
ACMOVLHI
ACMOVLLE
ACMOVLLS
ACMOVLLT
ACMOVLMI
ACMOVLNE
ACMOVLOC
ACMOVLOS
ACMOVLPC
ACMOVLPL
ACMOVLPS
ACMOVWCC
ACMOVWCS
ACMOVWEQ
ACMOVWGE
ACMOVWGT
ACMOVWHI
ACMOVWLE
ACMOVWLS
ACMOVWLT
ACMOVWMI
ACMOVWNE
ACMOVWOC
ACMOVWOS
ACMOVWPC
ACMOVWPL
ACMOVWPS
AFCMOVCC
AFCMOVCS
AFCMOVEQ
AFCMOVHI
AFCMOVLS
AFCMOVNE
AFCMOVNU
AFCMOVUN
ALFENCE
AMFENCE
ASFENCE
AEMMS
APREFETCHT0
APREFETCHT1
APREFETCHT2
APREFETCHNTA
ABSWAPL
AADDPD
AADDPS
AADDSD
AADDSS
AANDNPD
AANDNPS
AANDPD
AANDPS
ACMPPD
ACMPPS
ACMPSD
ACMPSS
ACOMISD
ACOMISS
ACVTPL2PD
ACVTPL2PS
ACVTPD2PL
ACVTPD2PS
ACVTPS2PL
ACVTPS2PD
ACVTSD2SL
ACVTSD2SS
ACVTSL2SD
ACVTSL2SS
ACVTSS2SD
ACVTSS2SL
ACVTTPD2PL
ACVTTPS2PL
ACVTTSD2SL
ACVTTSS2SL
ADIVPD
ADIVPS
ADIVSD
ADIVSS
AMASKMOVOU
AMAXPD
AMAXPS
AMAXSD
AMAXSS
AMINPD
AMINPS
AMINSD
AMINSS
AMOVAPD
AMOVAPS
AMOVO
AMOVOU
AMOVHLPS
AMOVHPD
AMOVHPS
AMOVLHPS
AMOVLPD
AMOVLPS
AMOVMSKPD
AMOVMSKPS
AMOVNTO
AMOVNTPD
AMOVNTPS
AMOVSD
AMOVSS
AMOVUPD
AMOVUPS
AMULPD
AMULPS
AMULSD
AMULSS
AORPD
AORPS
APADDQ
APAND
APCMPEQB
APMAXSW
APMAXUB
APMINSW
APMINUB
APMOVMSKB
APSADBW
APSUBB
APSUBL
APSUBQ
APSUBSB
APSUBSW
APSUBUSB
APSUBUSW
APSUBW
APUNPCKHQDQ
APUNPCKLQDQ
APXOR
ARCPPS
ARCPSS
ARSQRTPS
ARSQRTSS
ASQRTPD
ASQRTPS
ASQRTSD
ASQRTSS
ASUBPD
ASUBPS
ASUBSD
ASUBSS
AUCOMISD
AUCOMISS
AUNPCKHPD
AUNPCKHPS
AUNPCKLPD
AUNPCKLPS
AXORPD
AXORPS
APSHUFHW
APSHUFL
APSHUFLW
AAESENC
APINSRD
APSHUFB
ALAST
)
const (
REG_NONE = 0
REG_AL = obj.RBase386 + 0 + iota - 1
REG_CL
REG_DL
REG_BL
REG_AH = obj.RBase386 + 4 + iota - 5
REG_CH
REG_DH
REG_BH
REG_AX = obj.RBase386 + 8 + iota - 9
REG_CX
REG_DX
REG_BX
REG_SP
REG_BP
REG_SI
REG_DI
REG_F0 = obj.RBase386 + 16
REG_F7 = obj.RBase386 + REG_F0 + 7
REG_CS = obj.RBase386 + 24 + iota - 19
REG_SS
REG_DS
REG_ES
REG_FS
REG_GS
REG_GDTR
REG_IDTR
REG_LDTR
REG_MSW
REG_TASK
REG_CR = obj.RBase386 + 35
REG_DR = obj.RBase386 + 43
REG_TR = obj.RBase386 + 51
REG_X0 = obj.RBase386 + 59 + iota - 33
REG_X1
REG_X2
REG_X3
REG_X4
REG_X5
REG_X6
REG_X7
REG_TLS = obj.RBase386 + 67
MAXREG = obj.RBase386 + 68
T_TYPE = 1 << 0
T_INDEX = 1 << 1
T_OFFSET = 1 << 2
T_FCONST = 1 << 3
T_SYM = 1 << 4
T_SCONST = 1 << 5
T_OFFSET2 = 1 << 6
T_GOTYPE = 1 << 7
REGARG = -1
REGRET = REG_AX
FREGRET = REG_F0
REGSP = REG_SP
REGTMP = REG_DI
REGCTXT = REG_DX
)
package i386
import "cmd/internal/obj"
/*
* this is the ranlib header
*/
var Anames = []string{
obj.A_ARCHSPECIFIC: "AAA",
"AAD",
"AAM",
"AAS",
"ADCB",
"ADCL",
"ADCW",
"ADDB",
"ADDL",
"ADDW",
"ADJSP",
"ANDB",
"ANDL",
"ANDW",
"ARPL",
"BOUNDL",
"BOUNDW",
"BSFL",
"BSFW",
"BSRL",
"BSRW",
"BTL",
"BTW",
"BTCL",
"BTCW",
"BTRL",
"BTRW",
"BTSL",
"BTSW",
"BYTE",
"CLC",
"CLD",
"CLI",
"CLTS",
"CMC",
"CMPB",
"CMPL",
"CMPW",
"CMPSB",
"CMPSL",
"CMPSW",
"DAA",
"DAS",
"DECB",
"DECL",
"DECW",
"DIVB",
"DIVL",
"DIVW",
"ENTER",
"HLT",
"IDIVB",
"IDIVL",
"IDIVW",
"IMULB",
"IMULL",
"IMULW",
"INB",
"INL",
"INW",
"INCB",
"INCL",
"INCW",
"INSB",
"INSL",
"INSW",
"INT",
"INTO",
"IRETL",
"IRETW",
"JCC",
"JCS",
"JCXZL",
"JCXZW",
"JEQ",
"JGE",
"JGT",
"JHI",
"JLE",
"JLS",
"JLT",
"JMI",
"JNE",
"JOC",
"JOS",
"JPC",
"JPL",
"JPS",
"LAHF",
"LARL",
"LARW",
"LEAL",
"LEAW",
"LEAVEL",
"LEAVEW",
"LOCK",
"LODSB",
"LODSL",
"LODSW",
"LONG",
"LOOP",
"LOOPEQ",
"LOOPNE",
"LSLL",
"LSLW",
"MOVB",
"MOVL",
"MOVW",
"MOVQ",
"MOVBLSX",
"MOVBLZX",
"MOVBWSX",
"MOVBWZX",
"MOVWLSX",
"MOVWLZX",
"MOVSB",
"MOVSL",
"MOVSW",
"MULB",
"MULL",
"MULW",
"NEGB",
"NEGL",
"NEGW",
"NOTB",
"NOTL",
"NOTW",
"ORB",
"ORL",
"ORW",
"OUTB",
"OUTL",
"OUTW",
"OUTSB",
"OUTSL",
"OUTSW",
"PAUSE",
"POPAL",
"POPAW",
"POPFL",
"POPFW",
"POPL",
"POPW",
"PUSHAL",
"PUSHAW",
"PUSHFL",
"PUSHFW",
"PUSHL",
"PUSHW",
"RCLB",
"RCLL",
"RCLW",
"RCRB",
"RCRL",
"RCRW",
"REP",
"REPN",
"ROLB",
"ROLL",
"ROLW",
"RORB",
"RORL",
"RORW",
"SAHF",
"SALB",
"SALL",
"SALW",
"SARB",
"SARL",
"SARW",
"SBBB",
"SBBL",
"SBBW",
"SCASB",
"SCASL",
"SCASW",
"SETCC",
"SETCS",
"SETEQ",
"SETGE",
"SETGT",
"SETHI",
"SETLE",
"SETLS",
"SETLT",
"SETMI",
"SETNE",
"SETOC",
"SETOS",
"SETPC",
"SETPL",
"SETPS",
"CDQ",
"CWD",
"SHLB",
"SHLL",
"SHLW",
"SHRB",
"SHRL",
"SHRW",
"STC",
"STD",
"STI",
"STOSB",
"STOSL",
"STOSW",
"SUBB",
"SUBL",
"SUBW",
"SYSCALL",
"TESTB",
"TESTL",
"TESTW",
"VERR",
"VERW",
"WAIT",
"WORD",
"XCHGB",
"XCHGL",
"XCHGW",
"XLAT",
"XORB",
"XORL",
"XORW",
"FMOVB",
"FMOVBP",
"FMOVD",
"FMOVDP",
"FMOVF",
"FMOVFP",
"FMOVL",
"FMOVLP",
"FMOVV",
"FMOVVP",
"FMOVW",
"FMOVWP",
"FMOVX",
"FMOVXP",
"FCOMB",
"FCOMBP",
"FCOMD",
"FCOMDP",
"FCOMDPP",
"FCOMF",
"FCOMFP",
"FCOMI",
"FCOMIP",
"FCOML",
"FCOMLP",
"FCOMW",
"FCOMWP",
"FUCOM",
"FUCOMI",
"FUCOMIP",
"FUCOMP",
"FUCOMPP",
"FADDDP",
"FADDW",
"FADDL",
"FADDF",
"FADDD",
"FMULDP",
"FMULW",
"FMULL",
"FMULF",
"FMULD",
"FSUBDP",
"FSUBW",
"FSUBL",
"FSUBF",
"FSUBD",
"FSUBRDP",
"FSUBRW",
"FSUBRL",
"FSUBRF",
"FSUBRD",
"FDIVDP",
"FDIVW",
"FDIVL",
"FDIVF",
"FDIVD",
"FDIVRDP",
"FDIVRW",
"FDIVRL",
"FDIVRF",
"FDIVRD",
"FXCHD",
"FFREE",
"FLDCW",
"FLDENV",
"FRSTOR",
"FSAVE",
"FSTCW",
"FSTENV",
"FSTSW",
"F2XM1",
"FABS",
"FCHS",
"FCLEX",
"FCOS",
"FDECSTP",
"FINCSTP",
"FINIT",
"FLD1",
"FLDL2E",
"FLDL2T",
"FLDLG2",
"FLDLN2",
"FLDPI",
"FLDZ",
"FNOP",
"FPATAN",
"FPREM",
"FPREM1",
"FPTAN",
"FRNDINT",
"FSCALE",
"FSIN",
"FSINCOS",
"FSQRT",
"FTST",
"FXAM",
"FXTRACT",
"FYL2X",
"FYL2XP1",
"CMPXCHGB",
"CMPXCHGL",
"CMPXCHGW",
"CMPXCHG8B",
"CPUID",
"RDTSC",
"XADDB",
"XADDL",
"XADDW",
"CMOVLCC",
"CMOVLCS",
"CMOVLEQ",
"CMOVLGE",
"CMOVLGT",
"CMOVLHI",
"CMOVLLE",
"CMOVLLS",
"CMOVLLT",
"CMOVLMI",
"CMOVLNE",
"CMOVLOC",
"CMOVLOS",
"CMOVLPC",
"CMOVLPL",
"CMOVLPS",
"CMOVWCC",
"CMOVWCS",
"CMOVWEQ",
"CMOVWGE",
"CMOVWGT",
"CMOVWHI",
"CMOVWLE",
"CMOVWLS",
"CMOVWLT",
"CMOVWMI",
"CMOVWNE",
"CMOVWOC",
"CMOVWOS",
"CMOVWPC",
"CMOVWPL",
"CMOVWPS",
"FCMOVCC",
"FCMOVCS",
"FCMOVEQ",
"FCMOVHI",
"FCMOVLS",
"FCMOVNE",
"FCMOVNU",
"FCMOVUN",
"LFENCE",
"MFENCE",
"SFENCE",
"EMMS",
"PREFETCHT0",
"PREFETCHT1",
"PREFETCHT2",
"PREFETCHNTA",
"BSWAPL",
"ADDPD",
"ADDPS",
"ADDSD",
"ADDSS",
"ANDNPD",
"ANDNPS",
"ANDPD",
"ANDPS",
"CMPPD",
"CMPPS",
"CMPSD",
"CMPSS",
"COMISD",
"COMISS",
"CVTPL2PD",
"CVTPL2PS",
"CVTPD2PL",
"CVTPD2PS",
"CVTPS2PL",
"CVTPS2PD",
"CVTSD2SL",
"CVTSD2SS",
"CVTSL2SD",
"CVTSL2SS",
"CVTSS2SD",
"CVTSS2SL",
"CVTTPD2PL",
"CVTTPS2PL",
"CVTTSD2SL",
"CVTTSS2SL",
"DIVPD",
"DIVPS",
"DIVSD",
"DIVSS",
"MASKMOVOU",
"MAXPD",
"MAXPS",
"MAXSD",
"MAXSS",
"MINPD",
"MINPS",
"MINSD",
"MINSS",
"MOVAPD",
"MOVAPS",
"MOVO",
"MOVOU",
"MOVHLPS",
"MOVHPD",
"MOVHPS",
"MOVLHPS",
"MOVLPD",
"MOVLPS",
"MOVMSKPD",
"MOVMSKPS",
"MOVNTO",
"MOVNTPD",
"MOVNTPS",
"MOVSD",
"MOVSS",
"MOVUPD",
"MOVUPS",
"MULPD",
"MULPS",
"MULSD",
"MULSS",
"ORPD",
"ORPS",
"PADDQ",
"PAND",
"PCMPEQB",
"PMAXSW",
"PMAXUB",
"PMINSW",
"PMINUB",
"PMOVMSKB",
"PSADBW",
"PSUBB",
"PSUBL",
"PSUBQ",
"PSUBSB",
"PSUBSW",
"PSUBUSB",
"PSUBUSW",
"PSUBW",
"PUNPCKHQDQ",
"PUNPCKLQDQ",
"PXOR",
"RCPPS",
"RCPSS",
"RSQRTPS",
"RSQRTSS",
"SQRTPD",
"SQRTPS",
"SQRTSD",
"SQRTSS",
"SUBPD",
"SUBPS",
"SUBSD",
"SUBSS",
"UCOMISD",
"UCOMISS",
"UNPCKHPD",
"UNPCKHPS",
"UNPCKLPD",
"UNPCKLPS",
"XORPD",
"XORPS",
"PSHUFHW",
"PSHUFL",
"PSHUFLW",
"AESENC",
"PINSRD",
"PSHUFB",
"LAST",
}
// Inferno utils/8l/span.c
// http://code.google.com/p/inferno-os/source/browse/utils/8l/span.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package i386
import (
"cmd/internal/obj"
"fmt"
"log"
"strings"
)
// Instruction layout.
const (
MaxAlign = 32
FuncAlign = 16
)
type Optab struct {
as int16
ytab []ytab
prefix uint8
op [13]uint8
}
type ytab struct {
from uint8
to uint8
zcase uint8
zoffset uint8
}
var opindex [(ALAST + 1) & obj.AMask]*Optab
const (
Yxxx = 0 + iota
Ynone
Yi0
Yi1
Yi8
Yi32
Yiauto
Yal
Ycl
Yax
Ycx
Yrb
Yrl
Yrf
Yf0
Yrx
Ymb
Yml
Ym
Ybr
Ycol
Ytextsize
Ytls
Ycs
Yss
Yds
Yes
Yfs
Ygs
Ygdtr
Yidtr
Yldtr
Ymsw
Ytask
Ycr0
Ycr1
Ycr2
Ycr3
Ycr4
Ycr5
Ycr6
Ycr7
Ydr0
Ydr1
Ydr2
Ydr3
Ydr4
Ydr5
Ydr6
Ydr7
Ytr0
Ytr1
Ytr2
Ytr3
Ytr4
Ytr5
Ytr6
Ytr7
Ymr
Ymm
Yxr
Yxm
Ymax
Zxxx = 0 + iota - 63
Zlit
Zlitm_r
Z_rp
Zbr
Zcall
Zcallcon
Zcallind
Zcallindreg
Zib_
Zib_rp
Zibo_m
Zil_
Zil_rp
Zilo_m
Zjmp
Zjmpcon
Zloop
Zm_o
Zm_r
Zm2_r
Zm_r_xm
Zm_r_i_xm
Zaut_r
Zo_m
Zpseudo
Zr_m
Zr_m_xm
Zr_m_i_xm
Zrp_
Z_ib
Z_il
Zm_ibo
Zm_ilo
Zib_rr
Zil_rr
Zclr
Zibm_r
Zbyte
Zmov
Zmax
Px = 0
Pe = 0x66
Pm = 0x0f
Pq = 0xff
Pb = 0xfe
Pf2 = 0xf2
Pf3 = 0xf3
)
var ycover [Ymax * Ymax]uint8
var reg [MAXREG]int
var ynone = []ytab{
{Ynone, Ynone, Zlit, 1},
}
var ytext = []ytab{
{Ymb, Ytextsize, Zpseudo, 1},
}
var ynop = []ytab{
{Ynone, Ynone, Zpseudo, 0},
{Ynone, Yiauto, Zpseudo, 0},
{Ynone, Yml, Zpseudo, 0},
{Ynone, Yrf, Zpseudo, 0},
{Yiauto, Ynone, Zpseudo, 0},
{Ynone, Yxr, Zpseudo, 0},
{Yml, Ynone, Zpseudo, 0},
{Yrf, Ynone, Zpseudo, 0},
{Yxr, Ynone, Zpseudo, 1},
}
var yfuncdata = []ytab{
{Yi32, Ym, Zpseudo, 0},
}
var ypcdata = []ytab{
{Yi32, Yi32, Zpseudo, 0},
}
var yxorb = []ytab{
{Yi32, Yal, Zib_, 1},
{Yi32, Ymb, Zibo_m, 2},
{Yrb, Ymb, Zr_m, 1},
{Ymb, Yrb, Zm_r, 1},
}
var yxorl = []ytab{
{Yi8, Yml, Zibo_m, 2},
{Yi32, Yax, Zil_, 1},
{Yi32, Yml, Zilo_m, 2},
{Yrl, Yml, Zr_m, 1},
{Yml, Yrl, Zm_r, 1},
}
var yaddl = []ytab{
{Yi8, Yml, Zibo_m, 2},
{Yi32, Yax, Zil_, 1},
{Yi32, Yml, Zilo_m, 2},
{Yrl, Yml, Zr_m, 1},
{Yml, Yrl, Zm_r, 1},
}
var yincb = []ytab{
{Ynone, Ymb, Zo_m, 2},
}
var yincl = []ytab{
{Ynone, Yrl, Z_rp, 1},
{Ynone, Yml, Zo_m, 2},
}
var ycmpb = []ytab{
{Yal, Yi32, Z_ib, 1},
{Ymb, Yi32, Zm_ibo, 2},
{Ymb, Yrb, Zm_r, 1},
{Yrb, Ymb, Zr_m, 1},
}
var ycmpl = []ytab{
{Yml, Yi8, Zm_ibo, 2},
{Yax, Yi32, Z_il, 1},
{Yml, Yi32, Zm_ilo, 2},
{Yml, Yrl, Zm_r, 1},
{Yrl, Yml, Zr_m, 1},
}
var yshb = []ytab{
{Yi1, Ymb, Zo_m, 2},
{Yi32, Ymb, Zibo_m, 2},
{Ycx, Ymb, Zo_m, 2},
}
var yshl = []ytab{
{Yi1, Yml, Zo_m, 2},
{Yi32, Yml, Zibo_m, 2},
{Ycl, Yml, Zo_m, 2},
{Ycx, Yml, Zo_m, 2},
}
var ytestb = []ytab{
{Yi32, Yal, Zib_, 1},
{Yi32, Ymb, Zibo_m, 2},
{Yrb, Ymb, Zr_m, 1},
{Ymb, Yrb, Zm_r, 1},
}
var ytestl = []ytab{
{Yi32, Yax, Zil_, 1},
{Yi32, Yml, Zilo_m, 2},
{Yrl, Yml, Zr_m, 1},
{Yml, Yrl, Zm_r, 1},
}
var ymovb = []ytab{
{Yrb, Ymb, Zr_m, 1},
{Ymb, Yrb, Zm_r, 1},
{Yi32, Yrb, Zib_rp, 1},
{Yi32, Ymb, Zibo_m, 2},
}
var ymovw = []ytab{
{Yrl, Yml, Zr_m, 1},
{Yml, Yrl, Zm_r, 1},
{Yi0, Yrl, Zclr, 1 + 2},
// Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
{Yi32, Yrl, Zil_rp, 1},
{Yi32, Yml, Zilo_m, 2},
{Yiauto, Yrl, Zaut_r, 1},
}
var ymovl = []ytab{
{Yrl, Yml, Zr_m, 1},
{Yml, Yrl, Zm_r, 1},
{Yi0, Yrl, Zclr, 1 + 2},
// Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
{Yi32, Yrl, Zil_rp, 1},
{Yi32, Yml, Zilo_m, 2},
{Yml, Yxr, Zm_r_xm, 2}, // XMM MOVD (32 bit)
{Yxr, Yml, Zr_m_xm, 2}, // XMM MOVD (32 bit)
{Yiauto, Yrl, Zaut_r, 1},
}
var ymovq = []ytab{
{Yml, Yxr, Zm_r_xm, 2},
}
var ym_rl = []ytab{
{Ym, Yrl, Zm_r, 1},
}
var yrl_m = []ytab{
{Yrl, Ym, Zr_m, 1},
}
var ymb_rl = []ytab{
{Ymb, Yrl, Zm_r, 1},
}
var yml_rl = []ytab{
{Yml, Yrl, Zm_r, 1},
}
var yrb_mb = []ytab{
{Yrb, Ymb, Zr_m, 1},
}
var yrl_ml = []ytab{
{Yrl, Yml, Zr_m, 1},
}
var yml_mb = []ytab{
{Yrb, Ymb, Zr_m, 1},
{Ymb, Yrb, Zm_r, 1},
}
var yxchg = []ytab{
{Yax, Yrl, Z_rp, 1},
{Yrl, Yax, Zrp_, 1},
{Yrl, Yml, Zr_m, 1},
{Yml, Yrl, Zm_r, 1},
}
var ydivl = []ytab{
{Yml, Ynone, Zm_o, 2},
}
var ydivb = []ytab{
{Ymb, Ynone, Zm_o, 2},
}
var yimul = []ytab{
{Yml, Ynone, Zm_o, 2},
{Yi8, Yrl, Zib_rr, 1},
{Yi32, Yrl, Zil_rr, 1},
}
var ybyte = []ytab{
{Yi32, Ynone, Zbyte, 1},
}
var yin = []ytab{
{Yi32, Ynone, Zib_, 1},
{Ynone, Ynone, Zlit, 1},
}
var yint = []ytab{
{Yi32, Ynone, Zib_, 1},
}
var ypushl = []ytab{
{Yrl, Ynone, Zrp_, 1},
{Ym, Ynone, Zm_o, 2},
{Yi8, Ynone, Zib_, 1},
{Yi32, Ynone, Zil_, 1},
}
var ypopl = []ytab{
{Ynone, Yrl, Z_rp, 1},
{Ynone, Ym, Zo_m, 2},
}
var ybswap = []ytab{
{Ynone, Yrl, Z_rp, 1},
}
var yscond = []ytab{
{Ynone, Ymb, Zo_m, 2},
}
var yjcond = []ytab{
{Ynone, Ybr, Zbr, 0},
{Yi0, Ybr, Zbr, 0},
{Yi1, Ybr, Zbr, 1},
}
var yloop = []ytab{
{Ynone, Ybr, Zloop, 1},
}
var ycall = []ytab{
{Ynone, Yml, Zcallindreg, 0},
{Yrx, Yrx, Zcallindreg, 2},
{Ynone, Ycol, Zcallind, 2},
{Ynone, Ybr, Zcall, 0},
{Ynone, Yi32, Zcallcon, 1},
}
var yduff = []ytab{
{Ynone, Yi32, Zcall, 1},
}
var yjmp = []ytab{
{Ynone, Yml, Zo_m, 2},
{Ynone, Ybr, Zjmp, 0},
{Ynone, Yi32, Zjmpcon, 1},
}
var yfmvd = []ytab{
{Ym, Yf0, Zm_o, 2},
{Yf0, Ym, Zo_m, 2},
{Yrf, Yf0, Zm_o, 2},
{Yf0, Yrf, Zo_m, 2},
}
var yfmvdp = []ytab{
{Yf0, Ym, Zo_m, 2},
{Yf0, Yrf, Zo_m, 2},
}
var yfmvf = []ytab{
{Ym, Yf0, Zm_o, 2},
{Yf0, Ym, Zo_m, 2},
}
var yfmvx = []ytab{
{Ym, Yf0, Zm_o, 2},
}
var yfmvp = []ytab{
{Yf0, Ym, Zo_m, 2},
}
var yfcmv = []ytab{
{Yrf, Yf0, Zm_o, 2},
}
var yfadd = []ytab{
{Ym, Yf0, Zm_o, 2},
{Yrf, Yf0, Zm_o, 2},
{Yf0, Yrf, Zo_m, 2},
}
var yfaddp = []ytab{
{Yf0, Yrf, Zo_m, 2},
}
var yfxch = []ytab{
{Yf0, Yrf, Zo_m, 2},
{Yrf, Yf0, Zm_o, 2},
}
var ycompp = []ytab{
{Yf0, Yrf, Zo_m, 2}, /* botch is really f0,f1 */
}
var ystsw = []ytab{
{Ynone, Ym, Zo_m, 2},
{Ynone, Yax, Zlit, 1},
}
var ystcw = []ytab{
{Ynone, Ym, Zo_m, 2},
{Ym, Ynone, Zm_o, 2},
}
var ysvrs = []ytab{
{Ynone, Ym, Zo_m, 2},
{Ym, Ynone, Zm_o, 2},
}
var ymskb = []ytab{
{Yxr, Yrl, Zm_r_xm, 2},
{Ymr, Yrl, Zm_r_xm, 1},
}
var yxm = []ytab{
{Yxm, Yxr, Zm_r_xm, 1},
}
var yxcvm1 = []ytab{
{Yxm, Yxr, Zm_r_xm, 2},
{Yxm, Ymr, Zm_r_xm, 2},
}
var yxcvm2 = []ytab{
{Yxm, Yxr, Zm_r_xm, 2},
{Ymm, Yxr, Zm_r_xm, 2},
}
var yxmq = []ytab{
{Yxm, Yxr, Zm_r_xm, 2},
}
var yxr = []ytab{
{Yxr, Yxr, Zm_r_xm, 1},
}
var yxr_ml = []ytab{
{Yxr, Yml, Zr_m_xm, 1},
}
var yxcmp = []ytab{
{Yxm, Yxr, Zm_r_xm, 1},
}
var yxcmpi = []ytab{
{Yxm, Yxr, Zm_r_i_xm, 2},
}
var yxmov = []ytab{
{Yxm, Yxr, Zm_r_xm, 1},
{Yxr, Yxm, Zr_m_xm, 1},
}
var yxcvfl = []ytab{
{Yxm, Yrl, Zm_r_xm, 1},
}
var yxcvlf = []ytab{
{Yml, Yxr, Zm_r_xm, 1},
}
/*
var yxcvfq = []ytab{
{Yxm, Yrl, Zm_r_xm, 2},
}
var yxcvqf = []ytab{
{Yml, Yxr, Zm_r_xm, 2},
}
*/
var yxrrl = []ytab{
{Yxr, Yrl, Zm_r, 1},
}
var yprefetch = []ytab{
{Ym, Ynone, Zm_o, 2},
}
var yaes = []ytab{
{Yxm, Yxr, Zlitm_r, 2},
}
var yinsrd = []ytab{
{Yml, Yxr, Zibm_r, 2},
}
var ymshufb = []ytab{
{Yxm, Yxr, Zm2_r, 2},
}
var yxshuf = []ytab{
{Yxm, Yxr, Zibm_r, 2},
}
var optab = []Optab{ /* as, ytab, andproto, opcode */
Optab{obj.AXXX, nil, 0, [13]uint8{}},
Optab{AAAA, ynone, Px, [13]uint8{0x37}},
Optab{AAAD, ynone, Px, [13]uint8{0xd5, 0x0a}},
Optab{AAAM, ynone, Px, [13]uint8{0xd4, 0x0a}},
Optab{AAAS, ynone, Px, [13]uint8{0x3f}},
Optab{AADCB, yxorb, Pb, [13]uint8{0x14, 0x80, 02, 0x10, 0x10}},
Optab{AADCL, yxorl, Px, [13]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
Optab{AADCW, yxorl, Pe, [13]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
Optab{AADDB, yxorb, Px, [13]uint8{0x04, 0x80, 00, 0x00, 0x02}},
Optab{AADDL, yaddl, Px, [13]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
Optab{AADDW, yaddl, Pe, [13]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
Optab{AADJSP, nil, 0, [13]uint8{}},
Optab{AANDB, yxorb, Pb, [13]uint8{0x24, 0x80, 04, 0x20, 0x22}},
Optab{AANDL, yxorl, Px, [13]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
Optab{AANDW, yxorl, Pe, [13]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
Optab{AARPL, yrl_ml, Px, [13]uint8{0x63}},
Optab{ABOUNDL, yrl_m, Px, [13]uint8{0x62}},
Optab{ABOUNDW, yrl_m, Pe, [13]uint8{0x62}},
Optab{ABSFL, yml_rl, Pm, [13]uint8{0xbc}},
Optab{ABSFW, yml_rl, Pq, [13]uint8{0xbc}},
Optab{ABSRL, yml_rl, Pm, [13]uint8{0xbd}},
Optab{ABSRW, yml_rl, Pq, [13]uint8{0xbd}},
Optab{ABTL, yml_rl, Pm, [13]uint8{0xa3}},
Optab{ABTW, yml_rl, Pq, [13]uint8{0xa3}},
Optab{ABTCL, yml_rl, Pm, [13]uint8{0xbb}},
Optab{ABTCW, yml_rl, Pq, [13]uint8{0xbb}},
Optab{ABTRL, yml_rl, Pm, [13]uint8{0xb3}},
Optab{ABTRW, yml_rl, Pq, [13]uint8{0xb3}},
Optab{ABTSL, yml_rl, Pm, [13]uint8{0xab}},
Optab{ABTSW, yml_rl, Pq, [13]uint8{0xab}},
Optab{ABYTE, ybyte, Px, [13]uint8{1}},
Optab{obj.ACALL, ycall, Px, [13]uint8{0xff, 02, 0xff, 0x15, 0xe8}},
Optab{ACLC, ynone, Px, [13]uint8{0xf8}},
Optab{ACLD, ynone, Px, [13]uint8{0xfc}},
Optab{ACLI, ynone, Px, [13]uint8{0xfa}},
Optab{ACLTS, ynone, Pm, [13]uint8{0x06}},
Optab{ACMC, ynone, Px, [13]uint8{0xf5}},
Optab{ACMPB, ycmpb, Pb, [13]uint8{0x3c, 0x80, 07, 0x38, 0x3a}},
Optab{ACMPL, ycmpl, Px, [13]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
Optab{ACMPW, ycmpl, Pe, [13]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
Optab{ACMPSB, ynone, Pb, [13]uint8{0xa6}},
Optab{ACMPSL, ynone, Px, [13]uint8{0xa7}},
Optab{ACMPSW, ynone, Pe, [13]uint8{0xa7}},
Optab{ADAA, ynone, Px, [13]uint8{0x27}},
Optab{ADAS, ynone, Px, [13]uint8{0x2f}},
Optab{obj.ADATA, nil, 0, [13]uint8{}},
Optab{ADECB, yincb, Pb, [13]uint8{0xfe, 01}},
Optab{ADECL, yincl, Px, [13]uint8{0x48, 0xff, 01}},
Optab{ADECW, yincl, Pe, [13]uint8{0x48, 0xff, 01}},
Optab{ADIVB, ydivb, Pb, [13]uint8{0xf6, 06}},
Optab{ADIVL, ydivl, Px, [13]uint8{0xf7, 06}},
Optab{ADIVW, ydivl, Pe, [13]uint8{0xf7, 06}},
Optab{AENTER, nil, 0, [13]uint8{}}, /* botch */
Optab{obj.AGLOBL, nil, 0, [13]uint8{}},
Optab{AHLT, ynone, Px, [13]uint8{0xf4}},
Optab{AIDIVB, ydivb, Pb, [13]uint8{0xf6, 07}},
Optab{AIDIVL, ydivl, Px, [13]uint8{0xf7, 07}},
Optab{AIDIVW, ydivl, Pe, [13]uint8{0xf7, 07}},
Optab{AIMULB, ydivb, Pb, [13]uint8{0xf6, 05}},
Optab{AIMULL, yimul, Px, [13]uint8{0xf7, 05, 0x6b, 0x69}},
Optab{AIMULW, yimul, Pe, [13]uint8{0xf7, 05, 0x6b, 0x69}},
Optab{AINB, yin, Pb, [13]uint8{0xe4, 0xec}},
Optab{AINL, yin, Px, [13]uint8{0xe5, 0xed}},
Optab{AINW, yin, Pe, [13]uint8{0xe5, 0xed}},
Optab{AINCB, yincb, Pb, [13]uint8{0xfe, 00}},
Optab{AINCL, yincl, Px, [13]uint8{0x40, 0xff, 00}},
Optab{AINCW, yincl, Pe, [13]uint8{0x40, 0xff, 00}},
Optab{AINSB, ynone, Pb, [13]uint8{0x6c}},
Optab{AINSL, ynone, Px, [13]uint8{0x6d}},
Optab{AINSW, ynone, Pe, [13]uint8{0x6d}},
Optab{AINT, yint, Px, [13]uint8{0xcd}},
Optab{AINTO, ynone, Px, [13]uint8{0xce}},
Optab{AIRETL, ynone, Px, [13]uint8{0xcf}},
Optab{AIRETW, ynone, Pe, [13]uint8{0xcf}},
Optab{AJCC, yjcond, Px, [13]uint8{0x73, 0x83, 00}},
Optab{AJCS, yjcond, Px, [13]uint8{0x72, 0x82}},
Optab{AJCXZL, yloop, Px, [13]uint8{0xe3}},
Optab{AJCXZW, yloop, Px, [13]uint8{0xe3}},
Optab{AJEQ, yjcond, Px, [13]uint8{0x74, 0x84}},
Optab{AJGE, yjcond, Px, [13]uint8{0x7d, 0x8d}},
Optab{AJGT, yjcond, Px, [13]uint8{0x7f, 0x8f}},
Optab{AJHI, yjcond, Px, [13]uint8{0x77, 0x87}},
Optab{AJLE, yjcond, Px, [13]uint8{0x7e, 0x8e}},
Optab{AJLS, yjcond, Px, [13]uint8{0x76, 0x86}},
Optab{AJLT, yjcond, Px, [13]uint8{0x7c, 0x8c}},
Optab{AJMI, yjcond, Px, [13]uint8{0x78, 0x88}},
Optab{obj.AJMP, yjmp, Px, [13]uint8{0xff, 04, 0xeb, 0xe9}},
Optab{AJNE, yjcond, Px, [13]uint8{0x75, 0x85}},
Optab{AJOC, yjcond, Px, [13]uint8{0x71, 0x81, 00}},
Optab{AJOS, yjcond, Px, [13]uint8{0x70, 0x80, 00}},
Optab{AJPC, yjcond, Px, [13]uint8{0x7b, 0x8b}},
Optab{AJPL, yjcond, Px, [13]uint8{0x79, 0x89}},
Optab{AJPS, yjcond, Px, [13]uint8{0x7a, 0x8a}},
Optab{ALAHF, ynone, Px, [13]uint8{0x9f}},
Optab{ALARL, yml_rl, Pm, [13]uint8{0x02}},
Optab{ALARW, yml_rl, Pq, [13]uint8{0x02}},
Optab{ALEAL, ym_rl, Px, [13]uint8{0x8d}},
Optab{ALEAW, ym_rl, Pe, [13]uint8{0x8d}},
Optab{ALEAVEL, ynone, Px, [13]uint8{0xc9}},
Optab{ALEAVEW, ynone, Pe, [13]uint8{0xc9}},
Optab{ALOCK, ynone, Px, [13]uint8{0xf0}},
Optab{ALODSB, ynone, Pb, [13]uint8{0xac}},
Optab{ALODSL, ynone, Px, [13]uint8{0xad}},
Optab{ALODSW, ynone, Pe, [13]uint8{0xad}},
Optab{ALONG, ybyte, Px, [13]uint8{4}},
Optab{ALOOP, yloop, Px, [13]uint8{0xe2}},
Optab{ALOOPEQ, yloop, Px, [13]uint8{0xe1}},
Optab{ALOOPNE, yloop, Px, [13]uint8{0xe0}},
Optab{ALSLL, yml_rl, Pm, [13]uint8{0x03}},
Optab{ALSLW, yml_rl, Pq, [13]uint8{0x03}},
Optab{AMOVB, ymovb, Pb, [13]uint8{0x88, 0x8a, 0xb0, 0xc6, 00}},
Optab{AMOVL, ymovl, Px, [13]uint8{0x89, 0x8b, 0x31, 0x83, 04, 0xb8, 0xc7, 00, Pe, 0x6e, Pe, 0x7e, 0}},
Optab{AMOVW, ymovw, Pe, [13]uint8{0x89, 0x8b, 0x31, 0x83, 04, 0xb8, 0xc7, 00, 0}},
Optab{AMOVQ, ymovq, Pf3, [13]uint8{0x7e}},
Optab{AMOVBLSX, ymb_rl, Pm, [13]uint8{0xbe}},
Optab{AMOVBLZX, ymb_rl, Pm, [13]uint8{0xb6}},
Optab{AMOVBWSX, ymb_rl, Pq, [13]uint8{0xbe}},
Optab{AMOVBWZX, ymb_rl, Pq, [13]uint8{0xb6}},
Optab{AMOVWLSX, yml_rl, Pm, [13]uint8{0xbf}},
Optab{AMOVWLZX, yml_rl, Pm, [13]uint8{0xb7}},
Optab{AMOVSB, ynone, Pb, [13]uint8{0xa4}},
Optab{AMOVSL, ynone, Px, [13]uint8{0xa5}},
Optab{AMOVSW, ynone, Pe, [13]uint8{0xa5}},
Optab{AMULB, ydivb, Pb, [13]uint8{0xf6, 04}},
Optab{AMULL, ydivl, Px, [13]uint8{0xf7, 04}},
Optab{AMULW, ydivl, Pe, [13]uint8{0xf7, 04}},
Optab{ANEGB, yscond, Px, [13]uint8{0xf6, 03}},
Optab{ANEGL, yscond, Px, [13]uint8{0xf7, 03}}, // TODO(rsc): yscond is wrong here.
Optab{ANEGW, yscond, Pe, [13]uint8{0xf7, 03}}, // TODO(rsc): yscond is wrong here.
Optab{obj.ANOP, ynop, Px, [13]uint8{0, 0}},
Optab{ANOTB, yscond, Px, [13]uint8{0xf6, 02}},
Optab{ANOTL, yscond, Px, [13]uint8{0xf7, 02}}, // TODO(rsc): yscond is wrong here.
Optab{ANOTW, yscond, Pe, [13]uint8{0xf7, 02}}, // TODO(rsc): yscond is wrong here.
Optab{AORB, yxorb, Pb, [13]uint8{0x0c, 0x80, 01, 0x08, 0x0a}},
Optab{AORL, yxorl, Px, [13]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
Optab{AORW, yxorl, Pe, [13]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
Optab{AOUTB, yin, Pb, [13]uint8{0xe6, 0xee}},
Optab{AOUTL, yin, Px, [13]uint8{0xe7, 0xef}},
Optab{AOUTW, yin, Pe, [13]uint8{0xe7, 0xef}},
Optab{AOUTSB, ynone, Pb, [13]uint8{0x6e}},
Optab{AOUTSL, ynone, Px, [13]uint8{0x6f}},
Optab{AOUTSW, ynone, Pe, [13]uint8{0x6f}},
Optab{APAUSE, ynone, Px, [13]uint8{0xf3, 0x90}},
Optab{APOPAL, ynone, Px, [13]uint8{0x61}},
Optab{APOPAW, ynone, Pe, [13]uint8{0x61}},
Optab{APOPFL, ynone, Px, [13]uint8{0x9d}},
Optab{APOPFW, ynone, Pe, [13]uint8{0x9d}},
Optab{APOPL, ypopl, Px, [13]uint8{0x58, 0x8f, 00}},
Optab{APOPW, ypopl, Pe, [13]uint8{0x58, 0x8f, 00}},
Optab{APUSHAL, ynone, Px, [13]uint8{0x60}},
Optab{APUSHAW, ynone, Pe, [13]uint8{0x60}},
Optab{APUSHFL, ynone, Px, [13]uint8{0x9c}},
Optab{APUSHFW, ynone, Pe, [13]uint8{0x9c}},
Optab{APUSHL, ypushl, Px, [13]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
Optab{APUSHW, ypushl, Pe, [13]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
Optab{ARCLB, yshb, Pb, [13]uint8{0xd0, 02, 0xc0, 02, 0xd2, 02}},
Optab{ARCLL, yshl, Px, [13]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
Optab{ARCLW, yshl, Pe, [13]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
Optab{ARCRB, yshb, Pb, [13]uint8{0xd0, 03, 0xc0, 03, 0xd2, 03}},
Optab{ARCRL, yshl, Px, [13]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
Optab{ARCRW, yshl, Pe, [13]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
Optab{AREP, ynone, Px, [13]uint8{0xf3}},
Optab{AREPN, ynone, Px, [13]uint8{0xf2}},
Optab{obj.ARET, ynone, Px, [13]uint8{0xc3}},
Optab{AROLB, yshb, Pb, [13]uint8{0xd0, 00, 0xc0, 00, 0xd2, 00}},
Optab{AROLL, yshl, Px, [13]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
Optab{AROLW, yshl, Pe, [13]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
Optab{ARORB, yshb, Pb, [13]uint8{0xd0, 01, 0xc0, 01, 0xd2, 01}},
Optab{ARORL, yshl, Px, [13]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
Optab{ARORW, yshl, Pe, [13]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
Optab{ASAHF, ynone, Px, [13]uint8{0x9e}},
Optab{ASALB, yshb, Pb, [13]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
Optab{ASALL, yshl, Px, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
Optab{ASALW, yshl, Pe, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
Optab{ASARB, yshb, Pb, [13]uint8{0xd0, 07, 0xc0, 07, 0xd2, 07}},
Optab{ASARL, yshl, Px, [13]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
Optab{ASARW, yshl, Pe, [13]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
Optab{ASBBB, yxorb, Pb, [13]uint8{0x1c, 0x80, 03, 0x18, 0x1a}},
Optab{ASBBL, yxorl, Px, [13]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
Optab{ASBBW, yxorl, Pe, [13]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
Optab{ASCASB, ynone, Pb, [13]uint8{0xae}},
Optab{ASCASL, ynone, Px, [13]uint8{0xaf}},
Optab{ASCASW, ynone, Pe, [13]uint8{0xaf}},
Optab{ASETCC, yscond, Pm, [13]uint8{0x93, 00}},
Optab{ASETCS, yscond, Pm, [13]uint8{0x92, 00}},
Optab{ASETEQ, yscond, Pm, [13]uint8{0x94, 00}},
Optab{ASETGE, yscond, Pm, [13]uint8{0x9d, 00}},
Optab{ASETGT, yscond, Pm, [13]uint8{0x9f, 00}},
Optab{ASETHI, yscond, Pm, [13]uint8{0x97, 00}},
Optab{ASETLE, yscond, Pm, [13]uint8{0x9e, 00}},
Optab{ASETLS, yscond, Pm, [13]uint8{0x96, 00}},
Optab{ASETLT, yscond, Pm, [13]uint8{0x9c, 00}},
Optab{ASETMI, yscond, Pm, [13]uint8{0x98, 00}},
Optab{ASETNE, yscond, Pm, [13]uint8{0x95, 00}},
Optab{ASETOC, yscond, Pm, [13]uint8{0x91, 00}},
Optab{ASETOS, yscond, Pm, [13]uint8{0x90, 00}},
Optab{ASETPC, yscond, Pm, [13]uint8{0x9b, 00}},
Optab{ASETPL, yscond, Pm, [13]uint8{0x99, 00}},
Optab{ASETPS, yscond, Pm, [13]uint8{0x9a, 00}},
Optab{ACDQ, ynone, Px, [13]uint8{0x99}},
Optab{ACWD, ynone, Pe, [13]uint8{0x99}},
Optab{ASHLB, yshb, Pb, [13]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
Optab{ASHLL, yshl, Px, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
Optab{ASHLW, yshl, Pe, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
Optab{ASHRB, yshb, Pb, [13]uint8{0xd0, 05, 0xc0, 05, 0xd2, 05}},
Optab{ASHRL, yshl, Px, [13]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
Optab{ASHRW, yshl, Pe, [13]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
Optab{ASTC, ynone, Px, [13]uint8{0xf9}},
Optab{ASTD, ynone, Px, [13]uint8{0xfd}},
Optab{ASTI, ynone, Px, [13]uint8{0xfb}},
Optab{ASTOSB, ynone, Pb, [13]uint8{0xaa}},
Optab{ASTOSL, ynone, Px, [13]uint8{0xab}},
Optab{ASTOSW, ynone, Pe, [13]uint8{0xab}},
Optab{ASUBB, yxorb, Pb, [13]uint8{0x2c, 0x80, 05, 0x28, 0x2a}},
Optab{ASUBL, yaddl, Px, [13]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
Optab{ASUBW, yaddl, Pe, [13]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
Optab{ASYSCALL, ynone, Px, [13]uint8{0xcd, 100}},
Optab{ATESTB, ytestb, Pb, [13]uint8{0xa8, 0xf6, 00, 0x84, 0x84}},
Optab{ATESTL, ytestl, Px, [13]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
Optab{ATESTW, ytestl, Pe, [13]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
Optab{obj.ATEXT, ytext, Px, [13]uint8{}},
Optab{AVERR, ydivl, Pm, [13]uint8{0x00, 04}},
Optab{AVERW, ydivl, Pm, [13]uint8{0x00, 05}},
Optab{AWAIT, ynone, Px, [13]uint8{0x9b}},
Optab{AWORD, ybyte, Px, [13]uint8{2}},
Optab{AXCHGB, yml_mb, Pb, [13]uint8{0x86, 0x86}},
Optab{AXCHGL, yxchg, Px, [13]uint8{0x90, 0x90, 0x87, 0x87}},
Optab{AXCHGW, yxchg, Pe, [13]uint8{0x90, 0x90, 0x87, 0x87}},
Optab{AXLAT, ynone, Px, [13]uint8{0xd7}},
Optab{AXORB, yxorb, Pb, [13]uint8{0x34, 0x80, 06, 0x30, 0x32}},
Optab{AXORL, yxorl, Px, [13]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
Optab{AXORW, yxorl, Pe, [13]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
Optab{AFMOVB, yfmvx, Px, [13]uint8{0xdf, 04}},
Optab{AFMOVBP, yfmvp, Px, [13]uint8{0xdf, 06}},
Optab{AFMOVD, yfmvd, Px, [13]uint8{0xdd, 00, 0xdd, 02, 0xd9, 00, 0xdd, 02}},
Optab{AFMOVDP, yfmvdp, Px, [13]uint8{0xdd, 03, 0xdd, 03}},
Optab{AFMOVF, yfmvf, Px, [13]uint8{0xd9, 00, 0xd9, 02}},
Optab{AFMOVFP, yfmvp, Px, [13]uint8{0xd9, 03}},
Optab{AFMOVL, yfmvf, Px, [13]uint8{0xdb, 00, 0xdb, 02}},
Optab{AFMOVLP, yfmvp, Px, [13]uint8{0xdb, 03}},
Optab{AFMOVV, yfmvx, Px, [13]uint8{0xdf, 05}},
Optab{AFMOVVP, yfmvp, Px, [13]uint8{0xdf, 07}},
Optab{AFMOVW, yfmvf, Px, [13]uint8{0xdf, 00, 0xdf, 02}},
Optab{AFMOVWP, yfmvp, Px, [13]uint8{0xdf, 03}},
Optab{AFMOVX, yfmvx, Px, [13]uint8{0xdb, 05}},
Optab{AFMOVXP, yfmvp, Px, [13]uint8{0xdb, 07}},
Optab{AFCOMB, nil, 0, [13]uint8{}},
Optab{AFCOMBP, nil, 0, [13]uint8{}},
Optab{AFCOMD, yfadd, Px, [13]uint8{0xdc, 02, 0xd8, 02, 0xdc, 02}}, /* botch */
Optab{AFCOMDP, yfadd, Px, [13]uint8{0xdc, 03, 0xd8, 03, 0xdc, 03}}, /* botch */
Optab{AFCOMDPP, ycompp, Px, [13]uint8{0xde, 03}},
Optab{AFCOMF, yfmvx, Px, [13]uint8{0xd8, 02}},
Optab{AFCOMFP, yfmvx, Px, [13]uint8{0xd8, 03}},
Optab{AFCOMI, yfmvx, Px, [13]uint8{0xdb, 06}},
Optab{AFCOMIP, yfmvx, Px, [13]uint8{0xdf, 06}},
Optab{AFCOML, yfmvx, Px, [13]uint8{0xda, 02}},
Optab{AFCOMLP, yfmvx, Px, [13]uint8{0xda, 03}},
Optab{AFCOMW, yfmvx, Px, [13]uint8{0xde, 02}},
Optab{AFCOMWP, yfmvx, Px, [13]uint8{0xde, 03}},
Optab{AFUCOM, ycompp, Px, [13]uint8{0xdd, 04}},
Optab{AFUCOMI, ycompp, Px, [13]uint8{0xdb, 05}},
Optab{AFUCOMIP, ycompp, Px, [13]uint8{0xdf, 05}},
Optab{AFUCOMP, ycompp, Px, [13]uint8{0xdd, 05}},
Optab{AFUCOMPP, ycompp, Px, [13]uint8{0xda, 13}},
Optab{AFADDDP, yfaddp, Px, [13]uint8{0xde, 00}},
Optab{AFADDW, yfmvx, Px, [13]uint8{0xde, 00}},
Optab{AFADDL, yfmvx, Px, [13]uint8{0xda, 00}},
Optab{AFADDF, yfmvx, Px, [13]uint8{0xd8, 00}},
Optab{AFADDD, yfadd, Px, [13]uint8{0xdc, 00, 0xd8, 00, 0xdc, 00}},
Optab{AFMULDP, yfaddp, Px, [13]uint8{0xde, 01}},
Optab{AFMULW, yfmvx, Px, [13]uint8{0xde, 01}},
Optab{AFMULL, yfmvx, Px, [13]uint8{0xda, 01}},
Optab{AFMULF, yfmvx, Px, [13]uint8{0xd8, 01}},
Optab{AFMULD, yfadd, Px, [13]uint8{0xdc, 01, 0xd8, 01, 0xdc, 01}},
Optab{AFSUBDP, yfaddp, Px, [13]uint8{0xde, 05}},
Optab{AFSUBW, yfmvx, Px, [13]uint8{0xde, 04}},
Optab{AFSUBL, yfmvx, Px, [13]uint8{0xda, 04}},
Optab{AFSUBF, yfmvx, Px, [13]uint8{0xd8, 04}},
Optab{AFSUBD, yfadd, Px, [13]uint8{0xdc, 04, 0xd8, 04, 0xdc, 05}},
Optab{AFSUBRDP, yfaddp, Px, [13]uint8{0xde, 04}},
Optab{AFSUBRW, yfmvx, Px, [13]uint8{0xde, 05}},
Optab{AFSUBRL, yfmvx, Px, [13]uint8{0xda, 05}},
Optab{AFSUBRF, yfmvx, Px, [13]uint8{0xd8, 05}},
Optab{AFSUBRD, yfadd, Px, [13]uint8{0xdc, 05, 0xd8, 05, 0xdc, 04}},
Optab{AFDIVDP, yfaddp, Px, [13]uint8{0xde, 07}},
Optab{AFDIVW, yfmvx, Px, [13]uint8{0xde, 06}},
Optab{AFDIVL, yfmvx, Px, [13]uint8{0xda, 06}},
Optab{AFDIVF, yfmvx, Px, [13]uint8{0xd8, 06}},
Optab{AFDIVD, yfadd, Px, [13]uint8{0xdc, 06, 0xd8, 06, 0xdc, 07}},
Optab{AFDIVRDP, yfaddp, Px, [13]uint8{0xde, 06}},
Optab{AFDIVRW, yfmvx, Px, [13]uint8{0xde, 07}},
Optab{AFDIVRL, yfmvx, Px, [13]uint8{0xda, 07}},
Optab{AFDIVRF, yfmvx, Px, [13]uint8{0xd8, 07}},
Optab{AFDIVRD, yfadd, Px, [13]uint8{0xdc, 07, 0xd8, 07, 0xdc, 06}},
Optab{AFXCHD, yfxch, Px, [13]uint8{0xd9, 01, 0xd9, 01}},
Optab{AFFREE, nil, 0, [13]uint8{}},
Optab{AFLDCW, ystcw, Px, [13]uint8{0xd9, 05, 0xd9, 05}},
Optab{AFLDENV, ystcw, Px, [13]uint8{0xd9, 04, 0xd9, 04}},
Optab{AFRSTOR, ysvrs, Px, [13]uint8{0xdd, 04, 0xdd, 04}},
Optab{AFSAVE, ysvrs, Px, [13]uint8{0xdd, 06, 0xdd, 06}},
Optab{AFSTCW, ystcw, Px, [13]uint8{0xd9, 07, 0xd9, 07}},
Optab{AFSTENV, ystcw, Px, [13]uint8{0xd9, 06, 0xd9, 06}},
Optab{AFSTSW, ystsw, Px, [13]uint8{0xdd, 07, 0xdf, 0xe0}},
Optab{AF2XM1, ynone, Px, [13]uint8{0xd9, 0xf0}},
Optab{AFABS, ynone, Px, [13]uint8{0xd9, 0xe1}},
Optab{AFCHS, ynone, Px, [13]uint8{0xd9, 0xe0}},
Optab{AFCLEX, ynone, Px, [13]uint8{0xdb, 0xe2}},
Optab{AFCOS, ynone, Px, [13]uint8{0xd9, 0xff}},
Optab{AFDECSTP, ynone, Px, [13]uint8{0xd9, 0xf6}},
Optab{AFINCSTP, ynone, Px, [13]uint8{0xd9, 0xf7}},
Optab{AFINIT, ynone, Px, [13]uint8{0xdb, 0xe3}},
Optab{AFLD1, ynone, Px, [13]uint8{0xd9, 0xe8}},
Optab{AFLDL2E, ynone, Px, [13]uint8{0xd9, 0xea}},
Optab{AFLDL2T, ynone, Px, [13]uint8{0xd9, 0xe9}},
Optab{AFLDLG2, ynone, Px, [13]uint8{0xd9, 0xec}},
Optab{AFLDLN2, ynone, Px, [13]uint8{0xd9, 0xed}},
Optab{AFLDPI, ynone, Px, [13]uint8{0xd9, 0xeb}},
Optab{AFLDZ, ynone, Px, [13]uint8{0xd9, 0xee}},
Optab{AFNOP, ynone, Px, [13]uint8{0xd9, 0xd0}},
Optab{AFPATAN, ynone, Px, [13]uint8{0xd9, 0xf3}},
Optab{AFPREM, ynone, Px, [13]uint8{0xd9, 0xf8}},
Optab{AFPREM1, ynone, Px, [13]uint8{0xd9, 0xf5}},
Optab{AFPTAN, ynone, Px, [13]uint8{0xd9, 0xf2}},
Optab{AFRNDINT, ynone, Px, [13]uint8{0xd9, 0xfc}},
Optab{AFSCALE, ynone, Px, [13]uint8{0xd9, 0xfd}},
Optab{AFSIN, ynone, Px, [13]uint8{0xd9, 0xfe}},
Optab{AFSINCOS, ynone, Px, [13]uint8{0xd9, 0xfb}},
Optab{AFSQRT, ynone, Px, [13]uint8{0xd9, 0xfa}},
Optab{AFTST, ynone, Px, [13]uint8{0xd9, 0xe4}},
Optab{AFXAM, ynone, Px, [13]uint8{0xd9, 0xe5}},
Optab{AFXTRACT, ynone, Px, [13]uint8{0xd9, 0xf4}},
Optab{AFYL2X, ynone, Px, [13]uint8{0xd9, 0xf1}},
Optab{AFYL2XP1, ynone, Px, [13]uint8{0xd9, 0xf9}},
Optab{obj.AEND, nil, 0, [13]uint8{}},
Optab{ACMPXCHGB, yrb_mb, Pm, [13]uint8{0xb0}},
Optab{ACMPXCHGL, yrl_ml, Pm, [13]uint8{0xb1}},
Optab{ACMPXCHGW, yrl_ml, Pm, [13]uint8{0xb1}},
Optab{ACMPXCHG8B, yscond, Pm, [13]uint8{0xc7, 01}}, // TODO(rsc): yscond is wrong here.
Optab{ACPUID, ynone, Pm, [13]uint8{0xa2}},
Optab{ARDTSC, ynone, Pm, [13]uint8{0x31}},
Optab{AXADDB, yrb_mb, Pb, [13]uint8{0x0f, 0xc0}},
Optab{AXADDL, yrl_ml, Pm, [13]uint8{0xc1}},
Optab{AXADDW, yrl_ml, Pe, [13]uint8{0x0f, 0xc1}},
Optab{ACMOVLCC, yml_rl, Pm, [13]uint8{0x43}},
Optab{ACMOVLCS, yml_rl, Pm, [13]uint8{0x42}},
Optab{ACMOVLEQ, yml_rl, Pm, [13]uint8{0x44}},
Optab{ACMOVLGE, yml_rl, Pm, [13]uint8{0x4d}},
Optab{ACMOVLGT, yml_rl, Pm, [13]uint8{0x4f}},
Optab{ACMOVLHI, yml_rl, Pm, [13]uint8{0x47}},
Optab{ACMOVLLE, yml_rl, Pm, [13]uint8{0x4e}},
Optab{ACMOVLLS, yml_rl, Pm, [13]uint8{0x46}},
Optab{ACMOVLLT, yml_rl, Pm, [13]uint8{0x4c}},
Optab{ACMOVLMI, yml_rl, Pm, [13]uint8{0x48}},
Optab{ACMOVLNE, yml_rl, Pm, [13]uint8{0x45}},
Optab{ACMOVLOC, yml_rl, Pm, [13]uint8{0x41}},
Optab{ACMOVLOS, yml_rl, Pm, [13]uint8{0x40}},
Optab{ACMOVLPC, yml_rl, Pm, [13]uint8{0x4b}},
Optab{ACMOVLPL, yml_rl, Pm, [13]uint8{0x49}},
Optab{ACMOVLPS, yml_rl, Pm, [13]uint8{0x4a}},
Optab{ACMOVWCC, yml_rl, Pq, [13]uint8{0x43}},
Optab{ACMOVWCS, yml_rl, Pq, [13]uint8{0x42}},
Optab{ACMOVWEQ, yml_rl, Pq, [13]uint8{0x44}},
Optab{ACMOVWGE, yml_rl, Pq, [13]uint8{0x4d}},
Optab{ACMOVWGT, yml_rl, Pq, [13]uint8{0x4f}},
Optab{ACMOVWHI, yml_rl, Pq, [13]uint8{0x47}},
Optab{ACMOVWLE, yml_rl, Pq, [13]uint8{0x4e}},
Optab{ACMOVWLS, yml_rl, Pq, [13]uint8{0x46}},
Optab{ACMOVWLT, yml_rl, Pq, [13]uint8{0x4c}},
Optab{ACMOVWMI, yml_rl, Pq, [13]uint8{0x48}},
Optab{ACMOVWNE, yml_rl, Pq, [13]uint8{0x45}},
Optab{ACMOVWOC, yml_rl, Pq, [13]uint8{0x41}},
Optab{ACMOVWOS, yml_rl, Pq, [13]uint8{0x40}},
Optab{ACMOVWPC, yml_rl, Pq, [13]uint8{0x4b}},
Optab{ACMOVWPL, yml_rl, Pq, [13]uint8{0x49}},
Optab{ACMOVWPS, yml_rl, Pq, [13]uint8{0x4a}},
Optab{AFCMOVCC, yfcmv, Px, [13]uint8{0xdb, 00}},
Optab{AFCMOVCS, yfcmv, Px, [13]uint8{0xda, 00}},
Optab{AFCMOVEQ, yfcmv, Px, [13]uint8{0xda, 01}},
Optab{AFCMOVHI, yfcmv, Px, [13]uint8{0xdb, 02}},
Optab{AFCMOVLS, yfcmv, Px, [13]uint8{0xda, 02}},
Optab{AFCMOVNE, yfcmv, Px, [13]uint8{0xdb, 01}},
Optab{AFCMOVNU, yfcmv, Px, [13]uint8{0xdb, 03}},
Optab{AFCMOVUN, yfcmv, Px, [13]uint8{0xda, 03}},
Optab{ALFENCE, ynone, Pm, [13]uint8{0xae, 0xe8}},
Optab{AMFENCE, ynone, Pm, [13]uint8{0xae, 0xf0}},
Optab{ASFENCE, ynone, Pm, [13]uint8{0xae, 0xf8}},
Optab{AEMMS, ynone, Pm, [13]uint8{0x77}},
Optab{APREFETCHT0, yprefetch, Pm, [13]uint8{0x18, 01}},
Optab{APREFETCHT1, yprefetch, Pm, [13]uint8{0x18, 02}},
Optab{APREFETCHT2, yprefetch, Pm, [13]uint8{0x18, 03}},
Optab{APREFETCHNTA, yprefetch, Pm, [13]uint8{0x18, 00}},
Optab{ABSWAPL, ybswap, Pm, [13]uint8{0xc8}},
Optab{obj.AUNDEF, ynone, Px, [13]uint8{0x0f, 0x0b}},
Optab{AADDPD, yxm, Pq, [13]uint8{0x58}},
Optab{AADDPS, yxm, Pm, [13]uint8{0x58}},
Optab{AADDSD, yxm, Pf2, [13]uint8{0x58}},
Optab{AADDSS, yxm, Pf3, [13]uint8{0x58}},
Optab{AANDNPD, yxm, Pq, [13]uint8{0x55}},
Optab{AANDNPS, yxm, Pm, [13]uint8{0x55}},
Optab{AANDPD, yxm, Pq, [13]uint8{0x54}},
Optab{AANDPS, yxm, Pq, [13]uint8{0x54}},
Optab{ACMPPD, yxcmpi, Px, [13]uint8{Pe, 0xc2}},
Optab{ACMPPS, yxcmpi, Pm, [13]uint8{0xc2, 0}},
Optab{ACMPSD, yxcmpi, Px, [13]uint8{Pf2, 0xc2}},
Optab{ACMPSS, yxcmpi, Px, [13]uint8{Pf3, 0xc2}},
Optab{ACOMISD, yxcmp, Pe, [13]uint8{0x2f}},
Optab{ACOMISS, yxcmp, Pm, [13]uint8{0x2f}},
Optab{ACVTPL2PD, yxcvm2, Px, [13]uint8{Pf3, 0xe6, Pe, 0x2a}},
Optab{ACVTPL2PS, yxcvm2, Pm, [13]uint8{0x5b, 0, 0x2a, 0}},
Optab{ACVTPD2PL, yxcvm1, Px, [13]uint8{Pf2, 0xe6, Pe, 0x2d}},
Optab{ACVTPD2PS, yxm, Pe, [13]uint8{0x5a}},
Optab{ACVTPS2PL, yxcvm1, Px, [13]uint8{Pe, 0x5b, Pm, 0x2d}},
Optab{ACVTPS2PD, yxm, Pm, [13]uint8{0x5a}},
Optab{ACVTSD2SL, yxcvfl, Pf2, [13]uint8{0x2d}},
Optab{ACVTSD2SS, yxm, Pf2, [13]uint8{0x5a}},
Optab{ACVTSL2SD, yxcvlf, Pf2, [13]uint8{0x2a}},
Optab{ACVTSL2SS, yxcvlf, Pf3, [13]uint8{0x2a}},
Optab{ACVTSS2SD, yxm, Pf3, [13]uint8{0x5a}},
Optab{ACVTSS2SL, yxcvfl, Pf3, [13]uint8{0x2d}},
Optab{ACVTTPD2PL, yxcvm1, Px, [13]uint8{Pe, 0xe6, Pe, 0x2c}},
Optab{ACVTTPS2PL, yxcvm1, Px, [13]uint8{Pf3, 0x5b, Pm, 0x2c}},
Optab{ACVTTSD2SL, yxcvfl, Pf2, [13]uint8{0x2c}},
Optab{ACVTTSS2SL, yxcvfl, Pf3, [13]uint8{0x2c}},
Optab{ADIVPD, yxm, Pe, [13]uint8{0x5e}},
Optab{ADIVPS, yxm, Pm, [13]uint8{0x5e}},
Optab{ADIVSD, yxm, Pf2, [13]uint8{0x5e}},
Optab{ADIVSS, yxm, Pf3, [13]uint8{0x5e}},
Optab{AMASKMOVOU, yxr, Pe, [13]uint8{0xf7}},
Optab{AMAXPD, yxm, Pe, [13]uint8{0x5f}},
Optab{AMAXPS, yxm, Pm, [13]uint8{0x5f}},
Optab{AMAXSD, yxm, Pf2, [13]uint8{0x5f}},
Optab{AMAXSS, yxm, Pf3, [13]uint8{0x5f}},
Optab{AMINPD, yxm, Pe, [13]uint8{0x5d}},
Optab{AMINPS, yxm, Pm, [13]uint8{0x5d}},
Optab{AMINSD, yxm, Pf2, [13]uint8{0x5d}},
Optab{AMINSS, yxm, Pf3, [13]uint8{0x5d}},
Optab{AMOVAPD, yxmov, Pe, [13]uint8{0x28, 0x29}},
Optab{AMOVAPS, yxmov, Pm, [13]uint8{0x28, 0x29}},
Optab{AMOVO, yxmov, Pe, [13]uint8{0x6f, 0x7f}},
Optab{AMOVOU, yxmov, Pf3, [13]uint8{0x6f, 0x7f}},
Optab{AMOVHLPS, yxr, Pm, [13]uint8{0x12}},
Optab{AMOVHPD, yxmov, Pe, [13]uint8{0x16, 0x17}},
Optab{AMOVHPS, yxmov, Pm, [13]uint8{0x16, 0x17}},
Optab{AMOVLHPS, yxr, Pm, [13]uint8{0x16}},
Optab{AMOVLPD, yxmov, Pe, [13]uint8{0x12, 0x13}},
Optab{AMOVLPS, yxmov, Pm, [13]uint8{0x12, 0x13}},
Optab{AMOVMSKPD, yxrrl, Pq, [13]uint8{0x50}},
Optab{AMOVMSKPS, yxrrl, Pm, [13]uint8{0x50}},
Optab{AMOVNTO, yxr_ml, Pe, [13]uint8{0xe7}},
Optab{AMOVNTPD, yxr_ml, Pe, [13]uint8{0x2b}},
Optab{AMOVNTPS, yxr_ml, Pm, [13]uint8{0x2b}},
Optab{AMOVSD, yxmov, Pf2, [13]uint8{0x10, 0x11}},
Optab{AMOVSS, yxmov, Pf3, [13]uint8{0x10, 0x11}},
Optab{AMOVUPD, yxmov, Pe, [13]uint8{0x10, 0x11}},
Optab{AMOVUPS, yxmov, Pm, [13]uint8{0x10, 0x11}},
Optab{AMULPD, yxm, Pe, [13]uint8{0x59}},
Optab{AMULPS, yxm, Ym, [13]uint8{0x59}},
Optab{AMULSD, yxm, Pf2, [13]uint8{0x59}},
Optab{AMULSS, yxm, Pf3, [13]uint8{0x59}},
Optab{AORPD, yxm, Pq, [13]uint8{0x56}},
Optab{AORPS, yxm, Pm, [13]uint8{0x56}},
Optab{APADDQ, yxm, Pe, [13]uint8{0xd4}},
Optab{APAND, yxm, Pe, [13]uint8{0xdb}},
Optab{APCMPEQB, yxmq, Pe, [13]uint8{0x74}},
Optab{APMAXSW, yxm, Pe, [13]uint8{0xee}},
Optab{APMAXUB, yxm, Pe, [13]uint8{0xde}},
Optab{APMINSW, yxm, Pe, [13]uint8{0xea}},
Optab{APMINUB, yxm, Pe, [13]uint8{0xda}},
Optab{APMOVMSKB, ymskb, Px, [13]uint8{Pe, 0xd7, 0xd7}},
Optab{APSADBW, yxm, Pq, [13]uint8{0xf6}},
Optab{APSUBB, yxm, Pe, [13]uint8{0xf8}},
Optab{APSUBL, yxm, Pe, [13]uint8{0xfa}},
Optab{APSUBQ, yxm, Pe, [13]uint8{0xfb}},
Optab{APSUBSB, yxm, Pe, [13]uint8{0xe8}},
Optab{APSUBSW, yxm, Pe, [13]uint8{0xe9}},
Optab{APSUBUSB, yxm, Pe, [13]uint8{0xd8}},
Optab{APSUBUSW, yxm, Pe, [13]uint8{0xd9}},
Optab{APSUBW, yxm, Pe, [13]uint8{0xf9}},
Optab{APUNPCKHQDQ, yxm, Pe, [13]uint8{0x6d}},
Optab{APUNPCKLQDQ, yxm, Pe, [13]uint8{0x6c}},
Optab{APXOR, yxm, Pe, [13]uint8{0xef}},
Optab{ARCPPS, yxm, Pm, [13]uint8{0x53}},
Optab{ARCPSS, yxm, Pf3, [13]uint8{0x53}},
Optab{ARSQRTPS, yxm, Pm, [13]uint8{0x52}},
Optab{ARSQRTSS, yxm, Pf3, [13]uint8{0x52}},
Optab{ASQRTPD, yxm, Pe, [13]uint8{0x51}},
Optab{ASQRTPS, yxm, Pm, [13]uint8{0x51}},
Optab{ASQRTSD, yxm, Pf2, [13]uint8{0x51}},
Optab{ASQRTSS, yxm, Pf3, [13]uint8{0x51}},
Optab{ASUBPD, yxm, Pe, [13]uint8{0x5c}},
Optab{ASUBPS, yxm, Pm, [13]uint8{0x5c}},
Optab{ASUBSD, yxm, Pf2, [13]uint8{0x5c}},
Optab{ASUBSS, yxm, Pf3, [13]uint8{0x5c}},
Optab{AUCOMISD, yxcmp, Pe, [13]uint8{0x2e}},
Optab{AUCOMISS, yxcmp, Pm, [13]uint8{0x2e}},
Optab{AUNPCKHPD, yxm, Pe, [13]uint8{0x15}},
Optab{AUNPCKHPS, yxm, Pm, [13]uint8{0x15}},
Optab{AUNPCKLPD, yxm, Pe, [13]uint8{0x14}},
Optab{AUNPCKLPS, yxm, Pm, [13]uint8{0x14}},
Optab{AXORPD, yxm, Pe, [13]uint8{0x57}},
Optab{AXORPS, yxm, Pm, [13]uint8{0x57}},
Optab{APSHUFHW, yxshuf, Pf3, [13]uint8{0x70, 00}},
Optab{APSHUFL, yxshuf, Pq, [13]uint8{0x70, 00}},
Optab{APSHUFLW, yxshuf, Pf2, [13]uint8{0x70, 00}},
Optab{AAESENC, yaes, Pq, [13]uint8{0x38, 0xdc, 0}},
Optab{APINSRD, yinsrd, Pq, [13]uint8{0x3a, 0x22, 00}},
Optab{APSHUFB, ymshufb, Pq, [13]uint8{0x38, 0x00}},
Optab{obj.AUSEFIELD, ynop, Px, [13]uint8{0, 0}},
Optab{obj.ATYPE, nil, 0, [13]uint8{}},
Optab{obj.AFUNCDATA, yfuncdata, Px, [13]uint8{0, 0}},
Optab{obj.APCDATA, ypcdata, Px, [13]uint8{0, 0}},
Optab{obj.ACHECKNIL, nil, 0, [13]uint8{}},
Optab{obj.AVARDEF, nil, 0, [13]uint8{}},
Optab{obj.AVARKILL, nil, 0, [13]uint8{}},
Optab{obj.ADUFFCOPY, yduff, Px, [13]uint8{0xe8}},
Optab{obj.ADUFFZERO, yduff, Px, [13]uint8{0xe8}},
Optab{0, nil, 0, [13]uint8{}},
}
// single-instruction no-ops of various lengths.
// constructed by hand and disassembled with gdb to verify.
// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
var nop = [][16]uint8{
[16]uint8{0x90},
[16]uint8{0x66, 0x90},
[16]uint8{0x0F, 0x1F, 0x00},
[16]uint8{0x0F, 0x1F, 0x40, 0x00},
[16]uint8{0x0F, 0x1F, 0x44, 0x00, 0x00},
[16]uint8{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
[16]uint8{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
[16]uint8{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
[16]uint8{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
}
// Native Client rejects the repeated 0x66 prefix.
// {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
func fillnop(p []byte, n int) {
var m int
for n > 0 {
m = n
if m > len(nop) {
m = len(nop)
}
copy(p[:m], nop[m-1][:m])
p = p[m:]
n -= m
}
}
func naclpad(ctxt *obj.Link, s *obj.LSym, c int32, pad int32) int32 {
obj.Symgrow(ctxt, s, int64(c)+int64(pad))
fillnop(s.P[c:], int(pad))
return c + pad
}
func span8(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
if s.Text == nil || s.Text.Link == nil {
return
}
if ycover[0] == 0 {
instinit()
}
var v int32
for p := s.Text; p != nil; p = p.Link {
if p.To.Type == obj.TYPE_BRANCH {
if p.Pcond == nil {
p.Pcond = p
}
}
if p.As == AADJSP {
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_SP
v = int32(-p.From.Offset)
p.From.Offset = int64(v)
p.As = AADDL
if v < 0 {
p.As = ASUBL
v = -v
p.From.Offset = int64(v)
}
if v == 0 {
p.As = obj.ANOP
}
}
}
var q *obj.Prog
for p := s.Text; p != nil; p = p.Link {
p.Back = 2 // use short branches first time through
q = p.Pcond
if q != nil && (q.Back&2 != 0) {
p.Back |= 1 // backward jump
}
if p.As == AADJSP {
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_SP
v = int32(-p.From.Offset)
p.From.Offset = int64(v)
p.As = AADDL
if v < 0 {
p.As = ASUBL
v = -v
p.From.Offset = int64(v)
}
if v == 0 {
p.As = obj.ANOP
}
}
}
n := 0
var bp []byte
var c int32
var i int
var loop int32
var m int
var p *obj.Prog
for {
loop = 0
for i = 0; i < len(s.R); i++ {
s.R[i] = obj.Reloc{}
}
s.R = s.R[:0]
s.P = s.P[:0]
c = 0
for p = s.Text; p != nil; p = p.Link {
if ctxt.Headtype == obj.Hnacl && p.Isize > 0 {
var deferreturn *obj.LSym
if deferreturn == nil {
deferreturn = obj.Linklookup(ctxt, "runtime.deferreturn", 0)
}
// pad everything to avoid crossing 32-byte boundary
if c>>5 != (c+int32(p.Isize)-1)>>5 {
c = naclpad(ctxt, s, c, -c&31)
}
// pad call deferreturn to start at 32-byte boundary
// so that subtracting 5 in jmpdefer will jump back
// to that boundary and rerun the call.
if p.As == obj.ACALL && p.To.Sym == deferreturn {
c = naclpad(ctxt, s, c, -c&31)
}
// pad call to end at 32-byte boundary
if p.As == obj.ACALL {
c = naclpad(ctxt, s, c, -(c+int32(p.Isize))&31)
}
// the linker treats REP and STOSQ as different instructions
// but in fact the REP is a prefix on the STOSQ.
// make sure REP has room for 2 more bytes, so that
// padding will not be inserted before the next instruction.
if p.As == AREP && c>>5 != (c+3-1)>>5 {
c = naclpad(ctxt, s, c, -c&31)
}
// same for LOCK.
// various instructions follow; the longest is 4 bytes.
// give ourselves 8 bytes so as to avoid surprises.
if p.As == ALOCK && c>>5 != (c+8-1)>>5 {
c = naclpad(ctxt, s, c, -c&31)
}
}
p.Pc = int64(c)
// process forward jumps to p
for q = p.Comefrom; q != nil; q = q.Forwd {
v = int32(p.Pc - (q.Pc + int64(q.Mark)))
if q.Back&2 != 0 { // short
if v > 127 {
loop++
q.Back ^= 2
}
if q.As == AJCXZW {
s.P[q.Pc+2] = byte(v)
} else {
s.P[q.Pc+1] = byte(v)
}
} else {
bp = s.P[q.Pc+int64(q.Mark)-4:]
bp[0] = byte(v)
bp = bp[1:]
bp[0] = byte(v >> 8)
bp = bp[1:]
bp[0] = byte(v >> 16)
bp = bp[1:]
bp[0] = byte(v >> 24)
}
}
p.Comefrom = nil
p.Pc = int64(c)
asmins(ctxt, p)
m = -cap(ctxt.Andptr) + cap(ctxt.And[:])
if int(p.Isize) != m {
p.Isize = uint8(m)
loop++
}
obj.Symgrow(ctxt, s, p.Pc+int64(m))
copy(s.P[p.Pc:][:m], ctxt.And[:m])
p.Mark = uint16(m)
c += int32(m)
}
n++
if n > 20 {
ctxt.Diag("span must be looping")
log.Fatalf("bad code")
}
if loop == 0 {
break
}
}
if ctxt.Headtype == obj.Hnacl {
c = naclpad(ctxt, s, c, -c&31)
}
c += -c & (FuncAlign - 1)
s.Size = int64(c)
if false { /* debug['a'] > 1 */
fmt.Printf("span1 %s %d (%d tries)\n %.6x", s.Name, s.Size, n, 0)
var i int
for i = 0; i < len(s.P); i++ {
fmt.Printf(" %.2x", s.P[i])
if i%16 == 15 {
fmt.Printf("\n %.6x", uint(i+1))
}
}
if i%16 != 0 {
fmt.Printf("\n")
}
for i := 0; i < len(s.R); i++ {
r := &s.R[i]
fmt.Printf(" rel %#.4x/%d %s%+d\n", uint32(r.Off), r.Siz, r.Sym.Name, r.Add)
}
}
}
func instinit() {
for i := 1; optab[i].as != 0; i++ {
c := optab[i].as & obj.AMask
if opindex[c] != nil {
log.Fatalf("phase error in optab: %d (%v)", i, obj.Aconv(int(optab[i].as)))
}
opindex[c] = &optab[i]
}
for i := 0; i < Ymax; i++ {
ycover[i*Ymax+i] = 1
}
ycover[Yi0*Ymax+Yi8] = 1
ycover[Yi1*Ymax+Yi8] = 1
ycover[Yi0*Ymax+Yi32] = 1
ycover[Yi1*Ymax+Yi32] = 1
ycover[Yi8*Ymax+Yi32] = 1
ycover[Yal*Ymax+Yrb] = 1
ycover[Ycl*Ymax+Yrb] = 1
ycover[Yax*Ymax+Yrb] = 1
ycover[Ycx*Ymax+Yrb] = 1
ycover[Yrx*Ymax+Yrb] = 1
ycover[Yax*Ymax+Yrx] = 1
ycover[Ycx*Ymax+Yrx] = 1
ycover[Yax*Ymax+Yrl] = 1
ycover[Ycx*Ymax+Yrl] = 1
ycover[Yrx*Ymax+Yrl] = 1
ycover[Yf0*Ymax+Yrf] = 1
ycover[Yal*Ymax+Ymb] = 1
ycover[Ycl*Ymax+Ymb] = 1
ycover[Yax*Ymax+Ymb] = 1
ycover[Ycx*Ymax+Ymb] = 1
ycover[Yrx*Ymax+Ymb] = 1
ycover[Yrb*Ymax+Ymb] = 1
ycover[Ym*Ymax+Ymb] = 1
ycover[Yax*Ymax+Yml] = 1
ycover[Ycx*Ymax+Yml] = 1
ycover[Yrx*Ymax+Yml] = 1
ycover[Yrl*Ymax+Yml] = 1
ycover[Ym*Ymax+Yml] = 1
ycover[Yax*Ymax+Ymm] = 1
ycover[Ycx*Ymax+Ymm] = 1
ycover[Yrx*Ymax+Ymm] = 1
ycover[Yrl*Ymax+Ymm] = 1
ycover[Ym*Ymax+Ymm] = 1
ycover[Ymr*Ymax+Ymm] = 1
ycover[Ym*Ymax+Yxm] = 1
ycover[Yxr*Ymax+Yxm] = 1
for i := 0; i < MAXREG; i++ {
reg[i] = -1
if i >= REG_AL && i <= REG_BH {
reg[i] = (i - REG_AL) & 7
}
if i >= REG_AX && i <= REG_DI {
reg[i] = (i - REG_AX) & 7
}
if i >= REG_F0 && i <= REG_F0+7 {
reg[i] = (i - REG_F0) & 7
}
if i >= REG_X0 && i <= REG_X0+7 {
reg[i] = (i - REG_X0) & 7
}
}
}
func prefixof(ctxt *obj.Link, a *obj.Addr) int {
if a.Type == obj.TYPE_MEM && a.Name == obj.NAME_NONE {
switch a.Reg {
case REG_CS:
return 0x2e
case REG_DS:
return 0x3e
case REG_ES:
return 0x26
case REG_FS:
return 0x64
case REG_GS:
return 0x65
// NOTE: Systems listed here should be only systems that
// support direct TLS references like 8(TLS) implemented as
// direct references from FS or GS. Systems that require
// the initial-exec model, where you load the TLS base into
// a register and then index from that register, do not reach
// this code and should not be listed.
case REG_TLS:
switch ctxt.Headtype {
default:
log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
case obj.Hdarwin,
obj.Hdragonfly,
obj.Hfreebsd,
obj.Hnetbsd,
obj.Hopenbsd:
return 0x65 // GS
}
}
}
return 0
}
func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
// TODO(rsc): This special case is for SHRQ $3, AX:DX,
// which encodes as SHRQ $32(DX*0), AX.
// Similarly SHRQ CX, AX:DX is really SHRQ CX(DX*0), AX.
// Change encoding and remove.
if (a.Type == obj.TYPE_CONST || a.Type == obj.TYPE_REG) && a.Index != REG_NONE && a.Scale == 0 {
return Ycol
}
switch a.Type {
case obj.TYPE_NONE:
return Ynone
case obj.TYPE_BRANCH:
return Ybr
// TODO(rsc): Why this is also Ycol is a mystery. Should split the two meanings.
case obj.TYPE_INDIR:
if a.Name != obj.NAME_NONE && a.Reg == REG_NONE && a.Index == REG_NONE && a.Scale == 0 {
return Ycol
}
return Yxxx
case obj.TYPE_MEM:
return Ym
case obj.TYPE_ADDR:
switch a.Name {
case obj.NAME_EXTERN,
obj.NAME_STATIC:
return Yi32
case obj.NAME_AUTO,
obj.NAME_PARAM:
return Yiauto
}
// DUFFZERO/DUFFCOPY encoding forgot to set a->index
// and got Yi32 in an earlier version of this code.
// Keep doing that until we fix yduff etc.
if a.Sym != nil && strings.HasPrefix(a.Sym.Name, "runtime.duff") {
return Yi32
}
if a.Sym != nil || a.Name != obj.NAME_NONE {
ctxt.Diag("unexpected addr: %v", obj.Dconv(p, a))
}
fallthrough
// fall through
case obj.TYPE_CONST:
if a.Sym != nil {
ctxt.Diag("TYPE_CONST with symbol: %v", obj.Dconv(p, a))
}
v := int32(a.Offset)
if v == 0 {
return Yi0
}
if v == 1 {
return Yi1
}
if v >= -128 && v <= 127 {
return Yi8
}
return Yi32
case obj.TYPE_TEXTSIZE:
return Ytextsize
}
if a.Type != obj.TYPE_REG {
ctxt.Diag("unexpected addr1: type=%d %v", a.Type, obj.Dconv(p, a))
return Yxxx
}
switch a.Reg {
case REG_AL:
return Yal
case REG_AX:
return Yax
case REG_CL,
REG_DL,
REG_BL,
REG_AH,
REG_CH,
REG_DH,
REG_BH:
return Yrb
case REG_CX:
return Ycx
case REG_DX,
REG_BX:
return Yrx
case REG_SP,
REG_BP,
REG_SI,
REG_DI:
return Yrl
case REG_F0 + 0:
return Yf0
case REG_F0 + 1,
REG_F0 + 2,
REG_F0 + 3,
REG_F0 + 4,
REG_F0 + 5,
REG_F0 + 6,
REG_F0 + 7:
return Yrf
case REG_X0 + 0,
REG_X0 + 1,
REG_X0 + 2,
REG_X0 + 3,
REG_X0 + 4,
REG_X0 + 5,
REG_X0 + 6,
REG_X0 + 7:
return Yxr
case REG_CS:
return Ycs
case REG_SS:
return Yss
case REG_DS:
return Yds
case REG_ES:
return Yes
case REG_FS:
return Yfs
case REG_GS:
return Ygs
case REG_TLS:
return Ytls
case REG_GDTR:
return Ygdtr
case REG_IDTR:
return Yidtr
case REG_LDTR:
return Yldtr
case REG_MSW:
return Ymsw
case REG_TASK:
return Ytask
case REG_CR + 0:
return Ycr0
case REG_CR + 1:
return Ycr1
case REG_CR + 2:
return Ycr2
case REG_CR + 3:
return Ycr3
case REG_CR + 4:
return Ycr4
case REG_CR + 5:
return Ycr5
case REG_CR + 6:
return Ycr6
case REG_CR + 7:
return Ycr7
case REG_DR + 0:
return Ydr0
case REG_DR + 1:
return Ydr1
case REG_DR + 2:
return Ydr2
case REG_DR + 3:
return Ydr3
case REG_DR + 4:
return Ydr4
case REG_DR + 5:
return Ydr5
case REG_DR + 6:
return Ydr6
case REG_DR + 7:
return Ydr7
case REG_TR + 0:
return Ytr0
case REG_TR + 1:
return Ytr1
case REG_TR + 2:
return Ytr2
case REG_TR + 3:
return Ytr3
case REG_TR + 4:
return Ytr4
case REG_TR + 5:
return Ytr5
case REG_TR + 6:
return Ytr6
case REG_TR + 7:
return Ytr7
}
return Yxxx
}
func asmidx(ctxt *obj.Link, scale int, index int, base int) {
var i int
switch index {
default:
goto bad
case obj.TYPE_NONE:
i = 4 << 3
goto bas
case REG_AX,
REG_CX,
REG_DX,
REG_BX,
REG_BP,
REG_SI,
REG_DI:
i = reg[index] << 3
}
switch scale {
default:
goto bad
case 1:
break
case 2:
i |= 1 << 6
case 4:
i |= 2 << 6
case 8:
i |= 3 << 6
}
bas:
switch base {
default:
goto bad
case REG_NONE: /* must be mod=00 */
i |= 5
case REG_AX,
REG_CX,
REG_DX,
REG_BX,
REG_SP,
REG_BP,
REG_SI,
REG_DI:
i |= reg[base]
}
ctxt.Andptr[0] = byte(i)
ctxt.Andptr = ctxt.Andptr[1:]
return
bad:
ctxt.Diag("asmidx: bad address %d,%d,%d", scale, index, base)
ctxt.Andptr[0] = 0
ctxt.Andptr = ctxt.Andptr[1:]
return
}
func put4(ctxt *obj.Link, v int32) {
ctxt.Andptr[0] = byte(v)
ctxt.Andptr[1] = byte(v >> 8)
ctxt.Andptr[2] = byte(v >> 16)
ctxt.Andptr[3] = byte(v >> 24)
ctxt.Andptr = ctxt.Andptr[4:]
}
func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
var rel obj.Reloc
v := int64(vaddr(ctxt, p, a, &rel))
if rel.Siz != 0 {
if rel.Siz != 4 {
ctxt.Diag("bad reloc")
}
r := obj.Addrel(ctxt.Cursym)
*r = rel
r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
}
put4(ctxt, int32(v))
}
func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int32 {
if r != nil {
*r = obj.Reloc{}
}
switch a.Name {
case obj.NAME_STATIC,
obj.NAME_EXTERN:
s := a.Sym
if s != nil {
if r == nil {
ctxt.Diag("need reloc for %v", obj.Dconv(p, a))
log.Fatalf("bad code")
}
r.Type = obj.R_ADDR
r.Siz = 4
r.Off = -1
r.Sym = s
r.Add = a.Offset
return 0
}
return int32(a.Offset)
}
if (a.Type == obj.TYPE_MEM || a.Type == obj.TYPE_ADDR) && a.Reg == REG_TLS {
if r == nil {
ctxt.Diag("need reloc for %v", obj.Dconv(p, a))
log.Fatalf("bad code")
}
r.Type = obj.R_TLS_LE
r.Siz = 4
r.Off = -1 // caller must fill in
r.Add = a.Offset
return 0
}
return int32(a.Offset)
}
func asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int) {
var base int
var rel obj.Reloc
v := int32(a.Offset)
rel.Siz = 0
switch a.Type {
case obj.TYPE_ADDR:
if a.Name == obj.NAME_NONE {
ctxt.Diag("unexpected TYPE_ADDR with NAME_NONE")
}
if a.Index == REG_TLS {
ctxt.Diag("unexpected TYPE_ADDR with index==REG_TLS")
}
goto bad
case obj.TYPE_REG:
if (a.Reg < REG_AL || REG_F7 < a.Reg) && (a.Reg < REG_X0 || REG_X0+7 < a.Reg) {
goto bad
}
if v != 0 {
goto bad
}
ctxt.Andptr[0] = byte(3<<6 | reg[a.Reg]<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
return
}
if a.Type != obj.TYPE_MEM {
goto bad
}
if a.Index != REG_NONE && a.Index != REG_TLS {
base := int(a.Reg)
switch a.Name {
case obj.NAME_EXTERN,
obj.NAME_STATIC:
base = REG_NONE
v = vaddr(ctxt, p, a, &rel)
case obj.NAME_AUTO,
obj.NAME_PARAM:
base = REG_SP
}
if base == REG_NONE {
ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
asmidx(ctxt, int(a.Scale), int(a.Index), base)
goto putrelv
}
if v == 0 && rel.Siz == 0 && base != REG_BP {
ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
asmidx(ctxt, int(a.Scale), int(a.Index), base)
return
}
if v >= -128 && v < 128 && rel.Siz == 0 {
ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
asmidx(ctxt, int(a.Scale), int(a.Index), base)
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
return
}
ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
asmidx(ctxt, int(a.Scale), int(a.Index), base)
goto putrelv
}
base = int(a.Reg)
switch a.Name {
case obj.NAME_STATIC,
obj.NAME_EXTERN:
base = REG_NONE
v = vaddr(ctxt, p, a, &rel)
case obj.NAME_AUTO,
obj.NAME_PARAM:
base = REG_SP
}
if base == REG_TLS {
v = vaddr(ctxt, p, a, &rel)
}
if base == REG_NONE || (REG_CS <= base && base <= REG_GS) || base == REG_TLS {
ctxt.Andptr[0] = byte(0<<6 | 5<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
goto putrelv
}
if base == REG_SP {
if v == 0 && rel.Siz == 0 {
ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
asmidx(ctxt, int(a.Scale), REG_NONE, base)
return
}
if v >= -128 && v < 128 && rel.Siz == 0 {
ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
asmidx(ctxt, int(a.Scale), REG_NONE, base)
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
return
}
ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
asmidx(ctxt, int(a.Scale), REG_NONE, base)
goto putrelv
}
if REG_AX <= base && base <= REG_DI {
if a.Index == REG_TLS {
rel = obj.Reloc{}
rel.Type = obj.R_TLS_IE
rel.Siz = 4
rel.Sym = nil
rel.Add = int64(v)
v = 0
}
if v == 0 && rel.Siz == 0 && base != REG_BP {
ctxt.Andptr[0] = byte(0<<6 | reg[base]<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
return
}
if v >= -128 && v < 128 && rel.Siz == 0 {
ctxt.Andptr[0] = byte(1<<6 | reg[base]<<0 | r<<3)
ctxt.Andptr[1] = byte(v)
ctxt.Andptr = ctxt.Andptr[2:]
return
}
ctxt.Andptr[0] = byte(2<<6 | reg[base]<<0 | r<<3)
ctxt.Andptr = ctxt.Andptr[1:]
goto putrelv
}
goto bad
putrelv:
if rel.Siz != 0 {
if rel.Siz != 4 {
ctxt.Diag("bad rel")
goto bad
}
r := obj.Addrel(ctxt.Cursym)
*r = rel
r.Off = int32(ctxt.Curp.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
}
put4(ctxt, v)
return
bad:
ctxt.Diag("asmand: bad address %v", obj.Dconv(p, a))
return
}
const (
E = 0xff
)
var ymovtab = []uint8{
/* push */
APUSHL & obj.AMask,
Ycs,
Ynone,
0,
0x0e,
E,
0,
0,
APUSHL & obj.AMask,
Yss,
Ynone,
0,
0x16,
E,
0,
0,
APUSHL & obj.AMask,
Yds,
Ynone,
0,
0x1e,
E,
0,
0,
APUSHL & obj.AMask,
Yes,
Ynone,
0,
0x06,
E,
0,
0,
APUSHL & obj.AMask,
Yfs,
Ynone,
0,
0x0f,
0xa0,
E,
0,
APUSHL & obj.AMask,
Ygs,
Ynone,
0,
0x0f,
0xa8,
E,
0,
APUSHW & obj.AMask,
Ycs,
Ynone,
0,
Pe,
0x0e,
E,
0,
APUSHW & obj.AMask,
Yss,
Ynone,
0,
Pe,
0x16,
E,
0,
APUSHW & obj.AMask,
Yds,
Ynone,
0,
Pe,
0x1e,
E,
0,
APUSHW & obj.AMask,
Yes,
Ynone,
0,
Pe,
0x06,
E,
0,
APUSHW & obj.AMask,
Yfs,
Ynone,
0,
Pe,
0x0f,
0xa0,
E,
APUSHW & obj.AMask,
Ygs,
Ynone,
0,
Pe,
0x0f,
0xa8,
E,
/* pop */
APOPL & obj.AMask,
Ynone,
Yds,
0,
0x1f,
E,
0,
0,
APOPL & obj.AMask,
Ynone,
Yes,
0,
0x07,
E,
0,
0,
APOPL & obj.AMask,
Ynone,
Yss,
0,
0x17,
E,
0,
0,
APOPL & obj.AMask,
Ynone,
Yfs,
0,
0x0f,
0xa1,
E,
0,
APOPL & obj.AMask,
Ynone,
Ygs,
0,
0x0f,
0xa9,
E,
0,
APOPW & obj.AMask,
Ynone,
Yds,
0,
Pe,
0x1f,
E,
0,
APOPW & obj.AMask,
Ynone,
Yes,
0,
Pe,
0x07,
E,
0,
APOPW & obj.AMask,
Ynone,
Yss,
0,
Pe,
0x17,
E,
0,
APOPW & obj.AMask,
Ynone,
Yfs,
0,
Pe,
0x0f,
0xa1,
E,
APOPW & obj.AMask,
Ynone,
Ygs,
0,
Pe,
0x0f,
0xa9,
E,
/* mov seg */
AMOVW & obj.AMask,
Yes,
Yml,
1,
0x8c,
0,
0,
0,
AMOVW & obj.AMask,
Ycs,
Yml,
1,
0x8c,
1,
0,
0,
AMOVW & obj.AMask,
Yss,
Yml,
1,
0x8c,
2,
0,
0,
AMOVW & obj.AMask,
Yds,
Yml,
1,
0x8c,
3,
0,
0,
AMOVW & obj.AMask,
Yfs,
Yml,
1,
0x8c,
4,
0,
0,
AMOVW & obj.AMask,
Ygs,
Yml,
1,
0x8c,
5,
0,
0,
AMOVW & obj.AMask,
Yml,
Yes,
2,
0x8e,
0,
0,
0,
AMOVW & obj.AMask,
Yml,
Ycs,
2,
0x8e,
1,
0,
0,
AMOVW & obj.AMask,
Yml,
Yss,
2,
0x8e,
2,
0,
0,
AMOVW & obj.AMask,
Yml,
Yds,
2,
0x8e,
3,
0,
0,
AMOVW & obj.AMask,
Yml,
Yfs,
2,
0x8e,
4,
0,
0,
AMOVW & obj.AMask,
Yml,
Ygs,
2,
0x8e,
5,
0,
0,
/* mov cr */
AMOVL & obj.AMask,
Ycr0,
Yml,
3,
0x0f,
0x20,
0,
0,
AMOVL & obj.AMask,
Ycr2,
Yml,
3,
0x0f,
0x20,
2,
0,
AMOVL & obj.AMask,
Ycr3,
Yml,
3,
0x0f,
0x20,
3,
0,
AMOVL & obj.AMask,
Ycr4,
Yml,
3,
0x0f,
0x20,
4,
0,
AMOVL & obj.AMask,
Yml,
Ycr0,
4,
0x0f,
0x22,
0,
0,
AMOVL & obj.AMask,
Yml,
Ycr2,
4,
0x0f,
0x22,
2,
0,
AMOVL & obj.AMask,
Yml,
Ycr3,
4,
0x0f,
0x22,
3,
0,
AMOVL & obj.AMask,
Yml,
Ycr4,
4,
0x0f,
0x22,
4,
0,
/* mov dr */
AMOVL & obj.AMask,
Ydr0,
Yml,
3,
0x0f,
0x21,
0,
0,
AMOVL & obj.AMask,
Ydr6,
Yml,
3,
0x0f,
0x21,
6,
0,
AMOVL & obj.AMask,
Ydr7,
Yml,
3,
0x0f,
0x21,
7,
0,
AMOVL & obj.AMask,
Yml,
Ydr0,
4,
0x0f,
0x23,
0,
0,
AMOVL & obj.AMask,
Yml,
Ydr6,
4,
0x0f,
0x23,
6,
0,
AMOVL & obj.AMask,
Yml,
Ydr7,
4,
0x0f,
0x23,
7,
0,
/* mov tr */
AMOVL & obj.AMask,
Ytr6,
Yml,
3,
0x0f,
0x24,
6,
0,
AMOVL & obj.AMask,
Ytr7,
Yml,
3,
0x0f,
0x24,
7,
0,
AMOVL & obj.AMask,
Yml,
Ytr6,
4,
0x0f,
0x26,
6,
E,
AMOVL & obj.AMask,
Yml,
Ytr7,
4,
0x0f,
0x26,
7,
E,
/* lgdt, sgdt, lidt, sidt */
AMOVL & obj.AMask,
Ym,
Ygdtr,
4,
0x0f,
0x01,
2,
0,
AMOVL & obj.AMask,
Ygdtr,
Ym,
3,
0x0f,
0x01,
0,
0,
AMOVL & obj.AMask,
Ym,
Yidtr,
4,
0x0f,
0x01,
3,
0,
AMOVL & obj.AMask,
Yidtr,
Ym,
3,
0x0f,
0x01,
1,
0,
/* lldt, sldt */
AMOVW & obj.AMask,
Yml,
Yldtr,
4,
0x0f,
0x00,
2,
0,
AMOVW & obj.AMask,
Yldtr,
Yml,
3,
0x0f,
0x00,
0,
0,
/* lmsw, smsw */
AMOVW & obj.AMask,
Yml,
Ymsw,
4,
0x0f,
0x01,
6,
0,
AMOVW & obj.AMask,
Ymsw,
Yml,
3,
0x0f,
0x01,
4,
0,
/* ltr, str */
AMOVW & obj.AMask,
Yml,
Ytask,
4,
0x0f,
0x00,
3,
0,
AMOVW & obj.AMask,
Ytask,
Yml,
3,
0x0f,
0x00,
1,
0,
/* load full pointer */
AMOVL & obj.AMask,
Yml,
Ycol,
5,
0,
0,
0,
0,
AMOVW & obj.AMask,
Yml,
Ycol,
5,
Pe,
0,
0,
0,
/* double shift */
ASHLL & obj.AMask,
Ycol,
Yml,
6,
0xa4,
0xa5,
0,
0,
ASHRL & obj.AMask,
Ycol,
Yml,
6,
0xac,
0xad,
0,
0,
/* extra imul */
AIMULW & obj.AMask,
Yml,
Yrl,
7,
Pq,
0xaf,
0,
0,
AIMULL & obj.AMask,
Yml,
Yrl,
7,
Pm,
0xaf,
0,
0,
/* load TLS base pointer */
AMOVL & obj.AMask,
Ytls,
Yrl,
8,
0,
0,
0,
0,
0,
}
// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
// which is not referenced in a.
// If a is empty, it returns BX to account for MULB-like instructions
// that might use DX and AX.
func byteswapreg(ctxt *obj.Link, a *obj.Addr) int {
cand := 1
canc := cand
canb := canc
cana := canb
if a.Type == obj.TYPE_NONE {
cand = 0
cana = cand
}
if a.Type == obj.TYPE_REG || ((a.Type == obj.TYPE_MEM || a.Type == obj.TYPE_ADDR) && a.Name == obj.NAME_NONE) {
switch a.Reg {
case REG_NONE:
cand = 0
cana = cand
case REG_AX,
REG_AL,
REG_AH:
cana = 0
case REG_BX,
REG_BL,
REG_BH:
canb = 0
case REG_CX,
REG_CL,
REG_CH:
canc = 0
case REG_DX,
REG_DL,
REG_DH:
cand = 0
}
}
if a.Type == obj.TYPE_MEM || a.Type == obj.TYPE_ADDR {
switch a.Index {
case REG_AX:
cana = 0
case REG_BX:
canb = 0
case REG_CX:
canc = 0
case REG_DX:
cand = 0
}
}
if cana != 0 {
return REG_AX
}
if canb != 0 {
return REG_BX
}
if canc != 0 {
return REG_CX
}
if cand != 0 {
return REG_DX
}
ctxt.Diag("impossible byte register")
log.Fatalf("bad code")
return 0
}
func subreg(p *obj.Prog, from int, to int) {
if false { /* debug['Q'] */
fmt.Printf("\n%v\ts/%v/%v/\n", p, Rconv(from), Rconv(to))
}
if int(p.From.Reg) == from {
p.From.Reg = int16(to)
p.Ft = 0
}
if int(p.To.Reg) == from {
p.To.Reg = int16(to)
p.Tt = 0
}
if int(p.From.Index) == from {
p.From.Index = int16(to)
p.Ft = 0
}
if int(p.To.Index) == from {
p.To.Index = int16(to)
p.Tt = 0
}
if false { /* debug['Q'] */
fmt.Printf("%v\n", p)
}
}
func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int {
switch op {
case Pm,
Pe,
Pf2,
Pf3:
if osize != 1 {
if op != Pm {
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
}
ctxt.Andptr[0] = Pm
ctxt.Andptr = ctxt.Andptr[1:]
z++
op = int(o.op[z])
break
}
fallthrough
default:
if -cap(ctxt.Andptr) == -cap(ctxt.And) || ctxt.And[-cap(ctxt.Andptr)+cap(ctxt.And[:])-1] != Pm {
ctxt.Andptr[0] = Pm
ctxt.Andptr = ctxt.Andptr[1:]
}
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
return z
}
func doasm(ctxt *obj.Link, p *obj.Prog) {
ctxt.Curp = p // TODO
pre := int32(prefixof(ctxt, &p.From))
if pre != 0 {
ctxt.Andptr[0] = byte(pre)
ctxt.Andptr = ctxt.Andptr[1:]
}
pre = int32(prefixof(ctxt, &p.To))
if pre != 0 {
ctxt.Andptr[0] = byte(pre)
ctxt.Andptr = ctxt.Andptr[1:]
}
if p.Ft == 0 {
p.Ft = uint8(oclass(ctxt, p, &p.From))
}
if p.Tt == 0 {
p.Tt = uint8(oclass(ctxt, p, &p.To))
}
ft := int(p.Ft) * Ymax
tt := int(p.Tt) * Ymax
o := opindex[p.As&obj.AMask]
z := 0
var a *obj.Addr
var op int
var q *obj.Prog
var r *obj.Reloc
var rel obj.Reloc
var v int32
var yt ytab
for _, yt = range o.ytab {
if ycover[ft+int(yt.from)] != 0 && ycover[tt+int(yt.to)] != 0 {
switch o.prefix {
case Pq: /* 16 bit escape and opcode escape */
ctxt.Andptr[0] = Pe
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = Pm
ctxt.Andptr = ctxt.Andptr[1:]
case Pf2, /* xmm opcode escape */
Pf3:
ctxt.Andptr[0] = byte(o.prefix)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = Pm
ctxt.Andptr = ctxt.Andptr[1:]
case Pm: /* opcode escape */
ctxt.Andptr[0] = Pm
ctxt.Andptr = ctxt.Andptr[1:]
case Pe: /* 16 bit escape */
ctxt.Andptr[0] = Pe
ctxt.Andptr = ctxt.Andptr[1:]
case Pb: /* botch */
break
}
op = int(o.op[z])
switch yt.zcase {
default:
ctxt.Diag("asmins: unknown z %d %v", yt.zcase, p)
return
case Zpseudo:
break
case Zlit:
for ; ; z++ {
op = int(o.op[z])
if op == 0 {
break
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
}
case Zlitm_r:
for ; ; z++ {
op = int(o.op[z])
if op == 0 {
break
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
}
asmand(ctxt, p, &p.From, reg[p.To.Reg])
case Zm_r:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, reg[p.To.Reg])
case Zm2_r:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(o.op[z+1])
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, reg[p.To.Reg])
case Zm_r_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.From, reg[p.To.Reg])
case Zm_r_i_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.From, reg[p.To.Reg])
ctxt.Andptr[0] = byte(p.To.Offset)
ctxt.Andptr = ctxt.Andptr[1:]
case Zibm_r:
for {
tmp2 := z
z++
op = int(o.op[tmp2])
if op == 0 {
break
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
}
asmand(ctxt, p, &p.From, reg[p.To.Reg])
ctxt.Andptr[0] = byte(p.To.Offset)
ctxt.Andptr = ctxt.Andptr[1:]
case Zaut_r:
ctxt.Andptr[0] = 0x8d
ctxt.Andptr = ctxt.Andptr[1:] /* leal */
if p.From.Type != obj.TYPE_ADDR {
ctxt.Diag("asmins: Zaut sb type ADDR")
}
p.From.Type = obj.TYPE_MEM
p.Ft = 0
asmand(ctxt, p, &p.From, reg[p.To.Reg])
p.From.Type = obj.TYPE_ADDR
p.Ft = 0
case Zm_o:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, int(o.op[z+1]))
case Zr_m:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, reg[p.From.Reg])
case Zr_m_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.To, reg[p.From.Reg])
case Zr_m_i_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.To, reg[p.From.Reg])
ctxt.Andptr[0] = byte(p.From.Offset)
ctxt.Andptr = ctxt.Andptr[1:]
case Zcallindreg:
r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc)
r.Type = obj.R_CALLIND
r.Siz = 0
fallthrough
// fallthrough
case Zo_m:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, int(o.op[z+1]))
case Zm_ibo:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, int(o.op[z+1]))
ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.To, nil))
ctxt.Andptr = ctxt.Andptr[1:]
case Zibo_m:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, int(o.op[z+1]))
ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
ctxt.Andptr = ctxt.Andptr[1:]
case Z_ib,
Zib_:
if yt.zcase == Zib_ {
a = &p.From
} else {
a = &p.To
}
v = vaddr(ctxt, p, a, nil)
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
case Zib_rp:
ctxt.Andptr[0] = byte(op + reg[p.To.Reg])
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
ctxt.Andptr = ctxt.Andptr[1:]
case Zil_rp:
ctxt.Andptr[0] = byte(op + reg[p.To.Reg])
ctxt.Andptr = ctxt.Andptr[1:]
if o.prefix == Pe {
v = vaddr(ctxt, p, &p.From, nil)
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 8)
ctxt.Andptr = ctxt.Andptr[1:]
} else {
relput4(ctxt, p, &p.From)
}
case Zib_rr:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, reg[p.To.Reg])
ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
ctxt.Andptr = ctxt.Andptr[1:]
case Z_il,
Zil_:
if yt.zcase == Zil_ {
a = &p.From
} else {
a = &p.To
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
if o.prefix == Pe {
v = vaddr(ctxt, p, a, nil)
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 8)
ctxt.Andptr = ctxt.Andptr[1:]
} else {
relput4(ctxt, p, a)
}
case Zm_ilo,
Zilo_m:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
if yt.zcase == Zilo_m {
a = &p.From
asmand(ctxt, p, &p.To, int(o.op[z+1]))
} else {
a = &p.To
asmand(ctxt, p, &p.From, int(o.op[z+1]))
}
if o.prefix == Pe {
v = vaddr(ctxt, p, a, nil)
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 8)
ctxt.Andptr = ctxt.Andptr[1:]
} else {
relput4(ctxt, p, a)
}
case Zil_rr:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, reg[p.To.Reg])
if o.prefix == Pe {
v = vaddr(ctxt, p, &p.From, nil)
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 8)
ctxt.Andptr = ctxt.Andptr[1:]
} else {
relput4(ctxt, p, &p.From)
}
case Z_rp:
ctxt.Andptr[0] = byte(op + reg[p.To.Reg])
ctxt.Andptr = ctxt.Andptr[1:]
case Zrp_:
ctxt.Andptr[0] = byte(op + reg[p.From.Reg])
ctxt.Andptr = ctxt.Andptr[1:]
case Zclr:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, reg[p.To.Reg])
case Zcall:
if p.To.Sym == nil {
ctxt.Diag("call without target")
log.Fatalf("bad code")
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
r.Type = obj.R_CALL
r.Siz = 4
r.Sym = p.To.Sym
r.Add = p.To.Offset
put4(ctxt, 0)
case Zbr,
Zjmp,
Zloop:
if p.To.Sym != nil {
if yt.zcase != Zjmp {
ctxt.Diag("branch to ATEXT")
log.Fatalf("bad code")
}
ctxt.Andptr[0] = byte(o.op[z+1])
ctxt.Andptr = ctxt.Andptr[1:]
r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
r.Sym = p.To.Sym
r.Type = obj.R_PCREL
r.Siz = 4
put4(ctxt, 0)
break
}
// Assumes q is in this function.
// Fill in backward jump now.
q = p.Pcond
if q == nil {
ctxt.Diag("jmp/branch/loop without target")
log.Fatalf("bad code")
}
if p.Back&1 != 0 {
v = int32(q.Pc - (p.Pc + 2))
if v >= -128 {
if p.As == AJCXZW {
ctxt.Andptr[0] = 0x67
ctxt.Andptr = ctxt.Andptr[1:]
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
} else if yt.zcase == Zloop {
ctxt.Diag("loop too far: %v", p)
} else {
v -= 5 - 2
if yt.zcase == Zbr {
ctxt.Andptr[0] = 0x0f
ctxt.Andptr = ctxt.Andptr[1:]
v--
}
ctxt.Andptr[0] = byte(o.op[z+1])
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 8)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 16)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 24)
ctxt.Andptr = ctxt.Andptr[1:]
}
break
}
// Annotate target; will fill in later.
p.Forwd = q.Comefrom
q.Comefrom = p
if p.Back&2 != 0 { // short
if p.As == AJCXZW {
ctxt.Andptr[0] = 0x67
ctxt.Andptr = ctxt.Andptr[1:]
}
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0
ctxt.Andptr = ctxt.Andptr[1:]
} else if yt.zcase == Zloop {
ctxt.Diag("loop too far: %v", p)
} else {
if yt.zcase == Zbr {
ctxt.Andptr[0] = 0x0f
ctxt.Andptr = ctxt.Andptr[1:]
}
ctxt.Andptr[0] = byte(o.op[z+1])
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0
ctxt.Andptr = ctxt.Andptr[1:]
}
case Zcallcon,
Zjmpcon:
if yt.zcase == Zcallcon {
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
} else {
ctxt.Andptr[0] = byte(o.op[z+1])
ctxt.Andptr = ctxt.Andptr[1:]
}
r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
r.Type = obj.R_PCREL
r.Siz = 4
r.Add = p.To.Offset
put4(ctxt, 0)
case Zcallind:
ctxt.Andptr[0] = byte(op)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(o.op[z+1])
ctxt.Andptr = ctxt.Andptr[1:]
r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
r.Type = obj.R_ADDR
r.Siz = 4
r.Add = p.To.Offset
r.Sym = p.To.Sym
put4(ctxt, 0)
case Zbyte:
v = vaddr(ctxt, p, &p.From, &rel)
if rel.Siz != 0 {
rel.Siz = uint8(op)
r = obj.Addrel(ctxt.Cursym)
*r = rel
r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
}
ctxt.Andptr[0] = byte(v)
ctxt.Andptr = ctxt.Andptr[1:]
if op > 1 {
ctxt.Andptr[0] = byte(v >> 8)
ctxt.Andptr = ctxt.Andptr[1:]
if op > 2 {
ctxt.Andptr[0] = byte(v >> 16)
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(v >> 24)
ctxt.Andptr = ctxt.Andptr[1:]
}
}
case Zmov:
goto domov
}
return
}
z += int(yt.zoffset)
}
goto domov
domov:
var pp obj.Prog
for t := []byte(ymovtab); t[0] != 0; t = t[8:] {
if p.As&obj.AMask == int16(t[0]) {
if ycover[ft+int(t[1])] != 0 {
if ycover[tt+int(t[2])] != 0 {
switch t[3] {
default:
ctxt.Diag("asmins: unknown mov %d %v", t[3], p)
case 0: /* lit */
for z = 4; t[z] != E; z++ {
ctxt.Andptr[0] = t[z]
ctxt.Andptr = ctxt.Andptr[1:]
}
case 1: /* r,m */
ctxt.Andptr[0] = t[4]
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, int(t[5]))
case 2: /* m,r */
ctxt.Andptr[0] = t[4]
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, int(t[5]))
case 3: /* r,m - 2op */
ctxt.Andptr[0] = t[4]
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = t[5]
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, int(t[6]))
case 4: /* m,r - 2op */
ctxt.Andptr[0] = t[4]
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = t[5]
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, int(t[6]))
case 5: /* load full pointer, trash heap */
if t[4] != 0 {
ctxt.Andptr[0] = t[4]
ctxt.Andptr = ctxt.Andptr[1:]
}
switch p.To.Index {
default:
goto bad
case REG_DS:
ctxt.Andptr[0] = 0xc5
ctxt.Andptr = ctxt.Andptr[1:]
case REG_SS:
ctxt.Andptr[0] = 0x0f
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0xb2
ctxt.Andptr = ctxt.Andptr[1:]
case REG_ES:
ctxt.Andptr[0] = 0xc4
ctxt.Andptr = ctxt.Andptr[1:]
case REG_FS:
ctxt.Andptr[0] = 0x0f
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0xb4
ctxt.Andptr = ctxt.Andptr[1:]
case REG_GS:
ctxt.Andptr[0] = 0x0f
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0xb5
ctxt.Andptr = ctxt.Andptr[1:]
}
asmand(ctxt, p, &p.From, reg[p.To.Reg])
case 6: /* double shift */
switch p.From.Type {
default:
goto bad
case obj.TYPE_CONST:
ctxt.Andptr[0] = 0x0f
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = t[4]
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, reg[p.From.Index])
ctxt.Andptr[0] = byte(p.From.Offset)
ctxt.Andptr = ctxt.Andptr[1:]
case obj.TYPE_REG:
switch p.From.Reg {
default:
goto bad
case REG_CL,
REG_CX:
ctxt.Andptr[0] = 0x0f
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = t[5]
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.To, reg[p.From.Index])
}
}
case 7: /* imul rm,r */
if t[4] == Pq {
ctxt.Andptr[0] = Pe
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = Pm
ctxt.Andptr = ctxt.Andptr[1:]
} else {
ctxt.Andptr[0] = t[4]
ctxt.Andptr = ctxt.Andptr[1:]
}
ctxt.Andptr[0] = t[5]
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &p.From, reg[p.To.Reg])
// NOTE: The systems listed here are the ones that use the "TLS initial exec" model,
// where you load the TLS base register into a register and then index off that
// register to access the actual TLS variables. Systems that allow direct TLS access
// are handled in prefixof above and should not be listed here.
case 8: /* mov tls, r */
switch ctxt.Headtype {
default:
log.Fatalf("unknown TLS base location for %s", obj.Headstr(ctxt.Headtype))
// ELF TLS base is 0(GS).
case obj.Hlinux,
obj.Hnacl:
pp.From = p.From
pp.From.Type = obj.TYPE_MEM
pp.From.Reg = REG_GS
pp.From.Offset = 0
pp.From.Index = REG_NONE
pp.From.Scale = 0
ctxt.Andptr[0] = 0x65
ctxt.Andptr = ctxt.Andptr[1:] // GS
ctxt.Andptr[0] = 0x8B
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &pp.From, reg[p.To.Reg])
case obj.Hplan9:
if ctxt.Plan9privates == nil {
ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
}
pp.From = obj.Addr{}
pp.From.Type = obj.TYPE_MEM
pp.From.Name = obj.NAME_EXTERN
pp.From.Sym = ctxt.Plan9privates
pp.From.Offset = 0
pp.From.Index = REG_NONE
ctxt.Andptr[0] = 0x8B
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &pp.From, reg[p.To.Reg])
// Windows TLS base is always 0x14(FS).
case obj.Hwindows:
pp.From = p.From
pp.From.Type = obj.TYPE_MEM
pp.From.Reg = REG_FS
pp.From.Offset = 0x14
pp.From.Index = REG_NONE
pp.From.Scale = 0
ctxt.Andptr[0] = 0x64
ctxt.Andptr = ctxt.Andptr[1:] // FS
ctxt.Andptr[0] = 0x8B
ctxt.Andptr = ctxt.Andptr[1:]
asmand(ctxt, p, &pp.From, reg[p.To.Reg])
}
}
return
}
}
}
}
/*
* here, the assembly has failed.
* if its a byte instruction that has
* unaddressable registers, try to
* exchange registers and reissue the
* instruction with the operands renamed.
*/
bad:
pp = *p
z = int(p.From.Reg)
if p.From.Type == obj.TYPE_REG && z >= REG_BP && z <= REG_DI {
breg := byteswapreg(ctxt, &p.To)
if breg != REG_AX {
ctxt.Andptr[0] = 0x87
ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
asmand(ctxt, p, &p.From, reg[breg])
subreg(&pp, z, breg)
doasm(ctxt, &pp)
ctxt.Andptr[0] = 0x87
ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
asmand(ctxt, p, &p.From, reg[breg])
} else {
ctxt.Andptr[0] = byte(0x90 + reg[z])
ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
subreg(&pp, z, REG_AX)
doasm(ctxt, &pp)
ctxt.Andptr[0] = byte(0x90 + reg[z])
ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
}
return
}
z = int(p.To.Reg)
if p.To.Type == obj.TYPE_REG && z >= REG_BP && z <= REG_DI {
breg := byteswapreg(ctxt, &p.From)
if breg != REG_AX {
ctxt.Andptr[0] = 0x87
ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
asmand(ctxt, p, &p.To, reg[breg])
subreg(&pp, z, breg)
doasm(ctxt, &pp)
ctxt.Andptr[0] = 0x87
ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
asmand(ctxt, p, &p.To, reg[breg])
} else {
ctxt.Andptr[0] = byte(0x90 + reg[z])
ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
subreg(&pp, z, REG_AX)
doasm(ctxt, &pp)
ctxt.Andptr[0] = byte(0x90 + reg[z])
ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
}
return
}
ctxt.Diag("doasm: notfound t2=%d from=%d to=%d %v", yt.zcase, p.Ft, p.Tt, p)
return
}
var naclret = []uint8{
0x5d, // POPL BP
// 0x8b, 0x7d, 0x00, // MOVL (BP), DI - catch return to invalid address, for debugging
0x83,
0xe5,
0xe0, // ANDL $~31, BP
0xff,
0xe5, // JMP BP
}
func asmins(ctxt *obj.Link, p *obj.Prog) {
ctxt.Andptr = ctxt.And[:]
if p.As == obj.AUSEFIELD {
r := obj.Addrel(ctxt.Cursym)
r.Off = 0
r.Sym = p.From.Sym
r.Type = obj.R_USEFIELD
r.Siz = 0
return
}
if ctxt.Headtype == obj.Hnacl {
switch p.As {
case obj.ARET:
copy(ctxt.Andptr, naclret)
ctxt.Andptr = ctxt.Andptr[len(naclret):]
return
case obj.ACALL,
obj.AJMP:
if p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI {
ctxt.Andptr[0] = 0x83
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = byte(0xe0 | (p.To.Reg - REG_AX))
ctxt.Andptr = ctxt.Andptr[1:]
ctxt.Andptr[0] = 0xe0
ctxt.Andptr = ctxt.Andptr[1:]
}
case AINT:
ctxt.Andptr[0] = 0xf4
ctxt.Andptr = ctxt.Andptr[1:]
return
}
}
doasm(ctxt, p)
if -cap(ctxt.Andptr) > -cap(ctxt.And[len(ctxt.And):]) {
fmt.Printf("and[] is too short - %d byte instruction\n", -cap(ctxt.Andptr)+cap(ctxt.And[:]))
log.Fatalf("bad code")
}
}
// Inferno utils/8c/list.c
// http://code.google.com/p/inferno-os/source/browse/utils/8c/list.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package i386
import (
"cmd/internal/obj"
"fmt"
)
const (
STRINGSZ = 1000
)
var bigP *obj.Prog
func Pconv(p *obj.Prog) string {
var str string
switch p.As {
case obj.ADATA:
str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v",
p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To))
case obj.ATEXT:
if p.From3.Offset != 0 {
str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v",
p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To))
break
}
str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v",
p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To))
default:
str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v",
p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To))
// TODO(rsc): This special case is for SHRQ $32, AX:DX, which encodes as
// SHRQ $32(DX*0), AX
// Remove.
if (p.From.Type == obj.TYPE_REG || p.From.Type == obj.TYPE_CONST) && p.From.Index != 0 {
str += fmt.Sprintf(":%v", Rconv(int(p.From.Index)))
}
}
var fp string
fp += str
return fp
}
var Register = []string{
"AL", /* [REG_AL] */
"CL",
"DL",
"BL",
"AH",
"CH",
"DH",
"BH",
"AX", /* [REG_AX] */
"CX",
"DX",
"BX",
"SP",
"BP",
"SI",
"DI",
"F0", /* [REG_F0] */
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"CS", /* [REG_CS] */
"SS",
"DS",
"ES",
"FS",
"GS",
"GDTR", /* [REG_GDTR] */
"IDTR", /* [REG_IDTR] */
"LDTR", /* [REG_LDTR] */
"MSW", /* [REG_MSW] */
"TASK", /* [REG_TASK] */
"CR0", /* [REG_CR] */
"CR1",
"CR2",
"CR3",
"CR4",
"CR5",
"CR6",
"CR7",
"DR0", /* [REG_DR] */
"DR1",
"DR2",
"DR3",
"DR4",
"DR5",
"DR6",
"DR7",
"TR0", /* [REG_TR] */
"TR1",
"TR2",
"TR3",
"TR4",
"TR5",
"TR6",
"TR7",
"X0", /* [REG_X0] */
"X1",
"X2",
"X3",
"X4",
"X5",
"X6",
"X7",
"TLS", /* [REG_TLS] */
"MAXREG", /* [MAXREG] */
}
func init() {
obj.RegisterRegister(obj.RBase386, obj.RBase386+len(Register), Rconv)
obj.RegisterOpcode(obj.ABase386, Anames)
}
func Rconv(r int) string {
if r >= REG_AL && r-REG_AL < len(Register) {
return Register[r-REG_AL]
}
return fmt.Sprintf("Rgok(%d)", r-obj.RBase386)
}
// Inferno utils/8l/pass.c
// http://code.google.com/p/inferno-os/source/browse/utils/8l/pass.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package i386
import (
"cmd/internal/obj"
"encoding/binary"
"fmt"
"log"
"math"
)
func canuselocaltls(ctxt *obj.Link) bool {
switch ctxt.Headtype {
case obj.Hlinux,
obj.Hnacl,
obj.Hplan9,
obj.Hwindows:
return false
}
return true
}
func progedit(ctxt *obj.Link, p *obj.Prog) {
// See obj6.c for discussion of TLS.
if canuselocaltls(ctxt) {
// Reduce TLS initial exec model to TLS local exec model.
// Sequences like
// MOVL TLS, BX
// ... off(BX)(TLS*1) ...
// become
// NOP
// ... off(TLS) ...
if p.As == AMOVL && p.From.Type == obj.TYPE_REG && p.From.Reg == REG_TLS && p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI {
p.As = obj.ANOP
p.From.Type = obj.TYPE_NONE
p.To.Type = obj.TYPE_NONE
}
if p.From.Type == obj.TYPE_MEM && p.From.Index == REG_TLS && REG_AX <= p.From.Reg && p.From.Reg <= REG_DI {
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_TLS
p.From.Scale = 0
p.From.Index = REG_NONE
}
if p.To.Type == obj.TYPE_MEM && p.To.Index == REG_TLS && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI {
p.To.Type = obj.TYPE_MEM
p.To.Reg = REG_TLS
p.To.Scale = 0
p.To.Index = REG_NONE
}
} else {
// As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
// The instruction
// MOVL off(TLS), BX
// becomes the sequence
// MOVL TLS, BX
// MOVL off(BX)(TLS*1), BX
// This allows the C compilers to emit references to m and g using the direct off(TLS) form.
if p.As == AMOVL && p.From.Type == obj.TYPE_MEM && p.From.Reg == REG_TLS && p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI {
q := obj.Appendp(ctxt, p)
q.As = p.As
q.From.Type = obj.TYPE_MEM
q.From.Reg = p.To.Reg
q.From.Index = REG_TLS
q.From.Scale = 2 // TODO: use 1
q.To = p.To
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_TLS
p.From.Index = REG_NONE
p.From.Offset = 0
}
}
// TODO: Remove.
if ctxt.Headtype == obj.Hplan9 {
if p.From.Scale == 1 && p.From.Index == REG_TLS {
p.From.Scale = 2
}
if p.To.Scale == 1 && p.To.Index == REG_TLS {
p.To.Scale = 2
}
}
// Rewrite CALL/JMP/RET to symbol as TYPE_BRANCH.
switch p.As {
case obj.ACALL,
obj.AJMP,
obj.ARET:
if p.To.Type == obj.TYPE_MEM && (p.To.Name == obj.NAME_EXTERN || p.To.Name == obj.NAME_STATIC) && p.To.Sym != nil {
p.To.Type = obj.TYPE_BRANCH
}
}
// Rewrite float constants to values stored in memory.
switch p.As {
// Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
case AMOVSS:
if p.From.Type == obj.TYPE_FCONST {
if p.From.U.Dval == 0 {
if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X7 {
p.As = AXORPS
p.From = p.To
break
}
}
}
fallthrough
// fallthrough
case AFMOVF,
AFADDF,
AFSUBF,
AFSUBRF,
AFMULF,
AFDIVF,
AFDIVRF,
AFCOMF,
AFCOMFP,
AADDSS,
ASUBSS,
AMULSS,
ADIVSS,
ACOMISS,
AUCOMISS:
if p.From.Type == obj.TYPE_FCONST {
f32 := float32(p.From.U.Dval)
i32 := math.Float32bits(f32)
literal := fmt.Sprintf("$f32.%08x", i32)
s := obj.Linklookup(ctxt, literal, 0)
if s.Type == 0 {
s.Type = obj.SRODATA
obj.Adduint32(ctxt, s, i32)
s.Reachable = 0
}
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_EXTERN
p.From.Sym = s
p.From.Offset = 0
}
// Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
case AMOVSD:
if p.From.Type == obj.TYPE_FCONST {
if p.From.U.Dval == 0 {
if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X7 {
p.As = AXORPS
p.From = p.To
break
}
}
}
fallthrough
// fallthrough
case AFMOVD,
AFADDD,
AFSUBD,
AFSUBRD,
AFMULD,
AFDIVD,
AFDIVRD,
AFCOMD,
AFCOMDP,
AADDSD,
ASUBSD,
AMULSD,
ADIVSD,
ACOMISD,
AUCOMISD:
if p.From.Type == obj.TYPE_FCONST {
i64 := math.Float64bits(p.From.U.Dval)
literal := fmt.Sprintf("$f64.%016x", i64)
s := obj.Linklookup(ctxt, literal, 0)
if s.Type == 0 {
s.Type = obj.SRODATA
obj.Adduint64(ctxt, s, i64)
s.Reachable = 0
}
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_EXTERN
p.From.Sym = s
p.From.Offset = 0
}
}
}
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
if ctxt.Symmorestack[0] == nil {
ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
}
if ctxt.Headtype == obj.Hplan9 && ctxt.Plan9privates == nil {
ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
}
ctxt.Cursym = cursym
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
p := cursym.Text
autoffset := int32(p.To.Offset)
if autoffset < 0 {
autoffset = 0
}
cursym.Locals = autoffset
cursym.Args = p.To.U.Argsize
if p.From3.Offset&obj.NOSPLIT == 0 || (p.From3.Offset&obj.WRAPPER != 0) {
p = obj.Appendp(ctxt, p)
p = load_g_cx(ctxt, p) // load g into CX
}
var q *obj.Prog
if cursym.Text.From3.Offset&obj.NOSPLIT == 0 {
p = stacksplit(ctxt, p, autoffset, cursym.Text.From3.Offset&obj.NEEDCTXT == 0, &q) // emit split check
}
if autoffset != 0 {
p = obj.Appendp(ctxt, p)
p.As = AADJSP
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autoffset)
p.Spadj = autoffset
} else {
// zero-byte stack adjustment.
// Insert a fake non-zero adjustment so that stkcheck can
// recognize the end of the stack-splitting prolog.
p = obj.Appendp(ctxt, p)
p.As = obj.ANOP
p.Spadj = int32(-ctxt.Arch.Ptrsize)
p = obj.Appendp(ctxt, p)
p.As = obj.ANOP
p.Spadj = int32(ctxt.Arch.Ptrsize)
}
if q != nil {
q.Pcond = p
}
deltasp := autoffset
if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
//
// MOVL g_panic(CX), BX
// TESTL BX, BX
// JEQ end
// LEAL (autoffset+4)(SP), DI
// CMPL panic_argp(BX), DI
// JNE end
// MOVL SP, panic_argp(BX)
// end:
// NOP
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
p = obj.Appendp(ctxt, p)
p.As = AMOVL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_CX
p.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_BX
p = obj.Appendp(ctxt, p)
p.As = ATESTL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_BX
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_BX
p = obj.Appendp(ctxt, p)
p.As = AJEQ
p.To.Type = obj.TYPE_BRANCH
p1 := p
p = obj.Appendp(ctxt, p)
p.As = ALEAL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_SP
p.From.Offset = int64(autoffset) + 4
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_DI
p = obj.Appendp(ctxt, p)
p.As = ACMPL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_BX
p.From.Offset = 0 // Panic.argp
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_DI
p = obj.Appendp(ctxt, p)
p.As = AJNE
p.To.Type = obj.TYPE_BRANCH
p2 := p
p = obj.Appendp(ctxt, p)
p.As = AMOVL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_SP
p.To.Type = obj.TYPE_MEM
p.To.Reg = REG_BX
p.To.Offset = 0 // Panic.argp
p = obj.Appendp(ctxt, p)
p.As = obj.ANOP
p1.Pcond = p
p2.Pcond = p
}
if ctxt.Debugzerostack != 0 && autoffset != 0 && cursym.Text.From3.Offset&obj.NOSPLIT == 0 {
// 8l -Z means zero the stack frame on entry.
// This slows down function calls but can help avoid
// false positives in garbage collection.
p = obj.Appendp(ctxt, p)
p.As = AMOVL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_SP
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_DI
p = obj.Appendp(ctxt, p)
p.As = AMOVL
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autoffset) / 4
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_CX
p = obj.Appendp(ctxt, p)
p.As = AMOVL
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_AX
p = obj.Appendp(ctxt, p)
p.As = AREP
p = obj.Appendp(ctxt, p)
p.As = ASTOSL
}
var a int
for ; p != nil; p = p.Link {
a = int(p.From.Name)
if a == obj.NAME_AUTO {
p.From.Offset += int64(deltasp)
}
if a == obj.NAME_PARAM {
p.From.Offset += int64(deltasp) + 4
}
a = int(p.To.Name)
if a == obj.NAME_AUTO {
p.To.Offset += int64(deltasp)
}
if a == obj.NAME_PARAM {
p.To.Offset += int64(deltasp) + 4
}
switch p.As {
default:
continue
case APUSHL,
APUSHFL:
deltasp += 4
p.Spadj = 4
continue
case APUSHW,
APUSHFW:
deltasp += 2
p.Spadj = 2
continue
case APOPL,
APOPFL:
deltasp -= 4
p.Spadj = -4
continue
case APOPW,
APOPFW:
deltasp -= 2
p.Spadj = -2
continue
case obj.ARET:
break
}
if autoffset != deltasp {
ctxt.Diag("unbalanced PUSH/POP")
}
if autoffset != 0 {
p.As = AADJSP
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(-autoffset)
p.Spadj = -autoffset
p = obj.Appendp(ctxt, p)
p.As = obj.ARET
// If there are instructions following
// this ARET, they come from a branch
// with the same stackframe, so undo
// the cleanup.
p.Spadj = +autoffset
}
if p.To.Sym != nil { // retjmp
p.As = obj.AJMP
}
}
}
// Append code to p to load g into cx.
// Overwrites p with the first instruction (no first appendp).
// Overwriting p is unusual but it lets use this in both the
// prologue (caller must call appendp first) and in the epilogue.
// Returns last new instruction.
func load_g_cx(ctxt *obj.Link, p *obj.Prog) *obj.Prog {
p.As = AMOVL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_TLS
p.From.Offset = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_CX
next := p.Link
progedit(ctxt, p)
for p.Link != next {
p = p.Link
}
if p.From.Index == REG_TLS {
p.From.Scale = 2
}
return p
}
// Append code to p to check for stack split.
// Appends to (does not overwrite) p.
// Assumes g is in CX.
// Returns last new instruction.
// On return, *jmpok is the instruction that should jump
// to the stack frame allocation if no split is needed.
func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt bool, jmpok **obj.Prog) *obj.Prog {
if ctxt.Debugstack != 0 {
// 8l -K means check not only for stack
// overflow but stack underflow.
// On underflow, INT 3 (breakpoint).
// Underflow itself is rare but this also
// catches out-of-sync stack guard info.
p = obj.Appendp(ctxt, p)
p.As = ACMPL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_CX
p.From.Offset = 4
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_SP
p = obj.Appendp(ctxt, p)
p.As = AJCC
p.To.Type = obj.TYPE_BRANCH
p.To.Offset = 4
q1 := p
p = obj.Appendp(ctxt, p)
p.As = AINT
p.From.Type = obj.TYPE_CONST
p.From.Offset = 3
p = obj.Appendp(ctxt, p)
p.As = obj.ANOP
q1.Pcond = p
}
var q1 *obj.Prog
if framesize <= obj.StackSmall {
// small stack: SP <= stackguard
// CMPL SP, stackguard
p = obj.Appendp(ctxt, p)
p.As = ACMPL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_SP
p.To.Type = obj.TYPE_MEM
p.To.Reg = REG_CX
p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
if ctxt.Cursym.Cfunc != 0 {
p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
}
} else if framesize <= obj.StackBig {
// large stack: SP-framesize <= stackguard-StackSmall
// LEAL -(framesize-StackSmall)(SP), AX
// CMPL AX, stackguard
p = obj.Appendp(ctxt, p)
p.As = ALEAL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_SP
p.From.Offset = -(int64(framesize) - obj.StackSmall)
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_AX
p = obj.Appendp(ctxt, p)
p.As = ACMPL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_AX
p.To.Type = obj.TYPE_MEM
p.To.Reg = REG_CX
p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
if ctxt.Cursym.Cfunc != 0 {
p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
}
} else {
// Such a large stack we need to protect against wraparound
// if SP is close to zero.
// SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
// The +StackGuard on both sides is required to keep the left side positive:
// SP is allowed to be slightly below stackguard. See stack.h.
//
// Preemption sets stackguard to StackPreempt, a very large value.
// That breaks the math above, so we have to check for that explicitly.
// MOVL stackguard, CX
// CMPL CX, $StackPreempt
// JEQ label-of-call-to-morestack
// LEAL StackGuard(SP), AX
// SUBL stackguard, AX
// CMPL AX, $(framesize+(StackGuard-StackSmall))
p = obj.Appendp(ctxt, p)
p.As = AMOVL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_CX
p.From.Offset = 0
p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
if ctxt.Cursym.Cfunc != 0 {
p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
}
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_SI
p = obj.Appendp(ctxt, p)
p.As = ACMPL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_SI
p.To.Type = obj.TYPE_CONST
p.To.Offset = int64(uint32(obj.StackPreempt & (1<<32 - 1)))
p = obj.Appendp(ctxt, p)
p.As = AJEQ
p.To.Type = obj.TYPE_BRANCH
q1 = p
p = obj.Appendp(ctxt, p)
p.As = ALEAL
p.From.Type = obj.TYPE_MEM
p.From.Reg = REG_SP
p.From.Offset = obj.StackGuard
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_AX
p = obj.Appendp(ctxt, p)
p.As = ASUBL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_SI
p.From.Offset = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_AX
p = obj.Appendp(ctxt, p)
p.As = ACMPL
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_AX
p.To.Type = obj.TYPE_CONST
p.To.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
}
// common
p = obj.Appendp(ctxt, p)
p.As = AJHI
p.To.Type = obj.TYPE_BRANCH
p.To.Offset = 4
q := p
p = obj.Appendp(ctxt, p)
p.As = obj.ACALL
p.To.Type = obj.TYPE_BRANCH
if ctxt.Cursym.Cfunc != 0 {
p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
} else {
p.To.Sym = ctxt.Symmorestack[bool2int(noctxt)]
}
p = obj.Appendp(ctxt, p)
p.As = obj.AJMP
p.To.Type = obj.TYPE_BRANCH
p.Pcond = ctxt.Cursym.Text.Link
if q != nil {
q.Pcond = p.Link
}
if q1 != nil {
q1.Pcond = q.Link
}
*jmpok = q
return p
}
func follow(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
firstp := ctxt.NewProg()
lastp := firstp
xfol(ctxt, s.Text, &lastp)
lastp.Link = nil
s.Text = firstp.Link
}
func nofollow(a int) bool {
switch a {
case obj.AJMP,
obj.ARET,
AIRETL,
AIRETW,
obj.AUNDEF:
return true
}
return false
}
func pushpop(a int) bool {
switch a {
case APUSHL,
APUSHFL,
APUSHW,
APUSHFW,
APOPL,
APOPFL,
APOPW,
APOPFW:
return true
}
return false
}
func relinv(a int) int {
switch a {
case AJEQ:
return AJNE
case AJNE:
return AJEQ
case AJLE:
return AJGT
case AJLS:
return AJHI
case AJLT:
return AJGE
case AJMI:
return AJPL
case AJGE:
return AJLT
case AJPL:
return AJMI
case AJGT:
return AJLE
case AJHI:
return AJLS
case AJCS:
return AJCC
case AJCC:
return AJCS
case AJPS:
return AJPC
case AJPC:
return AJPS
case AJOS:
return AJOC
case AJOC:
return AJOS
}
log.Fatalf("unknown relation: %s", Anames[a])
return 0
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var i int
var a int
loop:
if p == nil {
return
}
if p.As == obj.AJMP {
q = p.Pcond
if q != nil && q.As != obj.ATEXT {
/* mark instruction as done and continue layout at target of jump */
p.Mark = 1
p = q
if p.Mark == 0 {
goto loop
}
}
}
if p.Mark != 0 {
/*
* p goes here, but already used it elsewhere.
* copy up to 4 instructions or else branch to other copy.
*/
i = 0
q = p
for ; i < 4; (func() { i++; q = q.Link })() {
if q == nil {
break
}
if q == *last {
break
}
a = int(q.As)
if a == obj.ANOP {
i--
continue
}
if nofollow(a) || pushpop(a) {
break // NOTE(rsc): arm does goto copy
}
if q.Pcond == nil || q.Pcond.Mark != 0 {
continue
}
if a == obj.ACALL || a == ALOOP {
continue
}
for {
if p.As == obj.ANOP {
p = p.Link
continue
}
q = obj.Copyp(ctxt, p)
p = p.Link
q.Mark = 1
(*last).Link = q
*last = q
if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark != 0 {
continue
}
q.As = int16(relinv(int(q.As)))
p = q.Pcond
q.Pcond = q.Link
q.Link = p
xfol(ctxt, q.Link, last)
p = q.Link
if p.Mark != 0 {
return
}
goto loop
/* */
}
}
q = ctxt.NewProg()
q.As = obj.AJMP
q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.To.Offset = p.Pc
q.Pcond = p
p = q
}
/* emit p */
p.Mark = 1
(*last).Link = p
*last = p
a = int(p.As)
/* continue loop with what comes after p */
if nofollow(a) {
return
}
if p.Pcond != nil && a != obj.ACALL {
/*
* some kind of conditional branch.
* recurse to follow one path.
* continue loop on the other.
*/
q = obj.Brchain(ctxt, p.Pcond)
if q != nil {
p.Pcond = q
}
q = obj.Brchain(ctxt, p.Link)
if q != nil {
p.Link = q
}
if p.From.Type == obj.TYPE_CONST {
if p.From.Offset == 1 {
/*
* expect conditional jump to be taken.
* rewrite so that's the fall-through case.
*/
p.As = int16(relinv(a))
q = p.Link
p.Link = p.Pcond
p.Pcond = q
}
} else {
q = p.Link
if q.Mark != 0 {
if a != ALOOP {
p.As = int16(relinv(a))
p.Link = p.Pcond
p.Pcond = q
}
}
}
xfol(ctxt, p.Link, last)
if p.Pcond.Mark != 0 {
return
}
p = p.Pcond
goto loop
}
p = p.Link
goto loop
}
var unaryDst = map[int]bool{
ABSWAPL: true,
ACMPXCHG8B: true,
ADECB: true,
ADECL: true,
ADECW: true,
AINCB: true,
AINCL: true,
AINCW: true,
ANEGB: true,
ANEGL: true,
ANEGW: true,
ANOTB: true,
ANOTL: true,
ANOTW: true,
APOPL: true,
APOPW: true,
ASETCC: true,
ASETCS: true,
ASETEQ: true,
ASETGE: true,
ASETGT: true,
ASETHI: true,
ASETLE: true,
ASETLS: true,
ASETLT: true,
ASETMI: true,
ASETNE: true,
ASETOC: true,
ASETOS: true,
ASETPC: true,
ASETPL: true,
ASETPS: true,
AFFREE: true,
AFLDENV: true,
AFSAVE: true,
AFSTCW: true,
AFSTENV: true,
AFSTSW: true,
}
var Link386 = obj.LinkArch{
ByteOrder: binary.LittleEndian,
Pconv: Pconv,
Name: "386",
Thechar: '8',
Preprocess: preprocess,
Assemble: span8,
Follow: follow,
Progedit: progedit,
UnaryDst: unaryDst,
Minlc: 1,
Ptrsize: 4,
Regsize: 4,
}
// Copyright 2015 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 i386
func bool2int(b bool) int {
if b {
return 1
}
return 0
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment