ref: 7b65afc1ad13f3859eca6eadaa2c45d864320304
dir: /opcodes.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "dat.h" #include "fns.h" char *regnames[Reg_max] = { [RegIp] = "ip", [RegMod] = "mod", [RegFunc] = "func", [RegSp] = "sp", [RegFp] = "fp", [RegX] = "x", [RegY] = "y", [RegF] = "f", [RegG] = "g", [RegR] = "r", [RegT] = "t", }; OpcodeSpec optab[O_max] = { [Onop] = {"nop", 0}, [Oexit] = {"exit", 0}, [Ocall] = {"call", 1}, [Oreturn] = {"return", 0}, [Omov] = {"mov", 2}, [Olocals] = {"locals", 1}, [Oscalnum] = {"scalnum", 2}, [Odisplay] = {"display", 1}, }; void encodeinstr(ParsedInstr *p, Label *labels, uvlong nlabels) { /* Encoding: * 1 byte opcode * optional 1 byte argument info * optional 1st arg * optional 2nd arg */ u8int *d = p->buf; *d++ = p->opcode; if(optab[p->opcode].args > 0){ u8int info = 0; info |= (p->args[0].tag & 0xF) << 0; info |= (p->args[1].tag & 0xF) << 4; *d++ = info; int l; for(int i = 0; i < optab[p->opcode].args; i++){ OpArg arg = p->args[i]; switch(arg.tag){ case OAlabel: for(l = 0; l < nlabels; l++){ if(strcmp(arg.cp, labels[l].name) == 0){ d += write8u(d, labels[l].coffset); break; } } if(l == nlabels) sysfatal("Undefined label %s", arg.cp); break; case OAreg: d += write1u(d, arg.u64); break; case OAlocal1: d += write1u(d, arg.u64); break; case OAlocal2: d += write2u(d, arg.u64); break; case OAlocal4: d += write4u(d, arg.u64); break; case OAlocal8: d += write8u(d, arg.u64); break; case OAnum1: d += write1s(d, arg.s64); break; case OAnum2: d += write2s(d, arg.s64); break; case OAnum4: d += write4s(d, arg.s64); break; case OAnum8: d += write8s(d, arg.s64); break; default: sysfatal("missing case in encodeinstr: %d", p->args[i].tag); } } } p->len = d - p->buf; } void encodelabel(ParsedInstr *p, Label *labels, uvlong nlabels) { int islabel = 0; for(int i = 0; i < optab[p->opcode].args; i++){ if(p->args[i].tag == OAlabel) islabel = 1; } if(islabel) encodeinstr(p, labels, nlabels); } void decodeinstr(u8int *d, ParsedInstr *p, Label *labels, uvlong nlabels) { u8int *c = d; int fast = (labels == nil); p->opcode = *c++; int args = optab[p->opcode].args; if(args){ u8int info = *c++; for(int i = 0; i < args; i++){ p->args[i].tag = info & 0xF; info = info >> 4; u64int u64; int l; switch(p->args[i].tag){ case OAlabel: u64 = read8u(c); c += 8; if(fast){ p->args[i].u64 = u64; }else{ for(l = 0; l < nlabels; l++){ if(labels[l].coffset == u64) break; } if(l == nlabels) sysfatal("couldn't find label at offset %ulld", u64); p->args[i].cp = strdup(labels[l].name); } break; case OAreg: p->args[i].u64 = read1u(c); c += 1; break; case OAlocal1: p->args[i].u64 = read1u(c); c += 1; break; case OAlocal2: p->args[i].u64 = read2u(c); c += 2; break; case OAlocal4: p->args[i].u64 = read4u(c); c += 4; break; case OAlocal8: p->args[i].u64 = read8u(c); c += 8; break; case OAnum1: p->args[i].s64 = read1s(c); c += 1; break; case OAnum2: p->args[i].s64 = read2s(c); c += 2; break; case OAnum4: p->args[i].s64 = read4s(c); c += 4; break; case OAnum8: p->args[i].s64 = read8s(c); c += 8; break; default: sysfatal("missing case in decodeinstr: %d", p->args[i].tag); } } } p->len = c - d; if(!fast) memcpy(p->buf, d, p->len); }