This source file includes following definitions.
- fillnop
- naclpad
- span8
- instinit
- prefixof
- oclass
- asmidx
- put4
- relput4
- vaddr
- asmand
- byteswapreg
- subreg
- mediaop
- doasm
- asmins
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
#include "../cmd/8l/8.out.h"
#include "../pkg/runtime/stack.h"
enum
{
MaxAlign = 32,
FuncAlign = 16
};
extern char *anames6[];
typedef struct Optab Optab;
struct Optab
{
short as;
uchar* ytab;
uchar prefix;
uchar op[13];
};
enum
{
Yxxx = 0,
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,
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,
};
static uchar ycover[Ymax*Ymax];
static char reg[D_NONE];
static void asmins(Link *ctxt, Prog *p);
static uchar ynone[] =
{
Ynone, Ynone, Zlit, 1,
0
};
static uchar ytext[] =
{
Ymb, Yi32, Zpseudo,1,
0
};
static uchar ynop[] =
{
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
};
static uchar yfuncdata[] =
{
Yi32, Ym, Zpseudo, 0,
0
};
static uchar ypcdata[] =
{
Yi32, Yi32, Zpseudo, 0,
0,
};
static uchar yxorb[] =
{
Yi32, Yal, Zib_, 1,
Yi32, Ymb, Zibo_m, 2,
Yrb, Ymb, Zr_m, 1,
Ymb, Yrb, Zm_r, 1,
0
};
static uchar yxorl[] =
{
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
};
static uchar yaddl[] =
{
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
};
static uchar yincb[] =
{
Ynone, Ymb, Zo_m, 2,
0
};
static uchar yincl[] =
{
Ynone, Yrl, Z_rp, 1,
Ynone, Yml, Zo_m, 2,
0
};
static uchar ycmpb[] =
{
Yal, Yi32, Z_ib, 1,
Ymb, Yi32, Zm_ibo, 2,
Ymb, Yrb, Zm_r, 1,
Yrb, Ymb, Zr_m, 1,
0
};
static uchar ycmpl[] =
{
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
};
static uchar yshb[] =
{
Yi1, Ymb, Zo_m, 2,
Yi32, Ymb, Zibo_m, 2,
Ycx, Ymb, Zo_m, 2,
0
};
static uchar yshl[] =
{
Yi1, Yml, Zo_m, 2,
Yi32, Yml, Zibo_m, 2,
Ycl, Yml, Zo_m, 2,
Ycx, Yml, Zo_m, 2,
0
};
static uchar ytestb[] =
{
Yi32, Yal, Zib_, 1,
Yi32, Ymb, Zibo_m, 2,
Yrb, Ymb, Zr_m, 1,
Ymb, Yrb, Zm_r, 1,
0
};
static uchar ytestl[] =
{
Yi32, Yax, Zil_, 1,
Yi32, Yml, Zilo_m, 2,
Yrl, Yml, Zr_m, 1,
Yml, Yrl, Zm_r, 1,
0
};
static uchar ymovb[] =
{
Yrb, Ymb, Zr_m, 1,
Ymb, Yrb, Zm_r, 1,
Yi32, Yrb, Zib_rp, 1,
Yi32, Ymb, Zibo_m, 2,
0
};
static uchar ymovw[] =
{
Yrl, Yml, Zr_m, 1,
Yml, Yrl, Zm_r, 1,
Yi0, Yrl, Zclr, 1+2,
Yi32, Yrl, Zil_rp, 1,
Yi32, Yml, Zilo_m, 2,
Yiauto, Yrl, Zaut_r, 1,
0
};
static uchar ymovl[] =
{
Yrl, Yml, Zr_m, 1,
Yml, Yrl, Zm_r, 1,
Yi0, Yrl, Zclr, 1+2,
Yi32, Yrl, Zil_rp, 1,
Yi32, Yml, Zilo_m, 2,
Yml, Yxr, Zm_r_xm, 2,
Yxr, Yml, Zr_m_xm, 2,
Yiauto, Yrl, Zaut_r, 1,
0
};
static uchar ymovq[] =
{
Yml, Yxr, Zm_r_xm, 2,
0
};
static uchar ym_rl[] =
{
Ym, Yrl, Zm_r, 1,
0
};
static uchar yrl_m[] =
{
Yrl, Ym, Zr_m, 1,
0
};
static uchar ymb_rl[] =
{
Ymb, Yrl, Zm_r, 1,
0
};
static uchar yml_rl[] =
{
Yml, Yrl, Zm_r, 1,
0
};
static uchar yrb_mb[] =
{
Yrb, Ymb, Zr_m, 1,
0
};
static uchar yrl_ml[] =
{
Yrl, Yml, Zr_m, 1,
0
};
static uchar yml_mb[] =
{
Yrb, Ymb, Zr_m, 1,
Ymb, Yrb, Zm_r, 1,
0
};
static uchar yxchg[] =
{
Yax, Yrl, Z_rp, 1,
Yrl, Yax, Zrp_, 1,
Yrl, Yml, Zr_m, 1,
Yml, Yrl, Zm_r, 1,
0
};
static uchar ydivl[] =
{
Yml, Ynone, Zm_o, 2,
0
};
static uchar ydivb[] =
{
Ymb, Ynone, Zm_o, 2,
0
};
static uchar yimul[] =
{
Yml, Ynone, Zm_o, 2,
Yi8, Yrl, Zib_rr, 1,
Yi32, Yrl, Zil_rr, 1,
0
};
static uchar ybyte[] =
{
Yi32, Ynone, Zbyte, 1,
0
};
static uchar yin[] =
{
Yi32, Ynone, Zib_, 1,
Ynone, Ynone, Zlit, 1,
0
};
static uchar yint[] =
{
Yi32, Ynone, Zib_, 1,
0
};
static uchar ypushl[] =
{
Yrl, Ynone, Zrp_, 1,
Ym, Ynone, Zm_o, 2,
Yi8, Ynone, Zib_, 1,
Yi32, Ynone, Zil_, 1,
0
};
static uchar ypopl[] =
{
Ynone, Yrl, Z_rp, 1,
Ynone, Ym, Zo_m, 2,
0
};
static uchar ybswap[] =
{
Ynone, Yrl, Z_rp, 1,
0,
};
static uchar yscond[] =
{
Ynone, Ymb, Zo_m, 2,
0
};
static uchar yjcond[] =
{
Ynone, Ybr, Zbr, 0,
Yi0, Ybr, Zbr, 0,
Yi1, Ybr, Zbr, 1,
0
};
static uchar yloop[] =
{
Ynone, Ybr, Zloop, 1,
0
};
static uchar ycall[] =
{
Ynone, Yml, Zcallindreg, 0,
Yrx, Yrx, Zcallindreg, 2,
Ynone, Ycol, Zcallind, 2,
Ynone, Ybr, Zcall, 0,
Ynone, Yi32, Zcallcon, 1,
0
};
static uchar yduff[] =
{
Ynone, Yi32, Zcall, 1,
0
};
static uchar yjmp[] =
{
Ynone, Yml, Zo_m, 2,
Ynone, Ybr, Zjmp, 0,
Ynone, Yi32, Zjmpcon, 1,
0
};
static uchar yfmvd[] =
{
Ym, Yf0, Zm_o, 2,
Yf0, Ym, Zo_m, 2,
Yrf, Yf0, Zm_o, 2,
Yf0, Yrf, Zo_m, 2,
0
};
static uchar yfmvdp[] =
{
Yf0, Ym, Zo_m, 2,
Yf0, Yrf, Zo_m, 2,
0
};
static uchar yfmvf[] =
{
Ym, Yf0, Zm_o, 2,
Yf0, Ym, Zo_m, 2,
0
};
static uchar yfmvx[] =
{
Ym, Yf0, Zm_o, 2,
0
};
static uchar yfmvp[] =
{
Yf0, Ym, Zo_m, 2,
0
};
static uchar yfcmv[] =
{
Yrf, Yf0, Zm_o, 2,
0
};
static uchar yfadd[] =
{
Ym, Yf0, Zm_o, 2,
Yrf, Yf0, Zm_o, 2,
Yf0, Yrf, Zo_m, 2,
0
};
static uchar yfaddp[] =
{
Yf0, Yrf, Zo_m, 2,
0
};
static uchar yfxch[] =
{
Yf0, Yrf, Zo_m, 2,
Yrf, Yf0, Zm_o, 2,
0
};
static uchar ycompp[] =
{
Yf0, Yrf, Zo_m, 2,
0
};
static uchar ystsw[] =
{
Ynone, Ym, Zo_m, 2,
Ynone, Yax, Zlit, 1,
0
};
static uchar ystcw[] =
{
Ynone, Ym, Zo_m, 2,
Ym, Ynone, Zm_o, 2,
0
};
static uchar ysvrs[] =
{
Ynone, Ym, Zo_m, 2,
Ym, Ynone, Zm_o, 2,
0
};
static uchar ymskb[] =
{
Yxr, Yrl, Zm_r_xm, 2,
Ymr, Yrl, Zm_r_xm, 1,
0
};
static uchar yxm[] =
{
Yxm, Yxr, Zm_r_xm, 1,
0
};
static uchar yxcvm1[] =
{
Yxm, Yxr, Zm_r_xm, 2,
Yxm, Ymr, Zm_r_xm, 2,
0
};
static uchar yxcvm2[] =
{
Yxm, Yxr, Zm_r_xm, 2,
Ymm, Yxr, Zm_r_xm, 2,
0
};
static uchar yxmq[] =
{
Yxm, Yxr, Zm_r_xm, 2,
0
};
static uchar yxr[] =
{
Yxr, Yxr, Zm_r_xm, 1,
0
};
static uchar yxr_ml[] =
{
Yxr, Yml, Zr_m_xm, 1,
0
};
static uchar yxcmp[] =
{
Yxm, Yxr, Zm_r_xm, 1,
0
};
static uchar yxcmpi[] =
{
Yxm, Yxr, Zm_r_i_xm, 2,
0
};
static uchar yxmov[] =
{
Yxm, Yxr, Zm_r_xm, 1,
Yxr, Yxm, Zr_m_xm, 1,
0
};
static uchar yxcvfl[] =
{
Yxm, Yrl, Zm_r_xm, 1,
0
};
static uchar yxcvlf[] =
{
Yml, Yxr, Zm_r_xm, 1,
0
};
static uchar yxrrl[] =
{
Yxr, Yrl, Zm_r, 1,
0
};
static uchar yprefetch[] =
{
Ym, Ynone, Zm_o, 2,
0,
};
static uchar yaes[] =
{
Yxm, Yxr, Zlitm_r, 2,
0
};
static uchar yinsrd[] =
{
Yml, Yxr, Zibm_r, 2,
0
};
static uchar ymshufb[] =
{
Yxm, Yxr, Zm2_r, 2,
0
};
static Optab optab[] =
{
{ AXXX },
{ AAAA, ynone, Px, 0x37 },
{ AAAD, ynone, Px, 0xd5,0x0a },
{ AAAM, ynone, Px, 0xd4,0x0a },
{ AAAS, ynone, Px, 0x3f },
{ AADCB, yxorb, Pb, 0x14,0x80,(02),0x10,0x10 },
{ AADCL, yxorl, Px, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
{ AADCW, yxorl, Pe, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
{ AADDB, yxorb, Px, 0x04,0x80,(00),0x00,0x02 },
{ AADDL, yaddl, Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
{ AADDW, yaddl, Pe, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
{ AADJSP },
{ AANDB, yxorb, Pb, 0x24,0x80,(04),0x20,0x22 },
{ AANDL, yxorl, Px, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
{ AANDW, yxorl, Pe, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
{ AARPL, yrl_ml, Px, 0x63 },
{ ABOUNDL, yrl_m, Px, 0x62 },
{ ABOUNDW, yrl_m, Pe, 0x62 },
{ ABSFL, yml_rl, Pm, 0xbc },
{ ABSFW, yml_rl, Pq, 0xbc },
{ ABSRL, yml_rl, Pm, 0xbd },
{ ABSRW, yml_rl, Pq, 0xbd },
{ ABTL, yml_rl, Pm, 0xa3 },
{ ABTW, yml_rl, Pq, 0xa3 },
{ ABTCL, yml_rl, Pm, 0xbb },
{ ABTCW, yml_rl, Pq, 0xbb },
{ ABTRL, yml_rl, Pm, 0xb3 },
{ ABTRW, yml_rl, Pq, 0xb3 },
{ ABTSL, yml_rl, Pm, 0xab },
{ ABTSW, yml_rl, Pq, 0xab },
{ ABYTE, ybyte, Px, 1 },
{ ACALL, ycall, Px, 0xff,(02),0xff,(0x15),0xe8 },
{ ACLC, ynone, Px, 0xf8 },
{ ACLD, ynone, Px, 0xfc },
{ ACLI, ynone, Px, 0xfa },
{ ACLTS, ynone, Pm, 0x06 },
{ ACMC, ynone, Px, 0xf5 },
{ ACMPB, ycmpb, Pb, 0x3c,0x80,(07),0x38,0x3a },
{ ACMPL, ycmpl, Px, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
{ ACMPW, ycmpl, Pe, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
{ ACMPSB, ynone, Pb, 0xa6 },
{ ACMPSL, ynone, Px, 0xa7 },
{ ACMPSW, ynone, Pe, 0xa7 },
{ ADAA, ynone, Px, 0x27 },
{ ADAS, ynone, Px, 0x2f },
{ ADATA },
{ ADECB, yincb, Pb, 0xfe,(01) },
{ ADECL, yincl, Px, 0x48,0xff,(01) },
{ ADECW, yincl, Pe, 0x48,0xff,(01) },
{ ADIVB, ydivb, Pb, 0xf6,(06) },
{ ADIVL, ydivl, Px, 0xf7,(06) },
{ ADIVW, ydivl, Pe, 0xf7,(06) },
{ AENTER },
{ AGLOBL },
{ AGOK },
{ AHISTORY },
{ AHLT, ynone, Px, 0xf4 },
{ AIDIVB, ydivb, Pb, 0xf6,(07) },
{ AIDIVL, ydivl, Px, 0xf7,(07) },
{ AIDIVW, ydivl, Pe, 0xf7,(07) },
{ AIMULB, ydivb, Pb, 0xf6,(05) },
{ AIMULL, yimul, Px, 0xf7,(05),0x6b,0x69 },
{ AIMULW, yimul, Pe, 0xf7,(05),0x6b,0x69 },
{ AINB, yin, Pb, 0xe4,0xec },
{ AINL, yin, Px, 0xe5,0xed },
{ AINW, yin, Pe, 0xe5,0xed },
{ AINCB, yincb, Pb, 0xfe,(00) },
{ AINCL, yincl, Px, 0x40,0xff,(00) },
{ AINCW, yincl, Pe, 0x40,0xff,(00) },
{ AINSB, ynone, Pb, 0x6c },
{ AINSL, ynone, Px, 0x6d },
{ AINSW, ynone, Pe, 0x6d },
{ AINT, yint, Px, 0xcd },
{ AINTO, ynone, Px, 0xce },
{ AIRETL, ynone, Px, 0xcf },
{ AIRETW, ynone, Pe, 0xcf },
{ AJCC, yjcond, Px, 0x73,0x83,(00) },
{ AJCS, yjcond, Px, 0x72,0x82 },
{ AJCXZL, yloop, Px, 0xe3 },
{ AJCXZW, yloop, Px, 0xe3 },
{ AJEQ, yjcond, Px, 0x74,0x84 },
{ AJGE, yjcond, Px, 0x7d,0x8d },
{ AJGT, yjcond, Px, 0x7f,0x8f },
{ AJHI, yjcond, Px, 0x77,0x87 },
{ AJLE, yjcond, Px, 0x7e,0x8e },
{ AJLS, yjcond, Px, 0x76,0x86 },
{ AJLT, yjcond, Px, 0x7c,0x8c },
{ AJMI, yjcond, Px, 0x78,0x88 },
{ AJMP, yjmp, Px, 0xff,(04),0xeb,0xe9 },
{ AJNE, yjcond, Px, 0x75,0x85 },
{ AJOC, yjcond, Px, 0x71,0x81,(00) },
{ AJOS, yjcond, Px, 0x70,0x80,(00) },
{ AJPC, yjcond, Px, 0x7b,0x8b },
{ AJPL, yjcond, Px, 0x79,0x89 },
{ AJPS, yjcond, Px, 0x7a,0x8a },
{ ALAHF, ynone, Px, 0x9f },
{ ALARL, yml_rl, Pm, 0x02 },
{ ALARW, yml_rl, Pq, 0x02 },
{ ALEAL, ym_rl, Px, 0x8d },
{ ALEAW, ym_rl, Pe, 0x8d },
{ ALEAVEL, ynone, Px, 0xc9 },
{ ALEAVEW, ynone, Pe, 0xc9 },
{ ALOCK, ynone, Px, 0xf0 },
{ ALODSB, ynone, Pb, 0xac },
{ ALODSL, ynone, Px, 0xad },
{ ALODSW, ynone, Pe, 0xad },
{ ALONG, ybyte, Px, 4 },
{ ALOOP, yloop, Px, 0xe2 },
{ ALOOPEQ, yloop, Px, 0xe1 },
{ ALOOPNE, yloop, Px, 0xe0 },
{ ALSLL, yml_rl, Pm, 0x03 },
{ ALSLW, yml_rl, Pq, 0x03 },
{ AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) },
{ AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e,0 },
{ AMOVW, ymovw, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),0 },
{ AMOVQ, ymovq, Pf3, 0x7e },
{ AMOVBLSX, ymb_rl, Pm, 0xbe },
{ AMOVBLZX, ymb_rl, Pm, 0xb6 },
{ AMOVBWSX, ymb_rl, Pq, 0xbe },
{ AMOVBWZX, ymb_rl, Pq, 0xb6 },
{ AMOVWLSX, yml_rl, Pm, 0xbf },
{ AMOVWLZX, yml_rl, Pm, 0xb7 },
{ AMOVSB, ynone, Pb, 0xa4 },
{ AMOVSL, ynone, Px, 0xa5 },
{ AMOVSW, ynone, Pe, 0xa5 },
{ AMULB, ydivb, Pb, 0xf6,(04) },
{ AMULL, ydivl, Px, 0xf7,(04) },
{ AMULW, ydivl, Pe, 0xf7,(04) },
{ ANAME },
{ ANEGB, yscond, Px, 0xf6,(03) },
{ ANEGL, yscond, Px, 0xf7,(03) },
{ ANEGW, yscond, Pe, 0xf7,(03) },
{ ANOP, ynop, Px,0,0 },
{ ANOTB, yscond, Px, 0xf6,(02) },
{ ANOTL, yscond, Px, 0xf7,(02) },
{ ANOTW, yscond, Pe, 0xf7,(02) },
{ AORB, yxorb, Pb, 0x0c,0x80,(01),0x08,0x0a },
{ AORL, yxorl, Px, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
{ AORW, yxorl, Pe, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
{ AOUTB, yin, Pb, 0xe6,0xee },
{ AOUTL, yin, Px, 0xe7,0xef },
{ AOUTW, yin, Pe, 0xe7,0xef },
{ AOUTSB, ynone, Pb, 0x6e },
{ AOUTSL, ynone, Px, 0x6f },
{ AOUTSW, ynone, Pe, 0x6f },
{ APAUSE, ynone, Px, 0xf3,0x90 },
{ APOPAL, ynone, Px, 0x61 },
{ APOPAW, ynone, Pe, 0x61 },
{ APOPFL, ynone, Px, 0x9d },
{ APOPFW, ynone, Pe, 0x9d },
{ APOPL, ypopl, Px, 0x58,0x8f,(00) },
{ APOPW, ypopl, Pe, 0x58,0x8f,(00) },
{ APUSHAL, ynone, Px, 0x60 },
{ APUSHAW, ynone, Pe, 0x60 },
{ APUSHFL, ynone, Px, 0x9c },
{ APUSHFW, ynone, Pe, 0x9c },
{ APUSHL, ypushl, Px, 0x50,0xff,(06),0x6a,0x68 },
{ APUSHW, ypushl, Pe, 0x50,0xff,(06),0x6a,0x68 },
{ ARCLB, yshb, Pb, 0xd0,(02),0xc0,(02),0xd2,(02) },
{ ARCLL, yshl, Px, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
{ ARCLW, yshl, Pe, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
{ ARCRB, yshb, Pb, 0xd0,(03),0xc0,(03),0xd2,(03) },
{ ARCRL, yshl, Px, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) },
{ ARCRW, yshl, Pe, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) },
{ AREP, ynone, Px, 0xf3 },
{ AREPN, ynone, Px, 0xf2 },
{ ARET, ynone, Px, 0xc3 },
{ AROLB, yshb, Pb, 0xd0,(00),0xc0,(00),0xd2,(00) },
{ AROLL, yshl, Px, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) },
{ AROLW, yshl, Pe, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) },
{ ARORB, yshb, Pb, 0xd0,(01),0xc0,(01),0xd2,(01) },
{ ARORL, yshl, Px, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
{ ARORW, yshl, Pe, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
{ ASAHF, ynone, Px, 0x9e },
{ ASALB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
{ ASALL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
{ ASALW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
{ ASARB, yshb, Pb, 0xd0,(07),0xc0,(07),0xd2,(07) },
{ ASARL, yshl, Px, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) },
{ ASARW, yshl, Pe, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) },
{ ASBBB, yxorb, Pb, 0x1c,0x80,(03),0x18,0x1a },
{ ASBBL, yxorl, Px, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
{ ASBBW, yxorl, Pe, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
{ ASCASB, ynone, Pb, 0xae },
{ ASCASL, ynone, Px, 0xaf },
{ ASCASW, ynone, Pe, 0xaf },
{ ASETCC, yscond, Pm, 0x93,(00) },
{ ASETCS, yscond, Pm, 0x92,(00) },
{ ASETEQ, yscond, Pm, 0x94,(00) },
{ ASETGE, yscond, Pm, 0x9d,(00) },
{ ASETGT, yscond, Pm, 0x9f,(00) },
{ ASETHI, yscond, Pm, 0x97,(00) },
{ ASETLE, yscond, Pm, 0x9e,(00) },
{ ASETLS, yscond, Pm, 0x96,(00) },
{ ASETLT, yscond, Pm, 0x9c,(00) },
{ ASETMI, yscond, Pm, 0x98,(00) },
{ ASETNE, yscond, Pm, 0x95,(00) },
{ ASETOC, yscond, Pm, 0x91,(00) },
{ ASETOS, yscond, Pm, 0x90,(00) },
{ ASETPC, yscond, Pm, 0x96,(00) },
{ ASETPL, yscond, Pm, 0x99,(00) },
{ ASETPS, yscond, Pm, 0x9a,(00) },
{ ACDQ, ynone, Px, 0x99 },
{ ACWD, ynone, Pe, 0x99 },
{ ASHLB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
{ ASHLL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
{ ASHLW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) },
{ ASHRB, yshb, Pb, 0xd0,(05),0xc0,(05),0xd2,(05) },
{ ASHRL, yshl, Px, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
{ ASHRW, yshl, Pe, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
{ ASTC, ynone, Px, 0xf9 },
{ ASTD, ynone, Px, 0xfd },
{ ASTI, ynone, Px, 0xfb },
{ ASTOSB, ynone, Pb, 0xaa },
{ ASTOSL, ynone, Px, 0xab },
{ ASTOSW, ynone, Pe, 0xab },
{ ASUBB, yxorb, Pb, 0x2c,0x80,(05),0x28,0x2a },
{ ASUBL, yaddl, Px, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
{ ASUBW, yaddl, Pe, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
{ ASYSCALL, ynone, Px, 0xcd,100 },
{ ATESTB, ytestb, Pb, 0xa8,0xf6,(00),0x84,0x84 },
{ ATESTL, ytestl, Px, 0xa9,0xf7,(00),0x85,0x85 },
{ ATESTW, ytestl, Pe, 0xa9,0xf7,(00),0x85,0x85 },
{ ATEXT, ytext, Px },
{ AVERR, ydivl, Pm, 0x00,(04) },
{ AVERW, ydivl, Pm, 0x00,(05) },
{ AWAIT, ynone, Px, 0x9b },
{ AWORD, ybyte, Px, 2 },
{ AXCHGB, yml_mb, Pb, 0x86,0x86 },
{ AXCHGL, yxchg, Px, 0x90,0x90,0x87,0x87 },
{ AXCHGW, yxchg, Pe, 0x90,0x90,0x87,0x87 },
{ AXLAT, ynone, Px, 0xd7 },
{ AXORB, yxorb, Pb, 0x34,0x80,(06),0x30,0x32 },
{ AXORL, yxorl, Px, 0x83,(06),0x35,0x81,(06),0x31,0x33 },
{ AXORW, yxorl, Pe, 0x83,(06),0x35,0x81,(06),0x31,0x33 },
{ AFMOVB, yfmvx, Px, 0xdf,(04) },
{ AFMOVBP, yfmvp, Px, 0xdf,(06) },
{ AFMOVD, yfmvd, Px, 0xdd,(00),0xdd,(02),0xd9,(00),0xdd,(02) },
{ AFMOVDP, yfmvdp, Px, 0xdd,(03),0xdd,(03) },
{ AFMOVF, yfmvf, Px, 0xd9,(00),0xd9,(02) },
{ AFMOVFP, yfmvp, Px, 0xd9,(03) },
{ AFMOVL, yfmvf, Px, 0xdb,(00),0xdb,(02) },
{ AFMOVLP, yfmvp, Px, 0xdb,(03) },
{ AFMOVV, yfmvx, Px, 0xdf,(05) },
{ AFMOVVP, yfmvp, Px, 0xdf,(07) },
{ AFMOVW, yfmvf, Px, 0xdf,(00),0xdf,(02) },
{ AFMOVWP, yfmvp, Px, 0xdf,(03) },
{ AFMOVX, yfmvx, Px, 0xdb,(05) },
{ AFMOVXP, yfmvp, Px, 0xdb,(07) },
{ AFCOMB },
{ AFCOMBP },
{ AFCOMD, yfadd, Px, 0xdc,(02),0xd8,(02),0xdc,(02) },
{ AFCOMDP, yfadd, Px, 0xdc,(03),0xd8,(03),0xdc,(03) },
{ AFCOMDPP, ycompp, Px, 0xde,(03) },
{ AFCOMF, yfmvx, Px, 0xd8,(02) },
{ AFCOMFP, yfmvx, Px, 0xd8,(03) },
{ AFCOMI, yfmvx, Px, 0xdb,(06) },
{ AFCOMIP, yfmvx, Px, 0xdf,(06) },
{ AFCOML, yfmvx, Px, 0xda,(02) },
{ AFCOMLP, yfmvx, Px, 0xda,(03) },
{ AFCOMW, yfmvx, Px, 0xde,(02) },
{ AFCOMWP, yfmvx, Px, 0xde,(03) },
{ AFUCOM, ycompp, Px, 0xdd,(04) },
{ AFUCOMI, ycompp, Px, 0xdb,(05) },
{ AFUCOMIP, ycompp, Px, 0xdf,(05) },
{ AFUCOMP, ycompp, Px, 0xdd,(05) },
{ AFUCOMPP, ycompp, Px, 0xda,(13) },
{ AFADDDP, yfaddp, Px, 0xde,(00) },
{ AFADDW, yfmvx, Px, 0xde,(00) },
{ AFADDL, yfmvx, Px, 0xda,(00) },
{ AFADDF, yfmvx, Px, 0xd8,(00) },
{ AFADDD, yfadd, Px, 0xdc,(00),0xd8,(00),0xdc,(00) },
{ AFMULDP, yfaddp, Px, 0xde,(01) },
{ AFMULW, yfmvx, Px, 0xde,(01) },
{ AFMULL, yfmvx, Px, 0xda,(01) },
{ AFMULF, yfmvx, Px, 0xd8,(01) },
{ AFMULD, yfadd, Px, 0xdc,(01),0xd8,(01),0xdc,(01) },
{ AFSUBDP, yfaddp, Px, 0xde,(05) },
{ AFSUBW, yfmvx, Px, 0xde,(04) },
{ AFSUBL, yfmvx, Px, 0xda,(04) },
{ AFSUBF, yfmvx, Px, 0xd8,(04) },
{ AFSUBD, yfadd, Px, 0xdc,(04),0xd8,(04),0xdc,(05) },
{ AFSUBRDP, yfaddp, Px, 0xde,(04) },
{ AFSUBRW, yfmvx, Px, 0xde,(05) },
{ AFSUBRL, yfmvx, Px, 0xda,(05) },
{ AFSUBRF, yfmvx, Px, 0xd8,(05) },
{ AFSUBRD, yfadd, Px, 0xdc,(05),0xd8,(05),0xdc,(04) },
{ AFDIVDP, yfaddp, Px, 0xde,(07) },
{ AFDIVW, yfmvx, Px, 0xde,(06) },
{ AFDIVL, yfmvx, Px, 0xda,(06) },
{ AFDIVF, yfmvx, Px, 0xd8,(06) },
{ AFDIVD, yfadd, Px, 0xdc,(06),0xd8,(06),0xdc,(07) },
{ AFDIVRDP, yfaddp, Px, 0xde,(06) },
{ AFDIVRW, yfmvx, Px, 0xde,(07) },
{ AFDIVRL, yfmvx, Px, 0xda,(07) },
{ AFDIVRF, yfmvx, Px, 0xd8,(07) },
{ AFDIVRD, yfadd, Px, 0xdc,(07),0xd8,(07),0xdc,(06) },
{ AFXCHD, yfxch, Px, 0xd9,(01),0xd9,(01) },
{ AFFREE },
{ AFLDCW, ystcw, Px, 0xd9,(05),0xd9,(05) },
{ AFLDENV, ystcw, Px, 0xd9,(04),0xd9,(04) },
{ AFRSTOR, ysvrs, Px, 0xdd,(04),0xdd,(04) },
{ AFSAVE, ysvrs, Px, 0xdd,(06),0xdd,(06) },
{ AFSTCW, ystcw, Px, 0xd9,(07),0xd9,(07) },
{ AFSTENV, ystcw, Px, 0xd9,(06),0xd9,(06) },
{ AFSTSW, ystsw, Px, 0xdd,(07),0xdf,0xe0 },
{ AF2XM1, ynone, Px, 0xd9, 0xf0 },
{ AFABS, ynone, Px, 0xd9, 0xe1 },
{ AFCHS, ynone, Px, 0xd9, 0xe0 },
{ AFCLEX, ynone, Px, 0xdb, 0xe2 },
{ AFCOS, ynone, Px, 0xd9, 0xff },
{ AFDECSTP, ynone, Px, 0xd9, 0xf6 },
{ AFINCSTP, ynone, Px, 0xd9, 0xf7 },
{ AFINIT, ynone, Px, 0xdb, 0xe3 },
{ AFLD1, ynone, Px, 0xd9, 0xe8 },
{ AFLDL2E, ynone, Px, 0xd9, 0xea },
{ AFLDL2T, ynone, Px, 0xd9, 0xe9 },
{ AFLDLG2, ynone, Px, 0xd9, 0xec },
{ AFLDLN2, ynone, Px, 0xd9, 0xed },
{ AFLDPI, ynone, Px, 0xd9, 0xeb },
{ AFLDZ, ynone, Px, 0xd9, 0xee },
{ AFNOP, ynone, Px, 0xd9, 0xd0 },
{ AFPATAN, ynone, Px, 0xd9, 0xf3 },
{ AFPREM, ynone, Px, 0xd9, 0xf8 },
{ AFPREM1, ynone, Px, 0xd9, 0xf5 },
{ AFPTAN, ynone, Px, 0xd9, 0xf2 },
{ AFRNDINT, ynone, Px, 0xd9, 0xfc },
{ AFSCALE, ynone, Px, 0xd9, 0xfd },
{ AFSIN, ynone, Px, 0xd9, 0xfe },
{ AFSINCOS, ynone, Px, 0xd9, 0xfb },
{ AFSQRT, ynone, Px, 0xd9, 0xfa },
{ AFTST, ynone, Px, 0xd9, 0xe4 },
{ AFXAM, ynone, Px, 0xd9, 0xe5 },
{ AFXTRACT, ynone, Px, 0xd9, 0xf4 },
{ AFYL2X, ynone, Px, 0xd9, 0xf1 },
{ AFYL2XP1, ynone, Px, 0xd9, 0xf9 },
{ AEND },
{ ADYNT_ },
{ AINIT_ },
{ ASIGNAME },
{ ACMPXCHGB, yrb_mb, Pm, 0xb0 },
{ ACMPXCHGL, yrl_ml, Pm, 0xb1 },
{ ACMPXCHGW, yrl_ml, Pm, 0xb1 },
{ ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
{ ACPUID, ynone, Pm, 0xa2 },
{ ARDTSC, ynone, Pm, 0x31 },
{ AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
{ AXADDL, yrl_ml, Pm, 0xc1 },
{ AXADDW, yrl_ml, Pe, 0x0f,0xc1 },
{ ACMOVLCC, yml_rl, Pm, 0x43 },
{ ACMOVLCS, yml_rl, Pm, 0x42 },
{ ACMOVLEQ, yml_rl, Pm, 0x44 },
{ ACMOVLGE, yml_rl, Pm, 0x4d },
{ ACMOVLGT, yml_rl, Pm, 0x4f },
{ ACMOVLHI, yml_rl, Pm, 0x47 },
{ ACMOVLLE, yml_rl, Pm, 0x4e },
{ ACMOVLLS, yml_rl, Pm, 0x46 },
{ ACMOVLLT, yml_rl, Pm, 0x4c },
{ ACMOVLMI, yml_rl, Pm, 0x48 },
{ ACMOVLNE, yml_rl, Pm, 0x45 },
{ ACMOVLOC, yml_rl, Pm, 0x41 },
{ ACMOVLOS, yml_rl, Pm, 0x40 },
{ ACMOVLPC, yml_rl, Pm, 0x4b },
{ ACMOVLPL, yml_rl, Pm, 0x49 },
{ ACMOVLPS, yml_rl, Pm, 0x4a },
{ ACMOVWCC, yml_rl, Pq, 0x43 },
{ ACMOVWCS, yml_rl, Pq, 0x42 },
{ ACMOVWEQ, yml_rl, Pq, 0x44 },
{ ACMOVWGE, yml_rl, Pq, 0x4d },
{ ACMOVWGT, yml_rl, Pq, 0x4f },
{ ACMOVWHI, yml_rl, Pq, 0x47 },
{ ACMOVWLE, yml_rl, Pq, 0x4e },
{ ACMOVWLS, yml_rl, Pq, 0x46 },
{ ACMOVWLT, yml_rl, Pq, 0x4c },
{ ACMOVWMI, yml_rl, Pq, 0x48 },
{ ACMOVWNE, yml_rl, Pq, 0x45 },
{ ACMOVWOC, yml_rl, Pq, 0x41 },
{ ACMOVWOS, yml_rl, Pq, 0x40 },
{ ACMOVWPC, yml_rl, Pq, 0x4b },
{ ACMOVWPL, yml_rl, Pq, 0x49 },
{ ACMOVWPS, yml_rl, Pq, 0x4a },
{ AFCMOVCC, yfcmv, Px, 0xdb,(00) },
{ AFCMOVCS, yfcmv, Px, 0xda,(00) },
{ AFCMOVEQ, yfcmv, Px, 0xda,(01) },
{ AFCMOVHI, yfcmv, Px, 0xdb,(02) },
{ AFCMOVLS, yfcmv, Px, 0xda,(02) },
{ AFCMOVNE, yfcmv, Px, 0xdb,(01) },
{ AFCMOVNU, yfcmv, Px, 0xdb,(03) },
{ AFCMOVUN, yfcmv, Px, 0xda,(03) },
{ ALFENCE, ynone, Pm, 0xae,0xe8 },
{ AMFENCE, ynone, Pm, 0xae,0xf0 },
{ ASFENCE, ynone, Pm, 0xae,0xf8 },
{ AEMMS, ynone, Pm, 0x77 },
{ APREFETCHT0, yprefetch, Pm, 0x18,(01) },
{ APREFETCHT1, yprefetch, Pm, 0x18,(02) },
{ APREFETCHT2, yprefetch, Pm, 0x18,(03) },
{ APREFETCHNTA, yprefetch, Pm, 0x18,(00) },
{ ABSWAPL, ybswap, Pm, 0xc8 },
{ AUNDEF, ynone, Px, 0x0f, 0x0b },
{ AADDPD, yxm, Pq, 0x58 },
{ AADDPS, yxm, Pm, 0x58 },
{ AADDSD, yxm, Pf2, 0x58 },
{ AADDSS, yxm, Pf3, 0x58 },
{ AANDNPD, yxm, Pq, 0x55 },
{ AANDNPS, yxm, Pm, 0x55 },
{ AANDPD, yxm, Pq, 0x54 },
{ AANDPS, yxm, Pq, 0x54 },
{ ACMPPD, yxcmpi, Px, Pe,0xc2 },
{ ACMPPS, yxcmpi, Pm, 0xc2,0 },
{ ACMPSD, yxcmpi, Px, Pf2,0xc2 },
{ ACMPSS, yxcmpi, Px, Pf3,0xc2 },
{ ACOMISD, yxcmp, Pe, 0x2f },
{ ACOMISS, yxcmp, Pm, 0x2f },
{ ACVTPL2PD, yxcvm2, Px, Pf3,0xe6,Pe,0x2a },
{ ACVTPL2PS, yxcvm2, Pm, 0x5b,0,0x2a,0, },
{ ACVTPD2PL, yxcvm1, Px, Pf2,0xe6,Pe,0x2d },
{ ACVTPD2PS, yxm, Pe, 0x5a },
{ ACVTPS2PL, yxcvm1, Px, Pe,0x5b,Pm,0x2d },
{ ACVTPS2PD, yxm, Pm, 0x5a },
{ ACVTSD2SL, yxcvfl, Pf2, 0x2d },
{ ACVTSD2SS, yxm, Pf2, 0x5a },
{ ACVTSL2SD, yxcvlf, Pf2, 0x2a },
{ ACVTSL2SS, yxcvlf, Pf3, 0x2a },
{ ACVTSS2SD, yxm, Pf3, 0x5a },
{ ACVTSS2SL, yxcvfl, Pf3, 0x2d },
{ ACVTTPD2PL, yxcvm1, Px, Pe,0xe6,Pe,0x2c },
{ ACVTTPS2PL, yxcvm1, Px, Pf3,0x5b,Pm,0x2c },
{ ACVTTSD2SL, yxcvfl, Pf2, 0x2c },
{ ACVTTSS2SL, yxcvfl, Pf3, 0x2c },
{ ADIVPD, yxm, Pe, 0x5e },
{ ADIVPS, yxm, Pm, 0x5e },
{ ADIVSD, yxm, Pf2, 0x5e },
{ ADIVSS, yxm, Pf3, 0x5e },
{ AMASKMOVOU, yxr, Pe, 0xf7 },
{ AMAXPD, yxm, Pe, 0x5f },
{ AMAXPS, yxm, Pm, 0x5f },
{ AMAXSD, yxm, Pf2, 0x5f },
{ AMAXSS, yxm, Pf3, 0x5f },
{ AMINPD, yxm, Pe, 0x5d },
{ AMINPS, yxm, Pm, 0x5d },
{ AMINSD, yxm, Pf2, 0x5d },
{ AMINSS, yxm, Pf3, 0x5d },
{ AMOVAPD, yxmov, Pe, 0x28,0x29 },
{ AMOVAPS, yxmov, Pm, 0x28,0x29 },
{ AMOVO, yxmov, Pe, 0x6f,0x7f },
{ AMOVOU, yxmov, Pf3, 0x6f,0x7f },
{ AMOVHLPS, yxr, Pm, 0x12 },
{ AMOVHPD, yxmov, Pe, 0x16,0x17 },
{ AMOVHPS, yxmov, Pm, 0x16,0x17 },
{ AMOVLHPS, yxr, Pm, 0x16 },
{ AMOVLPD, yxmov, Pe, 0x12,0x13 },
{ AMOVLPS, yxmov, Pm, 0x12,0x13 },
{ AMOVMSKPD, yxrrl, Pq, 0x50 },
{ AMOVMSKPS, yxrrl, Pm, 0x50 },
{ AMOVNTO, yxr_ml, Pe, 0xe7 },
{ AMOVNTPD, yxr_ml, Pe, 0x2b },
{ AMOVNTPS, yxr_ml, Pm, 0x2b },
{ AMOVSD, yxmov, Pf2, 0x10,0x11 },
{ AMOVSS, yxmov, Pf3, 0x10,0x11 },
{ AMOVUPD, yxmov, Pe, 0x10,0x11 },
{ AMOVUPS, yxmov, Pm, 0x10,0x11 },
{ AMULPD, yxm, Pe, 0x59 },
{ AMULPS, yxm, Ym, 0x59 },
{ AMULSD, yxm, Pf2, 0x59 },
{ AMULSS, yxm, Pf3, 0x59 },
{ AORPD, yxm, Pq, 0x56 },
{ AORPS, yxm, Pm, 0x56 },
{ APADDQ, yxm, Pe, 0xd4 },
{ APAND, yxm, Pe, 0xdb },
{ APCMPEQB, yxmq, Pe ,0x74 },
{ APMAXSW, yxm, Pe, 0xee },
{ APMAXUB, yxm, Pe, 0xde },
{ APMINSW, yxm, Pe, 0xea },
{ APMINUB, yxm, Pe, 0xda },
{ APMOVMSKB, ymskb, Px, Pe,0xd7,0xd7 },
{ APSADBW, yxm, Pq, 0xf6 },
{ APSUBB, yxm, Pe, 0xf8 },
{ APSUBL, yxm, Pe, 0xfa },
{ APSUBQ, yxm, Pe, 0xfb },
{ APSUBSB, yxm, Pe, 0xe8 },
{ APSUBSW, yxm, Pe, 0xe9 },
{ APSUBUSB, yxm, Pe, 0xd8 },
{ APSUBUSW, yxm, Pe, 0xd9 },
{ APSUBW, yxm, Pe, 0xf9 },
{ APUNPCKHQDQ, yxm, Pe, 0x6d },
{ APUNPCKLQDQ, yxm, Pe, 0x6c },
{ APXOR, yxm, Pe, 0xef },
{ ARCPPS, yxm, Pm, 0x53 },
{ ARCPSS, yxm, Pf3, 0x53 },
{ ARSQRTPS, yxm, Pm, 0x52 },
{ ARSQRTSS, yxm, Pf3, 0x52 },
{ ASQRTPD, yxm, Pe, 0x51 },
{ ASQRTPS, yxm, Pm, 0x51 },
{ ASQRTSD, yxm, Pf2, 0x51 },
{ ASQRTSS, yxm, Pf3, 0x51 },
{ ASUBPD, yxm, Pe, 0x5c },
{ ASUBPS, yxm, Pm, 0x5c },
{ ASUBSD, yxm, Pf2, 0x5c },
{ ASUBSS, yxm, Pf3, 0x5c },
{ AUCOMISD, yxcmp, Pe, 0x2e },
{ AUCOMISS, yxcmp, Pm, 0x2e },
{ AUNPCKHPD, yxm, Pe, 0x15 },
{ AUNPCKHPS, yxm, Pm, 0x15 },
{ AUNPCKLPD, yxm, Pe, 0x14 },
{ AUNPCKLPS, yxm, Pm, 0x14 },
{ AXORPD, yxm, Pe, 0x57 },
{ AXORPS, yxm, Pm, 0x57 },
{ AAESENC, yaes, Pq, 0x38,0xdc,(0) },
{ APINSRD, yinsrd, Pq, 0x3a, 0x22, (00) },
{ APSHUFB, ymshufb,Pq, 0x38, 0x00 },
{ AUSEFIELD, ynop, Px, 0,0 },
{ ATYPE },
{ AFUNCDATA, yfuncdata, Px, 0,0 },
{ APCDATA, ypcdata, Px, 0,0 },
{ ACHECKNIL },
{ AVARDEF },
{ AVARKILL },
{ ADUFFCOPY, yduff, Px, 0xe8 },
{ ADUFFZERO, yduff, Px, 0xe8 },
0
};
static int32 vaddr(Link*, Addr*, Reloc*);
static uchar nop[][16] = {
{0x90},
{0x66, 0x90},
{0x0F, 0x1F, 0x00},
{0x0F, 0x1F, 0x40, 0x00},
{0x0F, 0x1F, 0x44, 0x00, 0x00},
{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
};
static void
fillnop(uchar *p, int n)
{
int m;
while(n > 0) {
m = n;
if(m > nelem(nop))
m = nelem(nop);
memmove(p, nop[m-1], m);
p += m;
n -= m;
}
}
static int32
naclpad(Link *ctxt, LSym *s, int32 c, int32 pad)
{
symgrow(ctxt, s, c+pad);
fillnop(s->p+c, pad);
return c+pad;
}
static void instinit(void);
void
span8(Link *ctxt, LSym *s)
{
Prog *p, *q;
int32 c, v, loop;
uchar *bp;
int n, m, i;
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;
if((q = p->pcond) != nil)
if(q->back != 2)
n = 1;
p->back = n;
if(p->as == AADJSP) {
p->to.type = D_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = AADDL;
if(v < 0) {
p->as = ASUBL;
v = -v;
p->from.offset = v;
}
if(v == 0)
p->as = ANOP;
}
}
for(p = s->text; p != nil; p = p->link) {
p->back = 2;
if((q = p->pcond) != nil && (q->back & 2))
p->back |= 1;
if(p->as == AADJSP) {
p->to.type = D_SP;
v = -p->from.offset;
p->from.offset = v;
p->as = AADDL;
if(v < 0) {
p->as = ASUBL;
v = -v;
p->from.offset = v;
}
if(v == 0)
p->as = ANOP;
}
}
n = 0;
do {
loop = 0;
memset(s->r, 0, s->nr*sizeof s->r[0]);
s->nr = 0;
s->np = 0;
c = 0;
for(p = s->text; p != nil; p = p->link) {
if(ctxt->headtype == Hnacl && p->isize > 0) {
static LSym *deferreturn;
if(deferreturn == nil)
deferreturn = linklookup(ctxt, "runtime.deferreturn", 0);
if((c>>5) != ((c+p->isize-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
if(p->as == ACALL && p->to.sym == deferreturn)
c = naclpad(ctxt, s, c, -c&31);
if(p->as == ACALL)
c = naclpad(ctxt, s, c, -(c+p->isize)&31);
if(p->as == AREP && (c>>5) != ((c+3-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
if(p->as == ALOCK && (c>>5) != ((c+8-1)>>5))
c = naclpad(ctxt, s, c, -c&31);
}
p->pc = c;
for(q = p->comefrom; q != nil; q = q->forwd) {
v = p->pc - (q->pc + q->mark);
if(q->back & 2) {
if(v > 127) {
loop++;
q->back ^= 2;
}
if(q->as == AJCXZW)
s->p[q->pc+2] = v;
else
s->p[q->pc+1] = v;
} else {
bp = s->p + q->pc + q->mark - 4;
*bp++ = v;
*bp++ = v>>8;
*bp++ = v>>16;
*bp = v>>24;
}
}
p->comefrom = nil;
p->pc = c;
asmins(ctxt, p);
m = ctxt->andptr-ctxt->and;
if(p->isize != m) {
p->isize = m;
loop++;
}
symgrow(ctxt, s, p->pc+m);
memmove(s->p+p->pc, ctxt->and, m);
p->mark = m;
c += m;
}
if(++n > 20) {
ctxt->diag("span must be looping");
sysfatal("bad code");
}
} while(loop);
if(ctxt->headtype == Hnacl)
c = naclpad(ctxt, s, c, -c&31);
c += -c&(FuncAlign-1);
s->size = c;
if(0 ) {
print("span1 %s %lld (%d tries)\n %.6ux", s->name, s->size, n, 0);
for(i=0; i<s->np; i++) {
print(" %.2ux", s->p[i]);
if(i%16 == 15)
print("\n %.6ux", i+1);
}
if(i%16)
print("\n");
for(i=0; i<s->nr; i++) {
Reloc *r;
r = &s->r[i];
print(" rel %#.4ux/%d %s%+lld\n", r->off, r->siz, r->sym->name, r->add);
}
}
}
static void
instinit(void)
{
int i;
for(i=1; optab[i].as; i++)
if(i != optab[i].as)
sysfatal("phase error in optab: at %A found %A", i, 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;
}
}
static int
prefixof(Link *ctxt, Addr *a)
{
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;
case D_INDIR+D_TLS:
switch(ctxt->headtype) {
default:
sysfatal("unknown TLS base register for %s", headstr(ctxt->headtype));
case Hdarwin:
case Hdragonfly:
case Hfreebsd:
case Hnetbsd:
case Hopenbsd:
return 0x65;
}
}
return 0;
}
static int
oclass(Addr *a)
{
int32 v;
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:
case D_STATIC:
return Yi32;
case D_AUTO:
case D_PARAM:
return Yiauto;
}
return Yxxx;
}
return Ycol;
}
return Ym;
}
switch(a->type)
{
case D_AL:
return Yal;
case D_AX:
return Yax;
case D_CL:
case D_DL:
case D_BL:
case D_AH:
case D_CH:
case D_DH:
case D_BH:
return Yrb;
case D_CX:
return Ycx;
case D_DX:
case D_BX:
return Yrx;
case D_SP:
case D_BP:
case D_SI:
case D_DI:
return Yrl;
case D_F0+0:
return Yf0;
case D_F0+1:
case D_F0+2:
case D_F0+3:
case D_F0+4:
case D_F0+5:
case D_F0+6:
case D_F0+7:
return Yrf;
case D_X0+0:
case D_X0+1:
case D_X0+2:
case D_X0+3:
case D_X0+4:
case D_X0+5:
case D_X0+6:
case 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:
case D_STATIC:
case D_AUTO:
case D_PARAM:
return Ym;
case D_CONST:
case D_CONST2:
case D_ADDR:
if(a->sym == nil) {
v = 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;
}
static void
asmidx(Link *ctxt, int scale, int index, int base)
{
int i;
switch(index) {
default:
goto bad;
case D_NONE:
i = 4 << 3;
goto bas;
case D_AX:
case D_CX:
case D_DX:
case D_BX:
case D_BP:
case D_SI:
case D_DI:
i = reg[index] << 3;
break;
}
switch(scale) {
default:
goto bad;
case 1:
break;
case 2:
i |= (1<<6);
break;
case 4:
i |= (2<<6);
break;
case 8:
i |= (3<<6);
break;
}
bas:
switch(base) {
default:
goto bad;
case D_NONE:
i |= 5;
break;
case D_AX:
case D_CX:
case D_DX:
case D_BX:
case D_SP:
case D_BP:
case D_SI:
case D_DI:
i |= reg[base];
break;
}
*ctxt->andptr++ = i;
return;
bad:
ctxt->diag("asmidx: bad address %d,%d,%d", scale, index, base);
*ctxt->andptr++ = 0;
return;
}
static void
put4(Link *ctxt, int32 v)
{
ctxt->andptr[0] = v;
ctxt->andptr[1] = v>>8;
ctxt->andptr[2] = v>>16;
ctxt->andptr[3] = v>>24;
ctxt->andptr += 4;
}
static void
relput4(Link *ctxt, Prog *p, Addr *a)
{
vlong v;
Reloc rel, *r;
v = vaddr(ctxt, a, &rel);
if(rel.siz != 0) {
if(rel.siz != 4)
ctxt->diag("bad reloc");
r = addrel(ctxt->cursym);
*r = rel;
r->off = p->pc + ctxt->andptr - ctxt->and;
}
put4(ctxt, v);
}
static int32
vaddr(Link *ctxt, Addr *a, Reloc *r)
{
int t;
int32 v;
LSym *s;
if(r != nil)
memset(r, 0, sizeof *r);
t = a->type;
v = a->offset;
if(t == D_ADDR)
t = a->index;
switch(t) {
case D_STATIC:
case D_EXTERN:
s = a->sym;
if(s != nil) {
if(r == nil) {
ctxt->diag("need reloc for %D", a);
sysfatal("bad code");
}
r->type = R_ADDR;
r->siz = 4;
r->off = -1;
r->sym = s;
r->add = v;
v = 0;
}
break;
case D_INDIR+D_TLS:
if(r == nil) {
ctxt->diag("need reloc for %D", a);
sysfatal("bad code");
}
r->type = R_TLS_LE;
r->siz = 4;
r->off = -1;
r->add = v;
v = 0;
break;
}
return v;
}
static void
asmand(Link *ctxt, Addr *a, int r)
{
int32 v;
int t, scale;
Reloc rel;
v = a->offset;
t = 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:
case D_EXTERN:
t = D_NONE;
v = vaddr(ctxt, a, &rel);
break;
case D_AUTO:
case D_PARAM:
t = D_SP;
break;
}
} else
t -= D_INDIR;
if(t == D_NONE) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
asmidx(ctxt, a->scale, a->index, t);
goto putrelv;
}
if(v == 0 && rel.siz == 0 && t != D_BP) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
asmidx(ctxt, a->scale, a->index, t);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
*ctxt->andptr++ = (1 << 6) | (4 << 0) | (r << 3);
asmidx(ctxt, a->scale, a->index, t);
*ctxt->andptr++ = v;
return;
}
*ctxt->andptr++ = (2 << 6) | (4 << 0) | (r << 3);
asmidx(ctxt, a->scale, a->index, t);
goto putrelv;
}
if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) {
if(v)
goto bad;
*ctxt->andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
return;
}
scale = a->scale;
if(t < D_INDIR || t >= 2*D_INDIR) {
switch(a->type) {
default:
goto bad;
case D_STATIC:
case D_EXTERN:
t = D_NONE;
v = vaddr(ctxt, a, &rel);
break;
case D_AUTO:
case D_PARAM:
t = D_SP;
break;
}
scale = 1;
} else
t -= D_INDIR;
if(t == D_TLS)
v = vaddr(ctxt, a, &rel);
if(t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS) {
*ctxt->andptr++ = (0 << 6) | (5 << 0) | (r << 3);
goto putrelv;
}
if(t == D_SP) {
if(v == 0 && rel.siz == 0) {
*ctxt->andptr++ = (0 << 6) | (4 << 0) | (r << 3);
asmidx(ctxt, scale, D_NONE, t);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
*ctxt->andptr++ = (1 << 6) | (4 << 0) | (r << 3);
asmidx(ctxt, scale, D_NONE, t);
*ctxt->andptr++ = v;
return;
}
*ctxt->andptr++ = (2 << 6) | (4 << 0) | (r << 3);
asmidx(ctxt, scale, D_NONE, t);
goto putrelv;
}
if(t >= D_AX && t <= D_DI) {
if(a->index == D_TLS) {
memset(&rel, 0, sizeof rel);
rel.type = R_TLS_IE;
rel.siz = 4;
rel.sym = nil;
rel.add = v;
v = 0;
}
if(v == 0 && rel.siz == 0 && t != D_BP) {
*ctxt->andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
return;
}
if(v >= -128 && v < 128 && rel.siz == 0) {
ctxt->andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
ctxt->andptr[1] = v;
ctxt->andptr += 2;
return;
}
*ctxt->andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
goto putrelv;
}
goto bad;
putrelv:
if(rel.siz != 0) {
Reloc *r;
if(rel.siz != 4) {
ctxt->diag("bad rel");
goto bad;
}
r = addrel(ctxt->cursym);
*r = rel;
r->off = ctxt->curp->pc + ctxt->andptr - ctxt->and;
}
put4(ctxt, v);
return;
bad:
ctxt->diag("asmand: bad address %D", a);
return;
}
#define E 0xff
static uchar ymovtab[] =
{
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,
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,
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,
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,
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,
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,
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,
AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0,
AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0,
AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0,
AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0,
AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0,
AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0,
AMOVL, Yml, Ycol, 5, 0,0,0,0,
AMOVW, Yml, Ycol, 5, Pe,0,0,0,
ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0,
ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0,
AIMULW, Yml, Yrl, 7, Pq,0xaf,0,0,
AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0,
AMOVL, Ytls, Yrl, 8, 0,0,0,0,
0
};
static int
byteswapreg(Link *ctxt, Addr *a)
{
int cana, canb, canc, cand;
cana = canb = canc = cand = 1;
switch(a->type) {
case D_NONE:
cana = cand = 0;
break;
case D_AX:
case D_AL:
case D_AH:
case D_INDIR+D_AX:
cana = 0;
break;
case D_BX:
case D_BL:
case D_BH:
case D_INDIR+D_BX:
canb = 0;
break;
case D_CX:
case D_CL:
case D_CH:
case D_INDIR+D_CX:
canc = 0;
break;
case D_DX:
case D_DL:
case D_DH:
case D_INDIR+D_DX:
cand = 0;
break;
}
switch(a->index) {
case D_AX:
cana = 0;
break;
case D_BX:
canb = 0;
break;
case D_CX:
canc = 0;
break;
case D_DX:
cand = 0;
break;
}
if(cana)
return D_AX;
if(canb)
return D_BX;
if(canc)
return D_CX;
if(cand)
return D_DX;
ctxt->diag("impossible byte register");
sysfatal("bad code");
return 0;
}
static void
subreg(Prog *p, int from, int to)
{
if(0 )
print("\n%P s/%R/%R/\n", p, from, to);
if(p->from.type == from) {
p->from.type = to;
p->ft = 0;
}
if(p->to.type == from) {
p->to.type = to;
p->tt = 0;
}
if(p->from.index == from) {
p->from.index = to;
p->ft = 0;
}
if(p->to.index == from) {
p->to.index = to;
p->tt = 0;
}
from += D_INDIR;
if(p->from.type == from) {
p->from.type = to+D_INDIR;
p->ft = 0;
}
if(p->to.type == from) {
p->to.type = to+D_INDIR;
p->tt = 0;
}
if(0 )
print("%P\n", p);
}
static int
mediaop(Link *ctxt, Optab *o, int op, int osize, int z)
{
switch(op){
case Pm:
case Pe:
case Pf2:
case Pf3:
if(osize != 1){
if(op != Pm)
*ctxt->andptr++ = op;
*ctxt->andptr++ = Pm;
op = o->op[++z];
break;
}
default:
if(ctxt->andptr == ctxt->and || ctxt->andptr[-1] != Pm)
*ctxt->andptr++ = Pm;
break;
}
*ctxt->andptr++ = op;
return z;
}
static void
doasm(Link *ctxt, Prog *p)
{
Optab *o;
Prog *q, pp;
uchar *t;
int z, op, ft, tt, breg;
int32 v, pre;
Reloc rel, *r;
Addr *a;
ctxt->curp = p;
pre = prefixof(ctxt, &p->from);
if(pre)
*ctxt->andptr++ = pre;
pre = prefixof(ctxt, &p->to);
if(pre)
*ctxt->andptr++ = pre;
if(p->ft == 0)
p->ft = oclass(&p->from);
if(p->tt == 0)
p->tt = oclass(&p->to);
ft = p->ft * Ymax;
tt = p->tt * Ymax;
o = &optab[p->as];
t = o->ytab;
if(t == 0) {
ctxt->diag("asmins: noproto %P", p);
return;
}
for(z=0; *t; z+=t[3],t+=4)
if(ycover[ft+t[0]])
if(ycover[tt+t[1]])
goto found;
goto domov;
found:
switch(o->prefix) {
case Pq:
*ctxt->andptr++ = Pe;
*ctxt->andptr++ = Pm;
break;
case Pf2:
case Pf3:
*ctxt->andptr++ = o->prefix;
*ctxt->andptr++ = Pm;
break;
case Pm:
*ctxt->andptr++ = Pm;
break;
case Pe:
*ctxt->andptr++ = Pe;
break;
case Pb:
break;
}
op = o->op[z];
switch(t[2]) {
default:
ctxt->diag("asmins: unknown z %d %P", t[2], p);
return;
case Zpseudo:
break;
case Zlit:
for(; op = o->op[z]; z++)
*ctxt->andptr++ = op;
break;
case Zlitm_r:
for(; op = o->op[z]; z++)
*ctxt->andptr++ = op;
asmand(ctxt, &p->from, reg[p->to.type]);
break;
case Zm_r:
*ctxt->andptr++ = op;
asmand(ctxt, &p->from, reg[p->to.type]);
break;
case Zm2_r:
*ctxt->andptr++ = op;
*ctxt->andptr++ = o->op[z+1];
asmand(ctxt, &p->from, reg[p->to.type]);
break;
case Zm_r_xm:
mediaop(ctxt, o, op, t[3], z);
asmand(ctxt, &p->from, reg[p->to.type]);
break;
case Zm_r_i_xm:
mediaop(ctxt, o, op, t[3], z);
asmand(ctxt, &p->from, reg[p->to.type]);
*ctxt->andptr++ = p->to.offset;
break;
case Zibm_r:
while ((op = o->op[z++]) != 0)
*ctxt->andptr++ = op;
asmand(ctxt, &p->from, reg[p->to.type]);
*ctxt->andptr++ = p->to.offset;
break;
case Zaut_r:
*ctxt->andptr++ = 0x8d;
if(p->from.type != D_ADDR)
ctxt->diag("asmins: Zaut sb type ADDR");
p->from.type = p->from.index;
p->from.index = D_NONE;
p->ft = 0;
asmand(ctxt, &p->from, reg[p->to.type]);
p->from.index = p->from.type;
p->from.type = D_ADDR;
p->ft = 0;
break;
case Zm_o:
*ctxt->andptr++ = op;
asmand(ctxt, &p->from, o->op[z+1]);
break;
case Zr_m:
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, reg[p->from.type]);
break;
case Zr_m_xm:
mediaop(ctxt, o, op, t[3], z);
asmand(ctxt, &p->to, reg[p->from.type]);
break;
case Zr_m_i_xm:
mediaop(ctxt, o, op, t[3], z);
asmand(ctxt, &p->to, reg[p->from.type]);
*ctxt->andptr++ = p->from.offset;
break;
case Zo_m:
case_Zo_m:
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, o->op[z+1]);
break;
case Zm_ibo:
*ctxt->andptr++ = op;
asmand(ctxt, &p->from, o->op[z+1]);
*ctxt->andptr++ = vaddr(ctxt, &p->to, nil);
break;
case Zibo_m:
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, o->op[z+1]);
*ctxt->andptr++ = vaddr(ctxt, &p->from, nil);
break;
case Z_ib:
case Zib_:
if(t[2] == Zib_)
a = &p->from;
else
a = &p->to;
v = vaddr(ctxt, a, nil);
*ctxt->andptr++ = op;
*ctxt->andptr++ = v;
break;
case Zib_rp:
*ctxt->andptr++ = op + reg[p->to.type];
*ctxt->andptr++ = vaddr(ctxt, &p->from, nil);
break;
case Zil_rp:
*ctxt->andptr++ = op + reg[p->to.type];
if(o->prefix == Pe) {
v = vaddr(ctxt, &p->from, nil);
*ctxt->andptr++ = v;
*ctxt->andptr++ = v>>8;
}
else
relput4(ctxt, p, &p->from);
break;
case Zib_rr:
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, reg[p->to.type]);
*ctxt->andptr++ = vaddr(ctxt, &p->from, nil);
break;
case Z_il:
case Zil_:
if(t[2] == Zil_)
a = &p->from;
else
a = &p->to;
*ctxt->andptr++ = op;
if(o->prefix == Pe) {
v = vaddr(ctxt, a, nil);
*ctxt->andptr++ = v;
*ctxt->andptr++ = v>>8;
}
else
relput4(ctxt, p, a);
break;
case Zm_ilo:
case Zilo_m:
*ctxt->andptr++ = op;
if(t[2] == Zilo_m) {
a = &p->from;
asmand(ctxt, &p->to, o->op[z+1]);
} else {
a = &p->to;
asmand(ctxt, &p->from, o->op[z+1]);
}
if(o->prefix == Pe) {
v = vaddr(ctxt, a, nil);
*ctxt->andptr++ = v;
*ctxt->andptr++ = v>>8;
}
else
relput4(ctxt, p, a);
break;
case Zil_rr:
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, reg[p->to.type]);
if(o->prefix == Pe) {
v = vaddr(ctxt, &p->from, nil);
*ctxt->andptr++ = v;
*ctxt->andptr++ = v>>8;
}
else
relput4(ctxt, p, &p->from);
break;
case Z_rp:
*ctxt->andptr++ = op + reg[p->to.type];
break;
case Zrp_:
*ctxt->andptr++ = op + reg[p->from.type];
break;
case Zclr:
*ctxt->andptr++ = op;
asmand(ctxt, &p->to, reg[p->to.type]);
break;
case Zcall:
if(p->to.sym == nil) {
ctxt->diag("call without target");
sysfatal("bad code");
}
*ctxt->andptr++ = op;
r = addrel(ctxt->cursym);
r->off = p->pc + ctxt->andptr - ctxt->and;
r->type = R_CALL;
r->siz = 4;
r->sym = p->to.sym;
r->add = p->to.offset;
put4(ctxt, 0);
break;
case Zbr:
case Zjmp:
case Zloop:
if(p->to.sym != nil) {
if(t[2] != Zjmp) {
ctxt->diag("branch to ATEXT");
sysfatal("bad code");
}
*ctxt->andptr++ = o->op[z+1];
r = addrel(ctxt->cursym);
r->off = p->pc + ctxt->andptr - ctxt->and;
r->sym = p->to.sym;
r->type = R_PCREL;
r->siz = 4;
put4(ctxt, 0);
break;
}
q = p->pcond;
if(q == nil) {
ctxt->diag("jmp/branch/loop without target");
sysfatal("bad code");
}
if(p->back & 1) {
v = q->pc - (p->pc + 2);
if(v >= -128) {
if(p->as == AJCXZW)
*ctxt->andptr++ = 0x67;
*ctxt->andptr++ = op;
*ctxt->andptr++ = v;
} else if(t[2] == Zloop) {
ctxt->diag("loop too far: %P", p);
} else {
v -= 5-2;
if(t[2] == Zbr) {
*ctxt->andptr++ = 0x0f;
v--;
}
*ctxt->andptr++ = o->op[z+1];
*ctxt->andptr++ = v;
*ctxt->andptr++ = v>>8;
*ctxt->andptr++ = v>>16;
*ctxt->andptr++ = v>>24;
}
break;
}
p->forwd = q->comefrom;
q->comefrom = p;
if(p->back & 2) {
if(p->as == AJCXZW)
*ctxt->andptr++ = 0x67;
*ctxt->andptr++ = op;
*ctxt->andptr++ = 0;
} else if(t[2] == Zloop) {
ctxt->diag("loop too far: %P", p);
} else {
if(t[2] == Zbr)
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = o->op[z+1];
*ctxt->andptr++ = 0;
*ctxt->andptr++ = 0;
*ctxt->andptr++ = 0;
*ctxt->andptr++ = 0;
}
break;
case Zcallcon:
case Zjmpcon:
if(t[2] == Zcallcon)
*ctxt->andptr++ = op;
else
*ctxt->andptr++ = o->op[z+1];
r = addrel(ctxt->cursym);
r->off = p->pc + ctxt->andptr - ctxt->and;
r->type = R_PCREL;
r->siz = 4;
r->add = p->to.offset;
put4(ctxt, 0);
break;
case Zcallind:
*ctxt->andptr++ = op;
*ctxt->andptr++ = o->op[z+1];
r = addrel(ctxt->cursym);
r->off = p->pc + ctxt->andptr - ctxt->and;
r->type = R_ADDR;
r->siz = 4;
r->add = p->to.offset;
r->sym = p->to.sym;
put4(ctxt, 0);
break;
case Zcallindreg:
r = addrel(ctxt->cursym);
r->off = p->pc;
r->type = R_CALLIND;
r->siz = 0;
goto case_Zo_m;
case Zbyte:
v = vaddr(ctxt, &p->from, &rel);
if(rel.siz != 0) {
rel.siz = op;
r = addrel(ctxt->cursym);
*r = rel;
r->off = p->pc + ctxt->andptr - ctxt->and;
}
*ctxt->andptr++ = v;
if(op > 1) {
*ctxt->andptr++ = v>>8;
if(op > 2) {
*ctxt->andptr++ = v>>16;
*ctxt->andptr++ = v>>24;
}
}
break;
case Zmov:
goto domov;
}
return;
domov:
for(t=ymovtab; *t; t+=8)
if(p->as == t[0])
if(ycover[ft+t[1]])
if(ycover[tt+t[2]])
goto mfound;
bad:
pp = *p;
z = p->from.type;
if(z >= D_BP && z <= D_DI) {
if((breg = byteswapreg(ctxt, &p->to)) != D_AX) {
*ctxt->andptr++ = 0x87;
asmand(ctxt, &p->from, reg[breg]);
subreg(&pp, z, breg);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x87;
asmand(ctxt, &p->from, reg[breg]);
} else {
*ctxt->andptr++ = 0x90 + reg[z];
subreg(&pp, z, D_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z];
}
return;
}
z = p->to.type;
if(z >= D_BP && z <= D_DI) {
if((breg = byteswapreg(ctxt, &p->from)) != D_AX) {
*ctxt->andptr++ = 0x87;
asmand(ctxt, &p->to, reg[breg]);
subreg(&pp, z, breg);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x87;
asmand(ctxt, &p->to, reg[breg]);
} else {
*ctxt->andptr++ = 0x90 + reg[z];
subreg(&pp, z, D_AX);
doasm(ctxt, &pp);
*ctxt->andptr++ = 0x90 + reg[z];
}
return;
}
ctxt->diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
return;
mfound:
switch(t[3]) {
default:
ctxt->diag("asmins: unknown mov %d %P", t[3], p);
break;
case 0:
for(z=4; t[z]!=E; z++)
*ctxt->andptr++ = t[z];
break;
case 1:
*ctxt->andptr++ = t[4];
asmand(ctxt, &p->to, t[5]);
break;
case 2:
*ctxt->andptr++ = t[4];
asmand(ctxt, &p->from, t[5]);
break;
case 3:
*ctxt->andptr++ = t[4];
*ctxt->andptr++ = t[5];
asmand(ctxt, &p->to, t[6]);
break;
case 4:
*ctxt->andptr++ = t[4];
*ctxt->andptr++ = t[5];
asmand(ctxt, &p->from, t[6]);
break;
case 5:
if(t[4])
*ctxt->andptr++ = t[4];
switch(p->to.index) {
default:
goto bad;
case D_DS:
*ctxt->andptr++ = 0xc5;
break;
case D_SS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb2;
break;
case D_ES:
*ctxt->andptr++ = 0xc4;
break;
case D_FS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb4;
break;
case D_GS:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = 0xb5;
break;
}
asmand(ctxt, &p->from, reg[p->to.type]);
break;
case 6:
z = p->from.type;
switch(z) {
default:
goto bad;
case D_CONST:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = t[4];
asmand(ctxt, &p->to, reg[p->from.index]);
*ctxt->andptr++ = p->from.offset;
break;
case D_CL:
case D_CX:
*ctxt->andptr++ = 0x0f;
*ctxt->andptr++ = t[5];
asmand(ctxt, &p->to, reg[p->from.index]);
break;
}
break;
case 7:
if(t[4] == Pq) {
*ctxt->andptr++ = Pe;
*ctxt->andptr++ = Pm;
} else
*ctxt->andptr++ = t[4];
*ctxt->andptr++ = t[5];
asmand(ctxt, &p->from, reg[p->to.type]);
break;
case 8:
switch(ctxt->headtype) {
default:
sysfatal("unknown TLS base location for %s", headstr(ctxt->headtype));
case Hlinux:
case 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++ = 0x65;
*ctxt->andptr++ = 0x8B;
asmand(ctxt, &pp.from, reg[p->to.type]);
break;
case Hplan9:
if(ctxt->plan9tos == nil)
ctxt->plan9tos = linklookup(ctxt, "_tos", 0);
memset(&pp.from, 0, sizeof pp.from);
pp.from.type = D_EXTERN;
pp.from.sym = ctxt->plan9tos;
pp.from.offset = 0;
pp.from.index = D_NONE;
*ctxt->andptr++ = 0x8B;
asmand(ctxt, &pp.from, reg[p->to.type]);
break;
case 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++ = 0x64;
*ctxt->andptr++ = 0x8B;
asmand(ctxt, &pp.from, reg[p->to.type]);
break;
}
break;
}
}
static uchar naclret[] = {
0x5d,
0x83, 0xe5, 0xe0,
0xff, 0xe5,
};
static void
asmins(Link *ctxt, Prog *p)
{
Reloc *r;
ctxt->andptr = ctxt->and;
if(p->as == AUSEFIELD) {
r = addrel(ctxt->cursym);
r->off = 0;
r->sym = p->from.sym;
r->type = R_USEFIELD;
r->siz = 0;
return;
}
if(ctxt->headtype == Hnacl) {
switch(p->as) {
case ARET:
memmove(ctxt->andptr, naclret, sizeof naclret);
ctxt->andptr += sizeof naclret;
return;
case ACALL:
case AJMP:
if(D_AX <= p->to.type && p->to.type <= D_DI) {
*ctxt->andptr++ = 0x83;
*ctxt->andptr++ = 0xe0 | (p->to.type - D_AX);
*ctxt->andptr++ = 0xe0;
}
break;
case AINT:
*ctxt->andptr++ = 0xf4;
return;
}
}
doasm(ctxt, p);
if(ctxt->andptr > ctxt->and+sizeof ctxt->and) {
print("and[] is too short - %ld byte instruction\n", ctxt->andptr - ctxt->and);
sysfatal("bad code");
}
}