| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879 |
- // Copyright (C) 2012 Zeex
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the "Software"),
- // to deal in the Software without restriction, including without limitation
- // the rights to use, copy, modify, merge, publish, distribute, sublicense,
- // and/or sell copies of the Software, and to permit persons to whom the
- // Software is furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- // DEALINGS IN THE SOFTWARE.
- #if defined OPCODE_INC
- #endinput
- #endif
- #define OPCODE_INC
- #if __Pawn >= 0x30A
- // Disable the recursion warning in the Russian compiler.
- #pragma warning push
- #pragma warning disable 207
- #pragma disablerecursion
- #pragma warning pop
-
- // Disable the recursion warning in the fast compiler.
- #pragma warning disable 238
- #endif
- #define OPCODE_MAX_INSN_NAME 15
- enum Opcode {
- OP_NONE, OP_LOAD_PRI, OP_LOAD_ALT,
- OP_LOAD_S_PRI, OP_LOAD_S_ALT, OP_LREF_PRI,
- OP_LREF_ALT, OP_LREF_S_PRI, OP_LREF_S_ALT,
- OP_LOAD_I, OP_LODB_I, OP_CONST_PRI,
- OP_CONST_ALT, OP_ADDR_PRI, OP_ADDR_ALT,
- OP_STOR_PRI, OP_STOR_ALT, OP_STOR_S_PRI,
- OP_STOR_S_ALT, OP_SREF_PRI, OP_SREF_ALT,
- OP_SREF_S_PRI, OP_SREF_S_ALT, OP_STOR_I,
- OP_STRB_I, OP_LIDX, OP_LIDX_B,
- OP_IDXADDR, OP_IDXADDR_B, OP_ALIGN_PRI,
- OP_ALIGN_ALT, OP_LCTRL, OP_SCTRL,
- OP_MOVE_PRI, OP_MOVE_ALT, OP_XCHG,
- OP_PUSH_PRI, OP_PUSH_ALT, OP_PUSH_R,
- OP_PUSH_C, OP_PUSH, OP_PUSH_S,
- OP_POP_PRI, OP_POP_ALT, OP_STACK,
- OP_HEAP, OP_PROC, OP_RET,
- OP_RETN, OP_CALL, OP_CALL_PRI,
- OP_JUMP, OP_JREL, OP_JZER,
- OP_JNZ, OP_JEQ, OP_JNEQ,
- OP_JLESS, OP_JLEQ, OP_JGRTR,
- OP_JGEQ, OP_JSLESS, OP_JSLEQ,
- OP_JSGRTR, OP_JSGEQ, OP_SHL,
- OP_SHR, OP_SSHR, OP_SHL_C_PRI,
- OP_SHL_C_ALT, OP_SHR_C_PRI, OP_SHR_C_ALT,
- OP_SMUL, OP_SDIV, OP_SDIV_ALT,
- OP_UMUL, OP_UDIV, OP_UDIV_ALT,
- OP_ADD, OP_SUB, OP_SUB_ALT,
- OP_AND, OP_OR, OP_XOR,
- OP_NOT, OP_NEG, OP_INVERT,
- OP_ADD_C, OP_SMUL_C, OP_ZERO_PRI,
- OP_ZERO_ALT, OP_ZERO, OP_ZERO_S,
- OP_SIGN_PRI, OP_SIGN_ALT, OP_EQ,
- OP_NEQ, OP_LESS, OP_LEQ,
- OP_GRTR, OP_GEQ, OP_SLESS,
- OP_SLEQ, OP_SGRTR, OP_SGEQ,
- OP_EQ_C_PRI, OP_EQ_C_ALT, OP_INC_PRI,
- OP_INC_ALT, OP_INC, OP_INC_S,
- OP_INC_I, OP_DEC_PRI, OP_DEC_ALT,
- OP_DEC, OP_DEC_S, OP_DEC_I,
- OP_MOVS, OP_CMPS, OP_FILL,
- OP_HALT, OP_BOUNDS, OP_SYSREQ_PRI,
- OP_SYSREQ_C, OP_FILE, OP_LINE,
- OP_SYMBOL, OP_SRANGE, OP_JUMP_PRI,
- OP_SWITCH, OP_CASETBL, OP_SWAP_PRI,
- OP_SWAP_ALT, OP_PUSH_ADR, OP_NOP,
- OP_SYSREQ_D, OP_SYMTAG, OP_BREAK,
- OP_LAST_
- };
- enum OpcodeInsnInfo {
- OpcodeInsnInfo_name[OPCODE_MAX_INSN_NAME],
- OpcodeInsnInfo_num_opers,
- bool:OpcodeInsnInfo_needs_reloc
- }
- static stock const insn_table[][OpcodeInsnInfo] = {
- { "none", 0, false },
- { "load.pri", 1, false },
- { "load.alt", 1, false },
- { "load.s.pri", 1, false },
- { "load.s.alt", 1, false },
- { "lref.pri", 1, false },
- { "lref.alt", 1, false },
- { "lref.s.pri", 1, false },
- { "lref.s.alt", 1, false },
- { "load.i", 0, false },
- { "lodb.i", 1, false },
- { "const.pri", 1, false },
- { "const.alt", 1, false },
- { "addr.pri", 1, false },
- { "addr.alt", 1, false },
- { "stor.pri", 1, false },
- { "stor.alt", 1, false },
- { "stor.s.pri", 1, false },
- { "stor.s.alt", 1, false },
- { "sref.pri", 1, false },
- { "sref.alt", 1, false },
- { "sref.s.pri", 1, false },
- { "sref.s.alt", 1, false },
- { "stor.i", 0, false },
- { "strb.i", 1, false },
- { "lidx", 0, false },
- { "lidx.b", 1, false },
- { "idxaddr", 0, false },
- { "idxaddr.b", 1, false },
- { "align.pri", 1, false },
- { "align.alt", 1, false },
- { "lctrl", 1, false },
- { "sctrl", 1, false },
- { "move.pri", 0, false },
- { "move.alt", 0, false },
- { "xchg", 0, false },
- { "push.pri", 0, false },
- { "push.alt", 0, false },
- { "push.r", 1, false },
- { "push.c", 1, false },
- { "push", 1, false },
- { "push.s", 1, false },
- { "pop.pri", 0, false },
- { "pop.alt", 0, false },
- { "stack", 1, false },
- { "heap", 1, false },
- { "proc", 0, false },
- { "ret", 0, false },
- { "retn", 0, false },
- { "call", 1, true },
- { "call.pri", 0, false },
- { "jump", 1, true },
- { "jrel", 1, false },
- { "jzer", 1, true },
- { "jnz", 1, true },
- { "jeq", 1, true },
- { "jneq", 1, true },
- { "jless", 1, true },
- { "jleq", 1, true },
- { "jgrtr", 1, true },
- { "jgeq", 1, true },
- { "jsless", 1, true },
- { "jsleq", 1, true },
- { "jsgrtr", 1, true },
- { "jsgeq", 1, true },
- { "shl", 0, false },
- { "shr", 0, false },
- { "sshr", 0, false },
- { "shl.c.pri", 1, false },
- { "shl.c.alt", 1, false },
- { "shr.c.pri", 1, false },
- { "shr.c.alt", 1, false },
- { "smul", 0, false },
- { "sdiv", 0, false },
- { "sdiv.alt", 0, false },
- { "umul", 0, false },
- { "udiv", 0, false },
- { "udiv.alt", 0, false },
- { "add", 0, false },
- { "sub", 0, false },
- { "sub.alt", 0, false },
- { "and", 0, false },
- { "or", 0, false },
- { "xort", 0, false },
- { "not", 0, false },
- { "neg", 0, false },
- { "invert", 0, false },
- { "add.c", 1, false },
- { "smul.c", 1, false },
- { "zero.pri", 0, false },
- { "zero.alt", 0, false },
- { "zero", 1, false },
- { "zero.s", 1, false },
- { "sign.pri", 0, false },
- { "sign.alt", 0, false },
- { "eq", 0, false },
- { "neq", 0, false },
- { "less", 0, false },
- { "leq", 0, false },
- { "grtr", 0, false },
- { "geq", 0, false },
- { "sless", 0, false },
- { "sleq", 0, false },
- { "sgrtr", 0, false },
- { "sgeq", 0, false },
- { "eq.c.pri", 1, false },
- { "eq.c.alt", 1, false },
- { "inc.pri", 0, false },
- { "inc.alt", 0, false },
- { "inc", 1, false },
- { "inc.s", 1, false },
- { "inc.i", 0, false },
- { "dec.pri", 0, false },
- { "dec.alt", 0, false },
- { "dec", 1, false },
- { "dec.s", 1, false },
- { "dec.i", 0, false },
- { "movs", 1, false },
- { "cmps", 1, false },
- { "fill", 1, false },
- { "halt", 1, false },
- { "bounds", 1, false },
- { "sysreq.pri", 0, false },
- { "sysreq.c", 1, false },
- { "file", -1, false }, // obsolete
- { "line", -1, false }, // obsolete
- { "symbol", -1, false }, // obsolete
- { "srange", -1, false }, // obsolete
- { "jump.pri", 0, false },
- { "switch", 1, true },
- { "casetbl", -1, true },
- { "swap.pri", 0, false },
- { "swap.alt", 0, false },
- { "push.adr", 1, false },
- { "nop", 0, false },
- { "sysreq.d", 1, false },
- { "symtag", 1, false }, // obsolete
- { "break", 0, false }
- };
- const NUM_OPCODES = _:OP_LAST_;
- static stock Opcode:ReadOpcodeNearThis(offset = 0) {
- new ret_addr;
- // Get return address + COD - DAT + offset.
- #emit load.s.alt 4
- #emit lctrl 0
- #emit add
- #emit move.alt
- #emit lctrl 1
- #emit xchg
- #emit sub
- #emit load.s.alt offset
- #emit add
- #emit stor.s.pri ret_addr
- #emit lref.s.pri ret_addr
- #emit stack 4
- #emit retn
- return OP_NONE; // make compiler happy
- }
- static stock bool:HaveToRelocateOpcodes() {
- return ReadOpcodeNearThis(-8) != OP_CALL;
- }
- // Based on this idea: http://forum.sa-mp.com/showthread.php?t=358084
- stock Opcode:RelocateOpcodeNow(Opcode:opcode) {
- if (!HaveToRelocateOpcodes()) {
- return opcode;
- }
- switch (opcode) {
- case OP_LOAD_PRI: {
- return ReadOpcodeNearThis(4);
- #emit load.pri 0
- }
- case OP_LOAD_ALT: {
- return ReadOpcodeNearThis(4);
- #emit load.alt 0
- }
- case OP_LOAD_S_PRI: {
- return ReadOpcodeNearThis(4);
- #emit load.s.pri 0
- }
- case OP_LOAD_S_ALT: {
- return ReadOpcodeNearThis(4);
- #emit load.s.alt 0
- }
- case OP_LREF_PRI: {
- return ReadOpcodeNearThis(4);
- #emit lref.pri 0
- }
- case OP_LREF_ALT: {
- return ReadOpcodeNearThis(4);
- #emit lref.alt 0
- }
- case OP_LREF_S_PRI: {
- return ReadOpcodeNearThis(4);
- #emit lref.s.pri 0
- }
- case OP_LREF_S_ALT: {
- return ReadOpcodeNearThis(4);
- #emit lref.s.alt 0
- }
- case OP_LOAD_I: {
- return ReadOpcodeNearThis(4);
- #emit load.i
- }
- case OP_LODB_I: {
- return ReadOpcodeNearThis(4);
- #emit lodb.i 1
- }
- case OP_CONST_PRI: {
- return ReadOpcodeNearThis(4);
- #emit const.pri 0
- }
- case OP_CONST_ALT: {
- return ReadOpcodeNearThis(4);
- #emit const.alt 0
- }
- case OP_ADDR_PRI: {
- return ReadOpcodeNearThis(4);
- #emit addr.pri 0
- }
- case OP_ADDR_ALT: {
- return ReadOpcodeNearThis(4);
- #emit addr.alt 0
- }
- case OP_STOR_PRI: {
- return ReadOpcodeNearThis(4);
- #emit stor.pri 0
- }
- case OP_STOR_ALT: {
- return ReadOpcodeNearThis(4);
- #emit stor.alt 0
- }
- case OP_STOR_S_PRI: {
- return ReadOpcodeNearThis(4);
- #emit stor.s.pri 0
- }
- case OP_STOR_S_ALT: {
- return ReadOpcodeNearThis(4);
- #emit stor.s.alt 0
- }
- case OP_SREF_PRI: {
- return ReadOpcodeNearThis(4);
- #emit sref.pri 0
- }
- case OP_SREF_ALT: {
- return ReadOpcodeNearThis(4);
- #emit sref.alt 0
- }
- case OP_SREF_S_PRI: {
- return ReadOpcodeNearThis(4);
- #emit sref.s.pri 0
- }
- case OP_SREF_S_ALT: {
- return ReadOpcodeNearThis(4);
- #emit sref.s.alt 0
- }
- case OP_STOR_I: {
- return ReadOpcodeNearThis(4);
- #emit stor.i
- }
- case OP_STRB_I: {
- return ReadOpcodeNearThis(4);
- #emit strb.i 1
- }
- case OP_LIDX: {
- return ReadOpcodeNearThis(4);
- #emit lidx
- }
- case OP_LIDX_B: {
- return ReadOpcodeNearThis(4);
- #emit lidx.b 0
- }
- case OP_IDXADDR: {
- return ReadOpcodeNearThis(4);
- #emit idxaddr
- }
- case OP_IDXADDR_B: {
- return ReadOpcodeNearThis(4);
- #emit idxaddr.b 0
- }
- case OP_ALIGN_PRI: {
- return ReadOpcodeNearThis(4);
- #emit align.pri 0
- }
- case OP_ALIGN_ALT: {
- return ReadOpcodeNearThis(4);
- #emit align.alt 0
- }
- case OP_LCTRL: {
- return ReadOpcodeNearThis(4);
- #emit lctrl 0
- }
- case OP_SCTRL: {
- return ReadOpcodeNearThis(4);
- #emit sctrl 0
- }
- case OP_MOVE_PRI: {
- return ReadOpcodeNearThis(4);
- #emit move.pri
- }
- case OP_MOVE_ALT: {
- return ReadOpcodeNearThis(4);
- #emit move.alt
- }
- case OP_XCHG: {
- return ReadOpcodeNearThis(4);
- #emit xchg
- }
- case OP_PUSH_PRI: {
- return ReadOpcodeNearThis(4);
- #emit push.pri
- }
- case OP_PUSH_ALT: {
- return ReadOpcodeNearThis(4);
- #emit push.alt
- }
- case OP_PUSH_C: {
- return ReadOpcodeNearThis(4);
- #emit push.c 0
- }
- case OP_PUSH: {
- return ReadOpcodeNearThis(4);
- #emit push 0
- }
- case OP_PUSH_S: {
- return ReadOpcodeNearThis(4);
- #emit push.s 0
- }
- case OP_POP_PRI: {
- return ReadOpcodeNearThis(4);
- #emit pop.pri
- }
- case OP_POP_ALT: {
- return ReadOpcodeNearThis(4);
- #emit pop.alt
- }
- case OP_STACK: {
- return ReadOpcodeNearThis(4);
- #emit stack 0
- }
- case OP_HEAP: {
- return ReadOpcodeNearThis(4);
- #emit heap 0
- }
- case OP_PROC: {
- return ReadOpcodeNearThis(4);
- #emit proc
- }
- case OP_RET: {
- return ReadOpcodeNearThis(4);
- #emit ret
- }
- case OP_RETN: {
- return ReadOpcodeNearThis(4);
- #emit retn
- }
- case OP_CALL: {
- // We can't do just "#emit call 0" - this will crash compiler for some reason (bug?).
- return ReadOpcodeNearThis(-8);
- }
- case OP_JUMP: {
- return ReadOpcodeNearThis(4);
- #emit jump 0
- }
- case OP_JZER: {
- return ReadOpcodeNearThis(4);
- #emit jzer 0
- }
- case OP_JNZ: {
- return ReadOpcodeNearThis(4);
- #emit jnz 0
- }
- case OP_JEQ: {
- return ReadOpcodeNearThis(4);
- #emit jeq 0
- }
- case OP_JNEQ: {
- return ReadOpcodeNearThis(4);
- #emit jneq 0
- }
- case OP_JLESS: {
- return ReadOpcodeNearThis(4);
- #emit jless 0
- }
- case OP_JLEQ: {
- return ReadOpcodeNearThis(4);
- #emit jleq 0
- }
- case OP_JGRTR: {
- return ReadOpcodeNearThis(4);
- #emit jgrtr 0
- }
- case OP_JGEQ: {
- return ReadOpcodeNearThis(4);
- #emit jgeq 0
- }
- case OP_JSLESS: {
- return ReadOpcodeNearThis(4);
- #emit jsless 0
- }
- case OP_JSLEQ: {
- return ReadOpcodeNearThis(4);
- #emit jsleq 0
- }
- case OP_JSGRTR: {
- return ReadOpcodeNearThis(4);
- #emit jsgrtr 0
- }
- case OP_JSGEQ: {
- return ReadOpcodeNearThis(4);
- #emit jsgeq 0
- }
- case OP_SHL: {
- return ReadOpcodeNearThis(4);
- #emit shl
- }
- case OP_SHR: {
- return ReadOpcodeNearThis(4);
- #emit shr
- }
- case OP_SSHR: {
- return ReadOpcodeNearThis(4);
- #emit sshr
- }
- case OP_SHL_C_PRI: {
- return ReadOpcodeNearThis(4);
- #emit shl.c.pri 0
- }
- case OP_SHL_C_ALT: {
- return ReadOpcodeNearThis(4);
- #emit shl.c.alt 0
- }
- case OP_SHR_C_PRI: {
- return ReadOpcodeNearThis(4);
- #emit shr.c.pri 0
- }
- case OP_SHR_C_ALT: {
- return ReadOpcodeNearThis(4);
- #emit shr.c.alt 0
- }
- case OP_SMUL: {
- return ReadOpcodeNearThis(4);
- #emit smul
- }
- case OP_SDIV: {
- return ReadOpcodeNearThis(4);
- #emit sdiv
- }
- case OP_SDIV_ALT: {
- return ReadOpcodeNearThis(4);
- #emit sdiv.alt
- }
- case OP_UMUL: {
- return ReadOpcodeNearThis(4);
- #emit umul
- }
- case OP_UDIV: {
- return ReadOpcodeNearThis(4);
- #emit udiv
- }
- case OP_UDIV_ALT: {
- return ReadOpcodeNearThis(4);
- #emit udiv.alt
- }
- case OP_ADD: {
- return ReadOpcodeNearThis(4);
- #emit add
- }
- case OP_SUB: {
- return ReadOpcodeNearThis(4);
- #emit sub
- }
- case OP_SUB_ALT: {
- return ReadOpcodeNearThis(4);
- #emit sub.alt
- }
- case OP_AND: {
- return ReadOpcodeNearThis(4);
- #emit and
- }
- case OP_OR: {
- return ReadOpcodeNearThis(4);
- #emit or
- }
- case OP_XOR: {
- return ReadOpcodeNearThis(4);
- #emit xor
- }
- case OP_NOT: {
- return ReadOpcodeNearThis(4);
- #emit not
- }
- case OP_NEG: {
- return ReadOpcodeNearThis(4);
- #emit neg
- }
- case OP_INVERT: {
- return ReadOpcodeNearThis(4);
- #emit invert
- }
- case OP_ADD_C: {
- return ReadOpcodeNearThis(4);
- #emit add.c 0
- }
- case OP_SMUL_C: {
- return ReadOpcodeNearThis(4);
- #emit smul.c 0
- }
- case OP_ZERO_PRI: {
- return ReadOpcodeNearThis(4);
- #emit zero.pri
- }
- case OP_ZERO_ALT: {
- return ReadOpcodeNearThis(4);
- #emit zero.alt
- }
- case OP_ZERO: {
- return ReadOpcodeNearThis(4);
- #emit zero 0
- }
- case OP_ZERO_S: {
- return ReadOpcodeNearThis(4);
- #emit zero.s 0
- }
- case OP_SIGN_PRI: {
- return ReadOpcodeNearThis(4);
- #emit sign.pri
- }
- case OP_SIGN_ALT: {
- return ReadOpcodeNearThis(4);
- #emit sign.alt
- }
- case OP_EQ: {
- return ReadOpcodeNearThis(4);
- #emit eq
- }
- case OP_NEQ: {
- return ReadOpcodeNearThis(4);
- #emit neq
- }
- case OP_LESS: {
- return ReadOpcodeNearThis(4);
- #emit less
- }
- case OP_LEQ: {
- return ReadOpcodeNearThis(4);
- #emit leq
- }
- case OP_GRTR: {
- return ReadOpcodeNearThis(4);
- #emit grtr
- }
- case OP_GEQ: {
- return ReadOpcodeNearThis(4);
- #emit geq
- }
- case OP_SLESS: {
- return ReadOpcodeNearThis(4);
- #emit sless
- }
- case OP_SLEQ: {
- return ReadOpcodeNearThis(4);
- #emit sleq
- }
- case OP_SGRTR: {
- return ReadOpcodeNearThis(4);
- #emit sgrtr
- }
- case OP_SGEQ: {
- return ReadOpcodeNearThis(4);
- #emit sgeq
- }
- case OP_EQ_C_PRI: {
- return ReadOpcodeNearThis(4);
- #emit eq.c.pri 0
- }
- case OP_EQ_C_ALT: {
- return ReadOpcodeNearThis(4);
- #emit eq.c.alt 0
- }
- case OP_INC_PRI: {
- return ReadOpcodeNearThis(4);
- #emit inc.pri
- }
- case OP_INC_ALT: {
- return ReadOpcodeNearThis(4);
- #emit inc.alt
- }
- case OP_INC: {
- return ReadOpcodeNearThis(4);
- #emit inc 0
- }
- case OP_INC_S: {
- return ReadOpcodeNearThis(4);
- #emit inc.s 0
- }
- case OP_INC_I: {
- return ReadOpcodeNearThis(4);
- #emit inc.i
- }
- case OP_DEC_PRI: {
- return ReadOpcodeNearThis(4);
- #emit dec.pri
- }
- case OP_DEC_ALT: {
- return ReadOpcodeNearThis(4);
- #emit dec.alt
- }
- case OP_DEC: {
- return ReadOpcodeNearThis(4);
- #emit dec 0
- }
- case OP_DEC_S: {
- return ReadOpcodeNearThis(4);
- #emit dec.s 0
- }
- case OP_DEC_I: {
- return ReadOpcodeNearThis(4);
- #emit dec.i
- }
- case OP_MOVS: {
- return ReadOpcodeNearThis(4);
- #emit movs 0
- }
- case OP_CMPS: {
- return ReadOpcodeNearThis(4);
- #emit cmps 0
- }
- case OP_FILL: {
- return ReadOpcodeNearThis(4);
- #emit fill 0
- }
- case OP_HALT: {
- return ReadOpcodeNearThis(4);
- #emit halt 0
- }
- case OP_BOUNDS: {
- return ReadOpcodeNearThis(4);
- #emit bounds 0
- }
- case OP_SYSREQ_C: {
- return ReadOpcodeNearThis(4);
- #emit sysreq.c 0
- }
- case OP_SWITCH: {
- static T = 1;
- #if debug > 0
- if (T) return ReadOpcodeNearThis(12);
- #else
- if (T) return ReadOpcodeNearThis(8);
- #endif
- switch (0) {
- case 0: {}
- }
- }
- case OP_CASETBL: {
- new x = 0;
- switch (x) { case 0: return ReadOpcodeNearThis(20); }
- }
- case OP_SWAP_PRI: {
- return ReadOpcodeNearThis(4);
- #emit swap.pri
- }
- case OP_SWAP_ALT: {
- return ReadOpcodeNearThis(4);
- #emit swap.alt
- }
- case OP_PUSH_ADR: {
- return ReadOpcodeNearThis(4);
- #emit push.adr 0
- }
- case OP_NOP: {
- return ReadOpcodeNearThis(4);
- #emit nop
- }
- case OP_SYSREQ_D: {
- // Since there's no way to #emit sysreq.d we have to compute its
- // address using a relative offset to another opcode, e.g. nop.
- new bool:is_crashdetect;
- #emit zero.pri
- #emit lctrl 0xFF
- #emit stor.s.pri is_crashdetect
- if (is_crashdetect) {
- // The offset is different when running under crashdetect as
- // it uses its own (modified) version of the VM. This value
- // value works only with crashdetect 4.13.
- return RelocateOpcodeNow(OP_NOP) - Opcode:0x1EA;
- } else {
- return RelocateOpcodeNow(OP_NOP) - Opcode:0x4F;
- }
- }
- case OP_BREAK: {
- return ReadOpcodeNearThis(4);
- #emit break
- }
- }
- return opcode;
- }
- static stock Opcode:opcode_table[NUM_OPCODES];
- static stock bool:opcode_table_is_ready = false;
- stock bool:IsOpcodeValid(Opcode:opcode) {
- return (OP_NONE <= opcode < Opcode:NUM_OPCODES);
- }
- static stock InitOpcodeTable() {
- for (new i = 0; i < NUM_OPCODES; i++) {
- opcode_table[i] = RelocateOpcodeNow(Opcode:i);
- }
- opcode_table_is_ready = true;
- }
- stock Opcode:RelocateOpcode(Opcode:opcode) {
- if (!opcode_table_is_ready) {
- InitOpcodeTable();
- }
- return opcode_table[_:opcode];
- }
- stock Opcode:UnrelocateOpcode(Opcode:opcode) {
- if (!opcode_table_is_ready) {
- InitOpcodeTable();
- }
- if (OP_NONE <= opcode < Opcode:NUM_OPCODES) {
- return opcode;
- }
- for (new i = 0; i < NUM_OPCODES; i++) {
- if (opcode_table[i] == opcode) {
- return Opcode:i;
- }
- }
- return opcode;
- }
- stock GetOpcodeInstructionInformation(Opcode:opcode) {
- if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
- return insn_table[_:opcode];
- }
- return insn_table[0];
- }
- stock GetOpcodeInstructionName(Opcode:opcode) {
- static const ret[OPCODE_MAX_INSN_NAME] = "none";
- if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
- // This doesn't work.
- //return insn_table[_:opcode][OpcodeInsnInfo_name];
- // Fake it without requiring `strcpy`.
- #emit CONST.alt insn_table
- #emit LOAD.S.pri opcode
- #emit IDXADDR
- #emit MOVE.alt
- #emit LOAD.I
- #emit ADD
- #emit LOAD.S.alt 16
- #emit MOVS 60 // 15 * 4
- #emit RETN
- // Check that the code is correct for the size of "OPCODE_MAX_INSN_NAME".
- #assert OPCODE_MAX_INSN_NAME == 15
- }
- return ret;
- }
- stock GetOpcodeInstructionParameters(Opcode:opcode) {
- if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
- return insn_table[_:opcode][OpcodeInsnInfo_num_opers];
- }
- return 0;
- }
- stock bool:GetOpcodeInstructionRelocatable(Opcode:opcode) {
- if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
- return insn_table[_:opcode][OpcodeInsnInfo_needs_reloc];
- }
- return false;
- }
|