#include <u.h>
#include <libc.h>
#include <bio.h>
AsmRule **asmrule;
int nasmrule;
static void
addrule(AsmRule a)
{
if(nasmrule%32 == 0)
asmrule = erealloc(asmrule, (nasmrule+32)*sizeof(asmrule[0]));
asmrule[nasmrule++] = a;
}
void
readrules(void)
{
char *s;
int nf;
char *f[10], *g[2];
int i, n;
AsmRule a;
Biobuf *b;
if((b = Bopen("inst.txt", OREAD)) == nil)
sysfatal("open inst.txt: %r");
while((s = Brdline(b, '\n')) != nil){
s[Blinelen(b)-1] = '\0';
memset(&a, 0, sizeof a);
if((nf = getfields(s, f, nelem(f), 1, "\t")) != 3){
fprint(2, "bad line: %s\n", s);
continue;
}
if(getfields(f[0], a.byte, nelem(a.byte), 1, " ") >= 4){
fprint(2, "bad bytes\n");
continue;
}
for(i=0; i<nelem(a.byte); i++)
if(a.byte[i])
a.byte[i] = atom(a.byte[i]);
if(getfields(f[1], g, nelem(g), 1, " ") == 1)
g[1] = "";
a.op = atom(g[0]);
getfields(g[1], a.arg, nelem(a.arg), 0, ",");
for(i=0; i<nelem(a.arg); i++)
if(a.arg[i])
a.arg[i] = atom(a.arg[i]);
addrule(&a);
}
}
typedef struct Asm Asm;
struct Asm
{
uint sib;
uint havesib;
uint mod;
uint r;
uint rm;
uint havemodrm;
uint disp;
uint ndisp;
uint imm;
uint nimm;
};
static int
cancoerce(Asm *m, Expr *e, char *arg)
{
switch(e->ty){
case ExReg8:
if(e->r8 == RAL && strcmp(arg, "AL") == 0)
return 1;
if(strcmp(arg, "r8") == 0){
m->r = e->r8;
m->havemodrm = 1;
return 1;
}
if(strcmp(arg, "r/m8") == 0){
m->rm = e->r8;
m->havemodrm = 1;
return 1;
}
return 0;
case ExReg32:
if(e->r32 == RAX && strcmp(arg, "EAX") == 0)
return 1;
if(strcmp(arg, "r32") == 0){
m->r = e->r32;
m->havemodrm = 1;
return 1;
}
if(strcmp(arg, "r/m32") == 0){
m->rm = e->r32;
m->havemodrm = 1;
return 1;
}
return 0;
case ExMem:
if(strcmp(arg, "r/m8") == 0 || strcmp(arg, "r/m32") == 0){
m->havemodrm = 1;
if(e->m.scale != -1 || e->m.index != -1){
m->havesib = 1;
m->sib = xxx;
}
if(e->m.disp != 0){
return 1;
}
return 0;
case ExConst:
if(e->i==1 && strcmp(arg, "1") == 0)
return 1;
if(e->i==3 && strcmp(arg, "3") == 0)
return 1;
if(-128 <= (signed)e->i && (signed)e->i <= 127 && strcmp(arg, "imm8) == 0){
m->imm = e->i;
m->nimm = 1;
return 1;
}
if(strcmp(arg, "imm32") == 0){
m->imm = e->i;
m->nimm = 4;
return 1;
}
return 0;
}
static int
match(AsmRule *a, Inst *inst)
{
int i;
Asm m;
if(inst->op != a->op)
return 0;
memset(&m, 0, sizeof m);
for(i=0; i<inst->ne; i++){
if(a->arg[i]==nil)
return 0;
if(!cancoerce(inst, &inst->e[i], a->arg[i]))
return 0;
}
return 1;
}
int
assem(Inst *inst)
{
int i;
AsmRule *a;
for(i=0; i<nasmrules; i++){
a = asmrules+i;
if(match(&a, inst))
return 1;
}
fprint(2, "cannot assemble %s\n", inst->op);
return 0;
}
|