]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
Add ADD_PIW, GLOBALADDRESS, LOADA_* and LOADP_* instructions.
authorRudolf Polzer <divVerent@gmail.com>
Thu, 31 Oct 2024 23:40:21 +0000 (19:40 -0400)
committerdivVerent <divVerent@gmail.com>
Tue, 12 Nov 2024 17:49:21 +0000 (12:49 -0500)
This is used by FTEQCC array and pointer support.

prvm_edict.c
prvm_exec.c
prvm_execprogram.h

index 024ac639ffea8b681c72cf9011b82793a951f648..d71db39a20c338c969dcf420dd72d15bc417f665 100644 (file)
@@ -2316,7 +2316,6 @@ 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:
                case OP_ADD_I:
                case OP_ADD_FI:
                case OP_ADD_IF:
@@ -2326,7 +2325,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
                case OP_CONV_IF:
                case OP_CONV_FI:
                case OP_LOAD_I:
-               case OP_STOREP_I:
                case OP_BITAND_I:
                case OP_BITOR_I:
                case OP_MUL_I:
@@ -2335,7 +2333,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:
@@ -2419,6 +2416,23 @@ 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:
                        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;
@@ -2446,6 +2460,7 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
                case OP_STOREP_S:
                case OP_STOREP_FNC:
                case OP_STOREP_V:
+               case OP_STOREP_I:
                        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);
                        if (a >= prog->progs_numglobals || b >= prog->progs_numglobals || c >= prog->progs_numglobals)
@@ -2461,6 +2476,8 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
                case OP_STORE_S:
                case OP_STORE_FNC:
                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);
index 02f03398c7fb70c2541b425e6ff76caa985ef039..8cfc97a95c28c7be7caf0f4acdd67549366c4f0f 100644 (file)
@@ -929,11 +929,12 @@ extern qbool prvm_runawaycheck;
        mstatement_t *cached_statements = prog->statements; \
        qbool cached_allowworldwrites = prog->allowworldwrites; \
        unsigned int cached_flag = prog->flag; \
+       unsigned int cached_vmglobals = prog->numglobals; \
        unsigned int cached_vmglobals_1 = prog->numglobals - 1; \
+       unsigned int cached_vmglobals_2 = prog->numglobals - 2; \
        unsigned int cached_vmglobals_3 = prog->numglobals - 3; \
-       unsigned int cached_vmglobalsstart = PRVM_GLOBALSBASE; \
-       unsigned int cached_vmglobal1 = cached_vmglobalsstart + 1; \
-       unsigned int cached_vmentity0start = cached_vmglobalsstart + prog->numglobals; \
+       unsigned int cached_vmglobal1 = PRVM_GLOBALSBASE + 1; \
+       unsigned int cached_vmentity0start = PRVM_GLOBALSBASE + prog->numglobals; \
        unsigned int cached_vmentity1start = cached_vmentity0start + prog->entityfields; \
        unsigned int cached_entityfields = prog->entityfields; \
        unsigned int cached_entityfields_2 = prog->entityfields - 2; \
@@ -944,6 +945,8 @@ extern qbool prvm_runawaycheck;
 #define CACHE_CHANGING(DECLARE) \
        DECLARE(prvm_vec_t *) cached_edictsfields = prog->edictsfields.fp; \
        DECLARE(prvm_vec_t *) cached_edictsfields_entity1 = cached_edictsfields + prog->entityfields; \
+       DECLARE(unsigned int) cached_entityfieldsarea = prog->entityfieldsarea; \
+       DECLARE(unsigned int) cached_entityfieldsarea_2 = prog->entityfieldsarea - 2; \
        DECLARE(unsigned int) cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields; \
        DECLARE(unsigned int) cached_entityfieldsarea_entityfields_2 = prog->entityfieldsarea - prog->entityfields - 2; \
        DECLARE(unsigned int) cached_max_edicts = prog->max_edicts
index ce532edbc2a7077d01549628818c8b139a131aaa..6b112342e76934909b213bb997aaae4cd2a134c2 100644 (file)
@@ -1,6 +1,7 @@
 extern cvar_t prvm_garbagecollection_enable;
 int i;
-prvm_uint_t ofs, addr;
+prvm_uint_t addr, ofs;
+prvm_eval_t *src;
 // NEED to reset startst after calling this! startst may or may not be clobbered!
 #define ADVANCE_PROFILE_BEFORE_JUMP() \
        prog->xfunction->profile += (st - startst); \
