Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Created September 13, 2015 13:15
Show Gist options
  • Save rikkimax/91cac344963bad098bc2 to your computer and use it in GitHub Desktop.
Save rikkimax/91cac344963bad098bc2 to your computer and use it in GitHub Desktop.
module bytecode.opcodes;
enum OpCode {
nop = 0x00,
add = 0x10,
sub = 0x11,
mul = 0x12,
div = 0x13,
mod = 0x14,
neg = 0x15,
bitand = 0x18,
bitor = 0x19,
bitxor = 0x1A,
bitnot = 0x1B,
shiftl = 0x1C,
sshiftr = 0x1D,
ushiftr = 0x1E,
jump = 0x20,
jz = 0x22,
jnz = 0x23,
jeq = 0x24,
jne = 0x25,
jlt = 0x26,
jge = 0x27,
jgt = 0x28,
jle = 0x29,
jltu = 0x2A,
jgeu = 0x2B,
jgtu = 0x2C,
jleu = 0x2D,
call = 0x30,
ret = 0x31,
excc = 0x32, // catch exception
exct = 0x33, // throw exception
tailcall = 0x34,
copy = 0x40,
copys = 0x41,
copyb = 0x42,
sexs = 0x44,
sexb = 0x45,
aload = 0x48,
aloads = 0x49,
aloadb = 0x4A,
aloadbit = 0x4B,
astore = 0x4C,
astores = 0x4D,
astoreb = 0x4E,
astorebit = 0x4F,
stkcount = 0x50,
stkpeek = 0x51,
stkswap = 0x52,
stkroll = 0x53,
stkcopy = 0x54,
streamchar = 0x70,
streamnum = 0x71,
streamstr = 0x72,
streamunichar = 0x73,
gestalt = 0x100,
debugtrap = 0x101,
getmemsize = 0x102,
setmemsize = 0x103,
jumpabs = 0x104,
random = 0x110,
setrandom = 0x111,
quit = 0x120,
verify = 0x121,
restart = 0x122,
save = 0x123,
restore = 0x124,
saveundo = 0x125,
restoreundo = 0x126,
protect = 0x127,
glk = 0x130,
getstringtbl = 0x140,
setstringtbl = 0x141,
getiosys = 0x148,
setiosys = 0x149,
linearsearch = 0x150,
binarysearch = 0x151,
linkedsearch = 0x152,
callf = 0x160,
callfi = 0x161,
callfii = 0x162,
callfiii = 0x163,
mzero = 0x170,
mcopy = 0x171,
malloc = 0x178,
mfree = 0x179,
accelfunc = 0x180,
accelparam = 0x181,
numtof = 0x190,
ftonumz = 0x191,
ftonumn = 0x192,
ceil = 0x198,
floor = 0x199,
fadd = 0x1A0,
fsub = 0x1A1,
fmul = 0x1A2,
fdiv = 0x1A3,
fmod = 0x1A4,
sqrt = 0x1A8,
exp = 0x1A9,
log = 0x1AA,
pow = 0x1AB,
sin = 0x1B0,
cos = 0x1B1,
tan = 0x1B2,
asin = 0x1B3,
acos = 0x1B4,
atan = 0x1B5,
atan2 = 0x1B6,
jfeq = 0x1C0,
jfne = 0x1C1,
jflt = 0x1C2,
jfle = 0x1C3,
jfgt = 0x1C4,
jfge = 0x1C5,
jisnan = 0x1C8,
jisinf = 0x1C9
}
enum OpCodeByteCount : ubyte {
one = 1,
two = 2,
four = 4
}
OpCodeByteCount byteCount(uint op) pure @safe @nogc {
if (op & 0x80) {
// > 1 byte
if (op & 0x40) {
// == 4 bytes
return OpCodeByteCount.four;
} else {
// == 2 bytes
return OpCodeByteCount.two;
}
} else {
return OpCodeByteCount.one;
}
}
OpCode decodeOpCode(uint v) pure @safe @nogc {
import std.bitmanip : nativeToLittleEndian;
ubyte[4] bytes = nativeToLittleEndian(cast(uint)v);
v = bytes[0];
OpCodeByteCount count = byteCount(v);
if (count == 1) {
return cast(OpCode)v;
} else if (count == 2) {
v &= 0x7f;
v <<= 8;
v |= bytes[1];
return cast(OpCode)v;
} else if (count == 4) {
v &= ~0xC0;
v <<= 24;
v |= bytes[1] << 16;
v |= bytes[2] << 8;
v |= bytes[3];
return cast(OpCode)v;
} else {
assert(0);
}
}
uint encodeOpCode(OpCode v) pure @safe @nogc {
import std.bitmanip : nativeToLittleEndian;
ubyte[4] bytes = nativeToLittleEndian(cast(uint)v);
if (bytes[3] != 0 || bytes[2] != 0) {
v = cast(OpCode)(bytes[3] | bytes[2] << 8 | bytes[1] << 16 | bytes[0] << 24);
return cast(uint)v | 0xC0;
} else if (bytes[1] != 0) {
v = cast(OpCode)(bytes[1] | bytes[0] << 8);
return cast(uint)v | 0x80;
} else {
return cast(uint)v;
}
}
pure @safe @nogc
unittest {
assert(encodeOpCode(OpCode.nop).decodeOpCode == OpCode.nop);
assert(encodeOpCode(OpCode.add).decodeOpCode == OpCode.add);
assert(encodeOpCode(OpCode.sub).decodeOpCode == OpCode.sub);
assert(encodeOpCode(OpCode.mul).decodeOpCode == OpCode.mul);
assert(encodeOpCode(OpCode.div).decodeOpCode == OpCode.div);
assert(encodeOpCode(OpCode.mod).decodeOpCode == OpCode.mod);
assert(encodeOpCode(OpCode.neg).decodeOpCode == OpCode.neg);
assert(encodeOpCode(OpCode.bitand).decodeOpCode == OpCode.bitand);
assert(encodeOpCode(OpCode.bitor).decodeOpCode == OpCode.bitor);
assert(encodeOpCode(OpCode.bitxor).decodeOpCode == OpCode.bitxor);
assert(encodeOpCode(OpCode.bitnot).decodeOpCode == OpCode.bitnot);
assert(encodeOpCode(OpCode.shiftl).decodeOpCode == OpCode.shiftl);
assert(encodeOpCode(OpCode.sshiftr).decodeOpCode == OpCode.sshiftr);
assert(encodeOpCode(OpCode.ushiftr).decodeOpCode == OpCode.ushiftr);
assert(encodeOpCode(OpCode.jump).decodeOpCode == OpCode.jump);
assert(encodeOpCode(OpCode.jz).decodeOpCode == OpCode.jz);
assert(encodeOpCode(OpCode.jnz).decodeOpCode == OpCode.jnz);
assert(encodeOpCode(OpCode.jeq).decodeOpCode == OpCode.jeq);
assert(encodeOpCode(OpCode.jne).decodeOpCode == OpCode.jne);
assert(encodeOpCode(OpCode.jlt).decodeOpCode == OpCode.jlt);
assert(encodeOpCode(OpCode.jge).decodeOpCode == OpCode.jge);
assert(encodeOpCode(OpCode.jgt).decodeOpCode == OpCode.jgt);
assert(encodeOpCode(OpCode.jle).decodeOpCode == OpCode.jle);
assert(encodeOpCode(OpCode.jltu).decodeOpCode == OpCode.jltu);
assert(encodeOpCode(OpCode.jgeu).decodeOpCode == OpCode.jgeu);
assert(encodeOpCode(OpCode.jgtu).decodeOpCode == OpCode.jgtu);
assert(encodeOpCode(OpCode.jleu).decodeOpCode == OpCode.jleu);
assert(encodeOpCode(OpCode.call).decodeOpCode == OpCode.call);
assert(encodeOpCode(OpCode.ret).decodeOpCode == OpCode.ret);
assert(encodeOpCode(OpCode.excc).decodeOpCode == OpCode.excc);
assert(encodeOpCode(OpCode.exct).decodeOpCode == OpCode.exct);
assert(encodeOpCode(OpCode.tailcall).decodeOpCode == OpCode.tailcall);
assert(encodeOpCode(OpCode.copy).decodeOpCode == OpCode.copy);
assert(encodeOpCode(OpCode.copys).decodeOpCode == OpCode.copys);
assert(encodeOpCode(OpCode.copyb).decodeOpCode == OpCode.copyb);
assert(encodeOpCode(OpCode.sexs).decodeOpCode == OpCode.sexs);
assert(encodeOpCode(OpCode.sexb).decodeOpCode == OpCode.sexb);
assert(encodeOpCode(OpCode.aload).decodeOpCode == OpCode.aload);
assert(encodeOpCode(OpCode.aloads).decodeOpCode == OpCode.aloads);
assert(encodeOpCode(OpCode.aloadb).decodeOpCode == OpCode.aloadb);
assert(encodeOpCode(OpCode.aloadbit).decodeOpCode == OpCode.aloadbit);
assert(encodeOpCode(OpCode.astore).decodeOpCode == OpCode.astore);
assert(encodeOpCode(OpCode.astores).decodeOpCode == OpCode.astores);
assert(encodeOpCode(OpCode.astoreb).decodeOpCode == OpCode.astoreb);
assert(encodeOpCode(OpCode.astorebit).decodeOpCode == OpCode.astorebit);
assert(encodeOpCode(OpCode.stkcount).decodeOpCode == OpCode.stkcount);
assert(encodeOpCode(OpCode.stkpeek).decodeOpCode == OpCode.stkpeek);
assert(encodeOpCode(OpCode.stkswap).decodeOpCode == OpCode.stkswap);
assert(encodeOpCode(OpCode.stkroll).decodeOpCode == OpCode.stkroll);
assert(encodeOpCode(OpCode.stkcopy).decodeOpCode == OpCode.stkcopy);
assert(encodeOpCode(OpCode.streamchar).decodeOpCode == OpCode.streamchar);
assert(encodeOpCode(OpCode.streamnum).decodeOpCode == OpCode.streamnum);
assert(encodeOpCode(OpCode.streamstr).decodeOpCode == OpCode.streamstr);
assert(encodeOpCode(OpCode.streamunichar).decodeOpCode == OpCode.streamunichar);
assert(encodeOpCode(OpCode.gestalt).decodeOpCode == OpCode.gestalt);
assert(encodeOpCode(OpCode.debugtrap).decodeOpCode == OpCode.debugtrap);
assert(encodeOpCode(OpCode.getmemsize).decodeOpCode == OpCode.getmemsize);
assert(encodeOpCode(OpCode.setmemsize).decodeOpCode == OpCode.setmemsize);
assert(encodeOpCode(OpCode.jumpabs).decodeOpCode == OpCode.jumpabs);
assert(encodeOpCode(OpCode.random).decodeOpCode == OpCode.random);
assert(encodeOpCode(OpCode.setrandom).decodeOpCode == OpCode.setrandom);
assert(encodeOpCode(OpCode.quit).decodeOpCode == OpCode.quit);
assert(encodeOpCode(OpCode.verify).decodeOpCode == OpCode.verify);
assert(encodeOpCode(OpCode.restart).decodeOpCode == OpCode.restart);
assert(encodeOpCode(OpCode.save).decodeOpCode == OpCode.save);
assert(encodeOpCode(OpCode.restore).decodeOpCode == OpCode.restore);
assert(encodeOpCode(OpCode.saveundo).decodeOpCode == OpCode.saveundo);
assert(encodeOpCode(OpCode.restoreundo).decodeOpCode == OpCode.restoreundo);
assert(encodeOpCode(OpCode.protect).decodeOpCode == OpCode.protect);
assert(encodeOpCode(OpCode.glk).decodeOpCode == OpCode.glk);
assert(encodeOpCode(OpCode.getstringtbl).decodeOpCode == OpCode.getstringtbl);
assert(encodeOpCode(OpCode.setstringtbl).decodeOpCode == OpCode.setstringtbl);
assert(encodeOpCode(OpCode.getiosys).decodeOpCode == OpCode.getiosys);
assert(encodeOpCode(OpCode.setiosys).decodeOpCode == OpCode.setiosys);
assert(encodeOpCode(OpCode.linearsearch).decodeOpCode == OpCode.linearsearch);
assert(encodeOpCode(OpCode.binarysearch).decodeOpCode == OpCode.binarysearch);
assert(encodeOpCode(OpCode.linkedsearch).decodeOpCode == OpCode.linkedsearch);
assert(encodeOpCode(OpCode.callf).decodeOpCode == OpCode.callf);
assert(encodeOpCode(OpCode.callfi).decodeOpCode == OpCode.callfi);
assert(encodeOpCode(OpCode.callfii).decodeOpCode == OpCode.callfii);
assert(encodeOpCode(OpCode.callfiii).decodeOpCode == OpCode.callfiii);
assert(encodeOpCode(OpCode.mzero).decodeOpCode == OpCode.mzero);
assert(encodeOpCode(OpCode.mcopy).decodeOpCode == OpCode.mcopy);
assert(encodeOpCode(OpCode.malloc).decodeOpCode == OpCode.malloc);
assert(encodeOpCode(OpCode.mfree).decodeOpCode == OpCode.mfree);
assert(encodeOpCode(OpCode.accelfunc).decodeOpCode == OpCode.accelfunc);
assert(encodeOpCode(OpCode.accelparam).decodeOpCode == OpCode.accelparam);
assert(encodeOpCode(OpCode.numtof).decodeOpCode == OpCode.numtof);
assert(encodeOpCode(OpCode.ftonumz).decodeOpCode == OpCode.ftonumz);
assert(encodeOpCode(OpCode.ftonumn).decodeOpCode == OpCode.ftonumn);
assert(encodeOpCode(OpCode.ceil).decodeOpCode == OpCode.ceil);
assert(encodeOpCode(OpCode.floor).decodeOpCode == OpCode.floor);
assert(encodeOpCode(OpCode.fadd).decodeOpCode == OpCode.fadd);
assert(encodeOpCode(OpCode.fsub).decodeOpCode == OpCode.fsub);
assert(encodeOpCode(OpCode.fmul).decodeOpCode == OpCode.fmul);
assert(encodeOpCode(OpCode.fdiv).decodeOpCode == OpCode.fdiv);
assert(encodeOpCode(OpCode.fmod).decodeOpCode == OpCode.fmod);
assert(encodeOpCode(OpCode.sqrt).decodeOpCode == OpCode.sqrt);
assert(encodeOpCode(OpCode.exp).decodeOpCode == OpCode.exp);
assert(encodeOpCode(OpCode.log).decodeOpCode == OpCode.log);
assert(encodeOpCode(OpCode.pow).decodeOpCode == OpCode.pow);
assert(encodeOpCode(OpCode.sin).decodeOpCode == OpCode.sin);
assert(encodeOpCode(OpCode.cos).decodeOpCode == OpCode.cos);
assert(encodeOpCode(OpCode.tan).decodeOpCode == OpCode.tan);
assert(encodeOpCode(OpCode.asin).decodeOpCode == OpCode.asin);
assert(encodeOpCode(OpCode.acos).decodeOpCode == OpCode.acos);
assert(encodeOpCode(OpCode.atan).decodeOpCode == OpCode.atan);
assert(encodeOpCode(OpCode.atan2).decodeOpCode == OpCode.atan2);
assert(encodeOpCode(OpCode.jfeq).decodeOpCode == OpCode.jfeq);
assert(encodeOpCode(OpCode.jfne).decodeOpCode == OpCode.jfne);
assert(encodeOpCode(OpCode.jflt).decodeOpCode == OpCode.jflt);
assert(encodeOpCode(OpCode.jfle).decodeOpCode == OpCode.jfle);
assert(encodeOpCode(OpCode.jfgt).decodeOpCode == OpCode.jfgt);
assert(encodeOpCode(OpCode.jfge).decodeOpCode == OpCode.jfge);
assert(encodeOpCode(OpCode.jisnan).decodeOpCode == OpCode.jisnan);
assert(encodeOpCode(OpCode.jisinf).decodeOpCode == OpCode.jisinf);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment