diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 6a9b40e2c..15e059a01 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -42,6 +42,7 @@ typedef enum { ev_pointer, // end of v6 types ev_quat, ev_integer, + ev_uinteger, ev_short, // value is embedded in the opcode ev_invalid, // invalid type. used for instruction checking @@ -260,7 +261,6 @@ typedef enum { OP_MOVEP, OP_MOVEPI, - OP_SHL_U, OP_SHR_U, OP_STATE_F, @@ -362,7 +362,7 @@ typedef struct pr_va_list_s { |(((0x##b) & 0xfff) << 12) \ |(((0x##c) & 0xfff) << 0) ) #define PROG_ID_VERSION 6 -#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,007) +#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,008) typedef struct dprograms_s { pr_uint_t version; diff --git a/libs/gamecode/engine/pr_debug.c b/libs/gamecode/engine/pr_debug.c index 7ee09bc0d..7eadc523d 100644 --- a/libs/gamecode/engine/pr_debug.c +++ b/libs/gamecode/engine/pr_debug.c @@ -660,6 +660,9 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val) case ev_integer: dsprintf (line, "%d", val->integer_var); break; + case ev_uinteger: + dsprintf (line, "$%08x", val->uinteger_var); + break; default: //dsprintf (line, "bad type %i", type); dsprintf (line, "<%x %x %x %x>", @@ -1058,6 +1061,7 @@ ED_Print (progs_t *pr, edict_t *ed) switch (type) { case ev_entity: case ev_integer: + case ev_uinteger: case ev_pointer: case ev_func: case ev_field: diff --git a/libs/gamecode/engine/pr_exec.c b/libs/gamecode/engine/pr_exec.c index b5493f407..2106e3714 100644 --- a/libs/gamecode/engine/pr_exec.c +++ b/libs/gamecode/engine/pr_exec.c @@ -465,14 +465,13 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) OPC.float_var = (int) OPA.float_var >> (int) OPB.float_var; break; case OP_SHL_I: - case OP_SHL_U: OPC.integer_var = OPA.integer_var << OPB.integer_var; break; case OP_SHR_I: OPC.integer_var = OPA.integer_var >> OPB.integer_var; break; case OP_SHR_U: - OPC.uinteger_var = OPA.uinteger_var >> OPB.uinteger_var; + OPC.uinteger_var = OPA.uinteger_var >> OPB.integer_var; break; case OP_GE_F: OPC.float_var = OPA.float_var >= OPB.float_var; diff --git a/libs/gamecode/engine/pr_opcode.c b/libs/gamecode/engine/pr_opcode.c index 1ac7b0107..15f4905b7 100644 --- a/libs/gamecode/engine/pr_opcode.c +++ b/libs/gamecode/engine/pr_opcode.c @@ -60,6 +60,7 @@ VISIBLE int pr_type_size[ev_type_count] = { 1, // ev_pointer 4, // ev_quat 1, // ev_integer + 1, // ev_uinteger 0, // ev_short value in opcode }; @@ -74,6 +75,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = { "pointer", "quaternion", "integer", + "uinteger", "short", "invalid", }; @@ -873,12 +875,8 @@ VISIBLE opcode_t pr_opcodes[] = { ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"<<", "shl.u", OP_SHL_U, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, {">>", "shr.u", OP_SHR_U, false, - ev_integer, ev_integer, ev_integer, + ev_uinteger, ev_integer, ev_uinteger, PROG_VERSION, }, @@ -964,22 +962,22 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_VERSION, }, -// {">=", "ge.u", OP_GE_U, false, -// ev_integer, ev_integer, ev_integer, -// PROG_VERSION, -// }, -// {"<=", "le.u", OP_LE_U, false, -// ev_integer, ev_integer, ev_integer, -// PROG_VERSION, -// }, -// {">", "gt.u", OP_GT_U, false, -// ev_integer, ev_integer, ev_integer, -// PROG_VERSION, -// }, -// {"<", "lt.u", OP_LT_U, false, -// ev_integer, ev_integer, ev_integer, -// PROG_VERSION, -// }, + {">=", "ge.u", OP_GE_U, false, + ev_uinteger, ev_uinteger, ev_integer, + PROG_VERSION, + }, + {"<=", "le.u", OP_LE_U, false, + ev_uinteger, ev_uinteger, ev_integer, + PROG_VERSION, + }, + {">", "gt.u", OP_GT_U, false, + ev_uinteger, ev_uinteger, ev_integer, + PROG_VERSION, + }, + {"<", "lt.u", OP_LT_U, false, + ev_uinteger, ev_uinteger, ev_integer, + PROG_VERSION, + }, {"^", "bitxor.f", OP_BITXOR_F, false, ev_float, ev_float, ev_float, diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 57f03b56b..1678e1fb6 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -370,6 +370,7 @@ set_address (sv_def_t *def, void *address) case ev_func: case ev_pointer: case ev_integer: + case ev_uinteger: *(int **)def->field = (int *) address; break; } diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index efbbdadd6..766a6ea43 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -371,6 +371,7 @@ set_address (sv_def_t *def, void *address) case ev_func: case ev_pointer: case ev_integer: + case ev_uinteger: *(int **)def->field = (int *) address; break; } diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index e736229e6..54a1d5e81 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -423,6 +423,15 @@ const float *expr_quaternion (expr_t *e); expr_t *new_integer_expr (int integer_val); int expr_integer (expr_t *e); +/** Create a new integer constant expression node. + + \param integer_val The integer constant being represented. + \return The new integer constant expression node + (expr_t::e::integer_val). +*/ +expr_t *new_uinteger_expr (unsigned uinteger_val); +unsigned expr_uinteger (expr_t *e); + /** Create a new short constant expression node. \param short_val The short constant being represented. diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 8d6fa4762..96f0b0e97 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -105,6 +105,7 @@ extern type_t type_pointer; extern type_t type_floatfield; extern type_t type_quaternion; extern type_t type_integer; +extern type_t type_uinteger; extern type_t type_short; extern type_t *type_nil; // for passing nil into ... diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 1f08d34be..20775c9ae 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -477,10 +477,8 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op != PAS && op != '.' && op != '&' && op != 'M' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); - //if ((op == '.' || op == '&') && get_type (e2) == &type_uinteger) { - // //FIXME should implement unsigned addressing - // e->e.expr.e2 = cf_cast_expr (&type_integer, e2); - //} + if ((op == '.' || op == '&') && get_type (e2) == &type_uinteger) + e->e.expr.e2 = cf_cast_expr (&type_integer, e2); return e; } @@ -700,6 +698,12 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) return e; } +static expr_t * +do_op_uinteger (int op, expr_t *e, expr_t *e1, expr_t *e2) +{ + return e; +} + static expr_t * do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) { @@ -872,6 +876,7 @@ static operation_t op_void[ev_type_count] = { do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion do_op_invalid, // ev_integer + do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_invalid }; @@ -887,6 +892,7 @@ static operation_t op_string[ev_type_count] = { do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion do_op_invalid, // ev_integer + do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_invalid }; @@ -902,6 +908,7 @@ static operation_t op_float[ev_type_count] = { do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion do_op_float, // ev_integer + do_op_float, // ev_uinteger do_op_float, // ev_short do_op_invalid, // ev_invalid }; @@ -917,6 +924,7 @@ static operation_t op_vector[ev_type_count] = { do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion do_op_vector, // ev_integer + do_op_vector, // ev_uinteger do_op_vector, // ev_short do_op_invalid, // ev_invalid }; @@ -932,6 +940,7 @@ static operation_t op_entity[ev_type_count] = { do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion do_op_invalid, // ev_integer + do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_invalid }; @@ -947,6 +956,7 @@ static operation_t op_field[ev_type_count] = { do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion do_op_invalid, // ev_integer + do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_invalid }; @@ -962,6 +972,7 @@ static operation_t op_func[ev_type_count] = { do_op_func, // ev_pointer do_op_func, // ev_quaternion do_op_func, // ev_integer + do_op_func, // ev_uinteger do_op_func, // ev_short do_op_func, // ev_invalid }; @@ -977,6 +988,7 @@ static operation_t op_pointer[ev_type_count] = { do_op_pointer, // ev_pointer do_op_pointer, // ev_quaternion do_op_pointer, // ev_integer + do_op_pointer, // ev_uinteger do_op_pointer, // ev_short do_op_pointer, // ev_invalid }; @@ -992,6 +1004,7 @@ static operation_t op_quaternion[ev_type_count] = { do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion do_op_quaternion, // ev_integer + do_op_quaternion, // ev_uinteger do_op_quaternion, // ev_short do_op_invalid, // ev_invalid }; @@ -1007,10 +1020,27 @@ static operation_t op_integer[ev_type_count] = { do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion do_op_integer, // ev_integer + do_op_uinteger, // ev_uinteger do_op_integer, // ev_short do_op_invalid, // ev_invalid }; +static operation_t op_uinteger[ev_type_count] = { + do_op_invalid, // ev_void + do_op_invalid, // ev_string + do_op_float, // ev_float + do_op_vector, // ev_vector + do_op_invalid, // ev_entity + do_op_invalid, // ev_field + do_op_invalid, // ev_func + do_op_invalid, // ev_pointer + do_op_quaternion, // ev_quaternion + do_op_uinteger, // ev_integer + do_op_uinteger, // ev_uinteger + do_op_uinteger, // ev_short + do_op_invalid, // ev_invalid +}; + static operation_t op_short[ev_type_count] = { do_op_invalid, // ev_void do_op_invalid, // ev_string @@ -1022,6 +1052,7 @@ static operation_t op_short[ev_type_count] = { do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion do_op_integer, // ev_integer + do_op_uinteger, // ev_uinteger do_op_short, // ev_short do_op_invalid, // ev_invalid }; @@ -1037,6 +1068,7 @@ static operation_t op_compound[ev_type_count] = { do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion do_op_compound, // ev_integer + do_op_compound, // ev_uinteger do_op_compound, // ev_short do_op_compound, // ev_invalid }; @@ -1052,6 +1084,7 @@ static operation_t *do_op[ev_type_count] = { op_pointer, // ev_pointer op_quaternion, // ev_quaternion op_integer, // ev_integer + op_uinteger, // ev_uinteger op_short, // ev_short op_compound, // ev_invalid }; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index ad095f20e..220f2dd2b 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -332,6 +332,9 @@ print_value (expr_t *e, int level, int id) case ev_integer: label = va ("%d", e->e.value.v.integer_val); break; + case ev_uinteger: + label = va ("%u", e->e.value.v.uinteger_val); + break; case ev_short: label = va ("%d", e->e.value.v.short_val); break; diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 89c33a2bc..8b9e3c930 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -122,6 +122,8 @@ get_operand (operand_t *op) return va ("func %d", op->o.value->v.integer_val); case ev_integer: return va ("int %d", op->o.value->v.integer_val); + case ev_uinteger: + return va ("uint %u", op->o.value->v.uinteger_val); case ev_short: return va ("short %d", op->o.value->v.short_val); case ev_void: diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index cedeaf87b..a0da890f9 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -78,6 +78,7 @@ type_t *ev_types[ev_type_count] = { &type_pointer, &type_quaternion, &type_integer, + &type_uinteger, &type_short, &type_invalid, }; @@ -584,6 +585,16 @@ new_integer_expr (int integer_val) return e; } +expr_t * +new_uinteger_expr (unsigned uinteger_val) +{ + expr_t *e = new_expr (); + e->type = ex_value; + e->e.value.type = ev_uinteger; + e->e.value.v.uinteger_val = uinteger_val; + return e; +} + expr_t * new_short_expr (short short_val) { @@ -771,6 +782,23 @@ expr_integer (expr_t *e) internal_error (e, "not an integer constant"); } +unsigned +expr_uinteger (expr_t *e) +{ + if (e->type == ex_nil) + return 0; + if (e->type == ex_value && e->e.value.type == ev_uinteger) + return e->e.value.v.uinteger_val; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_uinteger) + return e->e.symbol->s.value.v.uinteger_val; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var + && e->e.symbol->s.def->constant + && is_integral (e->e.symbol->s.def->type)) + return D_INT (e->e.symbol->s.def); + internal_error (e, "not an unsigned constant"); +} + int is_short_val (expr_t *e) { @@ -1029,7 +1057,7 @@ test_expr (expr_t *e) case ev_string: new = new_string_expr (0); break; -// case ev_uinteger: + case ev_uinteger: case ev_integer: case ev_short: if (type_default != &type_integer) @@ -1187,9 +1215,9 @@ convert_from_bool (expr_t *e, type_t *type) zero = new_integer_expr (0); } else if (is_enum (type) && enum_as_bool (type, &zero, &one)) { // don't need to do anything -// } else if (type == &type_uinteger) { -// one = new_uinteger_expr (1); -// zero = new_uinteger_expr (0); + } else if (type == &type_uinteger) { + one = new_uinteger_expr (1); + zero = new_uinteger_expr (0); } else { return error (e, "can't convert from bool value"); } @@ -1567,6 +1595,8 @@ unary_expr (int op, expr_t *e) return new_vector_expr (q); case ev_integer: return new_integer_expr (-expr_integer (e)); + case ev_uinteger: + return new_uinteger_expr (-expr_uinteger (e)); case ev_short: return new_short_expr (-expr_short (e)); case ev_invalid: @@ -1627,6 +1657,8 @@ unary_expr (int op, expr_t *e) return new_integer_expr (!QuatIsZero (expr_quaternion (e))); case ev_integer: return new_integer_expr (!expr_integer (e)); + case ev_uinteger: + return new_uinteger_expr (!expr_uinteger (e)); case ev_short: return new_short_expr (!expr_short (e)); case ev_invalid: @@ -1682,6 +1714,8 @@ unary_expr (int op, expr_t *e) return new_vector_expr (q); case ev_integer: return new_integer_expr (~expr_integer (e)); + case ev_uinteger: + return new_uinteger_expr (~expr_uinteger (e)); case ev_short: return new_short_expr (~expr_short (e)); case ev_invalid: @@ -2607,6 +2641,9 @@ cast_expr (type_t *type, expr_t *e) if ((type == type_default && is_enum (e_type)) || (is_enum (type) && e_type == type_default)) return e; + if ((type == &type_integer && e_type == &type_uinteger) + || (type == &type_uinteger && e_type == &type_integer)) + return new_alias_expr (type, e); if (!(type->type == ev_pointer && (e_type->type == ev_pointer || e_type == &type_integer //|| e_type == &type_uinteger diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 388f0c173..78b5cafb0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -98,6 +98,9 @@ print_operand (operand_t *op) case ev_integer: printf ("%d", op->o.value->v.integer_val); break; + case ev_uinteger: + printf ("%u", op->o.value->v.uinteger_val); + break; case ev_short: printf ("%d", op->o.value->v.short_val); break; diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index c4878baee..800922284 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -338,7 +338,6 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, range = fold_constants (range); - //FIXME unsigned int better? sym = make_symbol (name, array_type (&type_integer, high - low + 1), pr.near_data, st_static); table = new_symbol_expr (sym); @@ -348,8 +347,8 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, branch = branch_expr (IFB, temp, low_label); append_expr (sw, branch); } - //FIXME unsigned int - test = binary_expr (GT, cast_expr (&type_integer, temp), range); + test = binary_expr (GT, cast_expr (&type_uinteger, temp), + cast_expr (&type_uinteger, range)); branch = branch_expr ('i', test, high_label); append_expr (sw, branch); branch = new_binary_expr ('g', table, temp); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 2dca3bbf3..656705966 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -75,6 +75,7 @@ type_t type_function = { ev_func, "function", ty_none, {{&type_void}} }; type_t type_pointer = { ev_pointer, "pointer", ty_none, {{&type_void}} }; type_t type_quaternion = { ev_quat, "quaternion" }; type_t type_integer = { ev_integer, "integer" }; +type_t type_uinteger = { ev_uinteger, "uinteger" }; type_t type_short = { ev_short, "short" }; type_t *type_nil; @@ -154,6 +155,7 @@ free_type (type_t *type) case ev_type_count: case ev_quat: case ev_integer: + case ev_uinteger: case ev_short: break; case ev_field: @@ -188,6 +190,7 @@ append_type (type_t *type, type_t *new) case ev_type_count: case ev_quat: case ev_integer: + case ev_uinteger: case ev_short: internal_error (0, "append to basic type"); case ev_field: @@ -593,6 +596,9 @@ encode_type (dstring_t *encoding, type_t *type) case ev_integer: dasprintf (encoding, "i"); break; + case ev_uinteger: + dasprintf (encoding, "I"); + break; case ev_short: dasprintf (encoding, "s"); break; @@ -641,7 +647,7 @@ is_integral (type_t *type) { etype_t t = type->type; - if (t == ev_integer || t == ev_short) + if (t == ev_integer || t == ev_uinteger || t == ev_short) return 1; return is_enum (type); } @@ -758,6 +764,7 @@ type_size (type_t *type) case ev_pointer: case ev_quat: case ev_integer: + case ev_uinteger: case ev_short: case ev_type_count: return pr_type_size[type->type]; @@ -805,6 +812,7 @@ init_types (void) {"pointer_val", &type_pointer}, {"vector_val", &type_vector}, {"integer_val", &type_integer}, + {"uinteger_val", &type_uinteger}, {"quaternion_val", &type_quaternion}, {0, 0} }; @@ -817,6 +825,7 @@ init_types (void) {"func_val", &type_function}, {"pointer_val", &type_pointer}, {"integer_val", &type_integer}, + {"uinteger_val", &type_uinteger}, {"quaternion_val", &type_quaternion}, {0, 0} }; @@ -881,6 +890,7 @@ chain_initial_types (void) if (!options.traditional) { chain_type (&type_quaternion); chain_type (&type_integer); + chain_type (&type_uinteger); chain_type (&type_short); } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index d04f837d7..1e5661666 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -237,6 +237,7 @@ emit_value (ex_value_t *value, def_t *def) type = &type_pointer; break; case ev_integer: + case ev_uinteger: if (!def || def->type != &type_float) { tab = integer_imm_defs; type = &type_integer;