diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index ff71cd6fc..5d5efe942 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -403,17 +403,16 @@ typedef enum { #define OP_BREAK 0x8000 typedef struct opcode_s { - const char *name; - const char *opname; - pr_opcode_e opcode; - qboolean right_associative; - etype_t type_a, type_b, type_c; + const char *name; + const char *opname; + qboolean right_associative; + etype_t type_a, type_b, type_c; unsigned int min_version; - const char *fmt; + const char *fmt; } opcode_t; extern const opcode_t pr_opcodes[]; -opcode_t *PR_Opcode (pr_short_t opcode); +const opcode_t *PR_Opcode (pr_short_t opcode) __attribute__((const)); void PR_Opcode_Init (void); // idempotent typedef struct dstatement_s { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f9f743e0d..55cca36d0 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1482,7 +1482,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) int addr = s - pr->pr_statements; int dump_code = contents & 2; const char *fmt; - opcode_t *op; + const opcode_t *op; dfunction_t *call_func = 0; pr_def_t *parm_def = 0; pr_auxfunction_t *aux_func = 0; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 2c893b39f..62239c561 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -39,15 +39,12 @@ #endif #include "QF/cvar.h" -#include "QF/hash.h" #include "QF/pr_comp.h" #include "QF/progs.h" #include "QF/sys.h" #include "compat.h" -static hashtab_t *opcode_table; - VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_void 1, // ev_string @@ -99,1430 +96,1438 @@ VISIBLE const char * const pr_type_name[ev_type_count] = { // x place holder for P (padding) // 0-7 parameter index (for P) VISIBLE const opcode_t pr_opcodes[] = { - {"", "done", OP_DONE, false, // OP_DONE is actually the same as + [OP_DONE] = {"", "done", false, // OP_DONE is actually the same as ev_entity, ev_field, ev_void, // OP_RETURN, the types are bogus PROG_ID_VERSION, "%Va", }, - {"*", "mul.d", OP_MUL_D, false, + [OP_MUL_D] = {"*", "mul.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"*", "mul.f", OP_MUL_F, false, + [OP_MUL_F] = {"*", "mul.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"*", "mul.v", OP_MUL_V, false, + [OP_MUL_V] = {"*", "mul.v", false, ev_vector, ev_vector, ev_float, PROG_ID_VERSION, }, - {"*", "mul.fv", OP_MUL_FV, false, + [OP_MUL_FV] = {"*", "mul.fv", false, ev_float, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.vf", OP_MUL_VF, false, + [OP_MUL_VF] = {"*", "mul.vf", false, ev_vector, ev_float, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.dv", OP_MUL_DV, false, + [OP_MUL_DV] = {"*", "mul.dv", false, ev_double, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.vd", OP_MUL_VD, false, + [OP_MUL_VD] = {"*", "mul.vd", false, ev_vector, ev_double, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.q", OP_MUL_Q, false, + [OP_MUL_Q] = {"*", "mul.q", false, ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - {"*", "mul.fq", OP_MUL_FQ, false, + [OP_MUL_FQ] = {"*", "mul.fq", false, ev_float, ev_quat, ev_quat, PROG_VERSION, }, - {"*", "mul.qf", OP_MUL_QF, false, + [OP_MUL_QF] = {"*", "mul.qf", false, ev_quat, ev_float, ev_quat, PROG_VERSION, }, - {"*", "mul.dq", OP_MUL_DQ, false, + [OP_MUL_DQ] = {"*", "mul.dq", false, ev_double, ev_quat, ev_quat, PROG_VERSION, }, - {"*", "mul.qd", OP_MUL_QD, false, + [OP_MUL_QD] = {"*", "mul.qd", false, ev_quat, ev_double, ev_quat, PROG_VERSION, }, - {"*", "mul.qv", OP_MUL_QV, false, + [OP_MUL_QV] = {"*", "mul.qv", false, ev_quat, ev_vector, ev_vector, PROG_VERSION, }, - {"~", "conj.q", OP_CONJ_Q, false, + [OP_CONJ_Q] = {"~", "conj.q", false, ev_quat, ev_invalid, ev_quat, PROG_VERSION, "%Ga, %gc", }, - {"/", "div.f", OP_DIV_F, false, + [OP_DIV_F] = {"/", "div.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"/", "div.d", OP_DIV_D, false, + [OP_DIV_D] = {"/", "div.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"%", "rem.d", OP_REM_D, false, + [OP_REM_D] = {"%", "rem.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"%%", "mod.d", OP_MOD_D, false, + [OP_MOD_D] = {"%%", "mod.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"+", "add.d", OP_ADD_D, false, + [OP_ADD_D] = {"+", "add.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"+", "add.f", OP_ADD_F, false, + [OP_ADD_F] = {"+", "add.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"+", "add.v", OP_ADD_V, false, + [OP_ADD_V] = {"+", "add.v", false, ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"+", "add.q", OP_ADD_Q, false, + [OP_ADD_Q] = {"+", "add.q", false, ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - {"+", "add.s", OP_ADD_S, false, + [OP_ADD_S] = {"+", "add.s", false, ev_string, ev_string, ev_string, PROG_VERSION, }, - {"-", "sub.d", OP_SUB_D, false, + [OP_SUB_D] = {"-", "sub.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"-", "sub.f", OP_SUB_F, false, + [OP_SUB_F] = {"-", "sub.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"-", "sub.v", OP_SUB_V, false, + [OP_SUB_V] = {"-", "sub.v", false, ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"-", "sub.q", OP_SUB_Q, false, + [OP_SUB_Q] = {"-", "sub.q", false, ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - {"==", "eq.d", OP_EQ_D, false, + [OP_EQ_D] = {"==", "eq.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"==", "eq.f", OP_EQ_F, false, + [OP_EQ_F] = {"==", "eq.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.v", OP_EQ_V, false, + [OP_EQ_V] = {"==", "eq.v", false, ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.q", OP_EQ_Q, false, + [OP_EQ_Q] = {"==", "eq.q", false, ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - {"==", "eq.s", OP_EQ_S, false, + [OP_EQ_S] = {"==", "eq.s", false, ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.e", OP_EQ_E, false, + [OP_EQ_E] = {"==", "eq.e", false, ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.fn", OP_EQ_FN, false, + [OP_EQ_FN] = {"==", "eq.fn", false, ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.d", OP_NE_D, false, + [OP_NE_D] = {"!=", "ne.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"!=", "ne.f", OP_NE_F, false, + [OP_NE_F] = {"!=", "ne.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.v", OP_NE_V, false, + [OP_NE_V] = {"!=", "ne.v", false, ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.q", OP_NE_Q, false, + [OP_NE_Q] = {"!=", "ne.q", false, ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - {"!=", "ne.s", OP_NE_S, false, + [OP_NE_S] = {"!=", "ne.s", false, ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.e", OP_NE_E, false, + [OP_NE_E] = {"!=", "ne.e", false, ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.fn", OP_NE_FN, false, + [OP_NE_FN] = {"!=", "ne.fn", false, ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - {"<=", "le.d", OP_LE_D, false, + [OP_LE_D] = {"<=", "le.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"<=", "le.f", OP_LE_F, false, + [OP_LE_F] = {"<=", "le.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {">=", "ge.d", OP_GE_D, false, + [OP_GE_D] = {">=", "ge.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {">=", "ge.f", OP_GE_F, false, + [OP_GE_F] = {">=", "ge.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"<=", "le.s", OP_LE_S, false, + [OP_LE_S] = {"<=", "le.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {">=", "ge.s", OP_GE_S, false, + [OP_GE_S] = {">=", "ge.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {"<", "lt.d", OP_LT_D, false, + [OP_LT_D] = {"<", "lt.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"<", "lt.f", OP_LT_F, false, + [OP_LT_F] = {"<", "lt.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {">", "gt.d", OP_GT_D, false, + [OP_GT_D] = {">", "gt.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {">", "gt.f", OP_GT_F, false, + [OP_GT_F] = {">", "gt.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"<", "lt.s", OP_LT_S, false, + [OP_LT_S] = {"<", "lt.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {">", "gt.s", OP_GT_S, false, + [OP_GT_S] = {">", "gt.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {".", "load.f", OP_LOAD_F, false, + [OP_LOAD_F] = {".", "load.f", false, ev_entity, ev_field, ev_float, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible? }, - {".", "load.d", OP_LOAD_D, false, + [OP_LOAD_D] = {".", "load.d", false, ev_entity, ev_field, ev_double, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.v", OP_LOAD_V, false, + [OP_LOAD_V] = {".", "load.v", false, ev_entity, ev_field, ev_vector, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.q", OP_LOAD_Q, false, + [OP_LOAD_Q] = {".", "load.q", false, ev_entity, ev_field, ev_quat, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.s", OP_LOAD_S, false, + [OP_LOAD_S] = {".", "load.s", false, ev_entity, ev_field, ev_string, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.ent", OP_LOAD_ENT, false, + [OP_LOAD_ENT] = {".", "load.ent", false, ev_entity, ev_field, ev_entity, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.fld", OP_LOAD_FLD, false, + [OP_LOAD_FLD] = {".", "load.fld", false, ev_entity, ev_field, ev_field, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.fn", OP_LOAD_FN, false, + [OP_LOAD_FN] = {".", "load.fn", false, ev_entity, ev_field, ev_func, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.i", OP_LOAD_I, false, + [OP_LOAD_I] = {".", "load.i", false, ev_entity, ev_field, ev_integer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.p", OP_LOAD_P, false, + [OP_LOAD_P] = {".", "load.p", false, ev_entity, ev_field, ev_pointer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "loadb.d", OP_LOADB_D, false, + [OP_LOADB_D] = {".", "loadb.d", false, ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.f", OP_LOADB_F, false, + [OP_LOADB_F] = {".", "loadb.f", false, ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.v", OP_LOADB_V, false, + [OP_LOADB_V] = {".", "loadb.v", false, ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.q", OP_LOADB_Q, false, + [OP_LOADB_Q] = {".", "loadb.q", false, ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.s", OP_LOADB_S, false, + [OP_LOADB_S] = {".", "loadb.s", false, ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.ent", OP_LOADB_ENT, false, + [OP_LOADB_ENT] = {".", "loadb.ent", false, ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.fld", OP_LOADB_FLD, false, + [OP_LOADB_FLD] = {".", "loadb.fld", false, ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.fn", OP_LOADB_FN, false, + [OP_LOADB_FN] = {".", "loadb.fn", false, ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.i", OP_LOADB_I, false, + [OP_LOADB_I] = {".", "loadb.i", false, ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.p", OP_LOADB_P, false, + [OP_LOADB_P] = {".", "loadb.p", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadbi.d", OP_LOADBI_D, false, + [OP_LOADBI_D] = {".", "loadbi.d", false, ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.f", OP_LOADBI_F, false, + [OP_LOADBI_F] = {".", "loadbi.f", false, ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.v", OP_LOADBI_V, false, + [OP_LOADBI_V] = {".", "loadbi.v", false, ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.q", OP_LOADBI_Q, false, + [OP_LOADBI_Q] = {".", "loadbi.q", false, ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.s", OP_LOADBI_S, false, + [OP_LOADBI_S] = {".", "loadbi.s", false, ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.ent", OP_LOADBI_ENT, false, + [OP_LOADBI_ENT] = {".", "loadbi.ent", false, ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.fld", OP_LOADBI_FLD, false, + [OP_LOADBI_FLD] = {".", "loadbi.fld", false, ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.fn", OP_LOADBI_FN, false, + [OP_LOADBI_FN] = {".", "loadbi.fn", false, ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.i", OP_LOADBI_I, false, + [OP_LOADBI_I] = {".", "loadbi.i", false, ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.p", OP_LOADBI_P, false, + [OP_LOADBI_P] = {".", "loadbi.p", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {"&", "address", OP_ADDRESS, false, + [OP_ADDRESS] = {"&", "address", false, ev_entity, ev_field, ev_pointer, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {"&", "address", OP_ADDRESS_VOID, false, + [OP_ADDRESS_VOID] = {"&", "address", false, ev_void, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.d", OP_ADDRESS_D, false, + [OP_ADDRESS_D] = {"&", "address.d", false, ev_double, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.f", OP_ADDRESS_F, false, + [OP_ADDRESS_F] = {"&", "address.f", false, ev_float, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.v", OP_ADDRESS_V, false, + [OP_ADDRESS_V] = {"&", "address.v", false, ev_vector, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.q", OP_ADDRESS_Q, false, + [OP_ADDRESS_Q] = {"&", "address.q", false, ev_quat, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.s", OP_ADDRESS_S, false, + [OP_ADDRESS_S] = {"&", "address.s", false, ev_string, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.ent", OP_ADDRESS_ENT, false, + [OP_ADDRESS_ENT] = {"&", "address.ent", false, ev_entity, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.fld", OP_ADDRESS_FLD, false, + [OP_ADDRESS_FLD] = {"&", "address.fld", false, ev_field, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.fn", OP_ADDRESS_FN, false, + [OP_ADDRESS_FN] = {"&", "address.fn", false, ev_func, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.i", OP_ADDRESS_I, false, + [OP_ADDRESS_I] = {"&", "address.i", false, ev_integer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.p", OP_ADDRESS_P, false, + [OP_ADDRESS_P] = {"&", "address.p", false, ev_pointer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "lea", OP_LEA, false, + [OP_LEA] = {"&", "lea", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "(%Ga + %Gb), %gc", }, - {"&", "leai", OP_LEAI, false, + [OP_LEAI] = {"&", "leai", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "(%Ga + %sb), %gc", }, - {"", "conv.if", OP_CONV_IF, false, + [OP_CONV_IF] = {"", "conv.if", false, ev_integer, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.fi", OP_CONV_FI, false, + [OP_CONV_FI] = {"", "conv.fi", false, ev_float, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.id", OP_CONV_ID, false, + [OP_CONV_ID] = {"", "conv.id", false, ev_integer, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.di", OP_CONV_DI, false, + [OP_CONV_DI] = {"", "conv.di", false, ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.fd", OP_CONV_FD, false, + [OP_CONV_FD] = {"", "conv.fd", false, ev_float, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.df", OP_CONV_DF, false, + [OP_CONV_DF] = {"", "conv.df", false, ev_double, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - {"=", "store.d", OP_STORE_D, true, + [OP_STORE_D] = {"=", "store.d", true, ev_double, ev_double, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {"=", "store.f", OP_STORE_F, true, + [OP_STORE_F] = {"=", "store.f", true, ev_float, ev_float, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.v", OP_STORE_V, true, + [OP_STORE_V] = {"=", "store.v", true, ev_vector, ev_vector, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.q", OP_STORE_Q, true, + [OP_STORE_Q] = {"=", "store.q", true, ev_quat, ev_quat, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {"=", "store.s", OP_STORE_S, true, + [OP_STORE_S] = {"=", "store.s", true, ev_string, ev_string, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.ent", OP_STORE_ENT, true, + [OP_STORE_ENT] = {"=", "store.ent", true, ev_entity, ev_entity, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.fld", OP_STORE_FLD, true, + [OP_STORE_FLD] = {"=", "store.fld", true, ev_field, ev_field, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.fn", OP_STORE_FN, true, + [OP_STORE_FN] = {"=", "store.fn", true, ev_func, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.i", OP_STORE_I, true, + [OP_STORE_I] = {"=", "store.i", true, ev_integer, ev_integer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {"=", "store.p", OP_STORE_P, true, + [OP_STORE_P] = {"=", "store.p", true, ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {".=", "storep.d", OP_STOREP_D, true, + [OP_STOREP_D] = {".=", "storep.d", true, ev_double, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.f", OP_STOREP_F, true, + [OP_STOREP_F] = {".=", "storep.f", true, ev_float, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.v", OP_STOREP_V, true, + [OP_STOREP_V] = {".=", "storep.v", true, ev_vector, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.q", OP_STOREP_Q, true, + [OP_STOREP_Q] = {".=", "storep.q", true, ev_quat, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - {".=", "storep.s", OP_STOREP_S, true, + [OP_STOREP_S] = {".=", "storep.s", true, ev_string, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.ent", OP_STOREP_ENT, true, + [OP_STOREP_ENT] = {".=", "storep.ent", true, ev_entity, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.fld", OP_STOREP_FLD, true, + [OP_STOREP_FLD] = {".=", "storep.fld", true, ev_field, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.fn", OP_STOREP_FN, true, + [OP_STOREP_FN] = {".=", "storep.fn", true, ev_func, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.i", OP_STOREP_I, true, + [OP_STOREP_I] = {".=", "storep.i", true, ev_integer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - {".=", "storep.p", OP_STOREP_P, true, + [OP_STOREP_P] = {".=", "storep.p", true, ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - {".=", "storeb.d", OP_STOREB_D, true, + [OP_STOREB_D] = {".=", "storeb.d", true, ev_double, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.f", OP_STOREB_F, true, + [OP_STOREB_F] = {".=", "storeb.f", true, ev_float, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.v", OP_STOREB_V, true, + [OP_STOREB_V] = {".=", "storeb.v", true, ev_vector, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.q", OP_STOREB_Q, true, + [OP_STOREB_Q] = {".=", "storeb.q", true, ev_quat, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.s", OP_STOREB_S, true, + [OP_STOREB_S] = {".=", "storeb.s", true, ev_string, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.ent", OP_STOREB_ENT, true, + [OP_STOREB_ENT] = {".=", "storeb.ent", true, ev_entity, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.fld", OP_STOREB_FLD, true, + [OP_STOREB_FLD] = {".=", "storeb.fld", true, ev_field, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.fn", OP_STOREB_FN, true, + [OP_STOREB_FN] = {".=", "storeb.fn", true, ev_func, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.i", OP_STOREB_I, true, + [OP_STOREB_I] = {".=", "storeb.i", true, ev_integer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.p", OP_STOREB_P, true, + [OP_STOREB_P] = {".=", "storeb.p", true, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storebi.d", OP_STOREBI_D, true, + [OP_STOREBI_D] = {".=", "storebi.d", true, ev_double, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.f", OP_STOREBI_F, true, + [OP_STOREBI_F] = {".=", "storebi.f", true, ev_float, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.v", OP_STOREBI_V, true, + [OP_STOREBI_V] = {".=", "storebi.v", true, ev_vector, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.q", OP_STOREBI_Q, true, + [OP_STOREBI_Q] = {".=", "storebi.q", true, ev_quat, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.s", OP_STOREBI_S, true, + [OP_STOREBI_S] = {".=", "storebi.s", true, ev_string, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.ent", OP_STOREBI_ENT, true, + [OP_STOREBI_ENT] = {".=", "storebi.ent", true, ev_entity, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.fld", OP_STOREBI_FLD, true, + [OP_STOREBI_FLD] = {".=", "storebi.fld", true, ev_field, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.fn", OP_STOREBI_FN, true, + [OP_STOREBI_FN] = {".=", "storebi.fn", true, ev_func, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.i", OP_STOREBI_I, true, + [OP_STOREBI_I] = {".=", "storebi.i", true, ev_integer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.p", OP_STOREBI_P, true, + [OP_STOREBI_P] = {".=", "storebi.p", true, ev_pointer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {"", "return", OP_RETURN, false, + [OP_RETURN] = {"", "return", false, ev_void, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Ra", }, - {"", "return", OP_RETURN_V, false, + [OP_RETURN_V] = {"", "return", false, ev_invalid, ev_invalid, ev_invalid, PROG_VERSION, "", }, - {"!", "not.d", OP_NOT_D, false, + [OP_NOT_D] = {"!", "not.d", false, ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"!", "not.f", OP_NOT_F, false, + [OP_NOT_F] = {"!", "not.f", false, ev_float, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.v", OP_NOT_V, false, + [OP_NOT_V] = {"!", "not.v", false, ev_vector, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.q", OP_NOT_Q, false, + [OP_NOT_Q] = {"!", "not.q", false, ev_quat, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"!", "not.s", OP_NOT_S, false, + [OP_NOT_S] = {"!", "not.s", false, ev_string, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.ent", OP_NOT_ENT, false, + [OP_NOT_ENT] = {"!", "not.ent", false, ev_entity, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.fn", OP_NOT_FN, false, + [OP_NOT_FN] = {"!", "not.fn", false, ev_func, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.p", OP_NOT_P, false, + [OP_NOT_P] = {"!", "not.p", false, ev_pointer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"", "if", OP_IF, false, + [OP_IF] = {"", "if", false, ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifnot", OP_IFNOT, false, + [OP_IFNOT] = {"", "ifnot", false, ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifbe", OP_IFBE, true, + [OP_IFBE] = {"", "ifbe", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifb", OP_IFB, true, + [OP_IFB] = {"", "ifb", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifae", OP_IFAE, true, + [OP_IFAE] = {"", "ifae", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifa", OP_IFA, true, + [OP_IFA] = {"", "ifa", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, // calls returns REG_RETURN - {"", "call0", OP_CALL0, false, + [OP_CALL0] = {"", "call0", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa ()", }, - {"", "call1", OP_CALL1, false, + [OP_CALL1] = {"", "call1", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x)", }, - {"", "call2", OP_CALL2, false, + [OP_CALL2] = {"", "call2", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x)", }, - {"", "call3", OP_CALL3, false, + [OP_CALL3] = {"", "call3", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x)", }, - {"", "call4", OP_CALL4, false, + [OP_CALL4] = {"", "call4", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x)", }, - {"", "call5", OP_CALL5, false, + [OP_CALL5] = {"", "call5", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)", }, - {"", "call6", OP_CALL6, false, + [OP_CALL6] = {"", "call6", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)", }, - {"", "call7", OP_CALL7, false, + [OP_CALL7] = {"", "call7", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - {"", "call8", OP_CALL8, false, + [OP_CALL8] = {"", "call8", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - {"", "rcall1", OP_RCALL1, false, + [OP_RCALL0] = {"", 0, false, + ev_invalid, ev_invalid, ev_invalid, + ~0, // not a valid instruction + 0, + }, + [OP_RCALL1] = {"", "rcall1", false, ev_func, ev_void, ev_invalid, PROG_VERSION, "%Fa (%P0b)", }, - {"", "rcall2", OP_RCALL2, false, + [OP_RCALL2] = {"", "rcall2", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c)", }, - {"", "rcall3", OP_RCALL3, false, + [OP_RCALL3] = {"", "rcall3", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x)", }, - {"", "rcall4", OP_RCALL4, false, + [OP_RCALL4] = {"", "rcall4", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x)", }, - {"", "rcall5", OP_RCALL5, false, + [OP_RCALL5] = {"", "rcall5", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", }, - {"", "rcall6", OP_RCALL6, false, + [OP_RCALL6] = {"", "rcall6", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", }, - {"", "rcall7", OP_RCALL7, false, + [OP_RCALL7] = {"", "rcall7", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - {"", "rcall8", OP_RCALL8, false, + [OP_RCALL8] = {"", "rcall8", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - {"", "state", OP_STATE, false, + [OP_STATE] = {"", "state", false, ev_float, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %Gb", }, - {"", "state.f", OP_STATE_F, false, + [OP_STATE_F] = {"", "state.f", false, ev_float, ev_func, ev_float, PROG_VERSION, "%Ga, %Gb, %Gc", }, - {"", "goto", OP_GOTO, false, + [OP_GOTO] = {"", "goto", false, ev_short, ev_invalid, ev_invalid, PROG_ID_VERSION, "branch %sa (%Oa)", }, - {"", "jump", OP_JUMP, false, + [OP_JUMP] = {"", "jump", false, ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "jumpb", OP_JUMPB, false, + [OP_JUMPB] = {"", "jumpb", false, ev_void, ev_integer, ev_invalid, PROG_VERSION, "%Ga[%Gb]", }, - {"&&", "and.f", OP_AND, false, + [OP_AND] = {"&&", "and.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"||", "or.f", OP_OR, false, + [OP_OR] = {"||", "or.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"<<", "shl.f", OP_SHL_F, false, + [OP_SHL_F] = {"<<", "shl.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {">>", "shr.f", OP_SHR_F, false, + [OP_SHR_F] = {">>", "shr.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {"<<", "shl.i", OP_SHL_I, false, + [OP_SHL_I] = {"<<", "shl.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">>", "shr.i", OP_SHR_I, false, + [OP_SHR_I] = {">>", "shr.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">>", "shr.u", OP_SHR_U, false, + [OP_SHR_U] = {">>", "shr.u", false, ev_uinteger, ev_integer, ev_uinteger, PROG_VERSION, }, - {"&", "bitand", OP_BITAND, false, + [OP_BITAND] = {"&", "bitand", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"|", "bitor", OP_BITOR, false, + [OP_BITOR] = {"|", "bitor", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"+", "add.i", OP_ADD_I, false, + [OP_ADD_I] = {"+", "add.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"-", "sub.i", OP_SUB_I, false, + [OP_SUB_I] = {"-", "sub.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"*", "mul.i", OP_MUL_I, false, + [OP_MUL_I] = {"*", "mul.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"/", "div.i", OP_DIV_I, false, + [OP_DIV_I] = {"/", "div.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"%", "rem.i", OP_REM_I, false, + [OP_REM_I] = {"%", "rem.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"%%", "mod.i", OP_MOD_I, false, + [OP_MOD_I] = {"%%", "mod.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"&", "bitand.i", OP_BITAND_I, false, + [OP_BITAND_I] = {"&", "bitand.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"|", "bitor.i", OP_BITOR_I, false, + [OP_BITOR_I] = {"|", "bitor.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"%", "rem.f", OP_REM_F, false, + [OP_REM_F] = {"%", "rem.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {"%%", "mod.f", OP_MOD_F, false, + [OP_MOD_F] = {"%%", "mod.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {">=", "ge.i", OP_GE_I, false, + [OP_GE_I] = {">=", "ge.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"<=", "le.i", OP_LE_I, false, + [OP_LE_I] = {"<=", "le.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">", "gt.i", OP_GT_I, false, + [OP_GT_I] = {">", "gt.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"<", "lt.i", OP_LT_I, false, + [OP_LT_I] = {"<", "lt.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"&&", "and.i", OP_AND_I, false, + [OP_AND_I] = {"&&", "and.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"||", "or.i", OP_OR_I, false, + [OP_OR_I] = {"||", "or.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"!", "not.i", OP_NOT_I, false, + [OP_NOT_I] = {"!", "not.i", false, ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"==", "eq.i", OP_EQ_I, false, + [OP_EQ_I] = {"==", "eq.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"!=", "ne.i", OP_NE_I, false, + [OP_NE_I] = {"!=", "ne.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">=", "ge.u", OP_GE_U, false, + [OP_GE_U] = {">=", "ge.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {"<=", "le.u", OP_LE_U, false, + [OP_LE_U] = {"<=", "le.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {">", "gt.u", OP_GT_U, false, + [OP_GT_U] = {">", "gt.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {"<", "lt.u", OP_LT_U, false, + [OP_LT_U] = {"<", "lt.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {"^", "bitxor.f", OP_BITXOR_F, false, + [OP_BITXOR_F] = {"^", "bitxor.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {"~", "bitnot.f", OP_BITNOT_F, false, + [OP_BITNOT_F] = {"~", "bitnot.f", false, ev_float, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - {"^", "bitxor.i", OP_BITXOR_I, false, + [OP_BITXOR_I] = {"^", "bitxor.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"~", "bitnot.i", OP_BITNOT_I, false, + [OP_BITNOT_I] = {"~", "bitnot.i", false, ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {">=", "ge.p", OP_GE_P, false, + [OP_GE_P] = {">=", "ge.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"<=", "le.p", OP_LE_P, false, + [OP_LE_P] = {"<=", "le.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {">", "gt.p", OP_GT_P, false, + [OP_GT_P] = {">", "gt.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"<", "lt.p", OP_LT_P, false, + [OP_LT_P] = {"<", "lt.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"==", "eq.p", OP_EQ_P, false, + [OP_EQ_P] = {"==", "eq.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"!=", "ne.p", OP_NE_P, false, + [OP_NE_P] = {"!=", "ne.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"", "movei", OP_MOVEI, true, + [OP_MOVEI] = {"", "movei", true, ev_void, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - {"", "movep", OP_MOVEP, true, + [OP_MOVEP] = {"", "movep", true, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - {"", "movepi", OP_MOVEPI, true, + [OP_MOVEPI] = {"", "movepi", true, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - {"", "memseti", OP_MEMSETI, true, + [OP_MEMSETI] = {"", "memseti", true, ev_integer, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - {"", "memsetp", OP_MEMSETP, true, + [OP_MEMSETP] = {"", "memsetp", true, ev_integer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - {"", "memsetpi", OP_MEMSETPI, true, + [OP_MEMSETPI] = {"", "memsetpi", true, ev_integer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - {"", "push.s", OP_PUSH_S, false, + [OP_PUSH_S] = {"", "push.s", false, ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.f", OP_PUSH_F, false, + [OP_PUSH_F] = {"", "push.f", false, ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.v", OP_PUSH_V, false, + [OP_PUSH_V] = {"", "push.v", false, ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.ent", OP_PUSH_ENT, false, + [OP_PUSH_ENT] = {"", "push.ent", false, ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.fld", OP_PUSH_FLD, false, + [OP_PUSH_FLD] = {"", "push.fld", false, ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.fn", OP_PUSH_FN, false, + [OP_PUSH_FN] = {"", "push.fn", false, ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.p", OP_PUSH_P, false, + [OP_PUSH_P] = {"", "push.p", false, ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.q", OP_PUSH_Q, false, + [OP_PUSH_Q] = {"", "push.q", false, ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.i", OP_PUSH_I, false, + [OP_PUSH_I] = {"", "push.i", false, ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, + [OP_PUSH_D] = {"", "push.d", false, + ev_double, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, - {"", "pushb.s", OP_PUSHB_S, false, + [OP_PUSHB_S] = {"", "pushb.s", false, ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.f", OP_PUSHB_F, false, + [OP_PUSHB_F] = {"", "pushb.f", false, ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.v", OP_PUSHB_V, false, + [OP_PUSHB_V] = {"", "pushb.v", false, ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.ent", OP_PUSHB_ENT, false, + [OP_PUSHB_ENT] = {"", "pushb.ent", false, ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.fld", OP_PUSHB_FLD, false, + [OP_PUSHB_FLD] = {"", "pushb.fld", false, ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.fn", OP_PUSHB_FN, false, + [OP_PUSHB_FN] = {"", "pushb.fn", false, ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.p", OP_PUSHB_P, false, + [OP_PUSHB_P] = {"", "pushb.p", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.q", OP_PUSHB_Q, false, + [OP_PUSHB_Q] = {"", "pushb.q", false, ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.i", OP_PUSHB_I, false, + [OP_PUSHB_I] = {"", "pushb.i", false, ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, + [OP_PUSHB_D] = {"", "pushb.d", false, + ev_pointer, ev_integer, ev_double, + PROG_VERSION, + "*(%Ga + %Gb)", + }, - {"", "pushbi.s", OP_PUSHBI_S, false, + [OP_PUSHBI_S] = {"", "pushbi.s", false, ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.f", OP_PUSHBI_F, false, + [OP_PUSHBI_F] = {"", "pushbi.f", false, ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.v", OP_PUSHBI_V, false, + [OP_PUSHBI_V] = {"", "pushbi.v", false, ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.ent", OP_PUSHBI_ENT, false, + [OP_PUSHBI_ENT] = {"", "pushbi.ent", false, ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.fld", OP_PUSHBI_FLD, false, + [OP_PUSHBI_FLD] = {"", "pushbi.fld", false, ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.fn", OP_PUSHBI_FN, false, + [OP_PUSHBI_FN] = {"", "pushbi.fn", false, ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.p", OP_PUSHBI_P, false, + [OP_PUSHBI_P] = {"", "pushbi.p", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.q", OP_PUSHBI_Q, false, + [OP_PUSHBI_Q] = {"", "pushbi.q", false, ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.i", OP_PUSHBI_I, false, + [OP_PUSHBI_I] = {"", "pushbi.i", false, ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, + [OP_PUSHBI_D] = {"", "pushbi.d", false, + ev_pointer, ev_short, ev_double, + PROG_VERSION, + "*(%Ga + %sb)", + }, - {"", "pop.s", OP_POP_S, false, + [OP_POP_S] = {"", "pop.s", false, ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.f", OP_POP_F, false, + [OP_POP_F] = {"", "pop.f", false, ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.v", OP_POP_V, false, + [OP_POP_V] = {"", "pop.v", false, ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.ent", OP_POP_ENT, false, + [OP_POP_ENT] = {"", "pop.ent", false, ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.fld", OP_POP_FLD, false, + [OP_POP_FLD] = {"", "pop.fld", false, ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.fn", OP_POP_FN, false, + [OP_POP_FN] = {"", "pop.fn", false, ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.p", OP_POP_P, false, + [OP_POP_P] = {"", "pop.p", false, ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.q", OP_POP_Q, false, + [OP_POP_Q] = {"", "pop.q", false, ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.i", OP_POP_I, false, + [OP_POP_I] = {"", "pop.i", false, ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, + [OP_POP_D] = {"", "pop.d", false, + ev_double, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, - {"", "popb.s", OP_POPB_S, false, + [OP_POPB_S] = {"", "popb.s", false, ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.f", OP_POPB_F, false, + [OP_POPB_F] = {"", "popb.f", false, ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.v", OP_POPB_V, false, + [OP_POPB_V] = {"", "popb.v", false, ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.ent", OP_POPB_ENT, false, + [OP_POPB_ENT] = {"", "popb.ent", false, ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.fld", OP_POPB_FLD, false, + [OP_POPB_FLD] = {"", "popb.fld", false, ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.fn", OP_POPB_FN, false, + [OP_POPB_FN] = {"", "popb.fn", false, ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.p", OP_POPB_P, false, + [OP_POPB_P] = {"", "popb.p", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.q", OP_POPB_Q, false, + [OP_POPB_Q] = {"", "popb.q", false, ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.i", OP_POPB_I, false, + [OP_POPB_I] = {"", "popb.i", false, ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, + [OP_POPB_D] = {"", "popb.d", false, + ev_pointer, ev_integer, ev_double, + PROG_VERSION, + "*(%Ga + %Gb)", + }, - {"", "popbi.s", OP_POPBI_S, false, + [OP_POPBI_S] = {"", "popbi.s", false, ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.f", OP_POPBI_F, false, + [OP_POPBI_F] = {"", "popbi.f", false, ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.v", OP_POPBI_V, false, + [OP_POPBI_V] = {"", "popbi.v", false, ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.ent", OP_POPBI_ENT, false, + [OP_POPBI_ENT] = {"", "popbi.ent", false, ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.fld", OP_POPBI_FLD, false, + [OP_POPBI_FLD] = {"", "popbi.fld", false, ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.fn", OP_POPBI_FN, false, + [OP_POPBI_FN] = {"", "popbi.fn", false, ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.p", OP_POPBI_P, false, + [OP_POPBI_P] = {"", "popbi.p", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.q", OP_POPBI_Q, false, + [OP_POPBI_Q] = {"", "popbi.q", false, ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.i", OP_POPBI_I, false, + [OP_POPBI_I] = {"", "popbi.i", false, ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, + [OP_POPBI_D] = {"", "popbi.d", false, + ev_pointer, ev_short, ev_double, + PROG_VERSION, + "*(%Ga + %sb)", + }, // end of table - {0}, + [OP_MEMSETPI+1] = {0}, //XXX FIXME relies on OP_MEMSETPI being last }; - -static uintptr_t -opcode_get_hash (const void *op, void *unused) -{ - return ((opcode_t *)op)->opcode; -} - -static int -opcode_compare (const void *_opa, const void *_opb, void *unused) -{ - opcode_t *opa = (opcode_t *)_opa; - opcode_t *opb = (opcode_t *)_opb; - - return opa->opcode == opb->opcode; -} - -opcode_t * +const opcode_t * PR_Opcode (pr_short_t opcode) { - opcode_t op; - - op.opcode = opcode; - return Hash_FindElement (opcode_table, &op); + if (opcode < 0 + || opcode >= (int) (sizeof (pr_opcodes) / sizeof (pr_opcodes[0])) - 1) { + return 0; + } + return &pr_opcodes[opcode]; } VISIBLE void PR_Opcode_Init (void) { - const opcode_t *op; - - if (opcode_table) { - // already initialized - return; - } - opcode_table = Hash_NewTable (1021, 0, 0, 0, 0); - Hash_SetHashCompare (opcode_table, opcode_get_hash, opcode_compare); - - for (op = pr_opcodes; op->name; op++) { - Hash_AddElement (opcode_table, (void *) op); - } } static inline void -check_branch (progs_t *pr, dstatement_t *st, opcode_t *op, short offset) +check_branch (progs_t *pr, dstatement_t *st, const opcode_t *op, short offset) { pr_int_t address = st - pr->pr_statements; @@ -1551,7 +1556,7 @@ is_vector_parameter_store (progs_t *pr, dstatement_t *st, #define ISDENORM(x) ((x) && !((x) & 0x7f800000)) static inline void -check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type, +check_global (progs_t *pr, dstatement_t *st, const opcode_t *op, etype_t type, unsigned short operand, int check_denorm) { const char *msg; @@ -1609,7 +1614,7 @@ error: } static void -check_global_size (progs_t *pr, dstatement_t *st, opcode_t *op, +check_global_size (progs_t *pr, dstatement_t *st, const opcode_t *op, unsigned short size, unsigned short operand) { const char *msg; @@ -1627,7 +1632,7 @@ error: int PR_Check_Opcodes (progs_t *pr) { - opcode_t *op; + const opcode_t *op; dstatement_t *st; int state_ok = 0; int pushpop_ok = 0; @@ -1784,7 +1789,7 @@ PR_Check_Opcodes (progs_t *pr) default: check_global (pr, st, op, op->type_a, st->a, 1); check_global (pr, st, op, op->type_b, st->b, - op->opcode != OP_STORE_F); + (op - pr_opcodes) != OP_STORE_F); check_global (pr, st, op, op->type_c, st->c, 0); break; } diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index 779370340..2ffbe04c8 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -48,6 +48,8 @@ extern struct opcode_s *op_jumpb; struct operand_s; +extern struct opcode_s *opcode_map; + struct opcode_s *opcode_find (const char *name, struct operand_s *op_a, struct operand_s *op_b, struct operand_s *op_c); void opcode_init (void); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 5a7dd129a..c2dac98ec 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -213,7 +213,7 @@ emit_statement (statement_t *statement) } } s = codespace_newstatement (pr.code); - s->op = op->opcode; + s->op = op - opcode_map; s->a = def_a ? def_a->offset : 0; s->b = def_b ? def_b->offset : 0; s->c = def_c ? def_c->offset : 0; diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index a9bda7a3c..bf962ec96 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -49,6 +49,7 @@ hashtab_t *opcode_type_table; hashtab_t *opcode_void_table; +opcode_t *opcode_map; #define ROTL(x,n) ((((unsigned)(x))<<(n))|((unsigned)(x))>>(32-n)) @@ -95,7 +96,7 @@ opcode_t * opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { - opcode_t search_op; + opcode_t search_op = {}; opcode_t *op; opcode_t *sop; void **op_list; @@ -122,12 +123,6 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; } -static void -opcode_free (void *_op, void *unused) -{ - free (_op); -} - void opcode_init (void) { @@ -139,14 +134,23 @@ opcode_init (void) Hash_FlushTable (opcode_type_table); } else { PR_Opcode_Init (); - opcode_type_table = Hash_NewTable (1021, 0, opcode_free, 0, 0); + opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (opcode_type_table, get_hash, compare); opcode_void_table = Hash_NewTable (1021, get_key, 0, 0, 0); } + + int num_opcodes = 0; for (op = pr_opcodes; op->name; op++) { + num_opcodes++; + } + if (!opcode_map) { + opcode_map = calloc (num_opcodes, sizeof (opcode_t)); + } + for (int i = 0; i < num_opcodes; i++) { + op = pr_opcodes + i; if (op->min_version > options.code.progsversion) continue; - mop = malloc (sizeof (opcode_t)); + mop = opcode_map + i; *mop = *op; if (options.code.progsversion == PROG_ID_VERSION) { // v6 progs have no concept of integer, but the QF engine