#include "all.h"
/* implicit operands, not needed for assembly */
#define AFv ANONE
#define AXb ANONE
#define AXv ANONE
#define AYb ANONE
#define AYv ANONE
#define A0 ANONE
#define A1 ANONE
#define A2 ANONE
#define A3 ANONE
#define A4 ANONE
#define AMa2 ANONE
typedef struct Optab Optab;
struct Optab {
int op;
uchar arg1;
uchar arg2;
uchar arg3;
};
static uchar needmodrm[NAMODE] = {
[AEb] 1,
[AEv] 1,
[AGb] 1,
[AGv] 1,
[AM] 1,
[AMp] 1,
[ASw] 1,
};
/*
static uchar small[NAMODE] = {
[ANONE] 1,
[AEb] 1,
[AGb] 1,
[AOb] 1,
[AXb] 1,
[AYb] 1,
[AIb] 1,
[AAL] 1,
[ABL] 1,
[ACL] 1,
[ADL] 1,
[AAH] 1,
[ABH] 1,
[ACH] 1,
[ADH] 1,
};
*/
static Optab optab[256] = {
//00
{OADD, AEb, AGb}, {OADD, AEv, AGv}, {OADD, AGb, AEb}, {OADD, AGv, AEv},
{OADD, AAL, AIb}, {OADD, AAX, AIv}, {OPUSH, AES, }, {OPOP, AES },
{OOR, AEb, AGb}, {OOR, AEv, AGv}, {OOR, AGb, AEb}, {OOR, AGv, AEv},
{OOR, AAL, AIb}, {OOR, AAX, AIv}, {OPUSH, ACS, }, {OBAD, },
//10
{OADC, AEb, AGb}, {OADC, AEv, AGv}, {OADC, AGb, AEb}, {OADC, AGv, AEv},
{OADC, AAL, AIb}, {OADC, AAX, AIv}, {OPUSH, ASS, }, {OPOP, ASS, },
{OSBB, AEb, AGb}, {OSBB, AEv, AGv}, {OSBB, AGb, AEb}, {OSBB, AGv, AEv},
{OSBB, AAL, AIb}, {OSBB, AAX, AIv}, {OPUSH, ADS, }, {OPOP, ADS, },
//20
{OAND, AEb, AGb}, {OAND, AEv, AGv}, {OAND, AGb, AEb}, {OAND, AGv, AEv},
{OAND, AAL, AIb}, {OAND, AAX, AIv}, {OSEG, AES, }, {ODAA, },
{OSUB, AEb, AGb}, {OSUB, AEv, AGv}, {OSUB, AGb, AEb}, {OSUB, AGv, AEv},
{OSUB, AAL, AIb}, {OSUB, AAX, AIv}, {OSEG, ACS, }, {ODAS, },
//30
{OXOR, AEb, AGb}, {OXOR, AEv, AGv}, {OXOR, AGb, AEb}, {OXOR, AGv, AEv},
{OXOR, AAL, AIb}, {OXOR, AAX, AIv}, {OSEG, ASS, }, {OAAA, },
{OCMP, AEb, AGb}, {OCMP, AEv, AGv}, {OCMP, AGb, AEb}, {OCMP, AGv, AEv},
{OCMP, AAL, AIb}, {OCMP, AAX, AIv}, {OSEG, ADS, }, {OAAS, },
//40
{OINC, AAX, }, {OINC, ACX, }, {OINC, ADX, }, {OINC, ABX, },
{OINC, ASP, }, {OINC, ABP, }, {OINC, ASI, }, {OINC, ADI, },
{ODEC, AAX, }, {ODEC, ACX, }, {ODEC, ADX, }, {ODEC, ABX, },
{ODEC, ASP, }, {ODEC, ABP, }, {ODEC, ASI, }, {ODEC, ADI, },
//50
{OPUSH, AAX, }, {OPUSH, ACX, }, {OPUSH, ADX, }, {OPUSH, ABX, },
{OPUSH, ASP, }, {OPUSH, ABP, }, {OPUSH, ASI, }, {OPUSH, ADI, },
{OPOP, AAX, }, {OPOP, ACX, }, {OPOP, ADX, }, {OPOP, ABX, },
{OPOP, ASP, }, {OPOP, ABP, }, {OPOP, ASI, }, {OPOP, ADI, },
//60
{OPUSHA, }, {OPOPA, }, {OBOUND,AGv,AMa,AMa2}, {OARPL, AEw, AGw},
{OSEG, AFS, }, {OSEG, AGS, }, {OOSIZE, }, {OASIZE, },
{OPUSH, AIv, }, {OIMUL,AGv,AEv,AIv},{OPUSH, AIb, }, {OIMUL,AGv,AEv,AIb},
{OINS, AYb, ADX}, {OINS, AYv, ADX}, {OOUTS, ADX, AXb}, {OOUTS, ADX, AXv},
//70
{OJOS, AJb, }, {OJOC, AJb, }, {OJCS, AJb, }, {OJCC, AJb, },
{OJEQ, AJb, }, {OJNE, AJb, }, {OJLS, AJb, }, {OJHI, AJb, },
{OJMI, AJb, }, {OJPL, AJb, }, {OJPS, AJb, }, {OJPC, AJb, },
{OJLT, AJb, }, {OJGE, AJb, }, {OJLE, AJb, }, {OJGT, AJb, },
//80
{OGP1, AEb, AIb}, {OGP1, AEv, AIv}, {OGP1, AEv, AIc}, {OGP1, AEv, AIc},
{OTEST, AEb, AGb}, {OTEST, AEv, AGv}, {OXCHG, AEb, AGb}, {OXCHG, AEv, AGv},
{OMOV, AEb, AGb}, {OMOV, AEv, AGv}, {OMOV, AGb, AEb}, {OMOV, AGv, AEv},
{OMOV, AEw, ASw}, {OLEA, AGv, AM }, {OMOV, ASw, AEw}, {OPOP, AEv, },
//90
{ONOP, }, {OXCHG, AAX, ACX}, {OXCHG, AAX, ADX}, {OXCHG, AAX, ABX},
{OXCHG, AAX, ASP}, {OXCHG, AAX, ABP}, {OXCHG, AAX, ASI}, {OXCHG, AAX, ADI},
{OCBW, }, {OCWD, }, {OCALL, AAp, }, {OWAIT, },
{OPUSHF,AFv, }, {OPOPF, AFv, }, {OSAHF, AAH, }, {OLAHF, AAH, },
//A0
{OMOV, AAL, AOb}, {OMOV, AAX, AOv}, {OMOV, AOb, AAL}, {OMOV, AOv, AAX},
{OMOVS, AXb, AYb}, {OMOVS, AXv, AYv}, {OCMPS, AXb, AYb}, {OCMPS, AXv, AYv},
{OTEST, AAL, AIb}, {OTEST, AAX, AIv}, {OSTOS, AYb, AAL}, {OSTOS, AYv, AAX},
{OLODS, AAL, AXb}, {OLODS, AAX, AXv}, {OSCAS, AAL, AYb}, {OSCAS, AAX, AYv},
//B0
{OMOV, AAL, AIb}, {OMOV, ACL, AIb}, {OMOV, ADL, AIb}, {OMOV, ABL, AIb},
{OMOV, AAH, AIb}, {OMOV, ACH, AIb}, {OMOV, ADH, AIb}, {OMOV, ABH, AIb},
{OMOV, AAX, AIv}, {OMOV, ACX, AIv}, {OMOV, ADX, AIv}, {OMOV, ABX, AIv},
{OMOV, ASP, AIv}, {OMOV, ABP, AIv}, {OMOV, ASI, AIv}, {OMOV, ADI, AIv},
//C0
{OGP2, AEb, AIb}, {OGP2, AEv, AIb}, {ORET, AIw, }, {ORET, A0, },
{OLFP,AES,AGv,AMp},{OLFP,ADS,AGv,AMp},{OMOV, AEb, AIb}, {OMOV, AEv, AIv},
{OENTER,AIw, AIb}, {OLEAVE, }, {ORETF, AIw, }, {ORETF, A0, },
{OINT, A3, }, {OINT, AIb, }, {OINT, A4, }, {OIRET, },
//D0
{OGP2, AEb, A1 }, {OGP2, AEv, A1 }, {OGP2, AEb, ACL}, {OGP2, AEv, ACL},
{OAAM, AIb, }, {OAAD, AIb, }, {OBAD, }, {OXLAT, AAL, ABX},
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//E0
{OLOOPNZ,AJb,ACX}, {OLOOPZ,AJb, ACX}, {OLOOP, AJb, ACX}, {OJCXZ, AJb, },
{OIN, AAL, AIb}, {OIN, AAX, AIb}, {OOUT, AIb, AAL}, {OOUT, AIb, AAX},
{OCALL, AJv, }, {OJMP, AJv, }, {OJMP, AAp, }, {OJMP, AJb, },
{OIN, AAL, ADX}, {OIN, AAX, ADX}, {OOUT, ADX, AAL}, {OOUT, ADX, AAX},
//F0
{OLOCK, }, {OBAD, }, {OREPNZ, }, {OREPZ, },
{OHLT, }, {OCMC, }, {OGP3b, }, {OGP3v, },
{OCLC, }, {OSTC, }, {OCLI, }, {OSTI, },
{OCLD, }, {OSTD, }, {OGP4, }, {OGP5, },
};
static Optab optab0F[256] = {
//00
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//10 - mostly floating point and quadword moves
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//20 - doubleword <-> control register moves, other arcana
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//30 - wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//40 - conditional moves
{OCMOVOS,AGv,AEv}, {OCMOVOC,AGv,AEv}, {OCMOVCS,AGv,AEv}, {OCMOVCC,AGv,AEv},
{OCMOVEQ,AGv,AEv}, {OCMOVNE,AGv,AEv}, {OCMOVLS,AGv,AEv}, {OCMOVHI,AGv,AEv},
{OCMOVMI,AGv,AEv}, {OCMOVPL,AGv,AEv}, {OCMOVPS,AGv,AEv}, {OCMOVPC,AGv,AEv},
{OCMOVLT,AGv,AEv}, {OCMOVGE,AGv,AEv}, {OCMOVLE,AGv,AEv}, {OCMOVGT,AGv,AEv},
//50 - floating point, mmx stuff
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//60 - floating point, mmx stuff
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//70 - floating point, mmx stuff
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//80 - long-displacement jumps
{OJOS, AJv, }, {OJOC, AJv, }, {OJCS, AJv, }, {OJCC, AJv, },
{OJEQ, AJv, }, {OJNE, AJv, }, {OJLS, AJv, }, {OJHI, AJv, },
{OJMI, AJv, }, {OJPL, AJv, }, {OJPS, AJv, }, {OJPC, AJv, },
{OJLT, AJv, }, {OJGE, AJv, }, {OJLE, AJv, }, {OJGT, AJv, },
//90 - conditional byte set
{OSETOS,AEb, }, {OSETOC,AEb, }, {OSETCS,AEb, }, {OSETCC,AEb, },
{OSETEQ,AEb, }, {OSETNE,AEb, }, {OSETLS,AEb, }, {OSETHI,AEb, },
{OSETMI,AEb, }, {OSETPL,AEb, }, {OSETPS,AEb, }, {OSETPC,AEb, },
{OSETLT,AEb, }, {OSETGE,AEb, }, {OSETLE,AEb, }, {OSETGT,AEb, },
//A0
{OPUSH, AFS, }, {OPOP, AFS, }, {OBAD, }, {OBT, AEv, AGv},
{OSHLD,AEv,AGv,AIb}, {OSHLD,AEv,AGv,ACL}, {OBAD, }, {OBAD, },
{OPUSH, AGS, }, {OPOP, AGS, }, {OBAD, }, {OBTS, AEv, AGv},
{OSHRD,AEv,AGv,AIb}, {OSHRD,AEv,AGv,ACL}, {OBAD, }, {OIMUL, AGv,AGv,AEv},
//B0 - mostly arcana
{OBAD, }, {OBAD, }, {OLFP,ASS,AGv,AMp},{OBAD, },
{OLFP,AFS,AGv,AMp},{OLFP,AGS,AGv,AMp},{OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//C0 - more arcana
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//D0 - mmx
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//E0 - mmx
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
//F0 - mmx
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
};
/* some operands map to whole groups; group numbers from intel opcode map */
/* args filled in already (in OGP1 entries) */
static Optab optabgp1[8] = {
{OADD, }, {OOR, }, {OADC, }, {OSBB, },
{OAND, }, {OSUB, }, {OXOR, }, {OCMP, },
};
/* args filled in already (in OGP2 entries) */
static Optab optabgp2[8] = {
{OROL, }, {OROR, }, {ORCL, }, {ORCR, },
{OSHL, }, {OSHR, }, {OBAD, }, {OSAR, },
};
static Optab optabgp3b[8] = {
{OTEST, AEb, AIb}, {OBAD, }, {ONOT, AEb, }, {ONEG, AEb, },
{OMUL,AAX,AAL,AEb},{OIMUL,AAX,AAL,AEb},{ODIV, AEb, }, {OIDIV, AEb, },
};
static Optab optabgp3v[8] = {
{OTEST, AEv, AIv}, {OBAD, }, {ONOT, AEv, }, {ONEG, AEv, },
{OMUL,AAX,AAX,AEv},{OIMUL,AAX,AAX,AEv},{ODIV, AEv, }, {OIDIV, AEv, },
};
static Optab optabgp4[8] = {
{OINC, AEb, }, {ODEC, AEb, }, {OBAD, }, {OBAD, },
{OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
};
static Optab optabgp5[8] = {
{OINC, AEv, }, {ODEC, AEv, }, {OCALL, AEv, }, {OCALL, AEp },
{OJMP, AEv, }, {OJMP, AEp, }, {OPUSH, AEv, }, {OBAD, },
};
/* optabg6 unimplemented - mostly segment manipulation */
/* optabg7 unimplemented - more segment manipulation */
/* optabg8 unimplemented - bit tests */
/*
* most of optabg9 - optabg16 decode differently depending on the mod value of
* the modrm byte. they're mostly arcane instructions so they're not
* implemented.
*/
/*
* the above tables are in intel order, in which data moves right to left.
* change to plan9, left to right.
*/
static void
revtab(Optab *o, int n)
{
int i, t;
for(i=0; i<n; i++){
if(o[i].arg1!=ANONE && o[i].arg2!=ANONE && o[i].arg3==ANONE){
t = o[i].arg1;
o[i].arg1 = o[i].arg2;
o[i].arg2 = t;
}
}
}
void
plan9order(void)
{
revtab(optab, nelem(optab));
revtab(optab0F, nelem(optab0F));
/* revtab gp3b and gp3v? */
}
static Optab *optabgp[NUMOP] = {
[OGP1] optabgp1,
[OGP2] optabgp2,
[OGP3b] optabgp3b,
[OGP3v] optabgp3v,
[OGP4] optabgp4,
[OGP5] optabgp5,
};
static int
matchmodrm(Expr *e, Istate *is)
{
/* various memory references unimplemented */
return 0;
}
static int
isconst(Expr *e)
{
if(e == nil)
return 0;
switch(e->op){
case ENAME:
return 1;
case ECONST:
return 1;
case EMUL:
case EADD:
case ESUB:
return isconst(e->arg[0]) && isconst(e->arg[1]);
default:
return 0;
}
}
static int
matcharg(int a, Expr *e, Istate *is)
{
int seg;
int off;
if(a==ANONE && e==nil)
return 1;
if(a==ANONE || e==nil)
return 0;
switch(a){
case AAp: /* seg:off immediate address */
if(e->op==ESEG && isconst(e->arg[0]) && isconst(e->arg[1])){
seg = e->arg[0]->con;
is->byte[is->nbyte++] = seg;
is->byte[is->nbyte++] = seg>>8;
off = e->arg[0]->con;
is->byte[is->nbyte++] = off;
is->byte[is->nbyte++] = off>>8;
return 1;
}
return 0;
case AEb: /* r/m8 from modrm byte */
if(e->op==EREG && e->sz==8 && e->reg<8){
is->mod = 3;
is->rm = e->reg;
is->needmodrm = 1;
return 1;
}
if(e->op==EBYTE && matchmodrm(e, is))
return 1;
return 0;
case AEp: /* call indirect through memory */
if(e->op==EADDR && matchmodrm(e, is))
return 1;
return 0;
case AEw:
case AEv: /* r/m16 or r/m32 from modrm byte */
if(e->op==EREG && e->sz==16 && e->reg<8){
is->mod = 3;
is->rm = e->reg;
is->needmodrm = 1;
return 1;
}
if(e->op==EWORD && matchmodrm(e, is))
return 1;
return 0;
case AGb: /* r8 from modrm byte */
if(e->op==EREG && e->sz==8 && e->reg<8){
is->rop = e->reg;
is->needmodrm = 1;
return 1;
}
return 0;
case AGv: /* r16 or r32 from modrm byte */
if(e->op==EREG && e->sz==16 && e->reg<8){
is->rop = e->reg;
is->needmodrm = 1;
return 1;
}
return 0;
case AGw: /* r/m 16 */
if(e->op==EREG && e->sz==16 && e->reg<8){
is->rop = e->reg;
is->needmodrm = 1;
return 1;
}
return 0;
case AIb: /* immediate byte */
if(isconst(e) && 0x00 <= e->con && e->con <= 0xFF){
is->consz = 1;
is->conoff = is->nbyte;
is->byte[is->nbyte++] = e->con;
return 1;
}
return 0;
case AIc: /* immediate byte sign-extended */
if(isconst(e) && -0x80 <= e->con && e->con <= 0x7F){
is->consz = 1;
is->conoff = is->nbyte;
is->byte[is->nbyte++] = e->con;
return 1;
}
return 0;
case AIw: /* immediate 16-bit word */
if(isconst(e)){
is->consz = 2;
is->conoff = is->nbyte;
is->byte[is->nbyte++] = e->con;
is->byte[is->nbyte++] = e->con>>8;
return 1;
}
return 0;
case AIv: /* immediate 16-bit or 32-bit word */
if(isconst(e)){
is->consz = 2;
is->conoff = is->nbyte;
is->byte[is->nbyte++] = e->con;
is->byte[is->nbyte++] = e->con>>8;
return 1;
}
return 0;
case AJb: /* relative offset byte */
if(e->sz==1){
is->jmpoff = is->nbyte++;
return 1;
}
return 0;
case AJv: /* relative offset 16-bit or 32-bit word */
if(e->sz==2){
is->jmpoff = is->nbyte;
is->nbyte += 2;
return 1;
}
return 0;
case AJr: /* r/m16 or r/m32 register */
if(e->op==EREG && e->sz==16 && e->reg<8){
is->needmodrm = 1;
is->mod = 3;
is->rm = e->reg;
return 1;
}
return 0;
case AM: /* memory address from modrm */
if(e->op==EADDR && matchmodrm(e, is))
return 1;
return 0;
case AMa: /* something for bound? */
if(e->op==EADDR && matchmodrm(e, is))
return 1;
return 0;
case AMp: /* 32-bit or 48-bit memory address */
return e->op==EADDR && matchmodrm(e, is);
case AOb: /* immediate word-sized offset to a byte */
return 0;
case AOv: /* immediate word-sized offset to a word */
return 0;
case ASw: /* segment register selected by field of modrm */
if(e->op==EREG && e->reg >= RES && e->reg <= RDS){
is->needmodrm = 1;
is->rop = e->reg - RES;
return 1;
}
return 0;
case AAL:
return e->op==EREG && e->sz==8 && e->reg==RAL;
case ACL:
return e->op==EREG && e->sz==8 && e->reg==RCL;
case ADL:
return e->op==EREG && e->sz==8 && e->reg==RDL;
case ABL:
return e->op==EREG && e->sz==8 && e->reg==RBL;
case AAH:
return e->op==EREG && e->sz==8 && e->reg==RAH;
case ACH:
return e->op==EREG && e->sz==8 && e->reg==RCH;
case ADH:
return e->op==EREG && e->sz==8 && e->reg==RDH;
case ABH:
return e->op==EREG && e->sz==8 && e->reg==RBH;
case AAX:
return e->op==EREG && e->sz==16 && e->reg==RAX;
case ACX:
return e->op==EREG && e->sz==16 && e->reg==RCX;
case ADX:
return e->op==EREG && e->sz==16 && e->reg==RDX;
case ABX:
return e->op==EREG && e->sz==16 && e->reg==RBX;
case ASP:
return e->op==EREG && e->sz==16 && e->reg==RSP;
case ABP:
return e->op==EREG && e->sz==16 && e->reg==RBP;
case ASI:
return e->op==EREG && e->sz==16 && e->reg==RSI;
case ADI:
return e->op==EREG && e->sz==16 && e->reg==RDI;
case AES:
return e->op==EREG && e->sz==16 && e->reg==RES;
case ACS:
return e->op==EREG && e->sz==16 && e->reg==RCS;
case ASS:
return e->op==EREG && e->sz==16 && e->reg==RSS;
case ADS:
return e->op==EREG && e->sz==16 && e->reg==RDS;
case AFS:
return e->op==EREG && e->sz==16 && e->reg==RFS;
case AGS:
return e->op==EREG && e->sz==16 && e->reg==RGS;
default:
return 0;
}
}
static void
match(Optab *o, int b, Inst *inst, Istate *is)
{
uchar xb[16];
int nxb;
int i, modrmoff;
Istate ts, ots;
Optab *og;
switch(o->op){
case O0F:
ots = *is;
ots.byte[ots.nbyte++] = 0x0F;
for(i=0; i<nelem(optab0F); i++){
ts = ots;
match(&optab0F[i], i, inst, &ts);
}
return;
case OGP1:
case OGP2:
case OGP3b:
case OGP3v:
case OGP4:
case OGP5:
ots = *is;
og = optabgp[o->op];
for(i=0; i<8; i++){
if(o->arg1!=ANONE)
og[i].arg1 = o->arg1;
if(o->arg2!=ANONE)
og[i].arg2 = o->arg2;
if(o->arg3!=ANONE)
og[i].arg3 = o->arg3;
ts = ots;
ts.rop = i;
ts.needmodrm = 1;
match(&og[i], b, inst, &ts);
}
return;
}
if(o->op != inst->op)
return;
ts = *is;
ts.byte[ts.nbyte++] = b;
modrmoff = ts.nbyte;
if(!matcharg(o->arg1, inst->arg[0], &ts))
return;
if(!matcharg(o->arg2, inst->arg[1], &ts))
return;
if(!matcharg(o->arg3, inst->arg[2], &ts))
return;
if(ts.needmodrm){
nxb = ts.nbyte - modrmoff;
memmove(xb, ts.byte+modrmoff, nxb);
ts.nbyte = modrmoff;
ts.byte[ts.nbyte++] = (ts.mod<<6) | (ts.rop<<3) | ts.rm;
if(ts.mod==1)
ts.byte[ts.nbyte++] = ts.disp;
if((ts.mod==0 && ts.rm==6) || ts.mod==2){
ts.byte[ts.nbyte++] = ts.disp;
ts.byte[ts.nbyte++] = ts.disp>>8;
}
memmove(ts.byte+ts.nbyte, xb, nxb);
ts.nbyte += nxb;
}
if(ts.nbyte < inst->nbyte)
inst->Istate = ts;
}
static int isjmp[NUMOP] =
{
[OJCXZ] 1,
[OJOS] 1,
[OJOC] 1,
[OJCS] 1,
[OJCC] 1,
[OJEQ] 1,
[OJNE] 1,
[OJLS] 1,
[OJHI] 1,
[OJMI] 1,
[OJPL] 1,
[OJPS] 1,
[OJPC] 1,
[OJLT] 1,
[OJGE] 1,
[OJLE] 1,
[OJGT] 1,
[OJMP] 1,
};
static uchar prefix[] = { 0xF0, 0xF2, 0xF3, 0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65 };
static int
domatch(Inst *inst)
{
int i;
Istate ts;
memset(&ts, 0, sizeof ts);
for(i=0; i<inst->npref; i++)
ts.byte[ts.nbyte++] = prefix[inst->pref[i]];
inst->nbyte = 1000;
for(i=0; i<nelem(optab); i++)
match(&optab[i], i, inst, &ts);
if(inst->nbyte == 1000)
return -1;
return 0;
}
int
assinst(Inst *inst)
{
/* calc both spans
if(isjmp[inst->op] && inst->arg[0] && inst->arg[0]->op != EREG){
if(inst->arg[0]==nil)
return -1;
inst->arg[0]->sz = 1;
if(domatch(inst) < 0)
return -1;
inst->span1 = inst->Istate;
inst->arg[0]->sz = 2;
if(domatch(inst) < 0)
return -1;
inst->span2 = inst->Istate;
inst->isspan = 1;
return 0;
}
*/
/* punt on spans for now: */
if(isjmp[inst->op] && isconst(inst->arg[0]))
inst->arg[0]->sz = 2;
if(inst->op == OLABEL){
inst->nbyte = 0;
return 0;
}
return domatch(inst);
}
|