@@ -205,26 +206,26 @@ prvm_uint_t ofs, addr;
        NULL,
        NULL,
        NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
+       &&handle_OP_GLOBALADDRESS,
+       &&handle_OP_ADD_PIW,
+       &&handle_OP_LOADA_F,
+       &&handle_OP_LOADA_V,
+       &&handle_OP_LOADA_S,
+       &&handle_OP_LOADA_ENT,
+       &&handle_OP_LOADA_FLD,
+       &&handle_OP_LOADA_FNC,
+       &&handle_OP_LOADA_I,
 
        &&handle_OP_STORE_P,
+       &&handle_OP_LOAD_P,
 
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
+       &&handle_OP_LOADP_F,
+       &&handle_OP_LOADP_V,
+       &&handle_OP_LOADP_S,
+       &&handle_OP_LOADP_ENT,
+       &&handle_OP_LOADP_FLD,
+       &&handle_OP_LOADP_FNC,
+       &&handle_OP_LOADP_I,
 
        &&handle_OP_LE_I,
        &&handle_OP_GE_I,
@@ -479,26 +480,26 @@ prvm_uint_t ofs, addr;
                        HANDLE_OPCODE(OP_STOREP_ENT):
                        HANDLE_OPCODE(OP_STOREP_FLD):           // integers
                        HANDLE_OPCODE(OP_STOREP_FNC):           // pointers
-                               ofs = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int;
-                               if ((addr = ofs - cached_vmentity1start) < cached_entityfieldsarea_entityfields)
+                               addr = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int;
+                               if ((ofs = addr - cached_vmentity1start) < cached_entityfieldsarea_entityfields)
                                {
                                        // OK entity write.
-                                       ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + addr);
+                                       ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + ofs);
                                }
-                               else if ((addr = ofs - cached_vmglobal1) < cached_vmglobals_1)
+                               else if ((ofs = addr - cached_vmglobal1) < cached_vmglobals_1)
                                {
                                        // OK global write.
-                                       ptr = (prvm_eval_t *)(global1 + addr);
+                                       ptr = (prvm_eval_t *)(global1 + ofs);
                                }
-                               else if ((addr = ofs - cached_vmentity0start) < cached_entityfields)
+                               else if ((ofs = addr - cached_vmentity0start) < cached_entityfields)
                                {
                                        if (!cached_allowworldwrites)
                                        {
                                                PRE_ERROR();
-                                               VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, addr)->s_name), OPB->_int, OPC->_int);
+                                               VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, ofs)->s_name), OPB->_int, OPC->_int);
                                                // Perform entity write anyway.
                                        }
-                                       ptr = (prvm_eval_t *)(cached_edictsfields + addr);
+                                       ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
                                }
                                else
                                {
@@ -509,26 +510,26 @@ prvm_uint_t ofs, addr;
                                ptr->_int = OPA->_int;
                                DISPATCH_OPCODE();
                        HANDLE_OPCODE(OP_STOREP_S):
-                               ofs = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int;
-                               if ((addr = ofs - cached_vmentity1start) < cached_entityfieldsarea_entityfields)
+                               addr = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int;
+                               if ((ofs = addr - cached_vmentity1start) < cached_entityfieldsarea_entityfields)
                                {
                                        // OK entity write.
-                                       ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + addr);
+                                       ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + ofs);
                                }
-                               else if ((addr = ofs - cached_vmglobal1) < cached_vmglobals_1)
+                               else if ((ofs = addr - cached_vmglobal1) < cached_vmglobals_1)
                                {
                                        // OK global write.
-                                       ptr = (prvm_eval_t *)(global1 + addr);
+                                       ptr = (prvm_eval_t *)(global1 + ofs);
                                }
-                               else if ((addr = ofs - cached_vmentity0start) < cached_entityfields)
+                               else if ((ofs = addr - cached_vmentity0start) < cached_entityfields)
                                {
                                        if (!cached_allowworldwrites)
                                        {
                                                PRE_ERROR();
-                                               VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, addr)->s_name), OPB->_int, OPC->_int);
+                                               VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, ofs)->s_name), OPB->_int, OPC->_int);
                                                // Perform entity write anyway.
                                        }
