// 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" ) // Instruction layout. const ( MaxAlign = 32 FuncAlign = 16 ) type Optab struct { as int16 ytab []byte prefix uint8 op [13]uint8 } const ( Yxxx = 0 + iota Ynone Yi0 Yi1 Yi8 Yi32 Yiauto Yal Ycl Yax Ycx Yrb Yrl Yrf Yf0 Yrx Ymb Yml Ym Ybr Ycol 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 - 62 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 [D_NONE]int var ynone = []uint8{ Ynone, Ynone, Zlit, 1, 0, } var ytext = []uint8{ Ymb, Yi32, Zpseudo, 1, 0, } var ynop = []uint8{ 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, 0, } var yfuncdata = []uint8{ Yi32, Ym, Zpseudo, 0, 0, } var ypcdata = []uint8{ Yi32, Yi32, Zpseudo, 0, 0, } var yxorb = []uint8{ Yi32, Yal, Zib_, 1, Yi32, Ymb, Zibo_m, 2, Yrb, Ymb, Zr_m, 1, Ymb, Yrb, Zm_r, 1, 0, } var yxorl = []uint8{ Yi8, Yml, Zibo_m, 2, Yi32, Yax, Zil_, 1, Yi32, Yml, Zilo_m, 2, Yrl, Yml, Zr_m, 1, Yml, Yrl, Zm_r, 1, 0, } var yaddl = []uint8{ Yi8, Yml, Zibo_m, 2, Yi32, Yax, Zil_, 1, Yi32, Yml, Zilo_m, 2, Yrl, Yml, Zr_m, 1, Yml, Yrl, Zm_r, 1, 0, } var yincb = []uint8{ Ynone, Ymb, Zo_m, 2, 0, } var yincl = []uint8{ Ynone, Yrl, Z_rp, 1, Ynone, Yml, Zo_m, 2, 0, } var ycmpb = []uint8{ Yal, Yi32, Z_ib, 1, Ymb, Yi32, Zm_ibo, 2, Ymb, Yrb, Zm_r, 1, Yrb, Ymb, Zr_m, 1, 0, } var ycmpl = []uint8{ 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, 0, } var yshb = []uint8{ Yi1, Ymb, Zo_m, 2, Yi32, Ymb, Zibo_m, 2, Ycx, Ymb, Zo_m, 2, 0, } var yshl = []uint8{ Yi1, Yml, Zo_m, 2, Yi32, Yml, Zibo_m, 2, Ycl, Yml, Zo_m, 2, Ycx, Yml, Zo_m, 2, 0, } var ytestb = []uint8{ Yi32, Yal, Zib_, 1, Yi32, Ymb, Zibo_m, 2, Yrb, Ymb, Zr_m, 1, Ymb, Yrb, Zm_r, 1, 0, } var ytestl = []uint8{ Yi32, Yax, Zil_, 1, Yi32, Yml, Zilo_m, 2, Yrl, Yml, Zr_m, 1, Yml, Yrl, Zm_r, 1, 0, } var ymovb = []uint8{ Yrb, Ymb, Zr_m, 1, Ymb, Yrb, Zm_r, 1, Yi32, Yrb, Zib_rp, 1, Yi32, Ymb, Zibo_m, 2, 0, } var ymovw = []uint8{ 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, 0, } var ymovl = []uint8{ 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, 0, } var ymovq = []uint8{ Yml, Yxr, Zm_r_xm, 2, 0, } var ym_rl = []uint8{ Ym, Yrl, Zm_r, 1, 0, } var yrl_m = []uint8{ Yrl, Ym, Zr_m, 1, 0, } var ymb_rl = []uint8{ Ymb, Yrl, Zm_r, 1, 0, } var yml_rl = []uint8{ Yml, Yrl, Zm_r, 1, 0, } var yrb_mb = []uint8{ Yrb, Ymb, Zr_m, 1, 0, } var yrl_ml = []uint8{ Yrl, Yml, Zr_m, 1, 0, } var yml_mb = []uint8{ Yrb, Ymb, Zr_m, 1, Ymb, Yrb, Zm_r, 1, 0, } var yxchg = []uint8{ Yax, Yrl, Z_rp, 1, Yrl, Yax, Zrp_, 1, Yrl, Yml, Zr_m, 1, Yml, Yrl, Zm_r, 1, 0, } var ydivl = []uint8{ Yml, Ynone, Zm_o, 2, 0, } var ydivb = []uint8{ Ymb, Ynone, Zm_o, 2, 0, } var yimul = []uint8{ Yml, Ynone, Zm_o, 2, Yi8, Yrl, Zib_rr, 1, Yi32, Yrl, Zil_rr, 1, 0, } var ybyte = []uint8{ Yi32, Ynone, Zbyte, 1, 0, } var yin = []uint8{ Yi32, Ynone, Zib_, 1, Ynone, Ynone, Zlit, 1, 0, } var yint = []uint8{ Yi32, Ynone, Zib_, 1, 0, } var ypushl = []uint8{ Yrl, Ynone, Zrp_, 1, Ym, Ynone, Zm_o, 2, Yi8, Ynone, Zib_, 1, Yi32, Ynone, Zil_, 1, 0, } var ypopl = []uint8{ Ynone, Yrl, Z_rp, 1, Ynone, Ym, Zo_m, 2, 0, } var ybswap = []uint8{ Ynone, Yrl, Z_rp, 1, 0, } var yscond = []uint8{ Ynone, Ymb, Zo_m, 2, 0, } var yjcond = []uint8{ Ynone, Ybr, Zbr, 0, Yi0, Ybr, Zbr, 0, Yi1, Ybr, Zbr, 1, 0, } var yloop = []uint8{ Ynone, Ybr, Zloop, 1, 0, } var ycall = []uint8{ Ynone, Yml, Zcallindreg, 0, Yrx, Yrx, Zcallindreg, 2, Ynone, Ycol, Zcallind, 2, Ynone, Ybr, Zcall, 0, Ynone, Yi32, Zcallcon, 1, 0, } var yduff = []uint8{ Ynone, Yi32, Zcall, 1, 0, } var yjmp = []uint8{ Ynone, Yml, Zo_m, 2, Ynone, Ybr, Zjmp, 0, Ynone, Yi32, Zjmpcon, 1, 0, } var yfmvd = []uint8{ Ym, Yf0, Zm_o, 2, Yf0, Ym, Zo_m, 2, Yrf, Yf0, Zm_o, 2, Yf0, Yrf, Zo_m, 2, 0, } var yfmvdp = []uint8{ Yf0, Ym, Zo_m, 2, Yf0, Yrf, Zo_m, 2, 0, } var yfmvf = []uint8{ Ym, Yf0, Zm_o, 2, Yf0, Ym, Zo_m, 2, 0, } var yfmvx = []uint8{ Ym, Yf0, Zm_o, 2, 0, } var yfmvp = []uint8{ Yf0, Ym, Zo_m, 2, 0, } var yfcmv = []uint8{ Yrf, Yf0, Zm_o, 2, 0, } var yfadd = []uint8{ Ym, Yf0, Zm_o, 2, Yrf, Yf0, Zm_o, 2, Yf0, Yrf, Zo_m, 2, 0, } var yfaddp = []uint8{ Yf0, Yrf, Zo_m, 2, 0, } var yfxch = []uint8{ Yf0, Yrf, Zo_m, 2, Yrf, Yf0, Zm_o, 2, 0, } var ycompp = []uint8{ Yf0, Yrf, Zo_m, 2, /* botch is really f0,f1 */ 0, } var ystsw = []uint8{ Ynone, Ym, Zo_m, 2, Ynone, Yax, Zlit, 1, 0, } var ystcw = []uint8{ Ynone, Ym, Zo_m, 2, Ym, Ynone, Zm_o, 2, 0, } var ysvrs = []uint8{ Ynone, Ym, Zo_m, 2, Ym, Ynone, Zm_o, 2, 0, } var ymskb = []uint8{ Yxr, Yrl, Zm_r_xm, 2, Ymr, Yrl, Zm_r_xm, 1, 0, } var yxm = []uint8{ Yxm, Yxr, Zm_r_xm, 1, 0, } var yxcvm1 = []uint8{ Yxm, Yxr, Zm_r_xm, 2, Yxm, Ymr, Zm_r_xm, 2, 0, } var yxcvm2 = []uint8{ Yxm, Yxr, Zm_r_xm, 2, Ymm, Yxr, Zm_r_xm, 2, 0, } var yxmq = []uint8{ Yxm, Yxr, Zm_r_xm, 2, 0, } var yxr = []uint8{ Yxr, Yxr, Zm_r_xm, 1, 0, } var yxr_ml = []uint8{ Yxr, Yml, Zr_m_xm, 1, 0, } var yxcmp = []uint8{ Yxm, Yxr, Zm_r_xm, 1, 0, } var yxcmpi = []uint8{ Yxm, Yxr, Zm_r_i_xm, 2, 0, } var yxmov = []uint8{ Yxm, Yxr, Zm_r_xm, 1, Yxr, Yxm, Zr_m_xm, 1, 0, } var yxcvfl = []uint8{ Yxm, Yrl, Zm_r_xm, 1, 0, } var yxcvlf = []uint8{ Yml, Yxr, Zm_r_xm, 1, 0, } /* static uchar yxcvfq[] = { Yxm, Yrl, Zm_r_xm, 2, 0 }; static uchar yxcvqf[] = { Yml, Yxr, Zm_r_xm, 2, 0 }; */ var yxrrl = []uint8{ Yxr, Yrl, Zm_r, 1, 0, } var yprefetch = []uint8{ Ym, Ynone, Zm_o, 2, 0, } var yaes = []uint8{ Yxm, Yxr, Zlitm_r, 2, 0, } var yinsrd = []uint8{ Yml, Yxr, Zibm_r, 2, 0, } var ymshufb = []uint8{ Yxm, Yxr, Zm2_r, 2, 0, } var yxshuf = []uint8{ Yxm, Yxr, Zibm_r, 2, 0, } var optab = /* as, ytab, andproto, opcode */ []Optab{ Optab{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{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{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{AGLOBL, nil, 0, [13]uint8{}}, Optab{AGOK, nil, 0, [13]uint8{}}, Optab{AHISTORY, 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{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{ANAME, nil, 0, [13]uint8{}}, Optab{ANEGB, yscond, Px, [13]uint8{0xf6, 03}}, Optab{ANEGL, yscond, Px, [13]uint8{0xf7, 03}}, Optab{ANEGW, yscond, Pe, [13]uint8{0xf7, 03}}, Optab{ANOP, ynop, Px, [13]uint8{0, 0}}, Optab{ANOTB, yscond, Px, [13]uint8{0xf6, 02}}, Optab{ANOTL, yscond, Px, [13]uint8{0xf7, 02}}, Optab{ANOTW, yscond, Pe, [13]uint8{0xf7, 02}}, 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{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{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{AEND, nil, 0, [13]uint8{}}, Optab{ADYNT_, nil, 0, [13]uint8{}}, Optab{AINIT_, nil, 0, [13]uint8{}}, Optab{ASIGNAME, 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}}, 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{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{AUSEFIELD, ynop, Px, [13]uint8{0, 0}}, Optab{ATYPE, nil, 0, [13]uint8{}}, Optab{AFUNCDATA, yfuncdata, Px, [13]uint8{0, 0}}, Optab{APCDATA, ypcdata, Px, [13]uint8{0, 0}}, Optab{ACHECKNIL, nil, 0, [13]uint8{}}, Optab{AVARDEF, nil, 0, [13]uint8{}}, Optab{AVARKILL, nil, 0, [13]uint8{}}, Optab{ADUFFCOPY, yduff, Px, [13]uint8{0xe8}}, Optab{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) { var p *obj.Prog var q *obj.Prog var c int32 var v int32 var loop int32 var bp []byte var n int var m int var i int ctxt.Cursym = s if s.Text == nil || s.Text.Link == nil { return } if ycover[0] == 0 { instinit() } for p = s.Text; p != nil; p = p.Link { n = 0 if p.To.Type == D_BRANCH { if p.Pcond == nil { p.Pcond = p } } q = p.Pcond if q != nil { if q.Back != 2 { n = 1 } } p.Back = uint8(n) if p.As == AADJSP { p.To.Type = D_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 = ANOP } } } 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 = D_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 = ANOP } } } n = 0 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 == ACALL && p.To.Sym == deferreturn { c = naclpad(ctxt, s, c, -c&31) } // pad call to end at 32-byte boundary if p.As == 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) 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++ { var r *obj.Reloc r = &s.R[i] fmt.Printf(" rel %#.4x/%d %s%+d\n", uint32(r.Off), r.Siz, r.Sym.Name, r.Add) } } } func instinit() { var i int for i = 1; optab[i].as != 0; i++ { if i != int(optab[i].as) { log.Fatalf("phase error in optab: at %v found %v", Aconv(i), Aconv(int(optab[i].as))) } } 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 < D_NONE; i++ { reg[i] = -1 if i >= D_AL && i <= D_BH { reg[i] = (i - D_AL) & 7 } if i >= D_AX && i <= D_DI { reg[i] = (i - D_AX) & 7 } if i >= D_F0 && i <= D_F0+7 { reg[i] = (i - D_F0) & 7 } if i >= D_X0 && i <= D_X0+7 { reg[i] = (i - D_X0) & 7 } } } func prefixof(ctxt *obj.Link, a *obj.Addr) int { switch a.Type { case D_INDIR + D_CS: return 0x2e case D_INDIR + D_DS: return 0x3e case D_INDIR + D_ES: return 0x26 case D_INDIR + D_FS: return 0x64 case D_INDIR + D_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 D_INDIR + D_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(a *obj.Addr) int { var v int32 if (a.Type >= D_INDIR && a.Type < 2*D_INDIR) || a.Index != D_NONE { if a.Index != D_NONE && a.Scale == 0 { if a.Type == D_ADDR { switch a.Index { case D_EXTERN, D_STATIC: return Yi32 case D_AUTO, D_PARAM: return Yiauto } return Yxxx } //if(a->type == D_INDIR+D_ADDR) // print("*Ycol\n"); return Ycol } return Ym } switch a.Type { case D_AL: return Yal case D_AX: return Yax case D_CL, D_DL, D_BL, D_AH, D_CH, D_DH, D_BH: return Yrb case D_CX: return Ycx case D_DX, D_BX: return Yrx case D_SP, D_BP, D_SI, D_DI: return Yrl case D_F0 + 0: return Yf0 case D_F0 + 1, D_F0 + 2, D_F0 + 3, D_F0 + 4, D_F0 + 5, D_F0 + 6, D_F0 + 7: return Yrf case D_X0 + 0, D_X0 + 1, D_X0 + 2, D_X0 + 3, D_X0 + 4, D_X0 + 5, D_X0 + 6, D_X0 + 7: return Yxr case D_NONE: return Ynone case D_CS: return Ycs case D_SS: return Yss case D_DS: return Yds case D_ES: return Yes case D_FS: return Yfs case D_GS: return Ygs case D_TLS: return Ytls case D_GDTR: return Ygdtr case D_IDTR: return Yidtr case D_LDTR: return Yldtr case D_MSW: return Ymsw case D_TASK: return Ytask case D_CR + 0: return Ycr0 case D_CR + 1: return Ycr1 case D_CR + 2: return Ycr2 case D_CR + 3: return Ycr3 case D_CR + 4: return Ycr4 case D_CR + 5: return Ycr5 case D_CR + 6: return Ycr6 case D_CR + 7: return Ycr7 case D_DR + 0: return Ydr0 case D_DR + 1: return Ydr1 case D_DR + 2: return Ydr2 case D_DR + 3: return Ydr3 case D_DR + 4: return Ydr4 case D_DR + 5: return Ydr5 case D_DR + 6: return Ydr6 case D_DR + 7: return Ydr7 case D_TR + 0: return Ytr0 case D_TR + 1: return Ytr1 case D_TR + 2: return Ytr2 case D_TR + 3: return Ytr3 case D_TR + 4: return Ytr4 case D_TR + 5: return Ytr5 case D_TR + 6: return Ytr6 case D_TR + 7: return Ytr7 case D_EXTERN, D_STATIC, D_AUTO, D_PARAM: return Ym case D_CONST, D_CONST2, D_ADDR: if a.Sym == nil { v = int32(a.Offset) if v == 0 { return Yi0 } if v == 1 { return Yi1 } if v >= -128 && v <= 127 { return Yi8 } } return Yi32 case D_BRANCH: return Ybr } return Yxxx } func asmidx(ctxt *obj.Link, scale int, index int, base int) { var i int switch index { default: goto bad case D_NONE: i = 4 << 3 goto bas case D_AX, D_CX, D_DX, D_BX, D_BP, D_SI, D_DI: i = reg[index] << 3 break } switch scale { default: goto bad case 1: break case 2: i |= 1 << 6 case 4: i |= 2 << 6 case 8: i |= 3 << 6 break } bas: switch base { default: goto bad case D_NONE: /* must be mod=00 */ i |= 5 case D_AX, D_CX, D_DX, D_BX, D_SP, D_BP, D_SI, D_DI: i |= reg[base] break } 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 v int64 var rel obj.Reloc var r *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 { var t int var v int32 var s *obj.LSym if r != nil { *r = obj.Reloc{} } t = int(a.Type) v = int32(a.Offset) if t == D_ADDR { t = int(a.Index) } switch t { case D_STATIC, D_EXTERN: s = a.Sym if s != nil { if r == nil { ctxt.Diag("need reloc for %v", Dconv(p, 0, a)) log.Fatalf("bad code") } r.Type = obj.R_ADDR r.Siz = 4 r.Off = -1 r.Sym = s r.Add = int64(v) v = 0 } case D_INDIR + D_TLS: if r == nil { ctxt.Diag("need reloc for %v", Dconv(p, 0, a)) log.Fatalf("bad code") } r.Type = obj.R_TLS_LE r.Siz = 4 r.Off = -1 // caller must fill in r.Add = int64(v) v = 0 break } return v } func asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int) { var v int32 var t int var scale int var rel obj.Reloc v = int32(a.Offset) t = int(a.Type) rel.Siz = 0 if a.Index != D_NONE && a.Index != D_TLS { if t < D_INDIR || t >= 2*D_INDIR { switch t { default: goto bad case D_STATIC, D_EXTERN: t = D_NONE v = vaddr(ctxt, p, a, &rel) case D_AUTO, D_PARAM: t = D_SP break } } else { t -= D_INDIR } if t == D_NONE { ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3) ctxt.Andptr = ctxt.Andptr[1:] asmidx(ctxt, int(a.Scale), int(a.Index), t) goto putrelv } if v == 0 && rel.Siz == 0 && t != D_BP { ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3) ctxt.Andptr = ctxt.Andptr[1:] asmidx(ctxt, int(a.Scale), int(a.Index), t) 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), t) 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), t) goto putrelv } if t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7 { if v != 0 { goto bad } ctxt.Andptr[0] = byte(3<<6 | reg[t]<<0 | r<<3) ctxt.Andptr = ctxt.Andptr[1:] return } scale = int(a.Scale) if t < D_INDIR || t >= 2*D_INDIR { switch a.Type { default: goto bad case D_STATIC, D_EXTERN: t = D_NONE v = vaddr(ctxt, p, a, &rel) case D_AUTO, D_PARAM: t = D_SP break } scale = 1 } else { t -= D_INDIR } if t == D_TLS { v = vaddr(ctxt, p, a, &rel) } if t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS { ctxt.Andptr[0] = byte(0<<6 | 5<<0 | r<<3) ctxt.Andptr = ctxt.Andptr[1:] goto putrelv } if t == D_SP { if v == 0 && rel.Siz == 0 { ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3) ctxt.Andptr = ctxt.Andptr[1:] asmidx(ctxt, scale, D_NONE, t) 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, scale, D_NONE, t) 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, scale, D_NONE, t) goto putrelv } if t >= D_AX && t <= D_DI { if a.Index == D_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 && t != D_BP { ctxt.Andptr[0] = byte(0<<6 | reg[t]<<0 | r<<3) ctxt.Andptr = ctxt.Andptr[1:] return } if v >= -128 && v < 128 && rel.Siz == 0 { ctxt.Andptr[0] = byte(1<<6 | reg[t]<<0 | r<<3) ctxt.Andptr[1] = byte(v) ctxt.Andptr = ctxt.Andptr[2:] return } ctxt.Andptr[0] = byte(2<<6 | reg[t]<<0 | r<<3) ctxt.Andptr = ctxt.Andptr[1:] goto putrelv } goto bad putrelv: if rel.Siz != 0 { var r *obj.Reloc 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", Dconv(p, 0, a)) return } const ( E = 0xff ) var ymovtab = []uint8{ /* push */ APUSHL, Ycs, Ynone, 0, 0x0e, E, 0, 0, APUSHL, Yss, Ynone, 0, 0x16, E, 0, 0, APUSHL, Yds, Ynone, 0, 0x1e, E, 0, 0, APUSHL, Yes, Ynone, 0, 0x06, E, 0, 0, APUSHL, Yfs, Ynone, 0, 0x0f, 0xa0, E, 0, APUSHL, Ygs, Ynone, 0, 0x0f, 0xa8, E, 0, APUSHW, Ycs, Ynone, 0, Pe, 0x0e, E, 0, APUSHW, Yss, Ynone, 0, Pe, 0x16, E, 0, APUSHW, Yds, Ynone, 0, Pe, 0x1e, E, 0, APUSHW, Yes, Ynone, 0, Pe, 0x06, E, 0, APUSHW, Yfs, Ynone, 0, Pe, 0x0f, 0xa0, E, APUSHW, Ygs, Ynone, 0, Pe, 0x0f, 0xa8, E, /* pop */ APOPL, Ynone, Yds, 0, 0x1f, E, 0, 0, APOPL, Ynone, Yes, 0, 0x07, E, 0, 0, APOPL, Ynone, Yss, 0, 0x17, E, 0, 0, APOPL, Ynone, Yfs, 0, 0x0f, 0xa1, E, 0, APOPL, Ynone, Ygs, 0, 0x0f, 0xa9, E, 0, APOPW, Ynone, Yds, 0, Pe, 0x1f, E, 0, APOPW, Ynone, Yes, 0, Pe, 0x07, E, 0, APOPW, Ynone, Yss, 0, Pe, 0x17, E, 0, APOPW, Ynone, Yfs, 0, Pe, 0x0f, 0xa1, E, APOPW, Ynone, Ygs, 0, Pe, 0x0f, 0xa9, E, /* mov seg */ AMOVW, Yes, Yml, 1, 0x8c, 0, 0, 0, AMOVW, Ycs, Yml, 1, 0x8c, 1, 0, 0, AMOVW, Yss, Yml, 1, 0x8c, 2, 0, 0, AMOVW, Yds, Yml, 1, 0x8c, 3, 0, 0, AMOVW, Yfs, Yml, 1, 0x8c, 4, 0, 0, AMOVW, Ygs, Yml, 1, 0x8c, 5, 0, 0, AMOVW, Yml, Yes, 2, 0x8e, 0, 0, 0, AMOVW, Yml, Ycs, 2, 0x8e, 1, 0, 0, AMOVW, Yml, Yss, 2, 0x8e, 2, 0, 0, AMOVW, Yml, Yds, 2, 0x8e, 3, 0, 0, AMOVW, Yml, Yfs, 2, 0x8e, 4, 0, 0, AMOVW, Yml, Ygs, 2, 0x8e, 5, 0, 0, /* mov cr */ AMOVL, Ycr0, Yml, 3, 0x0f, 0x20, 0, 0, AMOVL, Ycr2, Yml, 3, 0x0f, 0x20, 2, 0, AMOVL, Ycr3, Yml, 3, 0x0f, 0x20, 3, 0, AMOVL, Ycr4, Yml, 3, 0x0f, 0x20, 4, 0, AMOVL, Yml, Ycr0, 4, 0x0f, 0x22, 0, 0, AMOVL, Yml, Ycr2, 4, 0x0f, 0x22, 2, 0, AMOVL, Yml, Ycr3, 4, 0x0f, 0x22, 3, 0, AMOVL, Yml, Ycr4, 4, 0x0f, 0x22, 4, 0, /* mov dr */ AMOVL, Ydr0, Yml, 3, 0x0f, 0x21, 0, 0, AMOVL, Ydr6, Yml, 3, 0x0f, 0x21, 6, 0, AMOVL, Ydr7, Yml, 3, 0x0f, 0x21, 7, 0, AMOVL, Yml, Ydr0, 4, 0x0f, 0x23, 0, 0, AMOVL, Yml, Ydr6, 4, 0x0f, 0x23, 6, 0, AMOVL, Yml, Ydr7, 4, 0x0f, 0x23, 7, 0, /* mov tr */ AMOVL, Ytr6, Yml, 3, 0x0f, 0x24, 6, 0, AMOVL, Ytr7, Yml, 3, 0x0f, 0x24, 7, 0, AMOVL, Yml, Ytr6, 4, 0x0f, 0x26, 6, E, AMOVL, Yml, Ytr7, 4, 0x0f, 0x26, 7, E, /* lgdt, sgdt, lidt, sidt */ AMOVL, Ym, Ygdtr, 4, 0x0f, 0x01, 2, 0, AMOVL, Ygdtr, Ym, 3, 0x0f, 0x01, 0, 0, AMOVL, Ym, Yidtr, 4, 0x0f, 0x01, 3, 0, AMOVL, Yidtr, Ym, 3, 0x0f, 0x01, 1, 0, /* lldt, sldt */ AMOVW, Yml, Yldtr, 4, 0x0f, 0x00, 2, 0, AMOVW, Yldtr, Yml, 3, 0x0f, 0x00, 0, 0, /* lmsw, smsw */ AMOVW, Yml, Ymsw, 4, 0x0f, 0x01, 6, 0, AMOVW, Ymsw, Yml, 3, 0x0f, 0x01, 4, 0, /* ltr, str */ AMOVW, Yml, Ytask, 4, 0x0f, 0x00, 3, 0, AMOVW, Ytask, Yml, 3, 0x0f, 0x00, 1, 0, /* load full pointer */ AMOVL, Yml, Ycol, 5, 0, 0, 0, 0, AMOVW, Yml, Ycol, 5, Pe, 0, 0, 0, /* double shift */ ASHLL, Ycol, Yml, 6, 0xa4, 0xa5, 0, 0, ASHRL, Ycol, Yml, 6, 0xac, 0xad, 0, 0, /* extra imul */ AIMULW, Yml, Yrl, 7, Pq, 0xaf, 0, 0, AIMULL, Yml, Yrl, 7, Pm, 0xaf, 0, 0, /* load TLS base pointer */ AMOVL, Ytls, Yrl, 8, 0, 0, 0, 0, 0, } // byteswapreg returns a byte-addressable register (AX, BX, CX, DX) // which is not referenced in a->type. // 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 { var cana int var canb int var canc int var cand int cand = 1 canc = cand canb = canc cana = canb switch a.Type { case D_NONE: cand = 0 cana = cand case D_AX, D_AL, D_AH, D_INDIR + D_AX: cana = 0 case D_BX, D_BL, D_BH, D_INDIR + D_BX: canb = 0 case D_CX, D_CL, D_CH, D_INDIR + D_CX: canc = 0 case D_DX, D_DL, D_DH, D_INDIR + D_DX: cand = 0 break } switch a.Index { case D_AX: cana = 0 case D_BX: canb = 0 case D_CX: canc = 0 case D_DX: cand = 0 break } if cana != 0 { return D_AX } if canb != 0 { return D_BX } if canc != 0 { return D_CX } if cand != 0 { return D_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.Type) == from { p.From.Type = int16(to) p.Ft = 0 } if int(p.To.Type) == from { p.To.Type = int16(to) p.Tt = 0 } if int(p.From.Index) == from { p.From.Index = uint8(to) p.Ft = 0 } if int(p.To.Index) == from { p.To.Index = uint8(to) p.Tt = 0 } from += D_INDIR if int(p.From.Type) == from { p.From.Type = int16(to + D_INDIR) p.Ft = 0 } if int(p.To.Type) == from { p.To.Type = int16(to + D_INDIR) 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:] } break } ctxt.Andptr[0] = byte(op) ctxt.Andptr = ctxt.Andptr[1:] return z } func doasm(ctxt *obj.Link, p *obj.Prog) { var o *Optab var q *obj.Prog var pp obj.Prog var t []byte var z int var op int var ft int var tt int var breg int var v int32 var pre int32 var rel obj.Reloc var r *obj.Reloc var a *obj.Addr 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(&p.From)) } if p.Tt == 0 { p.Tt = uint8(oclass(&p.To)) } ft = int(p.Ft) * Ymax tt = int(p.Tt) * Ymax o = &optab[p.As] t = o.ytab if t == nil { ctxt.Diag("asmins: noproto %v", p) return } for z = 0; t[0] != 0; (func() { z += int(t[3]); t = t[4:] })() { if ycover[ft+int(t[0])] != 0 { if ycover[tt+int(t[1])] != 0 { goto found } } } goto domov found: 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 t[2] { default: ctxt.Diag("asmins: unknown z %d %v", t[2], 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.Type]) case Zm_r: ctxt.Andptr[0] = byte(op) ctxt.Andptr = ctxt.Andptr[1:] asmand(ctxt, p, &p.From, reg[p.To.Type]) 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.Type]) case Zm_r_xm: mediaop(ctxt, o, op, int(t[3]), z) asmand(ctxt, p, &p.From, reg[p.To.Type]) case Zm_r_i_xm: mediaop(ctxt, o, op, int(t[3]), z) asmand(ctxt, p, &p.From, reg[p.To.Type]) 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.Type]) 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 != D_ADDR { ctxt.Diag("asmins: Zaut sb type ADDR") } p.From.Type = int16(p.From.Index) p.From.Index = D_NONE p.Ft = 0 asmand(ctxt, p, &p.From, reg[p.To.Type]) p.From.Index = uint8(p.From.Type) p.From.Type = D_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.Type]) case Zr_m_xm: mediaop(ctxt, o, op, int(t[3]), z) asmand(ctxt, p, &p.To, reg[p.From.Type]) case Zr_m_i_xm: mediaop(ctxt, o, op, int(t[3]), z) asmand(ctxt, p, &p.To, reg[p.From.Type]) 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 t[2] == 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.Type]) 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.Type]) 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.Type]) ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil)) ctxt.Andptr = ctxt.Andptr[1:] case Z_il, Zil_: if t[2] == 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 t[2] == 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.Type]) 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.Type]) ctxt.Andptr = ctxt.Andptr[1:] case Zrp_: ctxt.Andptr[0] = byte(op + reg[p.From.Type]) 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.Type]) 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 t[2] != 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 t[2] == Zloop { ctxt.Diag("loop too far: %v", p) } else { v -= 5 - 2 if t[2] == 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 t[2] == Zloop { ctxt.Diag("loop too far: %v", p) } else { if t[2] == 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 t[2] == 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 domov: for t = []byte(ymovtab); t[0] != 0; t = t[8:] { if p.As == int16(t[0]) { if ycover[ft+int(t[1])] != 0 { if ycover[tt+int(t[2])] != 0 { goto mfound } } } } /* * 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.Type) if z >= D_BP && z <= D_DI { breg = byteswapreg(ctxt, &p.To) if breg != D_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, D_AX) doasm(ctxt, &pp) ctxt.Andptr[0] = byte(0x90 + reg[z]) ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */ } return } z = int(p.To.Type) if z >= D_BP && z <= D_DI { breg = byteswapreg(ctxt, &p.From) if breg != D_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, D_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=%x from=%x to=%x %v", t[2], uint16(p.From.Type), uint16(p.To.Type), p) return mfound: 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 D_DS: ctxt.Andptr[0] = 0xc5 ctxt.Andptr = ctxt.Andptr[1:] case D_SS: ctxt.Andptr[0] = 0x0f ctxt.Andptr = ctxt.Andptr[1:] ctxt.Andptr[0] = 0xb2 ctxt.Andptr = ctxt.Andptr[1:] case D_ES: ctxt.Andptr[0] = 0xc4 ctxt.Andptr = ctxt.Andptr[1:] case D_FS: ctxt.Andptr[0] = 0x0f ctxt.Andptr = ctxt.Andptr[1:] ctxt.Andptr[0] = 0xb4 ctxt.Andptr = ctxt.Andptr[1:] case D_GS: ctxt.Andptr[0] = 0x0f ctxt.Andptr = ctxt.Andptr[1:] ctxt.Andptr[0] = 0xb5 ctxt.Andptr = ctxt.Andptr[1:] break } asmand(ctxt, p, &p.From, reg[p.To.Type]) case 6: /* double shift */ z = int(p.From.Type) switch z { default: goto bad case D_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 D_CL, D_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]) break } 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.Type]) // 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 = D_INDIR + D_GS pp.From.Offset = 0 pp.From.Index = D_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.Type]) case obj.Hplan9: if ctxt.Plan9privates == nil { ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0) } pp.From = obj.Addr{} pp.From.Type = D_EXTERN pp.From.Sym = ctxt.Plan9privates pp.From.Offset = 0 pp.From.Index = D_NONE ctxt.Andptr[0] = 0x8B ctxt.Andptr = ctxt.Andptr[1:] asmand(ctxt, p, &pp.From, reg[p.To.Type]) // Windows TLS base is always 0x14(FS). case obj.Hwindows: pp.From = p.From pp.From.Type = D_INDIR + D_FS pp.From.Offset = 0x14 pp.From.Index = D_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.Type]) break } break } } 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) { var r *obj.Reloc ctxt.Andptr = ctxt.And[:] if p.As == 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 ARET: copy(ctxt.Andptr, naclret) ctxt.Andptr = ctxt.Andptr[len(naclret):] return case ACALL, AJMP: if D_AX <= p.To.Type && p.To.Type <= D_DI { ctxt.Andptr[0] = 0x83 ctxt.Andptr = ctxt.Andptr[1:] ctxt.Andptr[0] = byte(0xe0 | (p.To.Type - D_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") } }