Created
September 13, 2015 13:15
-
-
Save rikkimax/91cac344963bad098bc2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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