-                                       ptr = (prvm_eval_t *)(cached_edictsfields + addr);
+                                       ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
                                }
                                else
                                {
@@ -545,26 +546,26 @@ prvm_uint_t ofs, addr;
                                ptr->_int = OPA->_int;
                                DISPATCH_OPCODE();
                        HANDLE_OPCODE(OP_STOREP_V):
-                               ofs = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int;
-                               if ((addr = ofs - cached_vmentity1start) < cached_entityfieldsarea_entityfields_2)
+                               addr = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int;
+                               if ((ofs = addr - cached_vmentity1start) < cached_entityfieldsarea_entityfields_2)
                                {
                                        // OK entity write.
-                                       ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + addr);
+                                       ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + ofs);
                                }
-                               else if ((addr = ofs - cached_vmglobal1) < cached_vmglobals_3)
+                               else if ((ofs = addr - cached_vmglobal1) < cached_vmglobals_3)
                                {
                                        // OK global write.
-                                       ptr = (prvm_eval_t *)(global1 + addr);
+                                       ptr = (prvm_eval_t *)(global1 + ofs);
                                }
-                               else if ((addr = ofs - cached_vmentity0start) < cached_entityfields_2)
+                               else if ((ofs = addr - cached_vmentity0start) < cached_entityfields_2)
                                {
                                        if (!cached_allowworldwrites)
                                        {
                                                PRE_ERROR();
-                                               VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, addr)->s_name), OPB->_int, OPC->_int);
+                                               VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, ofs)->s_name), OPB->_int, OPC->_int);
                                                // Perform entity write anyway.
                                        }
