From 95f366ee21e47e13d44b534db51af11536acda35 Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Fri, 3 Jan 2025 18:24:48 -0500 Subject: [PATCH] Add opcodes for uint and bit shifting. - OP_RSHIFT_I - OP_LSHIFT_I - OP_LE_U - OP_LT_U - OP_DIV_U - OP_RSHIFT_U For all other ops FTEQCC emits the _I operations; this is technically broken but meh. Compile DP with `-fwrapv` if you care. --- prvm_edict.c | 6 ++++++ prvm_exec.c | 22 +++++++++++++++++-- prvm_execprogram.h | 53 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/prvm_edict.c b/prvm_edict.c index 0bc9bbbd..c6fadd16 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -2443,6 +2443,12 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data case OP_STOREP_FNC: case OP_STOREP_V: case OP_STOREP_I: + case OP_RSHIFT_I: + case OP_LSHIFT_I: + case OP_LE_U: + case OP_LT_U: + case OP_DIV_U: + case OP_RSHIFT_U: 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; diff --git a/prvm_exec.c b/prvm_exec.c index 9bd38270..fc1e6b20 100644 --- a/prvm_exec.c +++ b/prvm_exec.c @@ -205,8 +205,8 @@ NULL, "DIV_VF", NULL, -NULL, -NULL, +"RSHIFT_I", +"LSHIFT_I", "GLOBALADDRESS", "ADD_PIW", @@ -294,6 +294,24 @@ NULL, NULL, "GLOAD_V", + +NULL, +NULL, + +NULL, +NULL, +NULL, +NULL, + + +NULL, +NULL, + + +"^2LE_U", +"^2LT_U", +"DIV_U", +"RSHIFT_U", }; diff --git a/prvm_execprogram.h b/prvm_execprogram.h index bf9100fe..173677fa 100644 --- a/prvm_execprogram.h +++ b/prvm_execprogram.h @@ -204,8 +204,8 @@ prvm_eval_t *src; &&handle_OP_DIV_VF, NULL, - NULL, - NULL, + &&handle_OP_RSHIFT_I, + &&handle_OP_LSHIFT_I, &&handle_OP_GLOBALADDRESS, &&handle_OP_ADD_PIW, @@ -287,11 +287,31 @@ prvm_eval_t *src; &&handle_OP_GLOAD_S, &&handle_OP_GLOAD_FNC, &&handle_OP_BOUNDCHECK, + + NULL, NULL, NULL, + NULL, + + &&handle_OP_GLOAD_V, + + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + + NULL, NULL, - &&handle_OP_GLOAD_V + + + &&handle_OP_LE_U, + &&handle_OP_LT_U, + &&handle_OP_DIV_U, + &&handle_OP_RSHIFT_U, }; #define DISPATCH_OPCODE() \ goto *dispatchtable[(++st)->op] @@ -1207,6 +1227,33 @@ prvm_eval_t *src; OPC->ivector[1] = ptr->ivector[1]; OPC->ivector[2] = ptr->ivector[2]; DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_RSHIFT_I): + OPC->_int = OPA->_int >> OPB->_int; + DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_LSHIFT_I): + OPC->_int = OPA->_int << OPB->_int; + DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_LE_U): + OPC->_int = (OPA->_uint <= OPB->_uint); + DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_LT_U): + OPC->_int = (OPA->_uint < OPB->_uint); + DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_DIV_U): + if( OPB->_uint != 0 ) + { + OPC->_uint = OPA->_uint / OPB->_uint; + } + else + { + PRE_ERROR(); + VM_Warning(prog, "Attempted division of %u by zero\n", OPA->_uint); + OPC->_uint = 0; + } + DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_RSHIFT_U): + OPC->_uint = OPA->_uint >> OPB->_uint; + DISPATCH_OPCODE(); #if !USE_COMPUTED_GOTOS default: -- 2.39.5