Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FTEQCC pointer instructions #215

Merged
merged 9 commits into from
Nov 12, 2024
95 changes: 77 additions & 18 deletions pr_comp.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ typedef enum opcode_e
OP_NE_E,
OP_NE_FNC,

OP_LE,
OP_GE,
OP_LT,
OP_GT,
OP_LE_F,
OP_GE_F,
OP_LT_F,
OP_GT_F,

OP_LOAD_F,
OP_LOAD_V,
Expand Down Expand Up @@ -114,14 +114,14 @@ typedef enum opcode_e
OP_CALL8,
OP_STATE,
OP_GOTO,
OP_AND,
OP_OR,
OP_AND_F,
OP_OR_F,

OP_BITAND,
OP_BITOR,
OP_BITAND_F,
OP_BITOR_F,

// TODO: actually support Hexen 2?

OP_MULSTORE_F, //66 redundant, for h2 compat
OP_MULSTORE_VF, //67 redundant, for h2 compat
OP_MULSTOREP_F, //68
Expand Down Expand Up @@ -194,11 +194,11 @@ typedef enum opcode_e
OP_SUB_FI,
OP_SUB_IF,

OP_CONV_IF,
OP_CONV_FI,
OP_LOADP_IF,
OP_LOADP_FI,
OP_CONV_ITOF,
OP_CONV_FTOI,

OP_LOADP_ITOF,
OP_LOADP_FTOI,

OP_LOAD_I,

Expand Down Expand Up @@ -230,7 +230,7 @@ typedef enum opcode_e
OP_ADD_PIW,

OP_LOADA_F,
OP_LOADA_V,
OP_LOADA_V,
OP_LOADA_S,
OP_LOADA_ENT,
OP_LOADA_FLD,
Expand All @@ -241,7 +241,7 @@ typedef enum opcode_e
OP_LOAD_P,

OP_LOADP_F,
OP_LOADP_V,
OP_LOADP_V,
OP_LOADP_S,
OP_LOADP_ENT,
OP_LOADP_FLD,
Expand All @@ -252,7 +252,7 @@ typedef enum opcode_e
OP_GE_I,
OP_LT_I,
OP_GT_I,

OP_LE_IF,
OP_GE_IF,
OP_LT_IF,
Expand Down Expand Up @@ -295,7 +295,7 @@ typedef enum opcode_e
OP_GSTOREP_ENT,
OP_GSTOREP_FLD,
OP_GSTOREP_S,
OP_GSTOREP_FNC,
OP_GSTOREP_FNC,
OP_GSTOREP_V,
OP_GADDRESS,
OP_GLOAD_I,
Expand All @@ -320,6 +320,65 @@ typedef enum opcode_e
OP_STOREF_F, //1 fpu element...
OP_STOREF_S, //1 string reference
OP_STOREF_I, //1 non-string reference/int

//fteqw r5744+
OP_STOREP_B,//((char*)b)[(int)c] = (int)a
OP_LOADP_B, //(int)c = *(char*)

//fteqw r5768+
//opcodes for 32bit uints
OP_LE_U, //aka GT
OP_LT_U, //aka GE
OP_DIV_U, //don't need mul+add+sub
OP_RSHIFT_U, //lshift is the same for signed+unsigned

//opcodes for 64bit ints
OP_ADD_I64,
OP_SUB_I64,
OP_MUL_I64,
OP_DIV_I64,
OP_BITAND_I64,
OP_BITOR_I64,
OP_BITXOR_I64,
OP_LSHIFT_I64I,
OP_RSHIFT_I64I,
OP_LE_I64, //aka GT
OP_LT_I64, //aka GE
OP_EQ_I64,
OP_NE_I64,
//extra opcodes for 64bit uints
OP_LE_U64, //aka GT
OP_LT_U64, //aka GE
OP_DIV_U64,
OP_RSHIFT_U64I,