-                                       ptr = (prvm_eval_t *)(cached_edictsfields + addr);
+                                       ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
                                }
                                else
                                {
@@ -605,6 +606,7 @@ prvm_uint_t ofs, addr;
                        HANDLE_OPCODE(OP_LOAD_FLD):
                        HANDLE_OPCODE(OP_LOAD_ENT):
                        HANDLE_OPCODE(OP_LOAD_FNC):
+                       HANDLE_OPCODE(OP_LOAD_P):
                                if ((prvm_uint_t)OPA->edict >= cached_max_edicts)
                                {
                                        PRE_ERROR();
@@ -1077,6 +1079,127 @@ prvm_uint_t ofs, addr;
                                }
                                DISPATCH_OPCODE();
 
+                       // FTEQW pointer instructions.
+                       HANDLE_OPCODE(OP_GLOBALADDRESS):
+                               OPC->_int = PRVM_GLOBALSBASE + st->operand[0] + 1 * OPB->_int;
+                               DISPATCH_OPCODE();
+                       HANDLE_OPCODE(OP_ADD_PIW):
+                               OPC->_int = OPA->_int + 1 * OPB->_int;
+                               DISPATCH_OPCODE();
+                       HANDLE_OPCODE(OP_LOADA_F):
+                       HANDLE_OPCODE(OP_LOADA_ENT):
+                       HANDLE_OPCODE(OP_LOADA_FLD):
+                       HANDLE_OPCODE(OP_LOADA_FNC):
+                       HANDLE_OPCODE(OP_LOADA_I):
+                               ofs = st->operand[0] + OPB->_int;
+                               if (ofs >= cached_vmglobals)
+                               {
+                                       PRE_ERROR();
+                                       prog->error_cmd("%s attempted to read from an out of bounds address %u+%i", prog->name, (unsigned int)st->operand[0], OPB->_int);
+                                       goto cleanup;
+                               }
+                               src = (prvm_eval_t *)&globals[ofs];
+                               OPC->_int = src->_int;
+                               DISPATCH_OPCODE();
+                       HANDLE_OPCODE(OP_LOADA_S):
+                               ofs = st->operand[0] + OPB->_int;
+                               if (ofs >= cached_vmglobals)
+                               {
+                                       PRE_ERROR();
+                                       prog->error_cmd("%s attempted to read from an out of bounds address %u+%i", prog->name, (unsigned int)st->operand[0], OPB->_int);
+                                       goto cleanup;
+                               }
+                               src = (prvm_eval_t *)&globals[ofs];
+                               // refresh the garbage collection on the string - this guards
+                               // against a certain sort of repeated migration to earlier
+                               // points in the scan that could otherwise result in the string
+                               // being freed for being unused
+                               if(prvm_garbagecollection_enable.integer)
+                                       PRVM_GetString(prog, src->_int);
+                               OPC->_int = src->_int;
+                               DISPATCH_OPCODE();
+                       HANDLE_OPCODE(OP_LOADA_V):
+                               ofs = st->operand[0] + OPB->_int;
+                               if (ofs >= cached_vmglobals_2)
+                               {
+                                       PRE_ERROR();
+                                       prog->error_cmd("%s attempted to read from an out of bounds address %u+%i", prog->name, (unsigned int)st->operand[0], OPB->_int);
+                                       goto cleanup;
+                               }
+                               src = (prvm_eval_t *)&globals[ofs];
+                               OPC->ivector[0] = src->ivector[0];
+                               OPC->ivector[1] = src->ivector[1];
+                               OPC->ivector[2] = src->ivector[2];
+                               DISPATCH_OPCODE();
+                       HANDLE_OPCODE(OP_LOADP_F):
+                       HANDLE_OPCODE(OP_LOADP_ENT):
+                       HANDLE_OPCODE(OP_LOADP_FLD):            // integers
+                       HANDLE_OPCODE(OP_LOADP_FNC):            // pointers
+                       HANDLE_OPCODE(OP_LOADP_I):
+                               addr = (prvm_uint_t)OPA->_int + (prvm_uint_t)OPB->_int;
+                               if ((ofs = addr - cached_vmentity0start) < cached_entityfieldsarea)
+                               {
+                                       // OK entity write.
+                                       ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
+                               }
+                               else if ((ofs = addr - PRVM_GLOBALSBASE) < cached_vmglobals)
+                               {
+                                       // OK global write.
+                                       ptr = (prvm_eval_t *)(globals + ofs);
+                               }
+                               else
+                               {
+                                       PRE_ERROR();
+                                       prog->error_cmd("%s attempted to read from an out of bounds address %u+%i", prog->name, (unsigned int)OPA->_int, OPB->_int);
+                                       goto cleanup;
+                               }
+                               OPC->_int = ptr->_int;
+                               DISPATCH_OPCODE();
+                       HANDLE_OPCODE(OP_LOADP_S):
+                               addr = (prvm_uint_t)OPA->_int + (prvm_uint_t)OPB->_int;
+                               if ((ofs = addr - cached_vmentity0start) < cached_entityfieldsarea)
+                               {
+                                       // OK entity write.
+                                       ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
+                               }
+                               else if ((ofs = addr - PRVM_GLOBALSBASE) < cached_vmglobals)
+                               {
+                                       // OK global write.
+                                       ptr = (prvm_eval_t *)(globals + ofs);
+                               }
+                               else
+                               {
+                                       PRE_ERROR();
+                                       prog->error_cmd("%s attempted to read from an out of bounds address %u+%i", prog->name, (unsigned int)OPA->_int, OPB->_int);
+                                       goto cleanup;
+                               }
+                               if(prvm_garbagecollection_enable.integer)
+                                       PRVM_GetString(prog, ptr->_int);
+                               OPC->_int = ptr->_int;
+                               DISPATCH_OPCODE();
+                       HANDLE_OPCODE(OP_LOADP_V):
+                               addr = (prvm_uint_t)OPA->_int + (prvm_uint_t)OPB->_int;
+                               if ((ofs = addr - cached_vmentity0start) < cached_entityfieldsarea_2)
+                               {
+                                       // OK entity write.
+                                       ptr = (prvm_eval_t *)(cached_edictsfields + ofs);
+                               }
+                               else if ((ofs = addr - PRVM_GLOBALSBASE) < cached_vmglobals_2)
+                               {
+                                       // OK global write.
+                                       ptr = (prvm_eval_t *)(globals + ofs);
+                               }
+                               else
+                               {
+                                       PRE_ERROR();
+                                       prog->error_cmd("%s attempted to read from an out of bounds address %u+%i", prog->name, (unsigned int)OPA->_int, OPB->_int);
+                                       goto cleanup;
+                               }
+                               OPC->ivector[0] = ptr->ivector[0];
+                               OPC->ivector[1] = ptr->ivector[1];
+                               OPC->ivector[2] = ptr->ivector[2];
+                               DISPATCH_OPCODE();
+
 #if !USE_COMPUTED_GOTOS
                        default:
                                PRE_ERROR();