//general 64bitness
OP_STORE_I64,
OP_STOREP_I64,
OP_STOREF_I64,
OP_LOAD_I64,
OP_LOADA_I64,
OP_LOADP_I64,
//various conversions for our 64bit types (yay type promotion)
OP_CONV_UI64, //zero extend
OP_CONV_II64, //sign extend
OP_CONV_I64I, //truncate
OP_CONV_FD, //extension
OP_CONV_DF, //truncation
OP_CONV_I64F, //logically a promotion (always signed)
OP_CONV_FI64, //demotion (always signed)
OP_CONV_I64D, //'promotion' (always signed)
OP_CONV_DI64, //demotion (always signed)

//opcodes for doubles.
OP_ADD_D,
OP_SUB_D,
OP_MUL_D,
OP_DIV_D,
OP_LE_D,
OP_LT_D,
OP_EQ_D,
OP_NE_D,
}
opcode_t;

Expand Down
89 changes: 60 additions & 29 deletions prvm_edict.c
Original file line number Diff line number Diff line change
Expand Up @@ -1458,9 +1458,9 @@ qbool PRVM_ED_CallSpawnFunction(prvm_prog_t *prog, prvm_edict_t *ent, const char
}
else
{

Con_DPrint("No spawn function for:\n");
if (developer.integer > 0) // don't confuse non-developers with errors
if (developer.integer > 0) // don't confuse non-developers with errors
PRVM_ED_Print(prog, ent, NULL);

PRVM_ED_Free (prog, ent);
Expand Down Expand Up @@ -1567,7 +1567,7 @@ void PRVM_ED_LoadFromFile (prvm_prog_t *prog, const char *data)

if(!PRVM_ED_CallSpawnFunction(prog, ent, data, start))
continue;

PRVM_ED_CallPostspawnFunction(prog, ent);

spawned++;
Expand Down Expand Up @@ -2052,6 +2052,7 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
char vabuf2[1024];
cvar_t *cvar;
int structtype = 0;
int max_safe_edicts;

if (prog->loaded)
prog->error_cmd("%s: there is already a %s program loaded!", __func__, prog->name);
Expand Down Expand Up @@ -2292,6 +2293,8 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
b = (short)b;
if (a >= prog->progs_numglobals || b + i < 0 || b + i >= prog->progs_numstatements)
prog->error_cmd("%s: out of bounds IF/IFNOT (statement %d) in %s", __func__, i, prog->name);
if (c)
Con_DPrintf("%s: unexpected offset on binary opcode in %s\n", __func__, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = b;
Expand All @@ -2301,6 +2304,8 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
a = (short)a;
if (a + i < 0 || a + i >= prog->progs_numstatements)
prog->error_cmd("%s: out of bounds GOTO (statement %d) in %s", __func__, i, prog->name);
if (b || c)
Con_DPrintf("%s: unexpected offset on unary opcode in %s\n", __func__, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = a;
prog->statements[i].operand[1] = -1;
Expand All @@ -2315,17 +2320,16 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
prog->statements[i].operand[1] =
prog->statements[i].operand[2] = op;
break;
case OP_STORE_I:
// global global global
case OP_ADD_I:
case OP_ADD_FI:
case OP_ADD_IF:
case OP_SUB_I:
case OP_SUB_FI:
case OP_SUB_IF:
case OP_CONV_IF:
case OP_CONV_FI:
case OP_CONV_ITOF:
case OP_CONV_FTOI:
case OP_LOAD_I:
case OP_STOREP_I:
case OP_BITAND_I:
case OP_BITOR_I:
case OP_MUL_I:
Expand All @@ -2334,7 +2338,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
case OP_NE_I:
case OP_NOT_I:
case OP_DIV_VF:
case OP_STORE_P:
case OP_LE_I:
case OP_GE_I:
case OP_LT_I:
Expand Down Expand Up @@ -2382,8 +2385,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
case OP_GLOAD_FNC:
case OP_BOUNDCHECK:
case OP_GLOAD_V:

// global global global
case OP_ADD_F:
case OP_ADD_V:
case OP_SUB_F:
Expand All @@ -2393,14 +2394,14 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
case OP_MUL_FV:
case OP_MUL_VF:
case OP_DIV_F:
case OP_BITAND:
case OP_BITOR:
case OP_GE:
case OP_LE:
case OP_GT:
case OP_LT:
case OP_AND:
case OP_OR:
case OP_BITAND_F:
case OP_BITOR_F:
case OP_GE_F:
case OP_LE_F:
case OP_GT_F:
case OP_LT_F:
case OP_AND_F:
case OP_OR_F:
case OP_EQ_F:
case OP_EQ_V:
case OP_EQ_S:
Expand All @@ -2418,6 +2419,30 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
case OP_LOAD_S:
case OP_LOAD_FNC:
case OP_LOAD_V:
case OP_LOAD_P:
case OP_ADD_PIW:
case OP_GLOBALADDRESS:
case OP_LOADA_F:
case OP_LOADA_V:
case OP_LOADA_S:
case OP_LOADA_ENT:
case OP_LOADA_FLD:
case OP_LOADA_FNC:
case OP_LOADA_I:
case OP_LOADP_F:
case OP_LOADP_V:
case OP_LOADP_S:
case OP_LOADP_ENT:
case OP_LOADP_FLD:
case OP_LOADP_FNC:
case OP_LOADP_I:
case OP_STOREP_F:
case OP_STOREP_ENT:
case OP_STOREP_FLD:
case OP_STOREP_S:
case OP_STOREP_FNC:
case OP_STOREP_V:
case OP_STOREP_I:
if (a >= prog->progs_numglobals || b >= prog->progs_numglobals || c >= prog->progs_numglobals)
prog->error_cmd("%s: out of bounds global index (statement %d)", __func__, i);
prog->statements[i].op = op;
Expand All @@ -2433,30 +2458,27 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
case OP_NOT_ENT:
if (a >= prog->progs_numglobals || c >= prog->progs_numglobals)
prog->error_cmd("%s: out of bounds global index (statement %d) in %s", __func__, i, prog->name);
if (b)
Con_DPrintf("%s: unexpected offset on binary opcode in %s\n", __func__, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = -1;
prog->statements[i].operand[2] = remapglobal(c);
break;
// 2 globals
case OP_STOREP_F:
case OP_STOREP_ENT:
case OP_STOREP_FLD:
case OP_STOREP_S:
case OP_STOREP_FNC:
if (c) //Spike -- DP is alergic to pointers in QC. Try to avoid too many nasty surprises.
Con_DPrintf("%s: storep-with-offset is not permitted in %s\n", __func__, prog->name);
//fallthrough
// global global none
case OP_STORE_F:
case OP_STORE_ENT:
case OP_STORE_FLD:
case OP_STORE_S:
case OP_STORE_FNC:
case OP_STATE:
case OP_STOREP_V:
case OP_STORE_V:
case OP_STORE_I:
case OP_STORE_P:
case OP_STATE:
if (a >= prog->progs_numglobals || b >= prog->progs_numglobals)
prog->error_cmd("%s: out of bounds global index (statement %d) in %s", __func__, i, prog->name);
if (c)
Con_DPrintf("%s: unexpected offset on binary opcode in %s\n", __func__, prog->name);
prog->statements[i].op = op;
prog->statements[i].operand[0] = remapglobal(a);
prog->statements[i].operand[1] = remapglobal(b);
Expand Down Expand Up @@ -2718,6 +2740,15 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data

PRVM_FindOffsets(prog);

// Do not allow more than 2^31 total entityfields. Achieve this by limiting maximum edict count.
// TODO: For PRVM_64, this can be relaxes. May require changing some types away from int.
max_safe_edicts = ((1 << 31) - prog->numglobals) / prog->entityfields;
if (prog->limit_edicts > max_safe_edicts)
{
Con_Printf("%s: reducing maximum entity count to %d to avoid address overflow in %s\n", __func__, max_safe_edicts, prog->name);
prog->limit_edicts = max_safe_edicts;
}

prog->init_cmd(prog);

// init mempools
Expand Down
Loading
Loading