diff --git a/.gitignore b/.gitignore index 25d1878ed..a3e375bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ core /ltmain.sh /missing /mkinstalldirs +/py-compile /quakeforge-config /quakeforge.lsm /test-driver diff --git a/Makefile.am b/Makefile.am index dbc83cea2..33aa5b689 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,6 +42,7 @@ noinst_LTLIBRARIES = noinst_LIBRARIES = noinst_PROGRAMS = noinst_HEADERS = +noinst_PYTHON = plugin_LTLIBRARIES = RANLIB=touch @@ -110,6 +111,11 @@ qcautodep = $(join $(addsuffix $(DEPDIR)/,$(dir $(basename $(1)))),$(addsuffix . r_depfiles_remade= pas_depfiles_remade= +V_PY = $(V_PY_@AM_V@) +V_PY_ = $(V_PY_@AM_DEFAULT_V@) +V_PY_0 = @echo " PY " $@; +V_PY_1 = + V_GLSLANG = $(V_GLSLANG_@AM_V@) V_GLSLANG_ = $(V_GLSLANG_@AM_DEFAULT_V@) V_GLSLANG_0 = @echo " GLSLANG " $@; diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index f55045a58..f3e59d2d5 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -316,9 +316,11 @@ if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) qfac_qfcc_include_qf="\$(qfcc_include_qf)" qfac_qfcc_include_qf_input="\$(qfcc_include_qf_input)" + qfac_qfcc_include_qf_progs="\$(qfcc_include_qf_progs)" fi QF_SUBST(qfac_qfcc_include_qf) QF_SUBST(qfac_qfcc_include_qf_input) +QF_SUBST(qfac_qfcc_include_qf_progs) if test x"${top_need_libs}" = xyes; then qfac_include_qf="\$(include_qf)" diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 1cd08dfa4..7fd5bd6c2 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -92,7 +92,6 @@ AC_ARG_ENABLE(simd, case "$enable_simd" in no) - QF_CC_OPTION(-Wno-psabi) simd=no ;; sse|sse2|avx|avx2) @@ -108,6 +107,13 @@ case "$enable_simd" in done ;; esac +case "$simd" in + avx*) + ;; + *) + QF_CC_OPTION(-Wno-psabi) + ;; +esac AC_MSG_CHECKING(for optimization) if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then diff --git a/config.d/programs.m4 b/config.d/programs.m4 index bcff065c5..bb8ac5e9d 100644 --- a/config.d/programs.m4 +++ b/config.d/programs.m4 @@ -8,6 +8,7 @@ AC_PROG_CPP AC_PROG_LN_S AC_PROG_RANLIB AM_PROG_AS +AM_PATH_PYTHON([3]) PKG_PROG_PKG_CONFIG diff --git a/doc/progs/vm-exec.c b/doc/progs/vm-exec.c index 1f9ae4b8e..b250848cd 100644 --- a/doc/progs/vm-exec.c +++ b/doc/progs/vm-exec.c @@ -5,7 +5,7 @@ call_progs_main (progs_t *pr, int argc, const char **argv) { int i; dfunction_t *dfunc; - func_t progs_main = 0; + pr_func_t progs_main = 0; string_t *pr_argv; if ((dfunc = PR_FindFunction (pr, "main"))) { diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index ff47836db..d36dd7ead 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -43,10 +43,6 @@ include_qf = \ include/QF/plist.h \ include/QF/plugin.h \ include/QF/pqueue.h \ - include/QF/pr_comp.h \ - include/QF/pr_debug.h \ - include/QF/pr_obj.h \ - include/QF/pr_type.h \ include/QF/progs.h \ include/QF/pvsfile.h \ include/QF/qargs.h \ @@ -119,6 +115,7 @@ include_qf_input = \ include/QF/input/imt.h include_qf_math = \ + include/QF/math/bitop.h \ include/QF/math/dual.h \ include/QF/math/half.h \ include/QF/math/matrix3.h \ @@ -135,6 +132,13 @@ include_qf_plugin = \ include/QF/plugin/snd_render.h \ include/QF/plugin/vid_render.h +include_qf_progs = \ + include/QF/progs/pr_comp.h \ + include/QF/progs/pr_debug.h \ + include/QF/progs/pr_obj.h \ + include/QF/progs/pr_type.h \ + include/QF/progs/pr_type_names.h + include_qf_scene = \ include/QF/scene/entity.h \ include/QF/scene/hierarchy.h \ @@ -145,8 +149,12 @@ include_qf_scene = \ include_qf_simd = \ include/QF/simd/mat4f.h \ include/QF/simd/types.h \ + include/QF/simd/vec2d.h \ + include/QF/simd/vec2f.h \ + include/QF/simd/vec2i.h \ include/QF/simd/vec4d.h \ - include/QF/simd/vec4f.h + include/QF/simd/vec4f.h \ + include/QF/simd/vec4i.h include_qf_ui = \ include/QF/ui/inputline.h \ @@ -191,6 +199,7 @@ include_qf_vulkan = \ # headers shared with ruamoko qfcc_include_qf = include/QF/input.h +qfcc_include_qf_progs = include/QF/progs/pr_type_names.h qfcc_include_qf_input = \ include/QF/input/binding.h \ include/QF/input/imt.h @@ -218,8 +227,10 @@ qf_vulkan_include_HEADERS = @qfac_include_qf_vulkan@ ruamoko_qf_includedir = $(ruamoko_includedir)/QF ruamoko_qf_input_includedir = $(ruamoko_includedir)/QF/input +ruamoko_qf_progs_includedir = $(ruamoko_includedir)/QF/progs ruamoko_qf_include_HEADERS = @qfac_qfcc_include_qf@ ruamoko_qf_input_include_HEADERS = @qfac_qfcc_include_qf_input@ +ruamoko_qf_progs_include_HEADERS = @qfac_qfcc_include_qf_progs@ EXTRA_HEADERS += \ $(include_qf) \ @@ -228,6 +239,7 @@ EXTRA_HEADERS += \ $(include_qf_input) \ $(include_qf_math) \ $(include_qf_plugin) \ + $(include_qf_progs) \ $(include_qf_scene) \ $(include_qf_simd) \ $(include_qf_ui) \ diff --git a/include/QF/math/bitop.h b/include/QF/math/bitop.h new file mode 100644 index 000000000..ee00ac6ca --- /dev/null +++ b/include/QF/math/bitop.h @@ -0,0 +1,73 @@ +/* + bitop.h + + bit-op functions + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/1/23 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_math_bitop_h +#define __QF_math_bitop_h + +/** \defgroup mathlib_bitop Bit-op functions + \ingroup utils +*/ +///@{ + +#include "QF/qtypes.h" + +#define BITOP_RUP1__(x) ( (x) | ( (x) >> 1)) +#define BITOP_RUP2__(x) (BITOP_RUP1__(x) | (BITOP_RUP1__(x) >> 2)) +#define BITOP_RUP4__(x) (BITOP_RUP2__(x) | (BITOP_RUP2__(x) >> 4)) +#define BITOP_RUP8__(x) (BITOP_RUP4__(x) | (BITOP_RUP4__(x) >> 8)) +#define BITOP_RUP16__(x) (BITOP_RUP8__(x) | (BITOP_RUP8__(x) >> 16)) +/** Round x up to the next power of two. + + Rounds x up to the next power of two leaving exact powers of two + untouched. + + \param x The value to round + \return The next higher power of two or x if it already is a power + of two. +*/ +#define BITOP_RUP(x) (BITOP_RUP16__((uint32_t)(x) - 1) + 1) + +#define BITOP_LOG2__(x) (((((x) & 0xffff0000) != 0) << 4) \ + |((((x) & 0xff00ff00) != 0) << 3) \ + |((((x) & 0xf0f0f0f0) != 0) << 2) \ + |((((x) & 0xcccccccc) != 0) << 1) \ + |((((x) & 0xaaaaaaaa) != 0) << 0)) +/** Log base 2 rounded up. + + Finds the base 2 logarithm of x rounded up (ceil(log2(x))). + + \param x The value for which to find the base 2 logarithm. + \return Log base 2 of x, rounded up (2 -> 1, 3 -> 2, 4 -> 2) +*/ +#define BITOP_LOG2(x) BITOP_LOG2__(BITOP_RUP(x)) + +///@} + +#endif // __QF_math_bitop_h diff --git a/include/QF/math/quaternion.h b/include/QF/math/quaternion.h index da39b7734..60245ad77 100644 --- a/include/QF/math/quaternion.h +++ b/include/QF/math/quaternion.h @@ -115,10 +115,17 @@ extern const vec_t *const quat_origin; (c)[2] = (a)[2] / (b)[2]; \ (c)[3] = (a)[3] / (b)[3]; \ } while (0) -#define QuatCompCompare(x, op, y) \ +#define QuatCompCompare(m, a, op, b, c) \ + do { \ + (c)[0] = m((a)[0] op (b)[0]); \ + (c)[1] = m((a)[1] op (b)[1]); \ + (c)[2] = m((a)[2] op (b)[2]); \ + (c)[3] = m((a)[3] op (b)[3]); \ + } while (0) +#define QuatCompCompareAll(x, op, y) \ (((x)[0] op (y)[0]) && ((x)[1] op (y)[1]) \ && ((x)[2] op (y)[2]) && ((x)[3] op (y)[3])) -#define QuatCompare(x, y) QuatCompCompare (x, ==, y) +#define QuatCompare(x, y) QuatCompCompareAll (x, ==, y) #define QuatCompMin(a, b, c) \ do { \ (c)[0] = min ((a)[0], (b)[0]); \ diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 6189d002c..f45893f50 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -37,25 +37,27 @@ extern const vec_t *const vec3_origin; +#define VectorCompUop(b, op, a) \ + do { \ + (b)[0] = op ((a)[0]); \ + (b)[1] = op ((a)[1]); \ + (b)[2] = op ((a)[2]); \ + } while (0) +#define VectorCompOp(c, a, op, b) \ + do { \ + (c)[0] = (a)[0] op (b)[0]; \ + (c)[1] = (a)[1] op (b)[1]; \ + (c)[2] = (a)[2] op (b)[2]; \ + } while (0) +#define VectorCompAdd(c,a,b) VectorCompOp (c, a, +, b) +#define VectorCompSub(c,a,b) VectorCompOp (c, a, -, b) +#define VectorCompMult(c,a,b) VectorCompOp (c, a, *, b) +#define VectorCompDiv(c,a,b) VectorCompOp (c, a, /, b) + #define DotProduct(a,b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2]) -#define VectorSubtract(a,b,c) \ - do { \ - (c)[0] = (a)[0] - (b)[0]; \ - (c)[1] = (a)[1] - (b)[1]; \ - (c)[2] = (a)[2] - (b)[2]; \ - } while (0) -#define VectorNegate(a,b) \ - do { \ - (b)[0] = -(a)[0]; \ - (b)[1] = -(a)[1]; \ - (b)[2] = -(a)[2]; \ - } while (0) -#define VectorAdd(a,b,c) \ - do { \ - (c)[0] = (a)[0] + (b)[0]; \ - (c)[1] = (a)[1] + (b)[1]; \ - (c)[2] = (a)[2] + (b)[2]; \ - } while (0) +#define VectorSubtract(a,b,c) VectorCompSub (c, a, b) +#define VectorNegate(a,b) VectorCompUop (b, -, a) +#define VectorAdd(a,b,c) VectorCompAdd (c, a, b) #define VectorCopy(a,b) \ do { \ (b)[0] = (a)[0]; \ @@ -119,21 +121,15 @@ extern const vec_t *const vec3_origin; (c)[1] = (b)[1] - (b)[0] * (a)[0]; \ (c)[0] = (b)[0]; \ } while (0) -#define VectorCompMult(a,b,c) \ +#define VectorCompCompare(c, m, a, op, b) \ do { \ - (c)[0] = (a)[0] * (b)[0]; \ - (c)[1] = (a)[1] * (b)[1]; \ - (c)[2] = (a)[2] * (b)[2]; \ + (c)[0] = m((a)[0] op (b)[0]); \ + (c)[1] = m((a)[1] op (b)[1]); \ + (c)[2] = m((a)[2] op (b)[2]); \ } while (0) -#define VectorCompDiv(a,b,c) \ - do { \ - (c)[0] = (a)[0] / (b)[0]; \ - (c)[1] = (a)[1] / (b)[1]; \ - (c)[2] = (a)[2] / (b)[2]; \ - } while (0) -#define VectorCompCompare(x, op, y) \ +#define VectorCompCompareAll(x, op, y) \ (((x)[0] op (y)[0]) && ((x)[1] op (y)[1]) && ((x)[2] op (y)[2])) -#define VectorCompare(x, y) VectorCompCompare (x, ==, y) +#define VectorCompare(x, y) VectorCompCompareAll (x, ==, y) #define VectorCompMin(a, b, c) \ do { \ (c)[0] = min ((a)[0], (b)[0]); \ diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h deleted file mode 100644 index 0cd65d7e5..000000000 --- a/include/QF/pr_comp.h +++ /dev/null @@ -1,521 +0,0 @@ -/* Copyright (C) 1996-1997 Id Software, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - See file, 'COPYING', for details. -*/ - -// this file is shared by QuakeForge and qfcc -#ifndef __QF_pr_comp_h -#define __QF_pr_comp_h - -#include "QF/qtypes.h" - -typedef int16_t pr_short_t; -typedef uint16_t pr_ushort_t; -typedef int32_t pr_int_t; -typedef uint32_t pr_uint_t; -typedef pr_uint_t func_t; -typedef pr_int_t string_t; -typedef pr_uint_t pointer_t; - -typedef enum { - ev_void, - ev_string, - ev_float, - ev_vector, - ev_entity, - ev_field, - ev_func, - ev_pointer, // end of v6 types - ev_quat, - ev_integer, - ev_uinteger, - ev_short, // value is embedded in the opcode - ev_double, - - ev_invalid, // invalid type. used for instruction checking - ev_type_count // not a type, gives number of types -} etype_t; - -extern const pr_ushort_t pr_type_size[ev_type_count]; -extern const char * const pr_type_name[ev_type_count]; - -#define OFS_NULL 0 -#define OFS_RETURN 1 -#define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors -#define OFS_PARM1 7 -#define OFS_PARM2 10 -#define OFS_PARM3 13 -#define OFS_PARM4 16 -#define OFS_PARM5 19 -#define OFS_PARM6 22 -#define OFS_PARM7 25 -#define RESERVED_OFS 28 - - -typedef enum { - OP_DONE, - OP_MUL_F, - OP_MUL_V, - OP_MUL_FV, - OP_MUL_VF, - OP_DIV_F, - OP_ADD_F, - OP_ADD_V, - OP_SUB_F, - OP_SUB_V, - - OP_EQ_F, - OP_EQ_V, - OP_EQ_S, - OP_EQ_E, - OP_EQ_FN, - - OP_NE_F, - OP_NE_V, - OP_NE_S, - OP_NE_E, - OP_NE_FN, - - OP_LE_F, - OP_GE_F, - OP_LT_F, - OP_GT_F, - - OP_LOAD_F, - OP_LOAD_V, - OP_LOAD_S, - OP_LOAD_ENT, - OP_LOAD_FLD, - OP_LOAD_FN, - - OP_ADDRESS, - - OP_STORE_F, - OP_STORE_V, - OP_STORE_S, - OP_STORE_ENT, - OP_STORE_FLD, - OP_STORE_FN, - - OP_STOREP_F, - OP_STOREP_V, - OP_STOREP_S, - OP_STOREP_ENT, - OP_STOREP_FLD, - OP_STOREP_FN, - - OP_RETURN, - OP_NOT_F, - OP_NOT_V, - OP_NOT_S, - OP_NOT_ENT, - OP_NOT_FN, - OP_IF, - OP_IFNOT, - OP_CALL0, - OP_CALL1, - OP_CALL2, - OP_CALL3, - OP_CALL4, - OP_CALL5, - OP_CALL6, - OP_CALL7, - OP_CALL8, - OP_STATE, - OP_GOTO, - OP_AND, - OP_OR, - - OP_BITAND, - OP_BITOR, // end of v6 opcodes - - OP_ADD_S, - OP_LE_S, - OP_GE_S, - OP_LT_S, - OP_GT_S, - - OP_ADD_I, - OP_SUB_I, - OP_MUL_I, - OP_DIV_I, - OP_BITAND_I, - OP_BITOR_I, - OP_GE_I, - OP_LE_I, - OP_GT_I, - OP_LT_I, - OP_AND_I, - OP_OR_I, - OP_NOT_I, - OP_EQ_I, - OP_NE_I, - OP_STORE_I, - OP_STOREP_I, - OP_LOAD_I, - - OP_CONV_IF, - OP_CONV_FI, - - OP_BITXOR_F, - OP_BITXOR_I, - OP_BITNOT_F, - OP_BITNOT_I, - - OP_SHL_F, - OP_SHR_F, - OP_SHL_I, - OP_SHR_I, - - OP_REM_F, - OP_REM_I, - - OP_LOADB_F, - OP_LOADB_V, - OP_LOADB_S, - OP_LOADB_ENT, - OP_LOADB_FLD, - OP_LOADB_FN, - OP_LOADB_I, - OP_LOADB_P, - - OP_STOREB_F, - OP_STOREB_V, - OP_STOREB_S, - OP_STOREB_ENT, - OP_STOREB_FLD, - OP_STOREB_FN, - OP_STOREB_I, - OP_STOREB_P, - - OP_ADDRESS_VOID, - OP_ADDRESS_F, - OP_ADDRESS_V, - OP_ADDRESS_S, - OP_ADDRESS_ENT, - OP_ADDRESS_FLD, - OP_ADDRESS_FN, - OP_ADDRESS_I, - OP_ADDRESS_P, - - OP_LEA, - - OP_IFBE, - OP_IFB, - OP_IFAE, - OP_IFA, - - OP_JUMP, - OP_JUMPB, - - OP_LT_U, - OP_GT_U, - OP_LE_U, - OP_GE_U, - - OP_LOADBI_F, - OP_LOADBI_V, - OP_LOADBI_S, - OP_LOADBI_ENT, - OP_LOADBI_FLD, - OP_LOADBI_FN, - OP_LOADBI_I, - OP_LOADBI_P, - - OP_STOREBI_F, - OP_STOREBI_V, - OP_STOREBI_S, - OP_STOREBI_ENT, - OP_STOREBI_FLD, - OP_STOREBI_FN, - OP_STOREBI_I, - OP_STOREBI_P, - - OP_LEAI, - - OP_LOAD_P, - OP_STORE_P, - OP_STOREP_P, - OP_NOT_P, - OP_EQ_P, - OP_NE_P, - OP_LE_P, - OP_GE_P, - OP_LT_P, - OP_GT_P, - - OP_MOVEI, - OP_MOVEP, - OP_MOVEPI, - - OP_SHR_U, - - OP_STATE_F, - - OP_ADD_Q, - OP_SUB_Q, - OP_MUL_Q, - OP_MUL_QF, - OP_MUL_FQ, - OP_MUL_QV, - OP_CONJ_Q, - OP_NOT_Q, - OP_EQ_Q, - OP_NE_Q, - OP_STORE_Q, - OP_STOREB_Q, - OP_STOREBI_Q, - OP_STOREP_Q, - OP_LOAD_Q, - OP_LOADB_Q, - OP_LOADBI_Q, - OP_ADDRESS_Q, - - OP_RCALL0, - OP_RCALL1, - OP_RCALL2, - OP_RCALL3, - OP_RCALL4, - OP_RCALL5, - OP_RCALL6, - OP_RCALL7, - OP_RCALL8, - - OP_RETURN_V, - - OP_PUSH_S, - OP_PUSH_F, - OP_PUSH_V, - OP_PUSH_ENT, - OP_PUSH_FLD, - OP_PUSH_FN, - OP_PUSH_P, - OP_PUSH_Q, - OP_PUSH_I, - OP_PUSH_D, - - OP_PUSHB_S, - OP_PUSHB_F, - OP_PUSHB_V, - OP_PUSHB_ENT, - OP_PUSHB_FLD, - OP_PUSHB_FN, - OP_PUSHB_P, - OP_PUSHB_Q, - OP_PUSHB_I, - OP_PUSHB_D, - - OP_PUSHBI_S, - OP_PUSHBI_F, - OP_PUSHBI_V, - OP_PUSHBI_ENT, - OP_PUSHBI_FLD, - OP_PUSHBI_FN, - OP_PUSHBI_P, - OP_PUSHBI_Q, - OP_PUSHBI_I, - OP_PUSHBI_D, - - OP_POP_S, - OP_POP_F, - OP_POP_V, - OP_POP_ENT, - OP_POP_FLD, - OP_POP_FN, - OP_POP_P, - OP_POP_Q, - OP_POP_I, - OP_POP_D, - - OP_POPB_S, - OP_POPB_F, - OP_POPB_V, - OP_POPB_ENT, - OP_POPB_FLD, - OP_POPB_FN, - OP_POPB_P, - OP_POPB_Q, - OP_POPB_I, - OP_POPB_D, - - OP_POPBI_S, - OP_POPBI_F, - OP_POPBI_V, - OP_POPBI_ENT, - OP_POPBI_FLD, - OP_POPBI_FN, - OP_POPBI_P, - OP_POPBI_Q, - OP_POPBI_I, - OP_POPBI_D, - - OP_ADD_D, - OP_SUB_D, - OP_MUL_D, - OP_MUL_QD, - OP_MUL_DQ, - OP_MUL_VD, - OP_MUL_DV, - OP_DIV_D, - OP_REM_D, - OP_GE_D, - OP_LE_D, - OP_GT_D, - OP_LT_D, - OP_NOT_D, - OP_EQ_D, - OP_NE_D, - OP_CONV_FD, - OP_CONV_DF, - OP_CONV_ID, - OP_CONV_DI, - OP_STORE_D, - OP_STOREB_D, - OP_STOREBI_D, - OP_STOREP_D, - OP_LOAD_D, - OP_LOADB_D, - OP_LOADBI_D, - OP_ADDRESS_D, - - OP_MOD_I, - OP_MOD_F, - OP_MOD_D, - - OP_MEMSETI, - OP_MEMSETP, - OP_MEMSETPI, -} pr_opcode_e; -#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; - unsigned int min_version; - const char *fmt; -} opcode_t; - -extern const opcode_t pr_opcodes[]; -opcode_t *PR_Opcode (pr_short_t opcode); -void PR_Opcode_Init (void); // idempotent - -typedef struct dstatement_s { - pr_opcode_e op:16; - pr_ushort_t a,b,c; -} GCC_STRUCT dstatement_t; - -typedef struct ddef_s { - pr_ushort_t type; // if DEF_SAVEGLOBAL bit is set - // the variable needs to be saved in savegames - pr_ushort_t ofs; - string_t s_name; -} ddef_t; - -typedef struct xdef_s { - pointer_t type; ///< pointer to type definition - pointer_t ofs; ///< 32-bit version of ddef_t.ofs -} xdef_t; - -typedef struct pr_xdefs_s { - pointer_t xdefs; - pr_int_t num_xdefs; -} pr_xdefs_t; - -typedef struct pr_def_s { - pr_ushort_t type; - pr_ushort_t size; ///< may not be correct - pointer_t ofs; - string_t name; - pointer_t type_encoding; -} pr_def_t; - -typedef struct dparmsize_s { - uint8_t size:5; - uint8_t alignment:3; -} dparmsize_t; - -#define DEF_SAVEGLOBAL (1<<15) - -#define MAX_PARMS 8 - -typedef struct dfunction_s { - pr_int_t first_statement; // negative numbers are builtins - pr_uint_t parm_start; - pr_uint_t locals; // total ints of parms + locals - - pr_uint_t profile; // runtime - - string_t s_name; - string_t s_file; // source file defined in - - pr_int_t numparms; - dparmsize_t parm_size[MAX_PARMS]; -} dfunction_t; - -typedef union pr_type_u { - float float_var; - string_t string_var; - func_t func_var; - pr_int_t entity_var; - float vector_var; // really [3], but this structure must be 32 bits - float quat_var; // really [4], but this structure must be 32 bits - pr_int_t integer_var; - pointer_t pointer_var; - pr_uint_t uinteger_var; -} pr_type_t; - -typedef struct pr_va_list_s { - pr_int_t count; - pointer_t list; // pr_type_t -} pr_va_list_t; - -#define PROG_VERSION_ENCODE(a,b,c) \ - ( (((0x##a) & 0x0ff) << 24) \ - |(((0x##b) & 0xfff) << 12) \ - |(((0x##c) & 0xfff) << 0) ) -#define PROG_ID_VERSION 6 -#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,00a) - -typedef struct dprograms_s { - pr_uint_t version; - pr_uint_t crc; // check of header file - - pr_uint_t ofs_statements; - pr_uint_t numstatements; // statement 0 is an error - - pr_uint_t ofs_globaldefs; - pr_uint_t numglobaldefs; - - pr_uint_t ofs_fielddefs; - pr_uint_t numfielddefs; - - pr_uint_t ofs_functions; - pr_uint_t numfunctions; // function 0 is an empty - - pr_uint_t ofs_strings; - pr_uint_t numstrings; // first string is a null string - - pr_uint_t ofs_globals; - pr_uint_t numglobals; - - pr_uint_t entityfields; -} dprograms_t; - -#endif//__QF_pr_comp_h diff --git a/include/QF/progs.h b/include/QF/progs.h index 3f6ad6ae3..0fd8efdfc 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -33,8 +33,9 @@ \image latex vm-mem.eps "VM memory map" */ -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/math/bitop.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" struct QFile_s; @@ -81,15 +82,13 @@ void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(PRI \warning Failure to use this macro before assigning to the P_* macros can cause corruption of the VM data due to "register" based calling. Can be safely ignored for parameterless functions, or forwarding parameters - though a builtin. + though a builtin. However, it is ok (and encouraged) to call + PR_SetupParams instead, as this macro calls PR_SetupParams with + PR_MAX_PARAMS and 1 for the alignment. \hideinitializer */ -#define PR_RESET_PARAMS(pr) \ - do { \ - (pr)->pr_params[0] = (pr)->pr_real_params[0]; \ - (pr)->pr_params[1] = (pr)->pr_real_params[1]; \ - } while (0) +#define PR_RESET_PARAMS(pr) PR_SetupParams (pr, PR_MAX_PARAMS, 1) /** \name Detouring Function Calls @@ -154,6 +153,38 @@ void PR_RestoreParams (progs_t *pr, pr_stashed_params_t *params); */ void PR_PushFrame (progs_t *pr); +/** Reserve space on the data stack and set up the param pointers. + + For v6p progs, this only sets up the param pointers as v6p progs do not + have a data stack. + + For Ruamoko progs, space for at least \a num_params (each being 4 words) + is created on the stack, with a minimum alignment of min_alignment words, + or 4, whichever is larger. + + \param pr pointer to ::progs_t VM struct + \param num_params Number of parameter slots needed for the function call. + Each slot is 4 words. dvec4 and lvec4 parameters require + 8 words and must be 8-word aligned. dvec3 and lvec3 + also require 8 words due to the minimum 4 word alignment, + but have no alignment requirements themselves. Be sure to + take this into account in size calculations. + \param min_alignment Minimum number of words to which the stack will be + aligned. Must be a power of two. Note that when passing + dvec4 or lvec4 parameters, they have a hardware-enforced + requirement of 8 word alignment. This means that for + something like (int, lvec4), there will be an unused + parameter slot between the int and the lvec4. + Ignored for v6p progs. + \return Pointer to the base of the created parameter area. For + v6p progs, this is just .param_0, but for Ruamoko progs + this will be the current top of the the data stack after + adjustment for the parameter space. + \note Attempting to pass more than PR_MAX_PARAMS parameters to v6p progs + is a hard error. +*/ +pr_type_t *PR_SetupParams (progs_t *pr, int num_params, int min_alignment); + /** Pop an execution frame from the VM stack. Restores execution state. Also frees any temporary strings allocated in this frame (via PR_FreeTempStrings()). @@ -166,8 +197,9 @@ void PR_PopFrame (progs_t *pr); return to the caller. Nested calls are fully supported. \param pr pointer to ::progs_t VM struct \param fnum number of the function to call + \note Calls PR_CallFunction() */ -void PR_ExecuteProgram (progs_t *pr, func_t fnum); +void PR_ExecuteProgram (progs_t *pr, pr_func_t fnum); /** Setup to call a function. If \p fnum is a builtin rather than a progs function, then the function is called immediately. When called from a @@ -175,10 +207,15 @@ void PR_ExecuteProgram (progs_t *pr, func_t fnum); execute upon return of control to PR_ExecuteProgram(). \param pr pointer to ::progs_t VM struct \param fnum number of the function to call + \param return_ptr pointer to location in which return values will be + written \return true if \p fnum was a progs function, false if \p fnum was a builtin + \note Called by PR_ExecuteProgram, so the only time this should be called + is in a builtin function that calls a progs function and returns + immediately (eg, to implement `return progsfunc();`). */ -int PR_CallFunction (progs_t *pr, func_t fnum); +int PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr); ///@} @@ -195,7 +232,7 @@ typedef int pr_load_func_t (progs_t *pr); /** Initialize a ::progs_t VM struct from an already open file. \param pr pointer to ::progs_t VM struct - \param file handle of file to read progs data from + \param file handle of file from which to read progs data \param size bytes of \p file to read \note \e All runtime strings (permanent or temporary) are allocated from @@ -262,8 +299,9 @@ int PR_RunPostLoadFuncs (progs_t *pr); \todo should this be elsewhere? */ int PR_Check_Opcodes (progs_t *pr); +int PR_Check_v6p_Opcodes (progs_t *pr); -void PR_BoundsCheckSize (progs_t *pr, pointer_t addr, unsigned size); +void PR_BoundsCheckSize (progs_t *pr, pr_ptr_t addr, unsigned size); void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); ///@} @@ -276,8 +314,8 @@ void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); struct edict_s { qboolean free; progs_t *pr; ///< progs owning this edict - int entnum; ///< number of this entity - int edict; ///< offset of this entity in pr_edict_area + pr_uint_t entnum; ///< number of this entity + pr_uint_t edict; ///< offset of this entity in pr_edict_area float freetime; ///< sv.time when the object was freed void *edata; ///< external per-edict data }; @@ -286,10 +324,10 @@ struct edict_s { void ED_ClearEdict (progs_t *pr, edict_t *e, int val); edict_t *ED_Alloc (progs_t *pr); void ED_Free (progs_t *pr, edict_t *ed); -edict_t *ED_EdictNum(progs_t *pr, pr_int_t n) __attribute__((pure)); -pr_int_t ED_NumForEdict(progs_t *pr, edict_t *e) __attribute__((pure)); +edict_t *ED_EdictNum(progs_t *pr, pr_uint_t n) __attribute__((pure)); +pr_uint_t ED_NumForEdict(progs_t *pr, edict_t *e) __attribute__((pure)); void ED_Count (progs_t *pr); -qboolean PR_EdictValid (progs_t *pr, pr_int_t e) __attribute__((pure)); +qboolean PR_EdictValid (progs_t *pr, pr_uint_t e) __attribute__((pure)); // pr_debug.c void ED_Print (progs_t *pr, edict_t *ed, const char *fieldname); @@ -314,10 +352,10 @@ void ED_EntityParseFunction (progs_t *pr); #define PR_edicts(p) (*(p)->pr_edicts) -#define NEXT_EDICT(p,e) ((e) + 1) -#define EDICT_TO_PROG(p,e) ((e)->entnum * (p)->pr_edict_size) +#define NEXT_EDICT(p,e) ((e) ? (e) + 1 : 0) +#define EDICT_TO_PROG(p,e) ((e) ? (e)->entnum * (p)->pr_edict_size : 0) #define PROG_TO_EDICT(p,e) (&PR_edicts(p)[(e) / (p)->pr_edict_size]) -#define NUM_FOR_BAD_EDICT(p,e) ((e)->entnum) +#define NUM_FOR_BAD_EDICT(p,e) ((e) ? (e)->entnum : 0) #ifndef PR_PARANOID_PROGS # define EDICT_NUM(p,n) (PR_edicts (p) + (n)) # define NUM_FOR_EDICT(p,e) NUM_FOR_BAD_EDICT ((p), (e)) @@ -334,10 +372,10 @@ void ED_EntityParseFunction (progs_t *pr); */ ///@{ -pr_def_t *PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) +pr_def_t *PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pr_ptr_t offset) __attribute__((pure)); -pr_def_t *PR_FieldAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); -pr_def_t *PR_GlobalAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); +pr_def_t *PR_FieldAtOfs (progs_t *pr, pr_ptr_t ofs) __attribute__((pure)); +pr_def_t *PR_GlobalAtOfs (progs_t *pr, pr_ptr_t ofs) __attribute__((pure)); pr_def_t *PR_FindField (progs_t *pr, const char *name); pr_def_t *PR_FindGlobal (progs_t *pr, const char *name); @@ -414,29 +452,29 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_DOUBLE(p,o) (*(double *) ((p)->pr_globals + o)) -/** Access an integer global. Can be assigned to. +/** Access an int global. Can be assigned to. \par QC type: - \c integer + \c int \param p pointer to ::progs_t VM struct \param o offset into global data space \return int lvalue \hideinitializer */ -#define G_INT(p,o) G_var (p, o, integer) +#define G_INT(p,o) G_var (p, o, int) -/** Access an unsigned integer global. Can be assigned to. +/** Access an unsigned int global. Can be assigned to. \par QC type: - \c uinteger + \c uint \param p pointer to ::progs_t VM struct \param o offset into global data space \return unsigned int lvalue \hideinitializer */ -#define G_UINT(p,o) G_var (p, o, uinteger) +#define G_UINT(p,o) G_var (p, o, uint) /** Access a vector global. Can be assigned to. @@ -468,7 +506,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c string \param p pointer to ::progs_t VM struct \param o offset into global data space - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ @@ -480,7 +518,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void() \param p pointer to ::progs_t VM struct \param o offset into global data space - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ @@ -492,7 +530,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void * \param p pointer to ::progs_t VM struct \param o offset into global data space - \return pointer_t lvalue + \return pr_ptr_t lvalue \hideinitializer */ @@ -630,29 +668,29 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_DOUBLE(p,n) P_PACKED(p, double, n) -/** Access an integer parameter. Can be assigned to. +/** Access an int parameter. Can be assigned to. \par QC type: - \c integer + \c int \param p pointer to ::progs_t VM struct \param n parameter number (0-7) \return int lvalue \hideinitializer */ -#define P_INT(p,n) P_var (p, n, integer) +#define P_INT(p,n) P_var (p, n, int) -/** Access an unsigned integer parameter. Can be assigned to. +/** Access an unsigned int parameter. Can be assigned to. \par QC type: - \c uinteger + \c uint \param p pointer to ::progs_t VM struct \param n parameter number (0-7) \return unsigned int lvalue \hideinitializer */ -#define P_UINT(p,n) P_var (p, n, uinteger) +#define P_UINT(p,n) P_var (p, n, uint) /** Access a vector parameter. Can be used any way a vec3_t variable can. @@ -684,7 +722,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c string \param p pointer to ::progs_t VM struct \param n parameter number (0-7) - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ @@ -696,7 +734,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void() \param p pointer to ::progs_t VM struct \param n parameter number (0-7) - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ @@ -708,7 +746,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void * \param p pointer to ::progs_t VM struct \param n parameter number (0-7) - \return pointer_t lvalue + \return pr_ptr_t lvalue \hideinitializer */ @@ -848,24 +886,24 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ /** Access the VM function return value as a \c ::pr_int_t (AKA int32_t) \par QC type: - \c integer + \c int \param p pointer to ::progs_t VM struct \return ::pr_int_t lvalue \hideinitializer */ -#define R_INT(p) R_var (p, integer) +#define R_INT(p) R_var (p, int) /** Access the VM function return value as a \c ::pr_uint_t (AKA uint32_t) \par QC type: - \c uinteger + \c uint \param p pointer to ::progs_t VM struct \return ::pr_int_t lvalue \hideinitializer */ -#define R_UINT(p) R_var (p, uinteger) +#define R_UINT(p) R_var (p, uint) /** Access the VM function return value as a \c ::vec3_t vector. @@ -889,34 +927,34 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_QUAT(p) (&R_var (p, quat)) -/** Access the VM function return value as a ::string_t (a VM string reference). +/** Access the VM function return value as a ::pr_string_t (a VM string reference). \par QC type: \c string \param p pointer to ::progs_t VM struct - \return ::string_t lvalue + \return ::pr_string_t lvalue \hideinitializer */ #define R_STRING(p) R_var (p, string) -/** Access the VM function return value as a ::func_t (a VM function reference) +/** Access the VM function return value as a ::pr_func_t (a VM function reference) \par QC type: \c void() \param p pointer to ::progs_t VM struct - \return ::func_t lvalue + \return ::pr_func_t lvalue \hideinitializer */ #define R_FUNCTION(p) R_var (p, func) -/** Access the VM function return value as a ::pointer_t (a VM "pointer") +/** Access the VM function return value as a ::pr_ptr_t (a VM "pointer") \par QC type: \c void * \param p pointer to ::progs_t VM struct - \return ::pointer_t lvalue + \return ::pr_ptr_t lvalue \hideinitializer */ @@ -978,7 +1016,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define RETURN_QUAT(p,q) VectorCopy (q, R_QUAT (p)) +#define RETURN_QUAT(p,q) QuatCopy (q, R_QUAT (p)) ///@} /** \defgroup prda_entity_fields Entity Fields @@ -1034,29 +1072,29 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define E_DOUBLE(e,o) (*(double *) ((e)->v + o)) -/** Access an integer entity field. Can be assigned to. +/** Access an int entity field. Can be assigned to. \par QC type: - \c integer + \c int \param e pointer to the entity \param o field offset into entity data space \return int lvalue \hideinitializer */ -#define E_INT(e,o) E_var (e, o, integer) +#define E_INT(e,o) E_var (e, o, int) -/** Access an unsigned integer entity field. Can be assigned to. +/** Access an unsigned int entity field. Can be assigned to. \par QC type: - \c uinteger + \c uint \param e pointer to the entity \param o field offset into entity data space \return unsigned int lvalue \hideinitializer */ -#define E_UINT(e,o) E_var (e, o, uinteger) +#define E_UINT(e,o) E_var (e, o, uint) /** Access a vector entity field. Can be used any way a vec3_t variable can. @@ -1089,7 +1127,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c string \param e pointer to the entity \param o field offset into entity data space - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ @@ -1101,7 +1139,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void() \param e pointer to the entity \param o field offset into entity data space - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ @@ -1113,7 +1151,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void * \param e pointer to the entity \param o field offset into entity data space - \return pointer_t lvalue + \return pr_ptr_t lvalue \hideinitializer */ @@ -1186,21 +1224,56 @@ typedef struct { /// The number of the builtin for \#N in QC. -1 for automatic allocation. /// 0 or >= ::PR_AUTOBUILTIN is invalid. pr_int_t binum; + /// The number of parameters the builtin takes. Negative numbers mean + /// varargs with ~num_params (-num_params - 1) being the number of real + /// parameters. + pr_int_t num_params; + /// Parameter size specificiation. + /// + /// Up to 8 parameters are supported for automatic parameter setup because + /// that's all that v6p progs can pass. Builtins taking more than 8 + /// parameters are already Ruamoko-only and thus know how to deal with the + /// parameters being on the data stack. + /// + /// The encoding is the same as for progs functions, with 3:5 for + /// alignment:size (size 0 means 32 words). + dparmsize_t params[PR_MAX_PARAMS]; + + /// Data passed to builtin functions. Set by PR_RegisterBuiltins + void *data; } builtin_t; +#define PR_PARAM(type) { \ + .size = PR_SIZEOF(type) & 0x1f, \ + .alignment = BITOP_LOG2(PR_ALIGNOF(type)), \ +} + /** Duplicate the dfunction_t descriptor with the addition of a pointer to the builtin function. Avoids a level of indirection when calling a builtin function. */ typedef struct { pr_int_t first_statement; - pr_int_t parm_start; - pr_int_t locals; - pr_uint_t profile; - pr_int_t numparms; - dparmsize_t parm_size[MAX_PARMS]; - dfunction_t *descriptor; - builtin_proc func; + pr_int_t numparams; + pr_ulong_t profile; + union { + struct { + dparmsize_t param_size[PR_MAX_PARAMS]; + dfunction_t *descriptor; + pr_uint_t params_start; + pr_uint_t locals; + }; + struct { + // although Ruamoko progs support more than PR_MAX_PARAMS + // arguments, only the first PR_MAX_PARAMS parameter pointers + // are initialized. This keeps builtins meant for both ISAs + // simple as they either will never accept more tha PR_MAX_PARAMS + // arugments, or they'll be modified to do the right thing. + pr_ushort_t param_offsets[PR_MAX_PARAMS]; + builtin_proc func; + void *data; ///< extra data passed to the builtin + }; + }; } bfunction_t; /** Register a set of builtin functions with the VM. Different VMs within the @@ -1208,8 +1281,10 @@ typedef struct { for the same VM, but redefining a builtin is an error. \param pr pointer to ::progs_t VM struct \param builtins array of builtin_t builtins + \param data pointer to builtin-specific data. Usually the resources + struct registered with PR_Resources_Register */ -void PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins); +void PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins, void *data); /** Lookup a builtin function referred by name. \param pr pointer to ::progs_t VM struct @@ -1280,28 +1355,28 @@ int PR_LoadStrings (progs_t *pr); \param num string index to be validated \return true if the index is valid, false otherwise */ -qboolean PR_StringValid (progs_t *pr, string_t num) __attribute__((pure)); +qboolean PR_StringValid (progs_t *pr, pr_string_t num) __attribute__((pure)); /** Check if a string is valid and mutable. \param pr pointer to ::progs_t VM struct \param num string index to be checked \return true if the string is valid and mutable, false otherwise */ -qboolean PR_StringMutable (progs_t *pr, string_t num) __attribute__((pure)); +qboolean PR_StringMutable (progs_t *pr, pr_string_t num) __attribute__((pure)); /** Convert a string index to a C string. \param pr pointer to ::progs_t VM struct \param num string index to be converted \return C pointer to the string. */ -const char *PR_GetString(progs_t *pr, string_t num) __attribute__((pure)); +const char *PR_GetString(progs_t *pr, pr_string_t num) __attribute__((pure)); /** Retrieve the dstring_t associated with a mutable string. \param pr pointer to ::progs_t VM struct \param num string index of the mutable string \return the dstring implementing the mutable string */ -struct dstring_s *PR_GetMutableString(progs_t *pr, string_t num) __attribute__((pure)); +struct dstring_s *PR_GetMutableString(progs_t *pr, pr_string_t num) __attribute__((pure)); /** Make a permanent progs string from the given C string. Will not create a duplicate permanent string (temporary and mutable strings are not checked). @@ -1309,7 +1384,7 @@ struct dstring_s *PR_GetMutableString(progs_t *pr, string_t num) __attribute__(( \param s C string to be made into a permanent progs string \return string index of the progs string */ -string_t PR_SetString(progs_t *pr, const char *s); +pr_string_t PR_SetString(progs_t *pr, const char *s); /** Get the progs string if it exists. Only static strings are searched. @@ -1318,7 +1393,7 @@ string_t PR_SetString(progs_t *pr, const char *s); \return string index of the progs string if it exists, otherwise 0 (ambiguous with ""). */ -string_t PR_FindString(progs_t *pr, const char *s); +pr_string_t PR_FindString(progs_t *pr, const char *s); /** Make a temporary progs string that will survive across function returns. Will not duplicate a permanent string. If a new progs string is created, @@ -1328,7 +1403,7 @@ string_t PR_FindString(progs_t *pr, const char *s); \param s C string to be returned to the progs code \return string index of the progs string */ -string_t PR_SetReturnString(progs_t *pr, const char *s); +pr_string_t PR_SetReturnString(progs_t *pr, const char *s); /** Make a temporary progs string that will be freed when the current progs stack frame is exited. Will not duplicate a permantent string. @@ -1336,7 +1411,7 @@ string_t PR_SetReturnString(progs_t *pr, const char *s); \param s C string \return string index of the progs string */ -string_t PR_SetTempString(progs_t *pr, const char *s); +pr_string_t PR_SetTempString(progs_t *pr, const char *s); /** Make a temporary memory block that will be freed when the current progs stack frame is exited. The contents may be anything and a new block is @@ -1348,7 +1423,7 @@ string_t PR_SetTempString(progs_t *pr, const char *s); \param size size of block in bytes \return string index of the block */ -string_t PR_AllocTempBlock (progs_t *pr, size_t size); +pr_string_t PR_AllocTempBlock (progs_t *pr, size_t size); /** Push a temporary string to the callee stack frame @@ -1359,7 +1434,7 @@ string_t PR_AllocTempBlock (progs_t *pr, size_t size); \param pr pointer to ::progs_t VM struct \param num string index of the temp string */ -void PR_PushTempString (progs_t *pr, string_t num); +void PR_PushTempString (progs_t *pr, pr_string_t num); /** Make a temporary progs string that is the concatenation of two C strings. \param pr pointer to ::progs_t VM struct @@ -1368,19 +1443,19 @@ void PR_PushTempString (progs_t *pr, string_t num); \return string index of the progs string that represents the concatenation of strings a and b */ -string_t PR_CatStrings (progs_t *pr, const char *a, const char *b); +pr_string_t PR_CatStrings (progs_t *pr, const char *a, const char *b); /** Convert a mutable string to a temporary string. \param pr pointer to ::progs_t VM struct \param str string index of the mutable string to be converted */ -void PR_MakeTempString(progs_t *pr, string_t str); +void PR_MakeTempString(progs_t *pr, pr_string_t str); /** Create a new mutable string. \param pr pointer to ::progs_t VM struct \return string index of the newly created mutable string */ -string_t PR_NewMutableString (progs_t *pr); +pr_string_t PR_NewMutableString (progs_t *pr); /** Make a dynamic progs string from the given C string. Will not create a duplicate permanent string (temporary, dynamic and mutable strings are @@ -1389,7 +1464,7 @@ string_t PR_NewMutableString (progs_t *pr); \param s C string to be made into a permanent progs string \return string index of the progs string */ -string_t PR_SetDynamicString (progs_t *pr, const char *s); +pr_string_t PR_SetDynamicString (progs_t *pr, const char *s); /** Convert an ephemeral string to a dynamic string. @@ -1401,13 +1476,13 @@ string_t PR_SetDynamicString (progs_t *pr, const char *s); \param str The string to be "held" (made non-ephemeral). Safe to call on any valid string, but affects only ephemeral strings. */ -void PR_HoldString (progs_t *pr, string_t str); +void PR_HoldString (progs_t *pr, pr_string_t str); /** Destroy a mutable, dynamic or temporary string. \param pr pointer to ::progs_t VM struct \param str string index of the string to be destroyed */ -void PR_FreeString (progs_t *pr, string_t str); +void PR_FreeString (progs_t *pr, pr_string_t str); /** Free all the temporary strings allocated in the current stack frame. \param pr pointer to ::progs_t VM struct @@ -1450,14 +1525,14 @@ void PR_FreeTempStrings (progs_t *pr); @@ -1501,7 +1576,6 @@ void PR_Resources_Clear (progs_t *pr); \param name The name of the resource. Used for retrieving the resource. \param data The resource data. - callback. \param clear Callback for performing any necessary cleanup. Called by PR_Resources_Clear(). The parameters are the current VM (\p pr) and \p data. @@ -1526,7 +1600,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); /** \name Resource Map support These macros can be used to create functions for mapping C resources - to QuakeC integer handles. + to QuakeC int handles. Valid handles are always negative. @@ -1720,25 +1794,13 @@ typedef void (*type_view_func) (struct qfot_type_s *type, pr_type_t *value, the entire contents of the data. */ typedef struct type_view_s { - type_view_func void_view; - type_view_func string_view; - type_view_func float_view; - type_view_func vector_view; - type_view_func entity_view; - type_view_func field_view; - type_view_func func_view; - type_view_func pointer_view; - type_view_func quat_view; - type_view_func integer_view; - type_view_func uinteger_view; - type_view_func short_view; - type_view_func double_view; - type_view_func struct_view; type_view_func union_view; type_view_func enum_view; type_view_func array_view; type_view_func class_view; +#define EV_TYPE(type) type_view_func type##_view; +#include "QF/progs/pr_type_names.h" } type_view_t; void PR_Debug_Init (progs_t *pr); @@ -1761,7 +1823,7 @@ pr_uint_t PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); const char *PR_Get_Source_Line (progs_t *pr, pr_uint_t addr); pr_def_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure)); -pr_def_t *PR_Get_Local_Def (progs_t *pr, pointer_t *offs) __attribute__((pure)); +pr_def_t *PR_Get_Local_Def (progs_t *pr, pr_ptr_t *offs) __attribute__((pure)); void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents); void PR_DumpState (progs_t *pr); void PR_StackTrace (progs_t *pr); @@ -1781,7 +1843,7 @@ extern struct cvar_s *pr_faultchecks; */ ///@{ -char *PF_VarString (progs_t *pr, int first); +char *PF_VarString (progs_t *pr, int first, int count); void PR_Cmds_Init (progs_t *pr); extern const char *pr_gametype; @@ -1790,16 +1852,21 @@ extern const char *pr_gametype; //============================================================================ -#define MAX_STACK_DEPTH 64 -#define LOCALSTACK_SIZE 4096 +#define PR_MAX_STACK_DEPTH 64 +#define PR_LOCAL_STACK_SIZE 4096 #define PR_RS_SLOTS 16 +#define PR_BASE_IND(o, b) (((o) & OP_##b##_BASE) >> OP_##b##_SHIFT) +#define PR_BASE(p, s, b) (p->pr_bases[PR_BASE_IND(s->op, b)]) typedef struct strref_s strref_t; typedef struct { - pr_int_t staddr; ///< Return statement. + pr_uivec4_t bases; ///< base registers on entry to function + pr_uint_t staddr; ///< Return statement. + pr_uint_t stack_ptr; ///< data stack on entry to function bfunction_t *func; ///< Calling function. strref_t *tstr; ///< Linked list of temporary strings. + pr_type_t *return_ptr; ///< Saved return address } prstack_t; struct progs_s { @@ -1843,6 +1910,12 @@ struct progs_s { struct hashtab_s *field_hash; ///@} + /// \name type encodings + ///@{ + struct hashtab_s *type_hash; + pr_ptr_t type_encodings; + ///@} + /// \name load hooks ///@{ int num_load_funcs; @@ -1875,33 +1948,37 @@ struct progs_s { pr_def_t *pr_fielddefs; dstatement_t *pr_statements; pr_type_t *pr_globals; - unsigned globals_size; + pr_uint_t globals_size; + pr_uint_t null_size; ///< size of block considered null page + pr_uivec4_t pr_bases; ///< base registers (index in opcode) ///@} /// \name parameter block ///@{ pr_type_t *pr_return; - pr_type_t *pr_params[MAX_PARMS]; - pr_type_t *pr_real_params[MAX_PARMS]; + pr_type_t *pr_params[PR_MAX_PARAMS]; + pr_type_t *pr_real_params[PR_MAX_PARAMS]; int pr_param_size; ///< covers both params and return int pr_param_alignment; ///< covers both params and return + pr_type_t *pr_return_buffer; ///< for discarded return values + ///< or returning values to C ///@} /// \name edicts /// \todo FIXME should this be outside the VM? ///@{ edict_t **pr_edicts; - int max_edicts; ///< set by user - int *num_edicts; - int *reserved_edicts; ///< alloc will start at reserved_edicts+1 + pr_uint_t max_edicts; ///< set by user + pr_uint_t *num_edicts; + pr_uint_t *reserved_edicts; ///< alloc will start at reserved_edicts+1 void (*unlink) (edict_t *ent); void (*flush) (void); int (*prune_edict) (progs_t *pr, edict_t *ent); void (*free_edict) (progs_t *pr, edict_t *ent); pr_type_t *pr_edict_area; int pr_edict_size; ///< # of pr_type_t slots - int pr_edict_area_size; ///< for bounds checking, starts at 0 - func_t edict_parse; + pr_uint_t pr_edict_area_size; ///< for bounds checking, starts at 0 + pr_func_t edict_parse; ///@} /// \name execution state @@ -1913,7 +1990,7 @@ struct progs_s { bfunction_t *pr_xfunction; int pr_xstatement; - prstack_t pr_stack[MAX_STACK_DEPTH]; + prstack_t pr_stack[PR_MAX_STACK_DEPTH]; int pr_depth; /// \name progs visible stack @@ -1925,11 +2002,11 @@ struct progs_s { /// stack. ///@{ pr_type_t *stack; - pointer_t stack_bottom; + pr_ptr_t stack_bottom; int stack_size; ///< set by user ///@} - int localstack[LOCALSTACK_SIZE]; + int localstack[PR_LOCAL_STACK_SIZE]; int localstack_used; ///@} @@ -1957,9 +2034,10 @@ struct progs_s { /// \name globals and fields needed by the VM ///@{ struct { - float *time; ///< required for OP_STATE - pr_int_t *self; ///< required for OP_STATE - pointer_t *stack; ///< required for OP_(PUSH|POP)* + double *dtime; ///< required for OP_STATE d + float *ftime; ///< required for OP_STATE f + pr_uint_t *self; ///< required for OP_STATE + pr_ptr_t *stack; ///< required for OP_(PUSH|POP)* } globals; struct { pr_int_t nextthink; ///< required for OP_STATE @@ -1980,7 +2058,7 @@ struct progs_s { \return C pointer represented by the parameter. 0 offset -> NULL */ static inline pr_type_t * -PR_GetPointer (const progs_t *pr, pointer_t o) +PR_GetPointer (const progs_t *pr, pr_ptr_t o) { return o ? pr->pr_globals + o : 0; } @@ -1990,7 +2068,7 @@ PR_GetPointer (const progs_t *pr, pointer_t o) \param p C pointer to be converted. \return Progs offset/pointer represented by \c p. NULL -> 0 offset */ -static inline pointer_t +static inline pr_ptr_t PR_SetPointer (const progs_t *pr, const void *p) { return p ? (const pr_type_t *) p - pr->pr_globals : 0; diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h new file mode 100644 index 000000000..bc0c1030e --- /dev/null +++ b/include/QF/progs/pr_comp.h @@ -0,0 +1,587 @@ +/* Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + See file, 'COPYING', for details. +*/ + +// this file is shared by QuakeForge and qfcc +#ifndef __QF_pr_comp_h +#define __QF_pr_comp_h + +#include "QF/qtypes.h" + +typedef int32_t pr_string_t __attribute__((aligned(4))); +typedef float pr_float_t __attribute__((aligned(4))); +typedef float pr_vector_t[3] __attribute__((aligned(4))); +typedef uint32_t pr_entity_t __attribute__((aligned(4))); +typedef uint32_t pr_field_t __attribute__((aligned(4))); +typedef uint32_t pr_func_t __attribute__((aligned(4))); +typedef uint32_t pr_ptr_t __attribute__((aligned(4))); +typedef float pr_quaternion_t[4] __attribute__((aligned(4))); +typedef int32_t pr_int_t __attribute__((aligned(4))); +typedef uint32_t pr_uint_t __attribute__((aligned(4))); +typedef int16_t pr_short_t __attribute__((aligned(2))); +typedef double pr_double_t __attribute__((aligned(8))); +typedef int64_t pr_long_t __attribute__((aligned(8))); +typedef uint64_t pr_ulong_t __attribute__((aligned(8))); +typedef uint16_t pr_ushort_t __attribute__((aligned(2)));; + +#define PR_VEC_TYPE(t,n,s) \ + typedef t n __attribute__ ((vector_size (s*sizeof (t)))) + +PR_VEC_TYPE (pr_int_t, pr_ivec2_t, 2); +typedef pr_int_t pr_ivec3_t[3]; +PR_VEC_TYPE (pr_int_t, pr_ivec4_t, 4); + +PR_VEC_TYPE (pr_uint_t, pr_uivec2_t, 2); +typedef pr_uint_t pr_uivec3_t[3]; +PR_VEC_TYPE (pr_uint_t, pr_uivec4_t, 4); + +PR_VEC_TYPE (float, pr_vec2_t, 2); +typedef pr_float_t pr_vec3_t[3]; +PR_VEC_TYPE (float, pr_vec4_t, 4); + +PR_VEC_TYPE (pr_long_t, pr_lvec2_t, 2); +typedef pr_long_t pr_lvec3_t[3]; +PR_VEC_TYPE (pr_long_t, pr_lvec4_t, 4); + +PR_VEC_TYPE (pr_ulong_t, pr_ulvec2_t, 2); +typedef pr_ulong_t pr_ulvec3_t[3]; +PR_VEC_TYPE (pr_ulong_t, pr_ulvec4_t, 4); + +PR_VEC_TYPE (double, pr_dvec2_t, 2); +typedef pr_double_t pr_dvec3_t[3]; +PR_VEC_TYPE (double, pr_dvec4_t, 4); + + +#define EV_TYPE(type) ev_##type, +typedef enum { +#include "QF/progs/pr_type_names.h" + ev_invalid, // invalid type. used for instruction checking + ev_type_count // not a type, gives number of types +} etype_t; + +#define PR_SIZEOF(type) (sizeof (pr_##type##_t) / (sizeof (pr_int_t))) +#define PR_ALIGNOF(type) (__alignof__ (pr_##type##_t) / __alignof__ (pr_int_t)) + +extern const pr_ushort_t pr_type_size[ev_type_count]; +extern const pr_ushort_t pr_type_alignment[ev_type_count]; +extern const char * const pr_type_name[ev_type_count]; + +#define OFS_NULL 0 +#define OFS_RETURN 1 +#define OFS_PARM0 4 // leave 3 ofs for each parm to hold vectors +#define OFS_PARM1 7 +#define OFS_PARM2 10 +#define OFS_PARM3 13 +#define OFS_PARM4 16 +#define OFS_PARM5 19 +#define OFS_PARM6 22 +#define OFS_PARM7 25 +#define RESERVED_OFS 28 + + +typedef enum { + OP_DONE_v6p, + OP_MUL_F_v6p, + OP_MUL_V_v6p, + OP_MUL_FV_v6p, + OP_MUL_VF_v6p, + OP_DIV_F_v6p, + OP_ADD_F_v6p, + OP_ADD_V_v6p, + OP_SUB_F_v6p, + OP_SUB_V_v6p, + + OP_EQ_F_v6p, + OP_EQ_V_v6p, + OP_EQ_S_v6p, + OP_EQ_E_v6p, + OP_EQ_FN_v6p, + + OP_NE_F_v6p, + OP_NE_V_v6p, + OP_NE_S_v6p, + OP_NE_E_v6p, + OP_NE_FN_v6p, + + OP_LE_F_v6p, + OP_GE_F_v6p, + OP_LT_F_v6p, + OP_GT_F_v6p, + + OP_LOAD_F_v6p, + OP_LOAD_V_v6p, + OP_LOAD_S_v6p, + OP_LOAD_ENT_v6p, + OP_LOAD_FLD_v6p, + OP_LOAD_FN_v6p, + + OP_ADDRESS_v6p, + + OP_STORE_F_v6p, + OP_STORE_V_v6p, + OP_STORE_S_v6p, + OP_STORE_ENT_v6p, + OP_STORE_FLD_v6p, + OP_STORE_FN_v6p, + + OP_STOREP_F_v6p, + OP_STOREP_V_v6p, + OP_STOREP_S_v6p, + OP_STOREP_ENT_v6p, + OP_STOREP_FLD_v6p, + OP_STOREP_FN_v6p, + + OP_RETURN_v6p, + OP_NOT_F_v6p, + OP_NOT_V_v6p, + OP_NOT_S_v6p, + OP_NOT_ENT_v6p, + OP_NOT_FN_v6p, + OP_IF_v6p, + OP_IFNOT_v6p, + OP_CALL0_v6p, + OP_CALL1_v6p, + OP_CALL2_v6p, + OP_CALL3_v6p, + OP_CALL4_v6p, + OP_CALL5_v6p, + OP_CALL6_v6p, + OP_CALL7_v6p, + OP_CALL8_v6p, + OP_STATE_v6p, + OP_GOTO_v6p, + OP_AND_v6p, + OP_OR_v6p, + + OP_BITAND_v6p, + OP_BITOR_v6p, // end of v6 opcodes + + OP_ADD_S_v6p, + OP_LE_S_v6p, + OP_GE_S_v6p, + OP_LT_S_v6p, + OP_GT_S_v6p, + + OP_ADD_I_v6p, + OP_SUB_I_v6p, + OP_MUL_I_v6p, + OP_DIV_I_v6p, + OP_BITAND_I_v6p, + OP_BITOR_I_v6p, + OP_GE_I_v6p, + OP_LE_I_v6p, + OP_GT_I_v6p, + OP_LT_I_v6p, + OP_AND_I_v6p, + OP_OR_I_v6p, + OP_NOT_I_v6p, + OP_EQ_I_v6p, + OP_NE_I_v6p, + OP_STORE_I_v6p, + OP_STOREP_I_v6p, + OP_LOAD_I_v6p, + + OP_CONV_IF_v6p, + OP_CONV_FI_v6p, + + OP_BITXOR_F_v6p, + OP_BITXOR_I_v6p, + OP_BITNOT_F_v6p, + OP_BITNOT_I_v6p, + + OP_SHL_F_v6p, + OP_SHR_F_v6p, + OP_SHL_I_v6p, + OP_SHR_I_v6p, + + OP_REM_F_v6p, + OP_REM_I_v6p, + + OP_LOADB_F_v6p, + OP_LOADB_V_v6p, + OP_LOADB_S_v6p, + OP_LOADB_ENT_v6p, + OP_LOADB_FLD_v6p, + OP_LOADB_FN_v6p, + OP_LOADB_I_v6p, + OP_LOADB_P_v6p, + + OP_STOREB_F_v6p, + OP_STOREB_V_v6p, + OP_STOREB_S_v6p, + OP_STOREB_ENT_v6p, + OP_STOREB_FLD_v6p, + OP_STOREB_FN_v6p, + OP_STOREB_I_v6p, + OP_STOREB_P_v6p, + + OP_ADDRESS_VOID_v6p, + OP_ADDRESS_F_v6p, + OP_ADDRESS_V_v6p, + OP_ADDRESS_S_v6p, + OP_ADDRESS_ENT_v6p, + OP_ADDRESS_FLD_v6p, + OP_ADDRESS_FN_v6p, + OP_ADDRESS_I_v6p, + OP_ADDRESS_P_v6p, + + OP_LEA_v6p, + + OP_IFBE_v6p, + OP_IFB_v6p, + OP_IFAE_v6p, + OP_IFA_v6p, + + OP_JUMP_v6p, + OP_JUMPB_v6p, + + OP_LT_U_v6p, + OP_GT_U_v6p, + OP_LE_U_v6p, + OP_GE_U_v6p, + + OP_LOADBI_F_v6p, + OP_LOADBI_V_v6p, + OP_LOADBI_S_v6p, + OP_LOADBI_ENT_v6p, + OP_LOADBI_FLD_v6p, + OP_LOADBI_FN_v6p, + OP_LOADBI_I_v6p, + OP_LOADBI_P_v6p, + + OP_STOREBI_F_v6p, + OP_STOREBI_V_v6p, + OP_STOREBI_S_v6p, + OP_STOREBI_ENT_v6p, + OP_STOREBI_FLD_v6p, + OP_STOREBI_FN_v6p, + OP_STOREBI_I_v6p, + OP_STOREBI_P_v6p, + + OP_LEAI_v6p, + + OP_LOAD_P_v6p, + OP_STORE_P_v6p, + OP_STOREP_P_v6p, + OP_NOT_P_v6p, + OP_EQ_P_v6p, + OP_NE_P_v6p, + OP_LE_P_v6p, + OP_GE_P_v6p, + OP_LT_P_v6p, + OP_GT_P_v6p, + + OP_MOVEI_v6p, + OP_MOVEP_v6p, + OP_MOVEPI_v6p, + + OP_SHR_U_v6p, + + OP_STATE_F_v6p, + + OP_ADD_Q_v6p, + OP_SUB_Q_v6p, + OP_MUL_Q_v6p, + OP_MUL_QF_v6p, + OP_MUL_FQ_v6p, + OP_MUL_QV_v6p, + OP_CONJ_Q_v6p, + OP_NOT_Q_v6p, + OP_EQ_Q_v6p, + OP_NE_Q_v6p, + OP_STORE_Q_v6p, + OP_STOREB_Q_v6p, + OP_STOREBI_Q_v6p, + OP_STOREP_Q_v6p, + OP_LOAD_Q_v6p, + OP_LOADB_Q_v6p, + OP_LOADBI_Q_v6p, + OP_ADDRESS_Q_v6p, + + OP_RCALL0_v6p, + OP_RCALL1_v6p, + OP_RCALL2_v6p, + OP_RCALL3_v6p, + OP_RCALL4_v6p, + OP_RCALL5_v6p, + OP_RCALL6_v6p, + OP_RCALL7_v6p, + OP_RCALL8_v6p, + + OP_RETURN_V_v6p, + + OP_PUSH_S_v6p, + OP_PUSH_F_v6p, + OP_PUSH_V_v6p, + OP_PUSH_ENT_v6p, + OP_PUSH_FLD_v6p, + OP_PUSH_FN_v6p, + OP_PUSH_P_v6p, + OP_PUSH_Q_v6p, + OP_PUSH_I_v6p, + OP_PUSH_D_v6p, + + OP_PUSHB_S_v6p, + OP_PUSHB_F_v6p, + OP_PUSHB_V_v6p, + OP_PUSHB_ENT_v6p, + OP_PUSHB_FLD_v6p, + OP_PUSHB_FN_v6p, + OP_PUSHB_P_v6p, + OP_PUSHB_Q_v6p, + OP_PUSHB_I_v6p, + OP_PUSHB_D_v6p, + + OP_PUSHBI_S_v6p, + OP_PUSHBI_F_v6p, + OP_PUSHBI_V_v6p, + OP_PUSHBI_ENT_v6p, + OP_PUSHBI_FLD_v6p, + OP_PUSHBI_FN_v6p, + OP_PUSHBI_P_v6p, + OP_PUSHBI_Q_v6p, + OP_PUSHBI_I_v6p, + OP_PUSHBI_D_v6p, + + OP_POP_S_v6p, + OP_POP_F_v6p, + OP_POP_V_v6p, + OP_POP_ENT_v6p, + OP_POP_FLD_v6p, + OP_POP_FN_v6p, + OP_POP_P_v6p, + OP_POP_Q_v6p, + OP_POP_I_v6p, + OP_POP_D_v6p, + + OP_POPB_S_v6p, + OP_POPB_F_v6p, + OP_POPB_V_v6p, + OP_POPB_ENT_v6p, + OP_POPB_FLD_v6p, + OP_POPB_FN_v6p, + OP_POPB_P_v6p, + OP_POPB_Q_v6p, + OP_POPB_I_v6p, + OP_POPB_D_v6p, + + OP_POPBI_S_v6p, + OP_POPBI_F_v6p, + OP_POPBI_V_v6p, + OP_POPBI_ENT_v6p, + OP_POPBI_FLD_v6p, + OP_POPBI_FN_v6p, + OP_POPBI_P_v6p, + OP_POPBI_Q_v6p, + OP_POPBI_I_v6p, + OP_POPBI_D_v6p, + + OP_ADD_D_v6p, + OP_SUB_D_v6p, + OP_MUL_D_v6p, + OP_MUL_QD_v6p, + OP_MUL_DQ_v6p, + OP_MUL_VD_v6p, + OP_MUL_DV_v6p, + OP_DIV_D_v6p, + OP_REM_D_v6p, + OP_GE_D_v6p, + OP_LE_D_v6p, + OP_GT_D_v6p, + OP_LT_D_v6p, + OP_NOT_D_v6p, + OP_EQ_D_v6p, + OP_NE_D_v6p, + OP_CONV_FD_v6p, + OP_CONV_DF_v6p, + OP_CONV_ID_v6p, + OP_CONV_DI_v6p, + OP_STORE_D_v6p, + OP_STOREB_D_v6p, + OP_STOREBI_D_v6p, + OP_STOREP_D_v6p, + OP_LOAD_D_v6p, + OP_LOADB_D_v6p, + OP_LOADBI_D_v6p, + OP_ADDRESS_D_v6p, + + OP_MOD_I_v6p, + OP_MOD_F_v6p, + OP_MOD_D_v6p, + + OP_MEMSETI_v6p, + OP_MEMSETP_v6p, + OP_MEMSETPI_v6p, +} pr_opcode_v6p_e; +#define OP_BREAK 0x8000 + +typedef enum { +#include "QF/progs/pr_opcode.hinc" +} pr_opcode_e; + +// Used for both branch and comparison, with jump and call being ignored for +// comparison. For branches, the test is against zero, while for comparison, +// it's a cmp b (where cmp takes the place of "branch" in the enum names). +typedef enum { + pr_branch_eq, + pr_branch_lt, + pr_branch_gt, + pr_branch_jump, + pr_branch_ne, + pr_branch_ge, + pr_branch_le, + pr_branch_call, +} pr_branch_e; + +#define OP_A_SHIFT (9) +#define OP_B_SHIFT (11) +#define OP_C_SHIFT (13) +#define OP_A_BASE (3 << OP_A_SHIFT) +#define OP_B_BASE (3 << OP_B_SHIFT) +#define OP_C_BASE (3 << OP_C_SHIFT) +#define OP_MASK (~(OP_BREAK|OP_A_BASE|OP_B_BASE|OP_C_BASE)) + +typedef enum { + OP_with_zero, + OP_with_base, + OP_with_stack, + OP_with_entity, +} pr_with_e; + +typedef struct v6p_opcode_s { + const char *name; + const char *opname; + etype_t type_a, type_b, type_c; + unsigned int min_version; + const char *fmt; +} v6p_opcode_t; + +extern const v6p_opcode_t pr_v6p_opcodes[]; +const v6p_opcode_t *PR_v6p_Opcode (pr_ushort_t opcode) __attribute__((const)); + +typedef struct opcode_s { + const char *opname; + const char *mnemonic; + int widths[3]; ///< component count for each argument (1-4) + etype_t types[3]; ///< component type for each argument + const char *fmt; +} opcode_t; +extern const opcode_t pr_opcodes[512]; +const opcode_t *PR_Opcode (pr_ushort_t opcode) __attribute__((const)); + +typedef struct dstatement_s { + pr_opcode_e op:16; // will be pr_opcode_v6p_e for older progs + pr_ushort_t a,b,c; +} GCC_STRUCT dstatement_t; + +typedef struct ddef_s { + pr_ushort_t type; // if DEF_SAVEGLOBAL bit is set + // the variable needs to be saved in savegames + pr_ushort_t ofs; + pr_string_t name; +} ddef_t; + +typedef struct xdef_s { + pr_ptr_t type; ///< pointer to type definition + pr_ptr_t ofs; ///< 32-bit version of ddef_t.ofs +} xdef_t; + +typedef struct pr_xdefs_s { + pr_ptr_t xdefs; + pr_int_t num_xdefs; +} pr_xdefs_t; + +typedef struct pr_def_s { + pr_ushort_t type; + pr_ushort_t size; ///< may not be correct + pr_ptr_t ofs; + pr_string_t name; + pr_ptr_t type_encoding; +} pr_def_t; + +typedef struct dparmsize_s { + uint8_t size:5; + uint8_t alignment:3; +} dparmsize_t; + +#define DEF_SAVEGLOBAL (1<<15) + +#define PR_MAX_PARAMS 8 +#define PR_MAX_RETURN 32 // maximum size of return value + +typedef struct dfunction_s { + pr_int_t first_statement; // negative numbers are builtins + pr_uint_t params_start; // beginning of locals data space + pr_uint_t locals; // total ints of params + locals + + pr_uint_t profile; // runtime + + pr_string_t name; // source function name + pr_string_t file; // source file defined in + + pr_int_t numparams; // -ve is varargs (1s comp of real count) + dparmsize_t param_size[PR_MAX_PARAMS]; +} dfunction_t; + +typedef union pr_type_u { + float float_var; + pr_string_t string_var; + pr_func_t func_var; + pr_uint_t entity_var; + float vector_var; // really [3], but this structure must be 32 bits + float quat_var; // really [4], but this structure must be 32 bits + pr_int_t int_var; + pr_ptr_t pointer_var; + pr_uint_t uint_var; +} pr_type_t; + +typedef pr_type_t pr_void_t; // so size of void is 1 + +typedef struct pr_va_list_s { + pr_int_t count; + pr_ptr_t list; // pr_type_t +} pr_va_list_t; + +#define PROG_VERSION_ENCODE(a,b,c) \ + ( (((0x##a) & 0x0ff) << 24) \ + |(((0x##b) & 0xfff) << 12) \ + |(((0x##c) & 0xfff) << 0) ) +#define PROG_ID_VERSION 6 +#define PROG_V6P_VERSION PROG_VERSION_ENCODE(0,fff,00a) +#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,010) + +typedef struct pr_chunk_s { + pr_uint_t offset; + pr_uint_t count; +} pr_chunk_t; + +typedef struct dprograms_s { + pr_uint_t version; + pr_uint_t crc; // checksum of header file + + pr_chunk_t statements; // statement 0 is an error + pr_chunk_t globaldefs; + pr_chunk_t fielddefs; + pr_chunk_t functions; // function 0 is an empty + pr_chunk_t strings; // first string is a null string, count is bytes + pr_chunk_t globals; + + pr_uint_t entityfields; +} dprograms_t; + +#endif//__QF_pr_comp_h diff --git a/include/QF/pr_debug.h b/include/QF/progs/pr_debug.h similarity index 97% rename from include/QF/pr_debug.h rename to include/QF/progs/pr_debug.h index 4015f6f65..20b65c25c 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/progs/pr_debug.h @@ -32,7 +32,7 @@ #define __QF_pr_debug_h #ifndef __QFCC__ -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" typedef struct pr_compunit_s { pr_uint_t unit_name; @@ -75,6 +75,8 @@ typedef struct pr_debug_header_s { pr_uint_t debug_data; pr_uint_t debug_data_size; } pr_debug_header_t; + +extern const char *prdebug_names[]; #endif typedef enum prdebug_e { diff --git a/include/QF/pr_obj.h b/include/QF/progs/pr_obj.h similarity index 70% rename from include/QF/pr_obj.h rename to include/QF/progs/pr_obj.h index 52f05aa16..2841f6064 100644 --- a/include/QF/pr_obj.h +++ b/include/QF/progs/pr_obj.h @@ -31,7 +31,7 @@ #ifndef __QF_pr_obj_h #define __QF_pr_obj_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #define PR_BITS_PER_INT (sizeof (pr_int_t) * 8) @@ -74,62 +74,62 @@ #define PR_CLS_GETNUMBER(cls) (__CLS_INFO (cls) >> (PR_BITS_PER_INT / 2)) #define PR_CLS_SETNUMBER(cls, num) \ (__PR_CLS_INFO (cls) = __PR_CLS_INFO (cls) & (~0U >> (PR_BITS_PER_INT / 2)) \ - | (num) << (PR_BITS_PER_INT / 2)) + | (num) << (PR_BITS_PER_INT / 2)) typedef struct pr_sel_s { - pointer_t sel_id; - string_t sel_types; + pr_ptr_t sel_id; + pr_string_t sel_types; } pr_sel_t; typedef struct pr_id_s { - pointer_t class_pointer; // pr_class_t + pr_ptr_t class_pointer; // pr_class_t } pr_id_t; typedef struct pr_class_s { - pointer_t class_pointer; // pr_class_t - pointer_t super_class; // pr_class_t - string_t name; + pr_ptr_t class_pointer; // pr_class_t + pr_ptr_t super_class; // pr_class_t + pr_string_t name; pr_int_t version; pr_uint_t info; pr_int_t instance_size; - pointer_t ivars; // pr_ivar_list_t - pointer_t methods; // pr_method_list_t - pointer_t dtable; // resource index - pointer_t subclass_list; // pr_class_t - pointer_t sibling_class; // pr_class_t - pointer_t protocols; // pr_protocol_list_t - pointer_t gc_object_type; + pr_ptr_t ivars; // pr_ivar_list_t + pr_ptr_t methods; // pr_method_list_t + pr_ptr_t dtable; // resource index + pr_ptr_t subclass_list; // pr_class_t + pr_ptr_t sibling_class; // pr_class_t + pr_ptr_t protocols; // pr_protocol_list_t + pr_ptr_t gc_object_type; } pr_class_t; typedef struct pr_protocol_s { - pointer_t class_pointer; // pr_class_t - string_t protocol_name; - pointer_t protocol_list; // pr_protocol_list_t - pointer_t instance_methods; // pr_method_description_list_t - pointer_t class_methods; // pr_method_description_list_t + pr_ptr_t class_pointer; // pr_class_t + pr_string_t protocol_name; + pr_ptr_t protocol_list; // pr_protocol_list_t + pr_ptr_t instance_methods; // pr_method_description_list_t + pr_ptr_t class_methods; // pr_method_description_list_t } pr_protocol_t; typedef struct pr_category_s { - string_t category_name; - string_t class_name; - pointer_t instance_methods; // pr_method_list_t - pointer_t class_methods; // pr_method_list_t - pointer_t protocols; // pr_protocol_list_t + pr_string_t category_name; + pr_string_t class_name; + pr_ptr_t instance_methods; // pr_method_list_t + pr_ptr_t class_methods; // pr_method_list_t + pr_ptr_t protocols; // pr_protocol_list_t } pr_category_t; typedef struct pr_protocol_list_s { - pointer_t next; + pr_ptr_t next; pr_int_t count; - pointer_t list[1]; // pr_protocol_t + pr_ptr_t list[1]; // pr_protocol_t } pr_protocol_list_t; typedef struct pr_method_list_s { - pointer_t method_next; + pr_ptr_t method_next; pr_int_t method_count; struct pr_method_s { - pointer_t method_name; // pr_sel_t - string_t method_types; - func_t method_imp; // typedef id (id, SEL, ...) IMP + pr_ptr_t method_name; // pr_sel_t + pr_string_t method_types; + pr_func_t method_imp; // typedef id (id, SEL, ...) IMP } method_list[1]; } pr_method_list_t; typedef struct pr_method_s pr_method_t; @@ -137,8 +137,8 @@ typedef struct pr_method_s pr_method_t; typedef struct pr_method_description_list_s { pr_int_t count; struct pr_method_description_s { - pointer_t name; // pr_sel_t - string_t types; + pr_ptr_t name; // pr_sel_t + pr_string_t types; } list[1]; } pr_method_description_list_t; typedef struct pr_method_description_s pr_method_description_t; @@ -146,8 +146,8 @@ typedef struct pr_method_description_s pr_method_description_t; typedef struct pr_ivar_list_s { pr_int_t ivar_count; struct pr_ivar_s { - string_t ivar_name; - string_t ivar_type; + pr_string_t ivar_name; + pr_string_t ivar_type; pr_int_t ivar_offset; } ivar_list[1]; } pr_ivar_list_t; @@ -157,16 +157,16 @@ typedef struct pr_static_instances_s { // one per staticly instanced class per module (eg, 3 instances of Object // will produce one of these structs with 3 pointers to those instances in // instances[] - string_t class_name; - pointer_t instances[1]; // null terminated array of pr_id_t + pr_string_t class_name; + pr_ptr_t instances[1]; // null terminated array of pr_id_t } pr_static_instances_t; typedef struct pr_symtab_s { pr_int_t sel_ref_cnt; - pointer_t refs; // pr_sel_t + pr_ptr_t refs; // pr_sel_t pr_int_t cls_def_cnt; pr_int_t cat_def_cnt; - pointer_t defs[1]; // variable array of cls_def_cnt class + pr_ptr_t defs[1]; // variable array of cls_def_cnt class // pointers then cat_def_cnt category // pointers followed by a null terminated // array of pr_static_instances (not yet @@ -176,13 +176,13 @@ typedef struct pr_symtab_s { typedef struct pr_module_s { pr_int_t version; pr_int_t size; - string_t name; - pointer_t symtab; // pr_symtab_t + pr_string_t name; + pr_ptr_t symtab; // pr_symtab_t } pr_module_t; typedef struct pr_super_s { - pointer_t self; - pointer_t class; + pr_ptr_t self; + pr_ptr_t class; } pr_super_t; #endif//__QF_pr_obj_h diff --git a/include/QF/pr_type.h b/include/QF/progs/pr_type.h similarity index 71% rename from include/QF/pr_type.h rename to include/QF/progs/pr_type.h index 56915724b..7f117e7a3 100644 --- a/include/QF/pr_type.h +++ b/include/QF/progs/pr_type.h @@ -34,11 +34,11 @@ /** \defgroup qfcc_qfo_type Object file type encoding \ingroup progs - All \c pointer_t \c type fields are pointers within the type qfo_space. + All \c pr_ptr_t \c type fields are pointers within the type qfo_space. */ ///@{ -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" typedef enum { ty_basic, ///< VM type (float, int, pointer, field, etc) @@ -52,43 +52,49 @@ typedef enum { typedef struct qfot_alias_s { etype_t type; ///< type at end of alias chain - pointer_t aux_type; ///< referenced type: stripped of aliases - pointer_t full_type; ///< includes full alias info - string_t name; ///< alias name, may be null + pr_ptr_t aux_type; ///< referenced type: stripped of aliases + pr_ptr_t full_type; ///< includes full alias info + pr_string_t name; ///< alias name, may be null } qfot_alias_t; typedef struct qfot_fldptr_s { - etype_t type; ///< ev_field or ev_pointer - pointer_t aux_type; ///< referenced type + etype_t type; ///< ev_field or ev_ptr + pr_ptr_t aux_type; ///< referenced type } qfot_fldptr_t; +typedef struct qfot_basic_s { + etype_t type; ///< integral and fp scalar types + pr_int_t width; ///< components in vector (1 for vector or + ///< quaternion) +} qfot_basic_t; + typedef struct qfot_func_s { etype_t type; ///< always ev_func - pointer_t return_type; ///< return type of the function + pr_ptr_t return_type; ///< return type of the function pr_int_t num_params; ///< ones compliment count of the ///< parameters. -ve values indicate the ///< number of real parameters before the ///< ellipsis - pointer_t param_types[1]; ///< variable length list of parameter + pr_ptr_t param_types[1]; ///< variable length list of parameter ///< types } qfot_func_t; typedef struct qfot_var_s { - pointer_t type; ///< type of field or self reference for + pr_ptr_t type; ///< type of field or self reference for ///< enum - string_t name; ///< name of field/enumerator + pr_string_t name; ///< name of field/enumerator pr_int_t offset; ///< value for enum, 0 for union } qfot_var_t; typedef struct qfot_struct_s { - string_t tag; ///< struct/union/enum tag + pr_string_t tag; ///< struct/union/enum tag pr_int_t num_fields; ///< number of fields/enumerators qfot_var_t fields[1]; ///< variable length list of ///< fields/enumerators } qfot_struct_t; typedef struct qfot_array_s { - pointer_t type; ///< element type + pr_ptr_t type; ///< element type pr_int_t base; ///< start index of array pr_int_t size; ///< number of elements in array } qfot_array_t; @@ -103,20 +109,21 @@ typedef struct qfot_array_s { typedef struct qfot_type_s { ty_meta_e meta; ///< meta type pr_uint_t size; ///< total word size of this encoding - string_t encoding; ///< Objective-QC encoding + pr_string_t encoding; ///< Objective-QC encoding union { etype_t type; ///< ty_basic: etype_t - qfot_fldptr_t fldptr; ///< ty_basic, ev_pointer/ev_field + qfot_basic_t basic; ///< ty_basic: int/float/double/long etc + qfot_fldptr_t fldptr; ///< ty_basic, ev_ptr/ev_field qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array - string_t class; ///< ty_class + pr_string_t class; ///< ty_class qfot_alias_t alias; ///< ty_alias }; } qfot_type_t; typedef struct qfot_type_encodings_s { - pointer_t types; + pr_ptr_t types; pr_uint_t size; } qfot_type_encodings_t; diff --git a/include/QF/progs/pr_type_names.h b/include/QF/progs/pr_type_names.h new file mode 100644 index 000000000..3e0daf10a --- /dev/null +++ b/include/QF/progs/pr_type_names.h @@ -0,0 +1,50 @@ +/* + pr_type_names.h + + Progs type names + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2022 Bill Currie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef EV_TYPE +#define EV_TYPE(event) +#endif + +EV_TYPE(void) +EV_TYPE(string) +EV_TYPE(float) +EV_TYPE(vector) +EV_TYPE(entity) +EV_TYPE(field) +EV_TYPE(func) +EV_TYPE(ptr) // end of v6 types +EV_TYPE(quaternion) +EV_TYPE(int) +EV_TYPE(uint) +EV_TYPE(short) // value is embedded in the opcode +EV_TYPE(double) +EV_TYPE(long) +EV_TYPE(ulong) +EV_TYPE(ushort) // value is embedded in the opcode + +#undef EV_TYPE diff --git a/include/QF/ruamoko.h b/include/QF/ruamoko.h index ba1531485..71c2fe6ee 100644 --- a/include/QF/ruamoko.h +++ b/include/QF/ruamoko.h @@ -31,15 +31,15 @@ #ifndef __QF_ruamoko_h #define __QF_ruamoko_h -#include "QF/pr_obj.h" +#include "QF/progs/pr_obj.h" struct progs_s; struct cbuf_s; void RUA_Init (struct progs_s *pr, int secure); void RUA_Cbuf_SetCbuf (struct progs_s *pr, struct cbuf_s *cbuf); -func_t RUA_Obj_msg_lookup (struct progs_s *pr, pointer_t _self, - pointer_t __cmd); +pr_func_t RUA_Obj_msg_lookup (struct progs_s *pr, pr_ptr_t _self, + pr_ptr_t __cmd); void RUA_Game_Init (struct progs_s *pr, int secure); diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 5764fe085..43d564745 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -29,8 +29,10 @@ #define __QF_simd_types_h #include +#include -#define VEC_TYPE(t,n) typedef t n __attribute__ ((vector_size (4*sizeof (t)))) +#define VEC_TYPE(t,n,s) \ + typedef t n __attribute__ ((vector_size (s*sizeof (t)))) /** Three element vector type for interfacing with compact data. * @@ -39,7 +41,9 @@ */ typedef double vec3d_t[3]; -#ifdef __AVX2__ +VEC_TYPE (double, vec2d_t, 2); +VEC_TYPE (int64_t, vec2l_t, 2); + /** Four element vector type for horizontal (AOS) vector data. * * This is used for both vectors (3D and 4D) and quaternions. 3D vectors @@ -49,12 +53,11 @@ typedef double vec3d_t[3]; * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (double, vec4d_t); +VEC_TYPE (double, vec4d_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int64_t, vec4l_t); -#endif +VEC_TYPE (int64_t, vec4l_t, 4); /** Three element vector type for interfacing with compact data. * @@ -63,6 +66,9 @@ VEC_TYPE (int64_t, vec4l_t); */ typedef float vec3f_t[3]; +VEC_TYPE (float, vec2f_t, 2); +VEC_TYPE (int, vec2i_t, 2); + /** Four element vector type for horizontal (AOS) vector data. * * This is used for both vectors (3D and 4D) and quaternions. 3D vectors @@ -72,20 +78,21 @@ typedef float vec3f_t[3]; * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (float, vec4f_t); +VEC_TYPE (float, vec4f_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int, vec4i_t); +VEC_TYPE (int, vec4i_t, 4); +#define VEC2D_FMT "[%.17g, %.17g]" +#define VEC2L_FMT "[%"PRIi64", %"PRIi64"]" #define VEC4D_FMT "[%.17g, %.17g, %.17g, %.17g]" -#if __WORDSIZE == 64 -#define VEC4L_FMT "[%ld, %ld, %ld, %ld]" -#else -#define VEC4L_FMT "[%lld, %lld, %lld, %lld]" -#endif +#define VEC4L_FMT "[%"PRIi64", %"PRIi64", %"PRIi64", %"PRIi64"]" +#define VEC2F_FMT "[%.9g, %.9g]" +#define VEC2I_FMT "[%d, %d]" #define VEC4F_FMT "[%.9g, %.9g, %.9g, %.9g]" #define VEC4I_FMT "[%d, %d, %d, %d]" +#define VEC2_EXP(v) (v)[0], (v)[1] #define VEC4_EXP(v) (v)[0], (v)[1], (v)[2], (v)[3] #define MAT4_ROW(m, r) (m)[0][r], (m)[1][r], (m)[2][r], (m)[3][r] diff --git a/include/QF/simd/vec2d.h b/include/QF/simd/vec2d.h new file mode 100644 index 000000000..86be9302b --- /dev/null +++ b/include/QF/simd/vec2d.h @@ -0,0 +1,141 @@ +/* + QF/simd/vec2d.h + + Vector functions for vec2d_t (ie, double precision) + + Copyright (C) 2020 Bill Currie + Copyright (C) 2022 Bill Currie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec2d_h +#define __QF_simd_vec2d_h + +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec2d_t vsqrt2d (vec2d_t v) __attribute__((const)); +GNU89INLINE inline vec2d_t vceil2d (vec2d_t v) __attribute__((const)); +GNU89INLINE inline vec2d_t vfloor2d (vec2d_t v) __attribute__((const)); +GNU89INLINE inline vec2d_t vtrunc2d (vec2d_t v) __attribute__((const)); +/** 2D vector dot product. + */ +GNU89INLINE inline vec2d_t dot2d (vec2d_t a, vec2d_t b) __attribute__((const)); +GNU89INLINE inline vec2d_t cmuld (vec2d_t a, vec2d_t b) __attribute__((const)); + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vsqrt2d (vec2d_t v) +{ + return _mm_sqrt_pd (v); +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vceil2d (vec2d_t v) +{ +#ifndef __SSE4_1__ + return (vec2d_t) { + ceil (v[0]), + ceil (v[1]), + }; +#else + return _mm_ceil_pd (v); +#endif +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vfloor2d (vec2d_t v) +{ +#ifndef __SSE4_1__ + return (vec2d_t) { + floor (v[0]), + floor (v[1]), + }; +#else + return _mm_floor_pd (v); +#endif +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vtrunc2d (vec2d_t v) +{ +#ifndef __SSE4_1__ + return (vec2d_t) { + trunc (v[0]), + trunc (v[1]), + }; +#else + return _mm_round_pd (v, _MM_FROUND_TRUNC); +#endif +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +dot2d (vec2d_t a, vec2d_t b) +{ + vec2d_t c = a * b; + // gcc-11 does a good job with hadd + c = (vec2d_t) { c[0] + c[1], c[0] + c[1] }; + return c; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +cmuld (vec2d_t a, vec2d_t b) +{ + vec2d_t c1 = a * b[0]; + vec2d_t c2 = a * b[1]; +#ifndef __SSE3__ + return (vec2d_t) { c1[0] - c2[1], c1[1] + c2[0] }; +#else + return _mm_addsub_pd (c1, (vec2d_t) { c2[1], c2[0] }); +#endif +} + +#endif//__QF_simd_vec2d_h diff --git a/include/QF/simd/vec2f.h b/include/QF/simd/vec2f.h new file mode 100644 index 000000000..1459dd37b --- /dev/null +++ b/include/QF/simd/vec2f.h @@ -0,0 +1,182 @@ +/* + QF/simd/vec2f.h + + Vector functions for vec2f_t (ie, float precision) + + Copyright (C) 2020 Bill Currie + Copyright (C) 2022 Bill Currie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec2f_h +#define __QF_simd_vec2f_h + +#include +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec2f_t vabs2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vsqrt2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vceil2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vfloor2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vtrunc2f (vec2f_t v) __attribute__((const)); +/** 2D vector dot product. + */ +GNU89INLINE inline vec2f_t dot2f (vec2f_t a, vec2f_t b) __attribute__((const)); +GNU89INLINE inline vec2f_t cmulf (vec2f_t a, vec2f_t b) __attribute__((const)); +GNU89INLINE inline vec2f_t normal2f (vec2f_t v) __attribute__((pure)); +GNU89INLINE inline vec2f_t magnitude2f (vec2f_t v) __attribute__((pure)); + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vabs2f (vec2f_t v) +{ + const uint32_t nan = ~0u >> 1; + const vec2i_t abs = { nan, nan }; + return (vec2f_t) ((vec2i_t) v & abs); +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vsqrt2f (vec2f_t v) +{ + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_sqrt_ps (t); + return (vec2f_t) { t[0], t[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vceil2f (vec2f_t v) +{ +#ifndef __SSE4_1__ + return (vec2f_t) { + ceilf (v[0]), + ceilf (v[1]), + }; +#else + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_ceil_ps (t); + return (vec2f_t) { t[0], t[1] }; +#endif +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vfloor2f (vec2f_t v) +{ +#ifndef __SSE4_1__ + return (vec2f_t) { + floorf (v[0]), + floorf (v[1]), + }; +#else + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_floor_ps (t); + return (vec2f_t) { t[0], t[1] }; +#endif +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vtrunc2f (vec2f_t v) +{ +#ifndef __SSE4_1__ + return (vec2f_t) { + truncf (v[0]), + truncf (v[1]), + }; +#else + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_round_ps (t, _MM_FROUND_TRUNC); + return (vec2f_t) { t[0], t[1] }; +#endif +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +dot2f (vec2f_t a, vec2f_t b) +{ + vec2f_t c = a * b; + return (vec2f_t) { c[0] + c[1], c[0] + c[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +cmulf (vec2f_t a, vec2f_t b) +{ + vec2f_t c1 = a * b[0]; + vec2f_t c2 = a * b[1]; + return (vec2f_t) { c1[0] - c2[1], c1[1] + c2[0] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +normal2f (vec2f_t v) +{ + return v / vsqrt2f (dot2f (v, v)); +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +magnitude2f (vec2f_t v) +{ + return vsqrt2f (dot2f (v, v)); +} + +#endif//__QF_simd_vec2f_h diff --git a/include/QF/simd/vec2i.h b/include/QF/simd/vec2i.h new file mode 100644 index 000000000..29f2cc57c --- /dev/null +++ b/include/QF/simd/vec2i.h @@ -0,0 +1,102 @@ +/* + QF/simd/vec2i.h + + Vector functions for vec2i_t (ie, int) + + Copyright (C) 2022 Bill Currie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec2i_h +#define __QF_simd_vec2i_h + +#include +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec2i_t vabs2i (vec2i_t v) __attribute__((const)); +GNU89INLINE inline int any2i (vec2i_t v) __attribute__((const)); +GNU89INLINE inline int all2i (vec2i_t v) __attribute__((const)); +GNU89INLINE inline int none2i (vec2i_t v) __attribute__((const)); + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2i_t +vabs2i (vec2i_t v) +{ + const uint32_t nan = ~0u >> 1; + const vec2i_t abs = { nan, nan }; + return (vec2i_t) ((vec2i_t) v & abs); +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +any2i (vec2i_t v) +{ + vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); +#ifndef __SSSE3__ + return (t[0] + t[1]) > -2; +#else + return _mm_hadd_pi32 (t, t)[0] > -2; +#endif +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +all2i (vec2i_t v) +{ + vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); +#ifndef __SSSE3__ + return (t[0] + t[1]) == 0; +#else + return _mm_hadd_pi32 (t, t)[0] == 0; +#endif +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +none2i (vec2i_t v) +{ + vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); +#ifndef __SSSE3__ + return (t[0] + t[1]) == -2; +#else + return _mm_hadd_pi32 (t, t)[0] == -2; +#endif +} + +#endif//__QF_simd_vec2i_h diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 058635dd7..791c48dde 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -28,15 +28,15 @@ #ifndef __QF_simd_vec4d_h #define __QF_simd_vec4d_h -#ifdef __AVX2__ #include #include "QF/simd/types.h" +#include "QF/simd/vec2d.h" -GNU89INLINE inline vec4d_t vsqrtd (vec4d_t v) __attribute__((const)); -GNU89INLINE inline vec4d_t vceild (vec4d_t v) __attribute__((const)); -GNU89INLINE inline vec4d_t vfloord (vec4d_t v) __attribute__((const)); -GNU89INLINE inline vec4d_t vtruncd (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vsqrt4d (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vceil4d (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vfloor4d (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vtrunc4d (vec4d_t v) __attribute__((const)); /** 3D vector cross product. * * The w (4th) component can be any value on input, and is guaranteed to be 0 @@ -96,6 +96,9 @@ GNU89INLINE inline vec4d_t qrotd (vec4d_t a, vec4d_t b) __attribute__((const)); GNU89INLINE inline vec4d_t qconjd (vec4d_t q) __attribute__((const)); GNU89INLINE inline vec4d_t loadvec3d (const double v3[]) __attribute__((pure)); GNU89INLINE inline void storevec3d (double v3[3], vec4d_t v4); +GNU89INLINE inline vec4l_t loadvec3l (const int64_t *v3) __attribute__((pure)); +GNU89INLINE inline vec4l_t loadvec3l1 (const int64_t *v3) __attribute__((pure)); +GNU89INLINE inline void storevec3l (int64_t *v3, vec4l_t v4); #ifndef IMPLEMENT_VEC4D_Funcs GNU89INLINE inline @@ -103,9 +106,17 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vsqrtd (vec4d_t v) +vsqrt4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vsqrt2d (xy); + zw = vsqrt2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_sqrt_pd (v); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -114,9 +125,17 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vceild (vec4d_t v) +vceil4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vceil2d (xy); + zw = vceil2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_ceil_pd (v); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -125,9 +144,17 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vfloord (vec4d_t v) +vfloor4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vfloor2d (xy); + zw = vfloor2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_floor_pd (v); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -136,9 +163,17 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vtruncd (vec4d_t v) +vtrunc4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vtrunc2d (xy); + zw = vtrunc2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_round_pd (v, _MM_FROUND_TRUNC); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -165,7 +200,11 @@ vec4d_t dotd (vec4d_t a, vec4d_t b) { vec4d_t c = a * b; +#ifndef __AVX__ + c = (vec4d_t) { c[0] + c[1], c[0] + c[1], c[2] + c[3], c[2] + c[3] }; +#else c = _mm256_hadd_pd (c, c); +#endif static const vec4l_t A = {2, 3, 0, 1}; c += __builtin_shuffle(c, A); return c; @@ -184,8 +223,7 @@ qmuld (vec4d_t a, vec4d_t b) vec4d_t c = crossd (a, b) + a * b[3] + a[3] * b; vec4d_t d = dotd (a, b); // zero out the vector component of dot product so only the scalar remains - d = _mm256_permute2f128_pd (d, d, 0x18); - d = _mm256_permute4x64_pd (d, 0xc0); + d = (vec4d_t) { 0, 0, 0, d[3] }; return c - d; } @@ -201,8 +239,12 @@ qvmuld (vec4d_t q, vec4d_t v) double s = q[3]; // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. +#ifndef __AVX__ + q = (vec4d_t) { q[0], q[1], q[2], 0 }; +#else vec4d_t z = {}; q = _mm256_blend_pd (q, z, 0x08); +#endif vec4d_t c = crossd (q, v); vec4d_t qv = dotd (q, v); // q.w is 0 so v.w is irrelevant vec4d_t qq = dotd (q, q); @@ -223,8 +265,12 @@ vqmuld (vec4d_t v, vec4d_t q) double s = q[3]; // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. +#ifndef __AVX__ + q = (vec4d_t) { q[0], q[1], q[2], 0 }; +#else vec4d_t z = {}; q = _mm256_blend_pd (q, z, 0x08); +#endif vec4d_t c = crossd (q, v); vec4d_t qv = dotd (q, v); // q.w is 0 so v.w is irrelevant vec4d_t qq = dotd (q, q); @@ -241,11 +287,11 @@ VISIBLE vec4d_t qrotd (vec4d_t a, vec4d_t b) { - vec4d_t ma = vsqrtd (dotd (a, a)); - vec4d_t mb = vsqrtd (dotd (b, b)); + vec4d_t ma = vsqrt4d (dotd (a, a)); + vec4d_t mb = vsqrt4d (dotd (b, b)); vec4d_t den = 2 * ma * mb; vec4d_t t = mb * a + ma * b; - vec4d_t mba_mab = vsqrtd (dotd (t, t)); + vec4d_t mba_mab = vsqrt4d (dotd (t, t)); vec4d_t q = crossd (a, b) / mba_mab; q[3] = (mba_mab / den)[0]; return q; @@ -261,7 +307,7 @@ qconjd (vec4d_t q) { const uint64_t sign = UINT64_C(1) << 63; const vec4l_t neg = { sign, sign, sign, 0 }; - return _mm256_xor_pd (q, (__m256d) neg); + return (vec4d_t) ((vec4l_t) q ^ neg); } #ifndef IMPLEMENT_VEC4D_Funcs @@ -293,6 +339,41 @@ storevec3d (double v3[3], vec4d_t v4) v3[2] = v4[2]; } +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE #endif +vec4l_t +loadvec3l (const int64_t *v3) +{ + vec4l_t v4 = { v3[0], v3[1], v3[2], 0 }; + return v4; +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4l_t +loadvec3l1 (const int64_t *v3) +{ + vec4l_t v4 = { v3[0], v3[1], v3[2], 1 }; + return v4; +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +storevec3l (int64_t *v3, vec4l_t v4) +{ + v3[0] = v4[0]; + v3[1] = v4[1]; + v3[2] = v4[2]; +} #endif//__QF_simd_vec4d_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 6bb0ae4ec..7b7c8429d 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -33,11 +33,11 @@ #include "QF/simd/types.h" -GNU89INLINE inline vec4f_t vabsf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vsqrtf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vceilf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vfloorf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vtruncf (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vabs4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vsqrt4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vceil4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vfloor4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vtrunc4f (vec4f_t v) __attribute__((const)); /** 3D vector cross product. * * The w (4th) component can be any value on input, and is guaranteed to be 0 @@ -106,7 +106,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vabsf (vec4f_t v) +vabs4f (vec4f_t v) { const uint32_t nan = ~0u >> 1; const vec4i_t abs = { nan, nan, nan, nan }; @@ -119,7 +119,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vsqrtf (vec4f_t v) +vsqrt4f (vec4f_t v) { #ifndef __SSE__ vec4f_t r = { sqrtf (v[0]), sqrtf (v[1]), sqrtf (v[2]), sqrtf (v[3]) }; @@ -135,7 +135,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vceilf (vec4f_t v) +vceil4f (vec4f_t v) { #ifndef __SSE4_1__ return (vec4f_t) { @@ -155,7 +155,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vfloorf (vec4f_t v) +vfloor4f (vec4f_t v) { #ifndef __SSE4_1__ return (vec4f_t) { @@ -175,7 +175,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vtruncf (vec4f_t v) +vtrunc4f (vec4f_t v) { #ifndef __SSE4_1__ return (vec4f_t) { @@ -296,11 +296,11 @@ VISIBLE vec4f_t qrotf (vec4f_t a, vec4f_t b) { - vec4f_t ma = vsqrtf (dotf (a, a)); - vec4f_t mb = vsqrtf (dotf (b, b)); + vec4f_t ma = vsqrt4f (dotf (a, a)); + vec4f_t mb = vsqrt4f (dotf (b, b)); vec4f_t den = 2 * ma * mb; vec4f_t t = mb * a + ma * b; - vec4f_t mba_mab = vsqrtf (dotf (t, t)); + vec4f_t mba_mab = vsqrt4f (dotf (t, t)); vec4f_t q = crossf (a, b) / mba_mab; q[3] = (mba_mab / den)[0]; return q; @@ -388,7 +388,7 @@ VISIBLE vec4f_t normalf (vec4f_t v) { - return v / vsqrtf (dotf (v, v)); + return v / vsqrt4f (dotf (v, v)); } #ifndef IMPLEMENT_VEC4F_Funcs @@ -399,7 +399,7 @@ VISIBLE vec4f_t magnitudef (vec4f_t v) { - return vsqrtf (dotf (v, v)); + return vsqrt4f (dotf (v, v)); } #ifndef IMPLEMENT_VEC4F_Funcs @@ -411,7 +411,7 @@ vec4f_t magnitude3f (vec4f_t v) { v[3] = 0; - return vsqrtf (dotf (v, v)); + return vsqrt4f (dotf (v, v)); } vec4f_t __attribute__((pure)) diff --git a/include/QF/simd/vec4i.h b/include/QF/simd/vec4i.h new file mode 100644 index 000000000..d3e4ac5dc --- /dev/null +++ b/include/QF/simd/vec4i.h @@ -0,0 +1,142 @@ +/* + QF/simd/vec4i.h + + Vector functions for vec4i_t (ie, int) + + Copyright (C) 2022 Bill Currie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec4i_h +#define __QF_simd_vec4i_h + +#include +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec4i_t vabs4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline int any4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline int all4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline int none4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline vec4i_t loadvec3i (const int *v3) __attribute__((pure)); +GNU89INLINE inline vec4i_t loadvec3i1 (const int *v3) __attribute__((pure)); +GNU89INLINE inline void storevec3i (int *v3, vec4i_t v4); + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4i_t +vabs4i (vec4i_t v) +{ + const uint32_t nan = ~0u >> 1; + const vec4i_t abs = { nan, nan, nan, nan }; + return (vec4i_t) ((vec4i_t) v & abs); +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +any4i (vec4i_t v) +{ +#ifndef __SSE4_1__ + vec4i_t t = (v != (vec4i_t) {}); + return (t[0] + t[1] + t[2] + t[3]) != 0; +#else + return !__builtin_ia32_ptestz128 ((__v2di)v, (__v2di)v); +#endif +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +all4i (vec4i_t v) +{ + vec4i_t t = (v == (vec4i_t) {}); +#ifndef __SSE4_1__ + return (t[0] + t[1] + t[2] + t[3]) == 0; +#else + return __builtin_ia32_ptestz128 ((__v2di)t, (__v2di)t); +#endif +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +none4i (vec4i_t v) +{ +#ifndef __SSE4_1__ + vec4i_t t = (v != (vec4i_t) {}); + return (t[0] + t[1] + t[2] + t[3]) == 0; +#else + return __builtin_ia32_ptestz128 ((__v2di)v, (__v2di)v); +#endif +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4i_t +loadvec3i (const int *v3) +{ + vec4i_t v4 = { v3[0], v3[1], v3[2], 0 }; + return v4; +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4i_t +loadvec3i1 (const int *v3) +{ + vec4i_t v4 = { v3[0], v3[1], v3[2], 1 }; + return v4; +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +storevec3i (int *v3, vec4i_t v4) +{ + v3[0] = v4[0]; + v3[1] = v4[1]; + v3[2] = v4[2]; +} + +#endif//__QF_simd_vec4i_h diff --git a/include/netchan.h b/include/netchan.h index a71902f64..5fe10eb81 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -64,12 +64,10 @@ extern struct msg_s *net_message; extern struct cvar_s *qport; -int Net_Log_Init (const char **sound_precache); +int Net_Log_Init (const char **sound_precache, int server); void Net_LogPrintf (const char *fmt, ...) __attribute__ ((format (PRINTF, 1, 2))); -void Log_Incoming_Packet (const byte *p, int len, int has_sequence, - int is_server); -void Log_Outgoing_Packet (const byte *p, int len, int has_sequence, - int is_server); +void Log_Incoming_Packet (const byte *p, int len, int has_sequence); +void Log_Outgoing_Packet (const byte *p, int len, int has_sequence); void Net_LogStop (void *data); void Analyze_Client_Packet (const byte * data, int len, int has_sequence); void Analyze_Server_Packet (const byte * data, int len, int has_sequence); diff --git a/include/netmain.h b/include/netmain.h index 43b947aa7..0a4587b26 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -268,7 +268,7 @@ void NET_AddCachedHost (const char *name, const char *map, const char *cname, extern double net_time; extern struct msg_s *net_message; -extern int net_activeconnections; +extern unsigned net_activeconnections; /** Initialize the networking sub-system. */ diff --git a/include/rua_internal.h b/include/rua_internal.h index 24e16cc6e..955e6d5e6 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -33,6 +33,9 @@ #include "QF/quakeio.h" +struct progs_s; +struct dstring_s; + void RUA_Cbuf_Init (struct progs_s *pr, int secure); void RUA_Cmd_Init (struct progs_s *pr, int secure); void RUA_Cvar_Init (struct progs_s *pr, int secure); @@ -49,6 +52,10 @@ void RUA_String_Init (struct progs_s *pr, int secure); void RUA_QFile_Init (struct progs_s *pr, int secure); void RUA_QFS_Init (struct progs_s *pr, int secure); +// the variable args are assumed to come immediately after fmt_arg +void RUA_Sprintf (struct progs_s *pr, struct dstring_s *dstr, const char *func, + int fmt_arg); + int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle); diff --git a/libs/audio/snd_progs.c b/libs/audio/snd_progs.c index a130fd44c..912686412 100644 --- a/libs/audio/snd_progs.c +++ b/libs/audio/snd_progs.c @@ -47,13 +47,15 @@ bi_S_LocalSound (progs_t *pr) S_LocalSound (sound); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"S_LocalSound", bi_S_LocalSound, -1}, + bi(S_LocalSound, 1, p(string)), {0} }; VISIBLE void S_Progs_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 76e9b676c..69494450f 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -49,8 +49,8 @@ typedef struct il_data_s { struct il_data_s **prev; inputline_t *line; progs_t *pr; - func_t enter; // enter key callback - pointer_t data[2]; // allow two data params for the callback + pr_func_t enter; // enter key callback + pr_ptr_t data[2]; // allow two data params for the callback int method; // true if method rather than function } il_data_t; @@ -302,21 +302,23 @@ bi_InputLine_Draw (progs_t *pr) line->line->draw (line->line); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"InputLine_Create", bi_InputLine_Create, -1}, - {"InputLine_SetPos", bi_InputLine_SetPos, -1}, - {"InputLine_SetCursor", bi_InputLine_SetCursor, -1}, + bi(InputLine_Create, 3, p(int), p(int), p(int)), + bi(InputLine_SetPos, 3, p(ptr), p(int), p(int)), + bi(InputLine_SetCursor, 2, p(ptr), p(int)), {"InputLine_SetEnter|^{tag _inputline_t=}(v*^v)^v", - bi_InputLine_SetEnter, -1}, + bi_InputLine_SetEnter, -1, 3, {p(ptr), p(func), p(ptr)}}, {"InputLine_SetEnter|^{tag _inputline_t=}(@@:.)@:", - bi_InputLine_SetEnter, -1}, - {"InputLine_SetWidth", bi_InputLine_SetWidth, -1}, - {"InputLine_SetText", bi_InputLine_SetText, -1}, - {"InputLine_GetText", bi_InputLine_GetText, -1}, - {"InputLine_Destroy", bi_InputLine_Destroy, -1}, - {"InputLine_Clear", bi_InputLine_Clear, -1}, - {"InputLine_Process", bi_InputLine_Process, -1}, - {"InputLine_Draw", bi_InputLine_Draw, -1}, + bi_InputLine_SetEnter, -1, 4, {p(ptr), p(func), p(ptr), p(ptr)}}, + bi(InputLine_SetWidth, 2, p(ptr), p(int)), + bi(InputLine_SetText, 2, p(ptr), p(string)), + bi(InputLine_GetText, 1, p(ptr)), + bi(InputLine_Destroy, 1, p(ptr)), + bi(InputLine_Clear, 2, p(ptr), p(int)), + bi(InputLine_Process, 2, p(ptr), p(int)), + bi(InputLine_Draw, 1, p(ptr)), {0} }; @@ -326,7 +328,7 @@ InputLine_Progs_Init (progs_t *pr) il_resources_t *res = calloc (1, sizeof (il_resources_t)); PR_Resources_Register (pr, "InputLine", res, bi_il_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } VISIBLE void diff --git a/libs/console/menu.c b/libs/console/menu.c index e6dcc72a4..171de8084 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -67,12 +67,12 @@ typedef struct menu_item_s { int max_items; int cur_item; int x, y; - func_t func; - func_t cursor; - func_t keyevent; - func_t draw; - func_t enter_hook; - func_t leave_hook; + pr_func_t func; + pr_func_t cursor; + pr_func_t keyevent; + pr_func_t draw; + pr_func_t enter_hook; + pr_func_t leave_hook; unsigned fadescreen:1; unsigned allkeys:1; const char *text; @@ -85,16 +85,16 @@ static progs_t menu_pr_state; static menu_item_t *menu; //static keydest_t menu_keydest; static hashtab_t *menu_hash; -static func_t menu_init; -static func_t menu_quit; -static func_t menu_draw_hud; -static func_t menu_pre; -static func_t menu_post; +static pr_func_t menu_init; +static pr_func_t menu_quit; +static pr_func_t menu_draw_hud; +static pr_func_t menu_pre; +static pr_func_t menu_post; static const char *top_menu; typedef struct menu_func_s { const char *name; - func_t *func; + pr_func_t *func; } menu_func_t; static menu_func_t menu_functions[] = { @@ -129,12 +129,12 @@ menu_resolve_globals (progs_t *pr) sym = menu_functions[i].name; if (!(f = PR_FindFunction (pr, sym))) goto error; - *menu_functions[i].func = (func_t) (f - menu_pr_state.pr_functions); + *menu_functions[i].func = (pr_func_t) (f - menu_pr_state.pr_functions); } if (!(def = PR_FindGlobal (pr, sym = "time"))) goto error; - menu_pr_state.globals.time = &G_FLOAT (pr, def->ofs); + menu_pr_state.globals.ftime = &G_FLOAT (pr, def->ofs);//FIXME double time return 1; error: Sys_Printf ("%s: undefined symbol %s\n", pr->progs_name, sym); @@ -315,7 +315,7 @@ bi_Menu_Item (progs_t *pr) int x = P_INT (pr, 0); int y = P_INT (pr, 1); const char *text = P_GSTRING (pr, 2); - func_t func = P_FUNCTION (pr, 3); + pr_func_t func = P_FUNCTION (pr, 3); int allkeys = P_INT (pr, 4); menu_item_t *mi = calloc (sizeof (menu_item_t), 1); @@ -331,7 +331,7 @@ bi_Menu_Item (progs_t *pr) static void bi_Menu_Cursor (progs_t *pr) { - func_t func = P_FUNCTION (pr, 0); + pr_func_t func = P_FUNCTION (pr, 0); menu->cursor = func; } @@ -339,7 +339,7 @@ bi_Menu_Cursor (progs_t *pr) static void bi_Menu_KeyEvent (progs_t *pr) { - func_t func = P_FUNCTION (pr, 0); + pr_func_t func = P_FUNCTION (pr, 0); menu->keyevent = func; } @@ -385,7 +385,7 @@ bi_Menu_SelectMenu (progs_t *pr) static void bi_Menu_SetQuit (progs_t *pr) { - func_t func = P_FUNCTION (pr, 0); + pr_func_t func = P_FUNCTION (pr, 0); menu_quit = func; } @@ -513,29 +513,33 @@ menu_load_file (progs_t *pr, const char *path, off_t *size) return data; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Menu_Begin", bi_Menu_Begin, -1}, - {"Menu_FadeScreen", bi_Menu_FadeScreen, -1}, - {"Menu_Draw", bi_Menu_Draw, -1}, - {"Menu_EnterHook", bi_Menu_EnterHook, -1}, - {"Menu_LeaveHook", bi_Menu_LeaveHook, -1}, - {"Menu_Pic", bi_Menu_Pic, -1}, - {"Menu_SubPic", bi_Menu_SubPic, -1}, - {"Menu_CenterPic", bi_Menu_CenterPic, -1}, - {"Menu_CenterSubPic", bi_Menu_CenterSubPic, -1}, - {"Menu_Item", bi_Menu_Item, -1}, - {"Menu_Cursor", bi_Menu_Cursor, -1}, - {"Menu_KeyEvent", bi_Menu_KeyEvent, -1}, - {"Menu_End", bi_Menu_End, -1}, - {"Menu_TopMenu", bi_Menu_TopMenu, -1}, - {"Menu_SelectMenu", bi_Menu_SelectMenu, -1}, - {"Menu_SetQuit", bi_Menu_SetQuit, -1}, - {"Menu_Quit", bi_Menu_Quit, -1}, - {"Menu_GetIndex", bi_Menu_GetIndex, -1}, - {"Menu_Next", bi_Menu_Next, -1}, - {"Menu_Prev", bi_Menu_Prev, -1}, - {"Menu_Enter", bi_Menu_Enter, -1}, - {"Menu_Leave", bi_Menu_Leave, -1}, + bi(Menu_Begin, 3, p(int), p(int), p(string)), + bi(Menu_FadeScreen, 1, p(int)), + bi(Menu_Draw, 2, p(int), p(int)), + bi(Menu_EnterHook, 1, p(func)), + bi(Menu_LeaveHook, 1, p(func)), + bi(Menu_Pic, 3, p(int), p(int), p(string)), + bi(Menu_SubPic, 7, p(int), p(int), p(string), + p(int), p(int), p(int), p(int)), + bi(Menu_CenterPic, 3, p(int), p(int), p(string)), + bi(Menu_CenterSubPic, 7, p(int), p(int), p(string), + p(int), p(int), p(int), p(int)), + bi(Menu_Item, 5, p(int), p(int), p(string), p(func), p(int)), + bi(Menu_Cursor, 1, p(func)), + bi(Menu_KeyEvent, 1, p(func)), + bi(Menu_End, 0), + bi(Menu_TopMenu, 1, p(string)), + bi(Menu_SelectMenu, 1, p(string)), + bi(Menu_SetQuit, 1, p(func)), + bi(Menu_Quit, 0), + bi(Menu_GetIndex, 0), + bi(Menu_Next, 0), + bi(Menu_Prev, 0), + bi(Menu_Enter, 0), + bi(Menu_Leave, 0), {0}, }; @@ -590,12 +594,13 @@ Menu_Init (void) menu_pr_state.max_edicts = 0; menu_pr_state.zone_size = 1024 * 1024; + menu_pr_state.stack_size = 64 * 1024; PR_Init (&menu_pr_state); menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0, 0); - PR_RegisterBuiltins (&menu_pr_state, builtins); + PR_RegisterBuiltins (&menu_pr_state, builtins, 0); RUA_Init (&menu_pr_state, 3); @@ -672,18 +677,20 @@ Menu_Draw (view_t *view) if (menu->fadescreen) r_funcs->Draw_FadeScreen (); - *menu_pr_state.globals.time = *con_data.realtime; + *menu_pr_state.globals.ftime = *con_data.realtime;//FIXME double time if (menu->draw) { int ret; run_menu_pre (); + PR_PushFrame (&menu_pr_state); PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x; P_INT (&menu_pr_state, 1) = y; menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, menu->draw); ret = R_INT (&menu_pr_state); + PR_PopFrame (&menu_pr_state); run_menu_post (); if (!ret) return; @@ -713,11 +720,13 @@ Menu_Draw (view_t *view) item = menu->items[menu->cur_item]; if (menu->cursor) { run_menu_pre (); + PR_PushFrame (&menu_pr_state); PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x + item->x; P_INT (&menu_pr_state, 1) = y + item->y; menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, menu->cursor); + PR_PopFrame (&menu_pr_state); run_menu_post (); } else { r_funcs->Draw_Character (x + item->x, y + item->y, @@ -729,7 +738,7 @@ void Menu_Draw_Hud (view_t *view) { run_menu_pre (); - *menu_pr_state.globals.time = *con_data.realtime; + *menu_pr_state.globals.ftime = *con_data.realtime;//FIXME double time PR_ExecuteProgram (&menu_pr_state, menu_draw_hud); run_menu_post (); @@ -746,6 +755,7 @@ menu_key_event (const IE_event_t *ie_event) return 0; if (menu->keyevent) { run_menu_pre (); + PR_PushFrame (&menu_pr_state); PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = key.code; P_INT (&menu_pr_state, 1) = key.unicode; @@ -753,6 +763,7 @@ menu_key_event (const IE_event_t *ie_event) menu_pr_state.pr_argc = 3; PR_ExecuteProgram (&menu_pr_state, menu->keyevent); ret = R_INT (&menu_pr_state); + PR_PopFrame (&menu_pr_state); run_menu_post (); if (ret) return 1; @@ -767,8 +778,8 @@ menu_key_event (const IE_event_t *ie_event) P_INT (&menu_pr_state, 1) = key.code; menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, item->func); - PR_PopFrame (&menu_pr_state); ret = R_INT (&menu_pr_state); + PR_PopFrame (&menu_pr_state); run_menu_post (); if (ret) return 1; diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index dfae7c388..dbffb47b3 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -1,3 +1,5 @@ +include libs/gamecode/test/Makemodule.am + gc_deps=libs/util/libQFutil.la noinst_LTLIBRARIES += libs/gamecode/libQFgamecode.la @@ -11,9 +13,49 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_debug.c \ libs/gamecode/pr_exec.c \ libs/gamecode/pr_load.c \ - libs/gamecode/pr_parse.c \ libs/gamecode/pr_opcode.c \ + libs/gamecode/pr_parse.c \ libs/gamecode/pr_resolve.c \ libs/gamecode/pr_resource.c \ libs/gamecode/pr_strings.c \ + libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c + +noinst_PYTHON += $(opcodes_py) + +opcodes_py = $(srcdir)/libs/gamecode/opcodes.py +pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc +pr_opcode_hinc = $(top_builddir)/include/QF/progs/pr_opcode.hinc +pr_opcode_src = \ + ${pr_opcode_cinc} \ + ${pr_opcode_hinc} +libs/gamecode/pr_opcode.lo: libs/gamecode/pr_opcode.c ${pr_opcode_src} + +convert_py = $(srcdir)/libs/gamecode/convert.py +pr_convert_cinc = $(top_builddir)/libs/gamecode/pr_convert.cinc + +hops_py = $(srcdir)/libs/gamecode/hops.py +pr_hops_cinc = $(top_builddir)/libs/gamecode/pr_hops.cinc + +BUILT_SOURCES += \ + $(pr_opcode_cinc) \ + $(pr_opcode_hinc) \ + $(pr_convert_cinc) \ + $(pr_hops_cinc) + +$(pr_opcode_cinc): $(opcodes_py) + $(V_PY)$(PYTHON) $(opcodes_py) table > $(pr_opcode_cinc).t && \ + $(am__mv) $(pr_opcode_cinc).t $(pr_opcode_cinc) + +$(pr_opcode_hinc): $(opcodes_py) + $(V_PY) mkdir -p `dirname $(pr_opcode_hinc)` &&\ + $(PYTHON) $(opcodes_py) enum > $(pr_opcode_hinc).t && \ + $(am__mv) $(pr_opcode_hinc).t $(pr_opcode_hinc) + +$(pr_convert_cinc): $(convert_py) + $(V_PY)$(PYTHON) $(convert_py) table > $(pr_convert_cinc).t && \ + $(am__mv) $(pr_convert_cinc).t $(pr_convert_cinc) + +$(pr_hops_cinc): $(hops_py) + $(V_PY)$(PYTHON) $(hops_py) table > $(pr_hops_cinc).t && \ + $(am__mv) $(pr_hops_cinc).t $(pr_hops_cinc) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py new file mode 100644 index 000000000..333846c66 --- /dev/null +++ b/libs/gamecode/convert.py @@ -0,0 +1,132 @@ +print("""// types are encoded as ubf where: +// u = 0: signed, u = 1: unsigned +// b = 0: 32-bit, b = 1: 64-bit +// f = 0: int, f = 1: float/double +// unsigned float/double is interpreted as bool +// width is ww where: +// ww = 00: 1 component +// ww = 01: 2 components +// ww = 10: 3 components +// ww = 11: 4 components +// full conversion code is wwsssddd where: +// ww = width +// sss = src type +// ddd = dst type +// case values are in octal +""") +types = [ + "int", + "float", + "long", + "double", + "uint", + "int", # 32-bit bool + "ulong", + "long", # 64-bit bool +] +#does not include size (2 or 4, 3 is special) +vec_types = [ + "ivec", + "vec", + "lvec", + "dvec", + "uivec", + "ivec", # 32-bit bool + "ulvec", + "lvec", # 64-bit bool +] +convert_matrix = [ + #i f l d ui b ul B + [0, 1, 1, 1, 0, 3, 1, 3], # i + [1, 0, 1, 1, 1, 3, 1, 3], # f + [1, 1, 0, 1, 1, 3, 0, 3], # l + [1, 1, 1, 0, 1, 3, 1, 3], # d + + [0, 1, 1, 1, 0, 3, 1, 3], # ui + [2, 2, 2, 2, 2, 0, 2, 3], # 32-bit bool + [1, 1, 0, 1, 1, 3, 0, 3], # ul + [2, 2, 2, 2, 2, 3, 2, 0], # 64-bit bool +] + +def case_str(width, src_type, dst_type): + case = (width << 6) | (src_type << 3) | (dst_type) + return f"case {case:04o}:" + +#FIXME look into using gcc's __builtin_convertvector +def cast_str(width, src_type, dst_type): + if width & 1: + return f"(pr_{vec_types[dst_type]}{width+1}_t)" + else: + return f"(pr_{types[dst_type]}_t)" + +def src_str(width, src_type, dst_type): + if width & 1: + return f"OPA({vec_types[src_type]}{width+1})" + else: + return f"OPA({types[src_type]})" + +def dst_str(width, src_type, dst_type): + if width & 1: + return f"OPC({vec_types[dst_type]}{width+1})" + else: + return f"OPC({types[dst_type]})" + +def zero_str(width, src_type): + ones = "{%s}" % (", ".join(["0"] * (width + 1))) + return f"{cast_str(width, src_type, src_type)} {ones}" + +def one_str(width, src_type): + ones = "{%s}" % (", ".join(["1"] * (width + 1))) + return f"{cast_str(width, src_type, src_type)} {ones}" + +def expand_str(width, src, pref=""): + src = [f"{pref}{src}[{i}]" for i in range(width + 1)] + return "{%s}" % (", ".join(src)); + +for width in range(4): + for src_type in range(8): + for dst_type in range(8): + case = case_str(width, src_type, dst_type) + cast = cast_str(width, src_type, dst_type) + src = src_str(width, src_type, dst_type) + dst = dst_str(width, src_type, dst_type) + mode = convert_matrix[src_type][dst_type] + if mode == 0: + if dst_type & 2 != src_type & 2: + continue + if dst_type & 2: + src = src_str(width, 2, 2) + dst = dst_str(width, 2, 2) + else: + src = src_str(width, 0, 0) + dst = dst_str(width, 0, 0) + if width == 2: + print(f"{case} VectorCopy(&{src},&{dst}); break;") + else: + print(f"{case} {dst} = {src}; break;") + elif mode == 1: + if width == 0: + print(f"{case} {dst} = {cast} {src}; break;") + elif width == 2: + print(f"{case} VectorCompUop(&{dst},{cast},&{src}); break;") + else: + expand = expand_str(width, src) + print(f"{case} {dst} = {cast} {expand}; break;") + elif mode == 2: + one = one_str(width, src_type) + if width == 0: + print(f"{case} {dst} = !!{src}; break;") + elif width == 2: + print(f"{case} VectorCompUop(&{dst},!!,&{src}); break;") + else: + expand = expand_str(width, src, "!!") + print(f"{case} {dst} = {cast} {expand}; break;") + elif mode == 3: + zero = zero_str(width, src_type) + if width == 0: + print(f"{case} {dst} = -!!{src}; break;") + elif width == 2: + print(f"{case} VectorCompUop(&{dst},-!!,&{src}); break;") + else: + expand = expand_str(width, src, "-!!") + print(f"{case} {dst} = {cast} {expand}; break;") diff --git a/libs/gamecode/hops.py b/libs/gamecode/hops.py new file mode 100644 index 000000000..634decc47 --- /dev/null +++ b/libs/gamecode/hops.py @@ -0,0 +1,55 @@ +print("""// encoding is tssooo +// t = 0: 32-bit, t = 1: 64-bit +// ss = 00: reserved +// ss = 01: 2 components +// ss = 10: 3 components +// ss = 11: 4 components +// ooo = 000: and +// ooo = 001: or +// ooo = 010: xor +// ooo = 011: add.i +// ooo = 100: nand +// ooo = 101: nor +// ooo = 110: xnor +// ooo = 111: add.f +""") +#for vec3 +types = [ + ["int", "int", "int", "int", "int", "int", "int", "float"], + ["long", "long", "long", "long", "long", "long", "long", "double"] +] +#does not include size (2 or 4, 3 is special) +vec_types = [ + ["ivec", "ivec", "ivec", "ivec", "ivec", "ivec", "ivec", "vec"], + ["lvec", "lvec", "lvec", "lvec", "lvec", "lvec", "lvec", "dvec"] +] +operators = ["&", "|", "^", "+"] + +def case_str(type, width, op): + case = (type << 5) | (width << 3) | (op) + return f"case {case:03o}:" + +def src_str(type, width, op): + if width & 1: + return f"OPA({vec_types[type][op]}{width+1})" + else: + return f"OPA({types[type][op]})" + +def dst_str(type, width, op): + return f"OPC({types[type][op]})" + +def hop_str(type, width, op): + return f"{'~' if op & 4 and op != 7 else ''}OP_hop{width+1}" + +for type in range(2): + for width in range(1, 4): # 0 is reserved + for opcode in range(8): + case = case_str(type, width, opcode) + src = src_str(type, width, opcode) + dst = dst_str(type, width, opcode) + hop = hop_str(type, width, opcode) + op = operators[opcode & 3] + if width == 2: + print(f"{case} {dst} = {hop} (&{src}, {op}); break;") + else: + print(f"{case} {dst} = {hop} ({src}, {op}); break;") diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py new file mode 100644 index 000000000..4ec39a71f --- /dev/null +++ b/libs/gamecode/opcodes.py @@ -0,0 +1,707 @@ +bitmap_txt = """ +0 0000 mmss load +0 0001 mmss store +0 0010 mmss push +0 0011 mmss pop +0 1ccc ttss compare +0 0000 00nn +0 0000 0000 noop +0 0000 0001 adjstk +0 0000 0010 constant +0 1011 otss udivops +0 1111 s0mm load64 +0 1111 s1mm store64 +0 1111 n000 + +1 0ooo ttss mathops +1 011r tuss shiftops +1 0110 o1oo string +1 1ccc t0ss compare2 +1 1t00 ooss bitops +1 1001 01mm jump +1 1001 11mm call (return specified st->c) +1 1001 1100 return (size in st->c) +1 1010 t1ss scale +1 1010 t100 swizzle +1 1011 tooo vecops +1 1101 01oo move +1 1101 11oo memset +1 1101 c111 statef +1 1110 c1cc branch +1 1110 c111 stated +1 1111 00mm lea +1 1111 01td vecops2 +1 1111 10oo fbitops +1 1111 1100 convert (conversion mode in st->b) +1 1111 1101 with (mode in st->a, value in st->b, reg in st->c) +1 1111 1110 +1 1111 1111 hops +""" + +import copy + +address_mode = "ABCD" +address_types = [ + "ev_void, ev_invalid", + "ev_entity, ev_field", + "ev_ptr, ev_short", + "ev_ptr, ev_int", +] +address_widths = [ + [ "1, 0", "1, 1", "1, 0", "1, 1", ], + [ "2, 0", "1, 1", "1, 0", "1, 1", ], + [ "3, 0", "1, 1", "1, 0", "1, 1", ], + [ "4, 0", "1, 1", "1, 0", "1, 1", ], + [ "-1, 0", "1, 1", "1, 0", "1, 1", ], +] +#store, pop and lea +store_fmt = [ + "%ga", + "%Ga.%Gb(%Ea)", + "*(%Ga + %sb)", + "*(%Ga + %Gb)", +] +# load and push +load_fmt = [ + "*%Ga, %gc", + "%Ga.%Gb(%Ea)", + "*(%Ga + %sb)", + "*(%Ga + %Gb)", +] +branch_fmt = [ + "branch %sa (%Oa)", + "*%Ga", + "%Ga[%sb]", + "%Ga[%Gb]", +] +compare_ccc = [ "eq", "lt", "gt", None, "ne", "ge", "le", None] +type_tt = ['I', 'F', 'L', 'D'] +etype_tt = ["ev_int", "ev_float", "ev_long", "ev_double"] +unsigned_t = ["ev_uint", "ev_ulong"] +float_t = ["ev_float", "ev_double"] + +adjstk_formats = { + "opcode": "OP_ADJSTK", + "mnemonic": "adjstk", + "opname": "adjstk", + "format": "%sa, %sb", + "widths": "0, 0, 0", + "types": "ev_short, ev_short, ev_invalid", +} +bitops_formats = { + "opcode": "OP_{op_bit[oo].upper()}_{bit_type[t]}_{ss+1}", + "mnemonic": "{op_bit[oo]}", + "opname": "{op_bit[oo]}", + "format": "{bit_fmt[oo]}", + "widths": "{ss+1}, { oo < 3 and ss+1 or 0}, {ss+1}", + "types": "{bit_types[t]}, {oo < 3 and bit_types[t] or 'ev_invalid'}, {bit_types[t]}", + "args": { + "op_bit": ["bitand", "bitor", "bitxor", "bitnot"], + "bit_type": ["I", "L"], + "bit_types": ["ev_int", "ev_long"], + "bit_fmt": [ + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %gc", + ], + }, +} +branch_formats = { + "opcode": "OP_{op_cond[c*4+cc].upper()}", + "mnemonic": "{op_cond[c*4+cc]}", + "opname": "{op_cond[c*4+cc]}", + "format": "{cond_fmt[c*4+cc]}{branch_fmt[0]}", + "widths": "0, 0, 1", + "types": "ev_short, ev_invalid, ev_int", + "args": { + "op_mode": "ABCD", + "op_cond": ["ifz", "ifb", "ifa", None, + "ifnz", "ifae", "ifbe", None], + "branch_fmt": branch_fmt, + "cond_fmt": ["%Gc ", "%Gc ", "%Gc ", "", "%Gc ", "%Gc ", "%Gc ", ""], + }, +} +call_formats = { + "opcode": "OP_CALL_{op_mode[mm]}", + "mnemonic": "call", + "opname": "call", + "format": "{call_fmt[mm]}", + "widths": "{call_widths[mm]}, -1", + "types": "{call_types[mm]}, ev_void", + "args": { + "op_mode": ".BCD", + "call_fmt": [ + None, # return handled seprately + "%Ga, %gc", + "%Ga[%sb], %gc", + "%Ga[%Gb], %gc", + ], + "call_types": [ + None, + "ev_void, ev_invalid", + "ev_ptr, ev_short", + "ev_ptr, ev_int", + ], + "call_widths": [ None, "1, 0", "1, 0", "1, 1" ] + }, +} +compare_formats = { + "opcode": "OP_{op_cmp[ccc].upper()}_{cmp_type[tt]}_{ss+1}", + "mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}", + "opname": "{op_cmp[ccc]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{cmp_types[tt]}, {cmp_types[tt]}, ev_int", + "args": { + "op_cmp": compare_ccc, + "cmp_type": type_tt, + "cmp_types": etype_tt, + }, +} +compare2_formats = { + "opcode": "OP_{op_cmp[ccc].upper()}_{cmp_type[t]}_{ss+1}", + "mnemonic": "{op_cmp[ccc]}.{cmp_type[t]}", + "opname": "{op_cmp[ccc]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{cmp_types[t]}, {cmp_types[t]}, ev_int", + "args": { + "op_cmp": compare_ccc, + "cmp_type": ['u', 'U'], + "cmp_types": unsigned_t, + }, +} +constant_formats = { + "opcode": "OP_LDCONST", + "mnemonic": "ldconst", + "opname": "ldconst", + "format": "%sa, %sb, %gc", + "widths": "0, 0, -1", + "types": "ev_short, ev_short, ev_void", +} +convert_formats = { + "opcode": "OP_CONV", + "mnemonic": "conv", + "opname": "conv", + "format": "%Ga %Cb %gc", + "widths": "-1, 0, -1", + "types": "ev_void, ev_short, ev_void", +} +fbitops_formats = { + "opcode": "OP_{op_fbit[oo].upper()}_F", + "mnemonic": "{op_fbit[oo]}.f", + "opname": "{op_fbit[oo]}", + "format": "{fbit_fmt[oo]}", + "widths": "1, 1, 1", + "types": "{fbit_types[0]}, {fbit_types[oo==3]}, {fbit_types[0]}", + "args": { + "op_fbit": ["bitand", "bitor", "bitxor", "bitnot"], + "fbit_types": ["ev_float", "ev_invalid"], + "fbit_fmt": [ + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %gc", + ], + }, +} +hops_formats = { + "opcode": "OP_HOPS", + "mnemonic": "hops", + "opname": "hops", + "format": "%Ga %Hb %gc", + "widths": "-1, 0, 1", + "types": "ev_void, ev_short, ev_void", +} +jump_formats = { + "opcode": "OP_JUMP_{op_mode[mm]}", + "mnemonic": "jump", + "opname": "jump", + "format": "{jump_fmt[mm]}", + "widths": "{jump_widths[mm]}, 0", + "types": "{jump_types[mm]}", + "args": { + "op_mode": "ABCD", + "jump_fmt": branch_fmt, + "jump_types": [ + "ev_short, ev_invalid, ev_invalid", + "ev_void, ev_int, ev_invalid", + "ev_ptr, ev_short, ev_invalid", + "ev_ptr, ev_int, ev_invalid", + ], + "jump_widths": [ "0, 0", "1, 1", "1, 0", "1, 1" ] + }, +} +load64_formats = { + "opcode": "OP_LOAD64_{op_mode[mm]}_{s+3}", + "mnemonic": "load64", + "opname": "load64", + "format": "{load_fmt[mm]}, %gc", + "widths": "{load_widths[s+2][mm]}, {s+3}", + "types": "{load_types[mm]}, ev_void", + "args": { + "op_mode": address_mode, + "load_fmt": load_fmt, + "load_types": address_types, + "load_widths": address_widths, + }, +} +lea_formats = { + "opcode": "OP_LEA_{op_mode[mm]}", + "mnemonic": "lea", + "opname": "lea", + "format": "{lea_fmt[mm]}, %gc", + "widths": "{lea_widths[mm]}, 1", + "types": "{lea_types[mm]}, ev_ptr", + "args": { + "op_mode": address_mode, + "lea_fmt": store_fmt, + "lea_types": address_types, + "lea_widths": address_widths[4], + }, +} +load_formats = { + "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", + "mnemonic": "load", + "opname": "load", + "format": "{load_fmt[mm]}, %gc", + "widths": "{load_widths[ss][mm]}, {ss+1}", + "types": "{load_types[mm]}, ev_void", + "args": { + "op_mode": address_mode, + "load_fmt": load_fmt, + "load_types": address_types, + "load_widths": address_widths, + }, +} +mathops_formats = { + "opcode": "OP_{op_math[ooo].upper()}_{math_type[tt]}_{ss+1}", + "mnemonic": "{op_math[ooo]}.{math_type[tt]}", + "opname": "{op_math[ooo]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{math_types[tt]}, {math_types[tt]}, {math_types[tt]}", + "args": { + "op_math": ["mul", "div", "rem", "mod", "add", "sub", None, None], + "math_type": type_tt, + "math_types": etype_tt, + }, +} +memset_formats = { + "opcode": "OP_MEMSET_{op_memset[oo].upper()}", + "mnemonic": "memset.{op_memset[oo]}", + "opname": "memset{suff_memset[oo]}", + "format": "{memset_fmt[oo]}", + "widths": "{memset_widths[oo]}", + "types": "{memset_types[oo]}", + "args": { + "op_memset": ["i", "p", "pi", None], + "suff_memset": ["", "p", "p", None], + "memset_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], + "memset_widths": [ + "1, 0, -1", + "1, 1, 1", + "1, 0, 1", + None, + ], + "memset_types": [ + "ev_int, ev_short, ev_void", + "ev_int, ev_int, ev_ptr", + "ev_int, ev_short, ev_ptr", + ], + }, +} +move_formats = { + "opcode": "OP_MOVE_{op_move[oo].upper()}", + "mnemonic": "move.{op_move[oo]}", + "opname": "move{suff_move[oo]}", + "format": "{move_fmt[oo]}", + "widths": "{move_widths[oo]}", + "types": "{move_types[oo]}", + "args": { + "op_move": ["i", "p", "pi", None], + "suff_move": ["", "p", "p", None], + "move_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], + "move_widths": [ + "-1, 0, -1", + "1, 1, 1", + "1, 0, 1", + None, + ], + "move_types": [ + "ev_void, ev_short, ev_void", + "ev_ptr, ev_int, ev_ptr", + "ev_ptr, ev_short, ev_ptr", + ], + }, +} +noop_formats = { + "opcode": "OP_NOP", + "mnemonic": "nop", + "opname": "nop", + "format": "there were plums...", + "widths": "0, 0, 0", + "types": "ev_invalid, ev_invalid, ev_invalid", +} +push_formats = { + "opcode": "OP_PUSH_{op_mode[mm]}_{ss+1}", + "mnemonic": "push", + "opname": "push", + "format": "{push_fmt[mm]}", + "widths": "{ss+1}, 0, 0", + "types": "{push_types[mm]}, ev_invalid", + "args": { + "op_mode": address_mode, + "push_fmt": load_fmt, + "push_types": address_types, + }, +} +pop_formats = { + "opcode": "OP_POP_{op_mode[mm]}_{ss+1}", + "mnemonic": "pop", + "opname": "pop", + "format": "{pop_fmt[mm]}", + "widths": "{ss+1}, 0, 0", + "types": "{pop_types[mm]}, ev_invalid", + "args": { + "op_mode": address_mode, + "pop_fmt": store_fmt, + "pop_types": address_types, + }, +} +scale_formats = { + "opcode": "OP_SCALE_{scale_type[t]}_{ss+1}", + "mnemonic": "scale.{scale_type[t]}", + "opname": "scale", + "widths": "{ss+1}, 1, {ss+1}", + "types": "{scale_types[t]}, {scale_types[t]}, {scale_types[t]}", + "args": { + "scale_type": ['F', 'D'], + "scale_types": float_t, + }, +} +shiftops_formats = { + "opcode": "OP_{mn_shift[u*2+r].upper()}_{shift_type[u*2+t]}_{ss+1}", + "mnemonic": "{mn_shift[u*2+r]}.{shift_type[u*2+t]}", + "opname": "{op_shift[u*2+r]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{shift_types[t][u]}, {shift_types[t][0]}, {shift_types[t][u]}", + "args": { + "mn_shift": ["shl", "asr", "shl", "shr"], + "op_shift": ["shl", "shr", "shl", "shr"], + "shift_type": ['I', 'L', 'u', 'U'], + "shift_types": [ + ["ev_int", "ev_uint"], + ["ev_long", "ev_ulong"], + ], + }, +} +statef_formats = { + "opcode": "OP_STATE_{state[c]}", + "mnemonic": "state.{state[c]}", + "opname": "state", + "format": "{state_fmt[c]}", + "widths": "1, 1, {c}", + "types": "ev_float, ev_func, {state_types[c]}", + "args": { + "state": ["ft", "ftt"], + "state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"], + "state_types": ["ev_invalid", "ev_float"], + }, +} +stated_formats = { + "opcode": "OP_STATE_{state[c]}", + "mnemonic": "state.{state[c]}", + "opname": "state", + "format": "{state_fmt[c]}", + "widths": "1, 1, {c}", + "types": "ev_int, ev_func, {state_types[c]}", + "args": { + "state": ["dt", "dtt"], + "state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"], + "state_types": ["ev_invalid", "ev_double"], + }, +} +store_formats = { + "opcode": "OP_STORE_{op_mode[mm]}_{ss+1}", + "mnemonic": "{store_op[mm]}", + "opname": "{store_op[mm]}", + "format": "%Gc, {store_fmt[mm]}", + "widths": "{store_widths[ss][mm]}, {ss+1}", + "types": "{store_types[mm]}, ev_void", + "args": { + "op_mode": address_mode, + "store_fmt": store_fmt, + "store_op": ["assign", "store", "store", "store"], + "store_types": address_types, + "store_widths": address_widths, + }, +} +store64_formats = { + "opcode": "OP_STORE64_{op_mode[mm]}_{s+3}", + "mnemonic": "{store_op[mm]}64", + "opname": "{store_op[mm]}64", + "format": "%Gc, {store_fmt[mm]}", + "widths": "{store_widths[s+2][mm]}, {s+3}", + "types": "{store_types[mm]}, ev_void", + "args": { + "op_mode": address_mode, + "store_fmt": store_fmt, + "store_op": ["assign", "store", "store", "store"], + "store_types": address_types, + "store_widths": address_widths, + }, +} +string_formats = { + "opcode": "OP_{op_str[o*4+oo].upper()}_S", + "mnemonic": "{op_str[o*4+oo]}.s", + "opname": "{op_str[o*4+oo]}", + "format": "{str_fmt[o*4+oo]}", + "widths": "1, {(o*4+oo)<7 and 1 or 0}, 1", + "types": "{str_types[o*4+oo]}", + "args": { + "op_str": ["eq", "lt", "gt", "add", "cmp", "ge", "le", "not"], + "str_fmt": [ + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %gc", + ], + "str_types": [ + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_string", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", + "ev_string, ev_invalid, ev_int", + ], + }, +} +swizzle_formats = { + "opcode": "OP_SWIZZLE_{swiz_type[t]}", + "mnemonic": "swizzle.{swiz_type[t]}", + "opname": "swizzle", + "format": "%Ga %sb %gc", + "widths": "4, 0, 4", + "types": "{swizzle_types[t]}", + "args": { + "swiz_type": ['F', 'D'], + "swizzle_types": float_t, + }, +} +return_formats = { + "opcode": "OP_RETURN", + "mnemonic": "return", + "opname": "return", + "widths": "-1, -1, 0", # width specified by st->c + "format": "%Mc5", + "types": "ev_void, ev_void, ev_void", +} +udivops_formats = { + "opcode": "OP_{op_udiv[o].upper()}_{udiv_type[t]}_{ss+1}", + "mnemonic": "{op_udiv[o]}.{udiv_type[t]}", + "opname": "{op_udiv[o]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{udiv_types[t]}, {udiv_types[t]}, {udiv_types[t]}", + "args": { + "op_udiv": ["div", "rem"], + "udiv_type": ['u', 'U'], + "udiv_types": ["ev_uint", "ev_ulong"], + }, +} +vecops_formats = { + "opcode": "OP_{op_vop[ooo].upper()}_{vop_type[t]}", + "mnemonic": "{op_vop[ooo]}.{vop_type[t]}", + "opname": "{op_vop[ooo]}", + "widths": "{vec_widths[ooo]}", + "types": "{vec_types[t]}, {vec_types[t]}, {vec_types[t]}", + "args": { + "op_vop": ["cross", "cdot", "vdot", "qdot", + "cmul", "qvmul", "vqmul", "qmul"], + "vop_type": ['F', 'D'], + "vec_widths": [ + "3, 3, 3", + "2, 2, 2", + "3, 3, 3", + "4, 4, 4", + "2, 2, 2", + "4, 3, 3", + "3, 4, 3", + "4, 4, 4", + ], + "vec_types": float_t, + }, +} +vecops2_formats = { + "opcode": "OP_{op_vop[d].upper()}_{vop_type[t]}", + "mnemonic": "{op_vop[d]}.{vop_type[t]}", + "opname": "{op_vop[d]}", + "widths": "4, 4, 4", + "types": "{vec_types[t]}, {vec_types[t]}, {vec_types[t]}", + "args": { + "op_vop": ["qv4mul", "v4qmul"], + "vop_type": ['F', 'D'], + "vec_types": float_t, + }, +} +with_formats = { + "opcode": "OP_WITH", + "mnemonic": "with", + "opname": "with", + "format": "%sa, %sb, %sc", + "widths": "0, -1, 0", + "types": "ev_short, ev_void, ev_short", +} + +group_map = { + "adjstk": adjstk_formats, + "bitops": bitops_formats, + "branch": branch_formats, + "call": call_formats, + "compare": compare_formats, + "compare2": compare2_formats, + "constant": constant_formats, + "convert": convert_formats, + "fbitops": fbitops_formats, + "hops": hops_formats, + "jump": jump_formats, + "lea": lea_formats, + "load": load_formats, + "load64": load64_formats, + "mathops": mathops_formats, + "memset": memset_formats, + "move": move_formats, + "noop": noop_formats, + "push": push_formats, + "pop": pop_formats, + "scale": scale_formats, + "shiftops": shiftops_formats, + "statef": statef_formats, + "stated": stated_formats, + "store": store_formats, + "store64": store64_formats, + "string": string_formats, + "swizzle": swizzle_formats, + "return": return_formats, + "udivops": udivops_formats, + "vecops": vecops_formats, + "vecops2": vecops2_formats, + "with": with_formats, +} + +def parse_bits(bit_string): + bits = [""] + isbit = bit_string[0] in ['0', '1'] + lastbit = bit_string[0] + while bit_string: + bit = bit_string[0] + bit_string = bit_string[1:] + if isbit and bit in ['0', '1']: + bits[-1] = bits[-1] + bit + elif lastbit == bit: + bits[-1] = bits[-1] + bit + else: + bits.append(bit) + lastbit = bit + isbit = bit in ['0', '1'] + return bits + +opcodes = [None] * 512 + +def expand_opcodes(bits, group, num=0): + if not bits: + opcodes[num] = group + return + block = bits[0] + bits = bits[1:] + num <<= len(block) + if block[0] in ['0', '1']: + num |= int(block, 2) + expand_opcodes(bits, group, num) + else: + for n in range(1<pr_statements + pr->pr_xstatement; dfunction_t *desc = pr->pr_functions + G_FUNCTION (pr, st->a); - const char *bi_name = PR_GetString (pr, desc->s_name); + const char *bi_name = PR_GetString (pr, desc->name); int ind = -desc->first_statement; PR_RunError (pr, "Bad builtin called: %s = #%d", bi_name, ind); } VISIBLE void -PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) +PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins, void *data) { builtin_t *bi; int count; @@ -135,21 +135,25 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) builtins = bi; while (builtins->name) { - if (builtins->binum == 0 || builtins->binum >= PR_AUTOBUILTIN) + if (builtins->binum == 0 || builtins->binum >= PR_AUTOBUILTIN) { PR_Error (pr, "bad builtin number: %s = #%d", builtins->name, builtins->binum); + } - if (builtins->binum < 0) + if (builtins->binum < 0) { builtins->binum = builtin_next (pr); + } if ((bi = Hash_Find (pr->builtin_hash, builtins->name)) - || (bi = Hash_FindElement (pr->builtin_num_hash, builtins))) + || (bi = Hash_FindElement (pr->builtin_num_hash, builtins))) { PR_Error (pr, "builtin %s = #%d already defined (%s = #%d)", builtins->name, builtins->binum, bi->name, bi->binum); + } Hash_Add (pr->builtin_hash, builtins); Hash_AddElement (pr->builtin_num_hash, builtins); + builtins->data = data; builtins++; } @@ -184,24 +188,24 @@ PR_RelocateBuiltins (progs_t *pr) if (pr->function_table) free (pr->function_table); - pr->function_table = calloc (pr->progs->numfunctions, + pr->function_table = calloc (pr->progs->functions.count, sizeof (bfunction_t)); - for (i = 1; i < pr->progs->numfunctions; i++) { + for (i = 1; i < pr->progs->functions.count; i++) { desc = pr->pr_functions + i; func = pr->function_table + i; func->first_statement = desc->first_statement; - func->parm_start = desc->parm_start; + func->params_start = desc->params_start; func->locals = desc->locals; - func->numparms = desc->numparms; - memcpy (func->parm_size, desc->parm_size, sizeof (func->parm_size)); + func->numparams = desc->numparams; + memcpy (func->param_size, desc->param_size, sizeof (func->param_size)); func->descriptor = desc; if (desc->first_statement > 0) continue; - bi_name = PR_GetString (pr, desc->s_name); + bi_name = PR_GetString (pr, desc->name); if (!desc->first_statement) { bi = PR_FindBuiltin (pr, bi_name); @@ -225,12 +229,15 @@ PR_RelocateBuiltins (progs_t *pr) bi_name, -desc->first_statement); proc = bi_no_function; } - if (!desc->s_name && bi) { - desc->s_name = PR_SetString (pr, bi->name); + if (!desc->name && bi) { + desc->name = PR_SetString (pr, bi->name); Hash_Add (pr->function_hash, &pr->pr_functions[i]); } func->first_statement = desc->first_statement; func->func = proc; + if (bi) { + func->data = bi->data; + } } if (bad) { Sys_Printf ("PR_RelocateBuiltins: %s: progs may not work due to " diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f80913137..67f6b981e 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -42,21 +42,25 @@ #include #include #include +#include #include "QF/fbsearch.h" #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" -#include "QF/pr_debug.h" -#include "QF/pr_type.h" #include "QF/progs.h" #include "QF/qendian.h" #include "QF/quakefs.h" #include "QF/script.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/zone.h" +#include "QF/progs/pr_debug.h" +#include "QF/progs/pr_type.h" +#include "QF/simd/types.h" + #include "compat.h" typedef struct { @@ -89,11 +93,12 @@ typedef struct prdeb_resources_s { dstring_t *dva; dstring_t *line; dstring_t *dstr; + va_ctx_t *va; const char *debugfile; pr_debug_header_t *debug; pr_auxfunction_t *auxfunctions; pr_auxfunction_t **auxfunction_map; - func_t *sorted_functions; + pr_func_t *sorted_functions; pr_lineno_t *linenos; pr_def_t *local_defs; pr_def_t *type_encodings_def; @@ -117,32 +122,6 @@ cvar_t *pr_source_path; static char *source_path_string; static char **source_paths; -static void pr_debug_void_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_string_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_float_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_field_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_func_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_integer_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_short_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_double_view (qfot_type_t *type, pr_type_t *value, - void *_data); static void pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_union_view (qfot_type_t *type, pr_type_t *value, @@ -153,26 +132,20 @@ static void pr_debug_array_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_class_view (qfot_type_t *type, pr_type_t *value, void *_data); +#define EV_TYPE(t) \ + static void pr_debug_##t##_view (qfot_type_t *type, pr_type_t *value, \ + void *_data); +#include "QF/progs/pr_type_names.h" static type_view_t raw_type_view = { - pr_debug_void_view, - pr_debug_string_view, - pr_debug_float_view, - pr_debug_vector_view, - pr_debug_entity_view, - pr_debug_field_view, - pr_debug_func_view, - pr_debug_pointer_view, - pr_debug_quat_view, - pr_debug_integer_view, - pr_debug_uinteger_view, - pr_debug_short_view, - pr_debug_double_view, pr_debug_struct_view, pr_debug_union_view, pr_debug_enum_view, pr_debug_array_view, pr_debug_class_view, +#define EV_TYPE(t) \ + pr_debug_##t##_view, +#include "QF/progs/pr_type_names.h" }; static const char * @@ -261,7 +234,7 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) } return size; case ty_enum: - return pr_type_size[ev_integer]; + return pr_type_size[ev_int]; case ty_array: aux_type = &G_STRUCT (pr, qfot_type_t, type->array.type); size = pr_debug_type_size (pr, aux_type); @@ -348,7 +321,7 @@ parse_expression (progs_t *pr, const char *expr, int conditional) goto error; if (!Script_GetToken (es, 1)) goto error; - pr->wp_val.integer_var = strtol (es->token->str, &e, 0); + pr->wp_val.int_var = strtol (es->token->str, &e, 0); if (e == es->token->str) goto error; if (*e == '.' || *e == 'e' || *e == 'E') @@ -396,7 +369,7 @@ pr_debug_clear (progs_t *pr, void *data) pr->watch = 0; pr->wp_conditional = 0; - pr->wp_val.integer_var = 0; + pr->wp_val.int_var = 0; for (int i = 0; i < ev_type_count; i++ ) { res->type_encodings[i] = &res->void_type; @@ -494,10 +467,10 @@ func_compare_sort (const void *_fa, const void *_fb, void *_res) { prdeb_resources_t *res = _res; progs_t *pr = res->pr; - func_t fa = *(const func_t *)_fa; - func_t fb = *(const func_t *)_fb; - const char *fa_file = PR_GetString (pr, pr->pr_functions[fa].s_file); - const char *fb_file = PR_GetString (pr, pr->pr_functions[fb].s_file); + pr_func_t fa = *(const pr_func_t *)_fa; + pr_func_t fb = *(const pr_func_t *)_fb; + const char *fa_file = PR_GetString (pr, pr->pr_functions[fa].file); + const char *fb_file = PR_GetString (pr, pr->pr_functions[fb].file); int cmp = strcmp (fa_file, fb_file); if (cmp) { return cmp; @@ -515,8 +488,8 @@ func_compare_search (const void *_key, const void *_f, void *_res) prdeb_resources_t *res = _res; progs_t *pr = res->pr; const func_key_t *key = _key; - func_t f = *(const func_t *)_f; - const char *f_file = PR_GetString (pr, pr->pr_functions[f].s_file); + pr_func_t f = *(const pr_func_t *)_f; + const char *f_file = PR_GetString (pr, pr->pr_functions[f].file); int cmp = strcmp (key->file, f_file); if (cmp) { return cmp; @@ -538,18 +511,18 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) res->debug_data = (pr_type_t*)((char*)debug + debug->debug_data); size_t size; - size = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); + size = pr->progs->functions.count * sizeof (pr_auxfunction_t *); res->auxfunction_map = pr->allocate_progs_mem (pr, size); - size = pr->progs->numfunctions * sizeof (func_t); + size = pr->progs->functions.count * sizeof (pr_func_t); res->sorted_functions = pr->allocate_progs_mem (pr, size); - for (pr_uint_t i = 0; i < pr->progs->numfunctions; i++) { + for (pr_uint_t i = 0; i < pr->progs->functions.count; i++) { res->auxfunction_map[i] = 0; res->sorted_functions[i] = i; } qfot_type_encodings_t *encodings = 0; - pointer_t type_encodings = 0; + pr_ptr_t type_encodings = 0; res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); if (res->type_encodings_def) { encodings = &G_STRUCT (pr, qfot_type_encodings_t, @@ -564,8 +537,8 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) res->auxfunction_map[res->auxfunctions[i].function] = &res->auxfunctions[i]; } - qsort_r (res->sorted_functions, pr->progs->numfunctions, sizeof (func_t), - func_compare_sort, res); + qsort_r (res->sorted_functions, pr->progs->functions.count, + sizeof (pr_func_t), func_compare_sort, res); for (pr_uint_t i = 0; i < debug->num_locals; i++) { if (type_encodings) { @@ -573,7 +546,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) } } - string_t compunit_str = PR_FindString (pr, ".compile_unit"); + pr_string_t compunit_str = PR_FindString (pr, ".compile_unit"); for (pr_uint_t i = 0; i < debug->num_debug_defs; i++) { pr_def_t *def = &res->debug_defs[i]; if (type_encodings) { @@ -587,7 +560,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) if (encodings) { qfot_type_t *type; - for (pointer_t type_ptr = 4; type_ptr < encodings->size; + for (pr_ptr_t type_ptr = 4; type_ptr < encodings->size; type_ptr += type->size) { type = &G_STRUCT (pr, qfot_type_t, type_encodings + type_ptr); if (type->meta == ty_basic @@ -722,7 +695,7 @@ VISIBLE pr_auxfunction_t * PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) { prdeb_resources_t *res = pr->pr_debug_resources; - if (!res->debug || func >= pr->progs->numfunctions) { + if (!res->debug || func >= pr->progs->functions.count) { return 0; } return res->auxfunction_map[func]; @@ -829,15 +802,15 @@ PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) { prdeb_resources_t *res = pr->pr_debug_resources; func_key_t key = { file, line }; - func_t *f = fbsearch_r (&key, res->sorted_functions, - pr->progs->numfunctions, sizeof (func_t), + pr_func_t *f = fbsearch_r (&key, res->sorted_functions, + pr->progs->functions.count, sizeof (pr_func_t), func_compare_search, res); if (!f) { return 0; } dfunction_t *func = &pr->pr_functions[*f]; if (func->first_statement <= 0 - || strcmp (file, PR_GetString (pr, func->s_file)) != 0) { + || strcmp (file, PR_GetString (pr, func->file)) != 0) { return 0; } pr_auxfunction_t *aux = res->auxfunction_map[*f]; @@ -867,9 +840,9 @@ PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) pr_auxfunction_t *f; f = PR_Get_Lineno_Func (pr, lineno); - if (f->function >= (unsigned) pr->progs->numfunctions) + if (f->function >= (unsigned) pr->progs->functions.count) return 0; - return PR_GetString(pr, pr->pr_functions[f->function].s_file); + return PR_GetString(pr, pr->pr_functions[f->function].file); } const char * @@ -903,7 +876,7 @@ PR_Get_Source_Line (progs_t *pr, pr_uint_t addr) } pr_def_t * -PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) +PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned param) { prdeb_resources_t *res = pr->pr_debug_resources; pr_uint_t i; @@ -917,12 +890,12 @@ PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) if (!func) return 0; - num_params = func->numparms; + num_params = func->numparams; if (num_params < 0) { num_params = ~num_params; // one's compliment param_offs = 1; // skip over @args def } - if (parm >= (unsigned) num_params) + if (param >= (unsigned) num_params) return 0; aux_func = res->auxfunction_map[func - pr->pr_functions]; @@ -931,7 +904,7 @@ PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) for (i = 0; i < aux_func->num_locals; i++) { ddef = &res->local_defs[aux_func->local_defs + param_offs + i]; - if (!parm--) + if (!param--) break; } return ddef; @@ -960,12 +933,12 @@ get_type (prdeb_resources_t *res, int typeptr) } pr_def_t * -PR_Get_Local_Def (progs_t *pr, pointer_t *offset) +PR_Get_Local_Def (progs_t *pr, pr_ptr_t *offset) { prdeb_resources_t *res = pr->pr_debug_resources; dfunction_t *func; pr_auxfunction_t *aux_func; - pointer_t offs = *offset; + pr_ptr_t offs = *offset; pr_def_t *def; if (!pr->pr_xfunction) @@ -976,7 +949,19 @@ PR_Get_Local_Def (progs_t *pr, pointer_t *offset) aux_func = res->auxfunction_map[func - pr->pr_functions]; if (!aux_func) return 0; - offs -= func->parm_start; + + pr_ptr_t locals_start; + if (pr->progs->version == PROG_VERSION) { + if (pr->pr_depth) { + prstack_t *frame = pr->pr_stack + pr->pr_depth - 1; + locals_start = frame->stack_ptr - func->params_start; + } else { + locals_start = 0; //FIXME ? when disassembling in qfprogs + } + } else { + locals_start = func->params_start; + } + offs -= locals_start; if (offs >= func->locals) return 0; if ((def = PR_SearchDefs (res->local_defs + aux_func->local_defs, @@ -1015,51 +1000,18 @@ PR_DumpState (progs_t *pr) #define ISDENORM(x) ((x) && !((x) & 0x7f800000)) -static const char * +static void value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) { switch (type->meta) { case ty_basic: switch (type->type) { - case ev_void: - raw_type_view.void_view (type, value, data); - break; - case ev_string: - raw_type_view.string_view (type, value, data); - break; - case ev_float: - raw_type_view.float_view (type, value, data); - break; - case ev_vector: - raw_type_view.vector_view (type, value, data); - break; - case ev_entity: - raw_type_view.entity_view (type, value, data); - break; - case ev_field: - raw_type_view.field_view (type, value, data); - break; - case ev_func: - raw_type_view.func_view (type, value, data); - break; - case ev_pointer: - raw_type_view.pointer_view (type, value, data); - break; - case ev_quat: - raw_type_view.quat_view (type, value, data); - break; - case ev_integer: - raw_type_view.integer_view (type, value, data); - break; - case ev_uinteger: - raw_type_view.uinteger_view (type, value, data); - break; - case ev_short: - raw_type_view.short_view (type, value, data); - break; - case ev_double: - raw_type_view.double_view (type, value, data); +#define EV_TYPE(t) \ + case ev_##t: \ + raw_type_view.t##_view (type, value, data); \ break; +#include "QF/progs/pr_type_names.h" + case ev_invalid: case ev_type_count: dstring_appendstr (data->dstr, ""); @@ -1082,23 +1034,23 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) break; case ty_alias://XXX type = &G_STRUCT (data->pr, qfot_type_t, type->alias.aux_type); - return value_string (data, type, value); + value_string (data, type, value); + break; } - return data->dstr->str; } static pr_def_t * -pr_debug_find_def (progs_t *pr, pointer_t *ofs) +pr_debug_find_def (progs_t *pr, pr_ptr_t *ofs) { prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t *def = 0; - if (*ofs >= pr->progs->numglobals) { - return 0; - } if (pr_debug->int_val && res->debug) { def = PR_Get_Local_Def (pr, ofs); } + if (*ofs >= pr->progs->globals.count) { + return 0; + } if (!def) { def = PR_GlobalAtOfs (pr, *ofs); if (def) { @@ -1109,7 +1061,7 @@ pr_debug_find_def (progs_t *pr, pointer_t *ofs) } static const char * -global_string (pr_debug_data_t *data, pointer_t offset, qfot_type_t *type, +global_string (pr_debug_data_t *data, pr_ptr_t offset, qfot_type_t *type, int contents) { progs_t *pr = data->pr; @@ -1118,7 +1070,7 @@ global_string (pr_debug_data_t *data, pointer_t offset, qfot_type_t *type, pr_def_t *def = NULL; qfot_type_t dummy_type = { }; const char *name = 0; - pointer_t offs = offset; + pr_ptr_t offs = offset; dstring_clearstr (dstr); @@ -1184,7 +1136,7 @@ pr_debug_string_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - string_t string = value->string_var; + pr_string_t string = value->string_var; if (PR_StringValid (data->pr, string)) { const char *str = PR_GetString (data->pr, string); @@ -1228,9 +1180,9 @@ pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_t *dstr = data->dstr; if (data->pr->progs->version == PROG_ID_VERSION - && ISDENORM (value->integer_var) - && value->uinteger_var != 0x80000000) { - dasprintf (dstr, "<%08x>", value->integer_var); + && ISDENORM (value->int_var) + && value->uint_var != 0x80000000) { + dasprintf (dstr, "<%08x>", value->int_var); } else { dasprintf (dstr, "%.9g", value->float_var); } @@ -1252,7 +1204,7 @@ pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (pr->pr_edicts && value->entity_var >= 0 + if (pr->pr_edicts && value->entity_var < pr->max_edicts && !(value->entity_var % pr->pr_edict_size)) { edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); @@ -1270,12 +1222,12 @@ pr_debug_field_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pr_def_t *def = PR_FieldAtOfs (pr, value->integer_var); + pr_def_t *def = PR_FieldAtOfs (pr, value->int_var); if (def) { dasprintf (dstr, ".%s", PR_GetString (pr, def->name)); } else { - dasprintf (dstr, ".<$%04x>", value->integer_var); + dasprintf (dstr, ".<$%04x>", value->int_var); } } @@ -1286,24 +1238,24 @@ pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (value->func_var >= pr->progs->numfunctions) { + if (value->func_var >= pr->progs->functions.count) { dasprintf (dstr, "INVALID:%d", value->func_var); } else if (!value->func_var) { dstring_appendstr (dstr, "NULL"); } else { dfunction_t *f = pr->pr_functions + value->func_var; - dasprintf (dstr, "%s()", PR_GetString (pr, f->s_name)); + dasprintf (dstr, "%s()", PR_GetString (pr, f->name)); } } static void -pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_ptr_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pointer_t offset = value->integer_var; - pointer_t offs = offset; + pr_ptr_t offset = value->int_var; + pr_ptr_t offs = offset; pr_def_t *def = 0; def = pr_debug_find_def (pr, &offs); @@ -1319,7 +1271,7 @@ pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) } static void -pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_quaternion_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; @@ -1328,21 +1280,21 @@ pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) } static void -pr_debug_integer_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_int_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%d", value->integer_var); + dasprintf (dstr, "%d", value->int_var); } static void -pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_uint_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "$%08x", value->uinteger_var); + dasprintf (dstr, "$%08x", value->uint_var); } static void @@ -1351,7 +1303,7 @@ pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%04x", (short)value->integer_var); + dasprintf (dstr, "%04x", (short)value->int_var); } static void @@ -1363,6 +1315,33 @@ pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data) dasprintf (dstr, "%.17g", *(double *)value); } +static void +pr_debug_long_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%" PRIi64, *(int64_t *)value); +} + +static void +pr_debug_ulong_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%" PRIu64, *(uint64_t *)value); +} + +static void +pr_debug_ushort_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%04x", (pr_ushort_t)value->int_var); +} + static void pr_dump_struct (qfot_type_t *type, pr_type_t *value, void *_data, const char *struct_type) @@ -1436,7 +1415,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) (int) (intptr_t) (pr->watch - pr->pr_globals)); if (pr->wp_conditional) Sys_Printf (" if new val == %d\n", - pr->wp_val.integer_var); + pr->wp_val.int_var); } else { Sys_Printf (" none active\n"); } return; @@ -1449,7 +1428,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) if (pr->watch) { Sys_Printf ("watchpoint set to [%d]\n", PR_SetPointer (pr, pr->watch)); if (pr->wp_conditional) - Sys_Printf (" if new val == %d\n", pr->wp_val.integer_var); + Sys_Printf (" if new val == %d\n", pr->wp_val.int_var); } else { Sys_Printf ("watchpoint cleared\n"); } @@ -1475,6 +1454,18 @@ PR_Debug_Print (progs_t *pr, const char *expr) } } +static const char * +print_raw_op (progs_t *pr, pr_ushort_t op, pr_ushort_t base_ind, + etype_t op_type, int op_width) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + const char *width = va (res->va, "%d", op_width); + return va (res->va, "%d:%04x<%08x>%s:%-8s", + base_ind, op, op + pr->pr_bases[base_ind], + op_width > 0 ? width : op_width < 0 ? "X" : "?", + pr_type_name[op_type]); +} + VISIBLE void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) { @@ -1482,11 +1473,13 @@ 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 char *mnemonic; dfunction_t *call_func = 0; - pr_def_t *parm_def = 0; + pr_def_t *param_def = 0; pr_auxfunction_t *aux_func = 0; pr_debug_data_t data; + etype_t op_type[3]; + int op_width[3]; dstring_clearstr (res->line); @@ -1508,24 +1501,54 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) return; } - op = PR_Opcode (s->op); - if (!op) { - Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); - return; + if (pr->progs->version < PROG_VERSION) { + const v6p_opcode_t *op = PR_v6p_Opcode (s->op); + if (!op) { + Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); + return; + } + VectorSet (op->type_a, op->type_b, op->type_c, op_type); + VectorSet (1, 1, 1, op_width); + fmt = op->fmt; + mnemonic = op->opname; + } else { + const opcode_t *op = PR_Opcode (s->op); + if (!op) { + Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); + return; + } + VectorCopy (op->widths, op_width); + VectorCopy (op->types, op_type); + fmt = op->fmt; + mnemonic = op->mnemonic; } - if (!(fmt = op->fmt)) + if (!fmt) { fmt = "%Ga, %Gb, %gc"; + } dasprintf (res->line, "%04x ", addr); - if (pr_debug->int_val > 2) - dasprintf (res->line, "%02x %04x(%8s) %04x(%8s) %04x(%8s)\t", - s->op, - s->a, pr_type_name[op->type_a], - s->b, pr_type_name[op->type_b], - s->c, pr_type_name[op->type_c]); + if (pr_debug->int_val > 2) { + if (pr->progs->version < PROG_VERSION) { + dasprintf (res->line, + "%03x %04x(%8s) %04x(%8s) %04x(%8s)\t", + s->op, + s->a, pr_type_name[op_type[0]], + s->b, pr_type_name[op_type[1]], + s->c, pr_type_name[op_type[2]]); + } else { + dasprintf (res->line, "%04x %s %s %s\t", + s->op, + print_raw_op (pr, s->a, PR_BASE_IND (s->op, A), + op_type[0], op_width[0]), + print_raw_op (pr, s->b, PR_BASE_IND (s->op, B), + op_type[0], op_width[0]), + print_raw_op (pr, s->c, PR_BASE_IND (s->op, C), + op_type[0], op_width[0])); + } + } - dasprintf (res->line, "%s ", op->opname); + dasprintf (res->line, "%s ", mnemonic); while (*fmt) { if (*fmt == '%') { @@ -1535,38 +1558,57 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) } else { const char *str; char mode = fmt[1], opchar = fmt[2]; - unsigned parm_ind = 0; - pr_int_t opval; + unsigned param_ind = 0; + pr_uint_t shift = 0; + pr_uint_t opreg; + pr_uint_t opval; qfot_type_t *optype = &res->void_type; - func_t func; + pr_func_t func; if (mode == 'P') { opchar = fmt[3]; - parm_ind = fmt[2] - '0'; + param_ind = fmt[2] - '0'; fmt++; // P has one extra item - if (parm_ind >= MAX_PARMS) + if (param_ind >= PR_MAX_PARAMS) goto err; } + if (mode == 'M' || mode == 'm') { + if (!isxdigit (fmt[3])) { + goto err; + } + shift = fmt[3]; + shift = (shift & 0xf) + + (((shift & 0x40) >> 3) | ((shift & 0x40) >> 5)); + fmt++; // M/m have one extra item + } switch (opchar) { case 'a': + opreg = PR_BASE_IND (s->op, A); opval = s->a; - optype = res->type_encodings[op->type_a]; + optype = res->type_encodings[op_type[0]]; break; case 'b': + opreg = PR_BASE_IND (s->op, B); opval = s->b; - optype = res->type_encodings[op->type_b]; + optype = res->type_encodings[op_type[1]]; break; case 'c': + opreg = PR_BASE_IND (s->op, C); opval = s->c; - optype = res->type_encodings[op->type_c]; + optype = res->type_encodings[op_type[2]]; + break; + case 'o': + opreg = 0; + opval = s->op; break; case 'x': if (mode == 'P') { - opval = pr->pr_real_params[parm_ind] + opval = pr->pr_real_params[param_ind] - pr->pr_globals; break; } + goto err; default: goto err; } @@ -1584,28 +1626,31 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) str = global_string (&data, opval, optype, contents & 1); func = G_FUNCTION (pr, opval); - if (func < pr->progs->numfunctions) { + if (func < pr->progs->functions.count) { call_func = pr->pr_functions + func; } break; case 'P': - parm_def = PR_Get_Param_Def (pr, call_func, parm_ind); + param_def = PR_Get_Param_Def (pr, call_func, param_ind); optype = &res->void_type; - if (parm_def) { - optype = get_type (res, parm_def->type_encoding); + if (param_def) { + optype = get_type (res, param_def->type_encoding); } str = global_string (&data, opval, optype, contents & 1); break; case 'V': + opval += pr->pr_bases[opreg]; str = global_string (&data, opval, ev_void, contents & 1); break; case 'G': + opval += pr->pr_bases[opreg]; str = global_string (&data, opval, optype, contents & 1); break; case 'g': + opval += pr->pr_bases[opreg]; str = global_string (&data, opval, optype, 0); break; case 's': @@ -1615,16 +1660,19 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) str = dsprintf (res->dva, "%04x", addr + (short) opval); break; + case 'C': + str = dsprintf (res->dva, "%03o", opval); + break; case 'E': { edict_t *ed = 0; opval = pr->pr_globals[s->a].entity_var; - parm_ind = pr->pr_globals[s->b].uinteger_var; - if (parm_ind < pr->progs->entityfields + param_ind = pr->pr_globals[s->b].uint_var; + if (param_ind < pr->progs->entityfields && opval > 0 && opval < pr->pr_edict_area_size) { ed = PROG_TO_EDICT (pr, opval); - opval = &E_fld(ed, parm_ind) - pr->pr_globals; + opval = &E_fld(ed, param_ind) - pr->pr_globals; } if (!ed) { str = "bad entity.field"; @@ -1636,6 +1684,34 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) s->a, s->b, str); } break; + case 'M': + case 'm': + { + pr_ptr_t ptr = 0; + pr_int_t offs = 0; + switch ((opval >> shift) & 3) { + case 0: + ptr = s->a + PR_BASE (pr, s, A); + break; + case 1: + break; + case 2: + ptr = s->a + PR_BASE (pr, s, A); + ptr = G_POINTER (pr, ptr); + offs = (short) s->b; + break; + case 3: + ptr = s->a + PR_BASE (pr, s, A); + ptr = G_POINTER (pr, ptr); + offs = s->b + PR_BASE (pr, s, B); + offs = G_INT (pr, offs); + break; + } + ptr += offs; + str = global_string (&data, ptr, optype, + mode == 'M'); + } + break; default: goto err; } @@ -1668,25 +1744,25 @@ dump_frame (progs_t *pr, prstack_t *frame) pr_lineno_t *lineno = PR_Find_Lineno (pr, frame->staddr); pr_auxfunction_t *func = PR_Get_Lineno_Func (pr, lineno); pr_uint_t line = PR_Get_Lineno_Line (pr, lineno); - pr_int_t addr = PR_Get_Lineno_Addr (pr, lineno); + pr_uint_t addr = PR_Get_Lineno_Addr (pr, lineno); line += func->source_line; if (addr == frame->staddr) { Sys_Printf ("%12s:%u : %s: %x\n", - PR_GetString (pr, f->s_file), + PR_GetString (pr, f->file), line, - PR_GetString (pr, f->s_name), + PR_GetString (pr, f->name), frame->staddr); } else { Sys_Printf ("%12s:%u+%d : %s: %x\n", - PR_GetString (pr, f->s_file), + PR_GetString (pr, f->file), line, frame->staddr - addr, - PR_GetString (pr, f->s_name), + PR_GetString (pr, f->name), frame->staddr); } } else { - Sys_Printf ("%12s : %s: %x\n", PR_GetString (pr, f->s_file), - PR_GetString (pr, f->s_name), frame->staddr); + Sys_Printf ("%12s : %s: %x\n", PR_GetString (pr, f->file), + PR_GetString (pr, f->name), frame->staddr); } } @@ -1711,15 +1787,21 @@ PR_StackTrace (progs_t *pr) VISIBLE void PR_Profile (progs_t * pr) { - pr_uint_t max, num, i; + pr_ulong_t max, num, i; + pr_ulong_t total; dfunction_t *f; bfunction_t *best, *bf; num = 0; + total = 0; + for (i = 0; i < pr->progs->functions.count; i++) { + bf = &pr->function_table[i]; + total += bf->profile; + } do { max = 0; best = NULL; - for (i = 0; i < pr->progs->numfunctions; i++) { + for (i = 0; i < pr->progs->functions.count; i++) { bf = &pr->function_table[i]; if (bf->profile > max) { max = bf->profile; @@ -1729,13 +1811,15 @@ PR_Profile (progs_t * pr) if (best) { if (num < 10) { f = pr->pr_functions + (best - pr->function_table); - Sys_Printf ("%7i %s\n", best->profile, - PR_GetString (pr, f->s_name)); + Sys_Printf ("%7"PRIu64" %s%s\n", best->profile, + PR_GetString (pr, f->name), + f->first_statement < 0 ? " (builtin)" : ""); } num++; best->profile = 0; } } while (best); + Sys_Printf ("total: %7"PRIu64"\n", total); } static void @@ -1791,7 +1875,7 @@ ED_Print (progs_t *pr, edict_t *ed, const char *fieldname) } return; } - for (i = 0; i < pr->progs->numfielddefs; i++) { + for (i = 0; i < pr->progs->fielddefs.count; i++) { d = &pr->pr_fielddefs[i]; if (!d->name) // null field def (probably 1st) continue; @@ -1824,6 +1908,7 @@ PR_Debug_Init (progs_t *pr) res->dva = dstring_newstr (); res->line = dstring_newstr (); res->dstr = dstring_newstr (); + res->va = va_create_context (8); res->void_type.meta = ty_basic; res->void_type.size = 4; diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 60233a0ce..34c132b20 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -68,7 +68,7 @@ ED_ClearEdict (progs_t *pr, edict_t *e, int val) VISIBLE edict_t * ED_Alloc (progs_t *pr) { - pr_int_t i; + pr_uint_t i; edict_t *e; int start = pr->reserved_edicts ? *pr->reserved_edicts : 0; @@ -79,9 +79,9 @@ ED_Alloc (progs_t *pr) e = EDICT_NUM (pr, i); // the first couple seconds of server time can involve a lot of // freeing and allocating, so relax the replacement policy - if (e->free && (!pr->globals.time + if (e->free && (!pr->globals.ftime//FIXME double time || e->freetime < 2 - || *pr->globals.time - e->freetime > 0.5)) { + || *pr->globals.ftime - e->freetime > 0.5)) { ED_ClearEdict (pr, e, 0); return e; } @@ -123,8 +123,8 @@ ED_Free (progs_t *pr, edict_t *ed) ED_ClearEdict (pr, ed, 0); } ed->free = true; - if (pr->globals.time) - ed->freetime = *pr->globals.time; + if (pr->globals.ftime)//FIXME double time + ed->freetime = *pr->globals.ftime; } //=========================================================================== @@ -149,7 +149,7 @@ ED_PrintNum (progs_t *pr, pr_int_t ent, const char *fieldname) VISIBLE void ED_PrintEdicts (progs_t *pr, const char *fieldval) { - pr_int_t i; + pr_uint_t i; int count; pr_def_t *def; @@ -183,7 +183,6 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval) VISIBLE void ED_Count (progs_t *pr) { - pr_int_t i; int active, models, solid, step, zombie; pr_def_t *solid_def; pr_def_t *model_def; @@ -196,10 +195,10 @@ ED_Count (progs_t *pr) solid_def = PR_FindField (pr, "solid"); model_def = PR_FindField (pr, "model"); active = models = solid = step = zombie = 0; - for (i = 0; i < *pr->num_edicts; i++) { + for (pr_uint_t i = 0; i < *pr->num_edicts; i++) { ent = EDICT_NUM (pr, i); if (ent->free) { - if (pr->globals.time && *pr->globals.time - ent->freetime <= 0.5) + if (pr->globals.ftime && *pr->globals.ftime - ent->freetime <= 0.5)//FIXME double time zombie++; continue; } @@ -218,22 +217,22 @@ ED_Count (progs_t *pr) } edict_t * -ED_EdictNum (progs_t *pr, pr_int_t n) +ED_EdictNum (progs_t *pr, pr_uint_t n) { - if (n < 0 || n >= *pr->num_edicts) + if (n >= *pr->num_edicts) PR_RunError (pr, "EDICT_NUM: bad number %d", n); return PR_edicts(pr) + n; } -pr_int_t +pr_uint_t ED_NumForEdict (progs_t *pr, edict_t *e) { - pr_int_t b; + pr_uint_t b; b = NUM_FOR_BAD_EDICT (pr, e); - if (b && (b < 0 || b >= *pr->num_edicts)) + if (b && b >= *pr->num_edicts) PR_RunError (pr, "NUM_FOR_EDICT: bad pointer %d %p %p", b, e, pr->pr_edicts); @@ -241,12 +240,12 @@ ED_NumForEdict (progs_t *pr, edict_t *e) } qboolean -PR_EdictValid (progs_t *pr, pr_int_t e) +PR_EdictValid (progs_t *pr, pr_uint_t e) { if (!pr->num_edicts) { return false; } - if (e < 0 || e >= pr->pr_edict_area_size) + if (e >= pr->pr_edict_area_size) return false; if (e % pr->pr_edict_size) return false; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 09d8b9fc8..c24d35bcf 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -44,8 +44,26 @@ #include "QF/sys.h" #include "QF/zone.h" +#include "QF/simd/vec2d.h" +#include "QF/simd/vec2f.h" +#include "QF/simd/vec2i.h" +#include "QF/simd/vec4d.h" +#include "QF/simd/vec4f.h" +#include "QF/simd/vec4i.h" #include "compat.h" +const char *prdebug_names[] = { + [prd_none] = "none", + [prd_trace] = "trace", + [prd_breakpoint] = "breakpoint", + [prd_watchpoint] = "watchpoint", + [prd_subenter] = "subenter", + [prd_subexit] = "subexit", + [prd_begin] = "begin", + [prd_terminate] = "terminate", + [prd_runerror] = "runerror", + [prd_error] = "error", +}; /* PR_RunError @@ -119,14 +137,19 @@ PR_PushFrame (progs_t *pr) { prstack_t *frame; - if (pr->pr_depth == MAX_STACK_DEPTH) + if (pr->pr_depth == PR_MAX_STACK_DEPTH) PR_RunError (pr, "stack overflow"); frame = pr->pr_stack + pr->pr_depth++; frame->staddr = pr->pr_xstatement; + if (pr->globals.stack) { + frame->stack_ptr = *pr->globals.stack; + } + frame->bases = pr->pr_bases; frame->func = pr->pr_xfunction; frame->tstr = pr->pr_xtstr; + frame->return_ptr = pr->pr_return; pr->pr_xtstr = pr->pr_pushtstr; pr->pr_pushtstr = 0; @@ -158,15 +181,21 @@ PR_PopFrame (progs_t *pr) // up stack frame = pr->pr_stack + --pr->pr_depth; + pr->pr_return = frame->return_ptr; pr->pr_xfunction = frame->func; pr->pr_xstatement = frame->staddr; pr->pr_xtstr = frame->tstr; + pr->pr_bases = frame->bases; + // restore data stack (discard any locals) + if (pr->globals.stack) { + *pr->globals.stack = frame->stack_ptr; + } } static __attribute__((pure)) long -align_offset (long offset, dparmsize_t parmsize) +align_offset (long offset, dparmsize_t paramsize) { - int mask = (1 << parmsize.alignment) - 1; + int mask = (1 << paramsize.alignment) - 1; return (offset + mask) & ~mask; } @@ -190,87 +219,94 @@ static void PR_EnterFunction (progs_t *pr, bfunction_t *f) { pr_int_t i; - pr_type_t *dstParams[MAX_PARMS]; - pointer_t paramofs = 0; + pr_type_t *dstParams[PR_MAX_PARAMS]; + pr_ptr_t paramofs = 0; if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Entering function %s\n", - PR_GetString (pr, f->descriptor->s_name)); + PR_GetString (pr, f->descriptor->name)); } PR_PushFrame (pr); - if (f->numparms > 0) { - paramofs = f->parm_start; - for (i = 0; i < f->numparms; i++) { - paramofs = align_offset (paramofs, f->parm_size[i]); + //Sys_Printf("%s:\n", PR_GetString(pr,f->name)); + pr->pr_xfunction = f; + pr->pr_xstatement = f->first_statement - 1; // offset the st++ + + if (pr->progs->version == PROG_VERSION) { + return; + } + + if (f->numparams > 0) { + paramofs = f->params_start; + for (i = 0; i < f->numparams; i++) { + paramofs = align_offset (paramofs, f->param_size[i]); dstParams[i] = pr->pr_globals + paramofs; - paramofs += f->parm_size[i].size; + paramofs += f->param_size[i].size; if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], - f->parm_size[i].size); + f->param_size[i].size); pr->pr_params[i] = pr->pr_real_params[i]; } } - } else if (f->numparms < 0) { - paramofs = f->parm_start + 2; // argc and argv - for (i = 0; i < -f->numparms - 1; i++) { - paramofs = align_offset (paramofs, f->parm_size[i]); + } else if (f->numparams < 0) { + paramofs = f->params_start + 2; // argc and argv + for (i = 0; i < -f->numparams - 1; i++) { + paramofs = align_offset (paramofs, f->param_size[i]); dstParams[i] = pr->pr_globals + paramofs; - paramofs += f->parm_size[i].size; + paramofs += f->param_size[i].size; if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], - f->parm_size[i].size); + f->param_size[i].size); pr->pr_params[i] = pr->pr_real_params[i]; } } - dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment }; - paramofs = align_offset (paramofs, parmsize ); - if (i < MAX_PARMS) { + dparmsize_t paramsize = { pr->pr_param_size, pr->pr_param_alignment }; + paramofs = align_offset (paramofs, paramsize ); + if (i < PR_MAX_PARAMS) { dstParams[i] = pr->pr_globals + paramofs; } for (; i < pr->pr_argc; i++) { if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], - parmsize.size); + paramsize.size); pr->pr_params[i] = pr->pr_real_params[i]; } } } - //Sys_Printf("%s:\n", PR_GetString(pr,f->s_name)); - pr->pr_xfunction = f; - pr->pr_xstatement = f->first_statement - 1; // offset the st++ - // save off any locals that the new function steps on - if (pr->localstack_used + f->locals > LOCALSTACK_SIZE) + if (pr->localstack_used + f->locals > PR_LOCAL_STACK_SIZE) PR_RunError (pr, "PR_EnterFunction: locals stack overflow"); memcpy (&pr->localstack[pr->localstack_used], - &pr->pr_globals[f->parm_start], + &pr->pr_globals[f->params_start], sizeof (pr_type_t) * f->locals); pr->localstack_used += f->locals; - if (pr_deadbeef_locals->int_val) - for (i = f->parm_start; i < f->parm_start + f->locals; i++) - pr->pr_globals[i].integer_var = 0xdeadbeef; + if (pr_deadbeef_locals->int_val) { + for (pr_uint_t i = f->params_start; + i < f->params_start + f->locals; i++) { + pr->pr_globals[i].int_var = 0xdeadbeef; + } + } // copy parameters - if (f->numparms >= 0) { - for (i = 0; i < f->numparms; i++) { - copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); + if (f->numparams >= 0) { + for (i = 0; i < f->numparams; i++) { + copy_param (dstParams[i], pr->pr_params[i], f->param_size[i].size); } } else { int copy_args; - pr_type_t *argc = &pr->pr_globals[f->parm_start + 0]; - pr_type_t *argv = &pr->pr_globals[f->parm_start + 1]; - for (i = 0; i < -f->numparms - 1; i++) { - copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); + pr_type_t *argc = &pr->pr_globals[f->params_start + 0]; + pr_type_t *argv = &pr->pr_globals[f->params_start + 1]; + for (i = 0; i < -f->numparams - 1; i++) { + copy_param (dstParams[i], pr->pr_params[i], f->param_size[i].size); } copy_args = pr->pr_argc - i; - argc->integer_var = copy_args; - argv->integer_var = dstParams[i] - pr->pr_globals; - if (i < MAX_PARMS) { + argc->int_var = copy_args; + argv->int_var = dstParams[i] - pr->pr_globals; + if (i < PR_MAX_PARAMS) { memcpy (dstParams[i], pr->pr_params[i], (copy_args * pr->pr_param_size) * sizeof (pr_type_t)); } @@ -286,32 +322,36 @@ PR_LeaveFunction (progs_t *pr, int to_engine) if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Leaving function %s\n", - PR_GetString (pr, f->descriptor->s_name)); + PR_GetString (pr, f->descriptor->name)); if (to_engine) { Sys_Printf ("Returning to engine\n"); } else { bfunction_t *rf = pr->pr_xfunction; if (rf) { Sys_Printf ("Returning to function %s\n", - PR_GetString (pr, rf->descriptor->s_name)); + PR_GetString (pr, rf->descriptor->name)); } } } + if (pr->progs->version == PROG_VERSION) { + return; + } + // restore locals from the stack pr->localstack_used -= f->locals; if (pr->localstack_used < 0) PR_RunError (pr, "PR_LeaveFunction: locals stack underflow"); - memcpy (&pr->pr_globals[f->parm_start], + memcpy (&pr->pr_globals[f->params_start], &pr->localstack[pr->localstack_used], sizeof (pr_type_t) * f->locals); } VISIBLE void -PR_BoundsCheckSize (progs_t *pr, pointer_t addr, unsigned size) +PR_BoundsCheckSize (progs_t *pr, pr_ptr_t addr, unsigned size) { - if (addr < (pointer_t) (pr->pr_return - pr->pr_globals)) + if (addr < pr->null_size) PR_RunError (pr, "null pointer access"); if (addr >= pr->globals_size || size > (unsigned) (pr->globals_size - addr)) @@ -330,19 +370,15 @@ PR_BoundsCheck (progs_t *pr, int addr, etype_t type) PR_BoundsCheckSize (pr, addr, pr_type_size[type]); } -#define OPA (*op_a) -#define OPB (*op_b) -#define OPC (*op_c) - -#define OPA_double_var (*((double *) (op_a))) -#define OPB_double_var (*((double *) (op_b))) -#define OPC_double_var (*((double *) (op_c))) +#define OPA(type) (*((pr_##type##_t *) (op_a))) +#define OPB(type) (*((pr_##type##_t *) (op_b))) +#define OPC(type) (*((pr_##type##_t *) (op_c))) /* This gets around the problem of needing to test for -0.0 but denormals causing exceptions (or wrong results for what we need) on the alpha. */ -#define FNZ(x) ((x).uinteger_var & ~0x80000000u) +#define FNZ(x) ((x) & ~0x80000000u) static int signal_hook (int sig, void *data) @@ -359,24 +395,24 @@ signal_hook (int sig, void *data) op_c = pr->pr_globals + st->c; switch (st->op) { - case OP_DIV_F: - if ((OPA.integer_var & 0x80000000) - ^ (OPB.integer_var & 0x80000000)) - OPC.integer_var = 0xff7fffff; + case OP_DIV_F_v6p: + if ((OPA(int) & 0x80000000) + ^ (OPB(int) & 0x80000000)) + OPC(int) = 0xff7fffff; else - OPC.integer_var = 0x7f7fffff; + OPC(int) = 0x7f7fffff; return 1; - case OP_DIV_I: - if (OPA.integer_var & 0x80000000) - OPC.integer_var = -0x80000000; + case OP_DIV_I_v6p: + if (OPA(int) & 0x80000000) + OPC(int) = -0x80000000; else - OPC.integer_var = 0x7fffffff; + OPC(int) = 0x7fffffff; return 1; - case OP_MOD_I: - case OP_MOD_F: - case OP_REM_I: - case OP_REM_F: - OPC.integer_var = 0x00000000; + case OP_MOD_I_v6p: + case OP_MOD_F_v6p: + case OP_REM_I_v6p: + case OP_REM_F_v6p: + OPC(int) = 0x00000000; return 1; default: break; @@ -396,30 +432,49 @@ error_handler (void *data) } VISIBLE int -PR_CallFunction (progs_t *pr, func_t fnum) +PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) { bfunction_t *f; if (!fnum) PR_RunError (pr, "NULL function"); + if (!return_ptr || return_ptr == pr->pr_globals) { + return_ptr = pr->pr_return_buffer; + } f = pr->function_table + fnum; if (f->first_statement < 0) { // negative statements are built in functions + if (pr->progs->version == PROG_VERSION) { + PR_SetupParams (pr, 0, 0); + } if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Calling builtin %s @ %p\n", - PR_GetString (pr, f->descriptor->s_name), f->func); + PR_GetString (pr, f->descriptor->name), f->func); } + pr_type_t *saved_return = pr->pr_return; + int builtin_depth = pr->pr_depth; + pr->pr_return = return_ptr; f->func (pr); + f->profile++; // to show number times the builtin is called + if (builtin_depth == pr->pr_depth) { + pr->pr_return = saved_return; + } else if (builtin_depth < pr->pr_depth) { + pr->pr_stack[builtin_depth].return_ptr = saved_return; + } return 0; } else { PR_EnterFunction (pr, f); + pr->pr_return = return_ptr; return 1; } } static void -check_stack_pointer (progs_t *pr, pointer_t stack, int size) +check_stack_pointer (progs_t *pr, pr_ptr_t stack, int size) { + if (stack & 3) { + PR_RunError (pr, "Progs stack not aligned"); + } if (stack < pr->stack_bottom) { PR_RunError (pr, "Progs stack overflow"); } @@ -428,23 +483,48 @@ check_stack_pointer (progs_t *pr, pointer_t stack, int size) } } +VISIBLE pr_type_t * +PR_SetupParams (progs_t *pr, int num_params, int min_alignment) +{ + if (pr->progs->version < PROG_VERSION) { + if (num_params > PR_MAX_PARAMS) { + PR_Error (pr, "attempt to settup more than %d params", + PR_MAX_PARAMS); + } + pr->pr_params[0] = pr->pr_real_params[0]; + pr->pr_params[1] = pr->pr_real_params[1]; + return pr->pr_real_params[0]; + } + int offset = num_params * 4; + if (min_alignment < 4) { + min_alignment = 4; + } + pr_ptr_t mask = ~(min_alignment - 1); + pr_ptr_t stack = (*pr->globals.stack - offset) & mask; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 0); + } + *pr->globals.stack = stack; + pr->pr_params[0] = pr->pr_globals + stack; + num_params = max (num_params, PR_MAX_PARAMS); + for (int i = 1; i < num_params; i++) { + pr->pr_params[i] = pr->pr_params[0] + i * 4; + } + return pr->pr_params[0]; +} + static inline void -pr_memset (pr_type_t *dst, int val, int count) +pr_memset (pr_type_t *dst, int val, pr_uint_t count) { while (count-- > 0) { - (*dst++).integer_var = val; + (*dst++).int_var = val; } } -/* - PR_ExecuteProgram - - The interpretation main loop -*/ -VISIBLE void -PR_ExecuteProgram (progs_t *pr, func_t fnum) +static void +pr_exec_quakec (progs_t *pr, int exitdepth) { - int exitdepth, profile, startprofile; + int profile, startprofile; int fldofs; pr_uint_t pointer; dstatement_t *st; @@ -452,26 +532,13 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) pr_type_t old_val = {0}; // make a stack frame - exitdepth = pr->pr_depth; startprofile = profile = 0; - Sys_PushSignalHook (signal_hook, pr); - Sys_PushErrorHandler (error_handler, pr); - - if (pr->debug_handler) { - pr->debug_handler (prd_subenter, &fnum, pr->debug_data); - } - - if (!PR_CallFunction (pr, fnum)) { - // called a builtin instead of progs code - goto exit_program; - } st = pr->pr_statements + pr->pr_xstatement; if (pr->watch) { old_val = *pr->watch; } - while (1) { pr_type_t *op_a, *op_b, *op_c; @@ -503,650 +570,642 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) } } - pr_opcode_e op = st->op & ~OP_BREAK; + pr_opcode_v6p_e op = st->op & ~OP_BREAK; switch (op) { - case OP_ADD_D: - OPC_double_var = OPA_double_var + OPB_double_var; + case OP_ADD_D_v6p: + OPC(double) = OPA(double) + OPB(double); break; - case OP_ADD_F: - OPC.float_var = OPA.float_var + OPB.float_var; + case OP_ADD_F_v6p: + OPC(float) = OPA(float) + OPB(float); break; - case OP_ADD_V: - VectorAdd (&OPA.vector_var, &OPB.vector_var, &OPC.vector_var); + case OP_ADD_V_v6p: + VectorAdd (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_ADD_Q: - QuatAdd (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); + case OP_ADD_Q_v6p: + QuatAdd (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_ADD_S: - OPC.string_var = PR_CatStrings (pr, + case OP_ADD_S_v6p: + OPC(string) = PR_CatStrings (pr, PR_GetString (pr, - OPA.string_var), + OPA(string)), PR_GetString (pr, - OPB.string_var)); + OPB(string))); break; - case OP_SUB_D: - OPC_double_var = OPA_double_var - OPB_double_var; + case OP_SUB_D_v6p: + OPC(double) = OPA(double) - OPB(double); break; - case OP_SUB_F: - OPC.float_var = OPA.float_var - OPB.float_var; + case OP_SUB_F_v6p: + OPC(float) = OPA(float) - OPB(float); break; - case OP_SUB_V: - VectorSubtract (&OPA.vector_var, &OPB.vector_var, - &OPC.vector_var); + case OP_SUB_V_v6p: + VectorSubtract (&OPA(float), &OPB(float), + &OPC(float)); break; - case OP_SUB_Q: - QuatSubtract (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); + case OP_SUB_Q_v6p: + QuatSubtract (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_MUL_D: - OPC_double_var = OPA_double_var * OPB_double_var; + case OP_MUL_D_v6p: + OPC(double) = OPA(double) * OPB(double); break; - case OP_MUL_F: - OPC.float_var = OPA.float_var * OPB.float_var; + case OP_MUL_F_v6p: + OPC(float) = OPA(float) * OPB(float); break; - case OP_MUL_V: - OPC.float_var = DotProduct (&OPA.vector_var, &OPB.vector_var); + case OP_MUL_V_v6p: + OPC(float) = DotProduct (&OPA(float), &OPB(float)); break; - case OP_MUL_DV: + case OP_MUL_DV_v6p: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too - double scale = OPA_double_var; - VectorScale (&OPB.vector_var, scale, &OPC.vector_var); + double scale = OPA(double); + VectorScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_VD: + case OP_MUL_VD_v6p: { // avoid issues with the likes of x = x * x.x; // makes for faster code, too - double scale = OPB_double_var; - VectorScale (&OPA.vector_var, scale, &OPC.vector_var); + double scale = OPB(double); + VectorScale (&OPA(float), scale, &OPC(float)); } break; - case OP_MUL_FV: + case OP_MUL_FV_v6p: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too - float scale = OPA.float_var; - VectorScale (&OPB.vector_var, scale, &OPC.vector_var); + float scale = OPA(float); + VectorScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_VF: + case OP_MUL_VF_v6p: { // avoid issues with the likes of x = x * x.x; // makes for faster code, too - float scale = OPB.float_var; - VectorScale (&OPA.vector_var, scale, &OPC.vector_var); + float scale = OPB(float); + VectorScale (&OPA(float), scale, &OPC(float)); } break; - case OP_MUL_Q: - QuatMult (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); + case OP_MUL_Q_v6p: + QuatMult (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_MUL_QV: - QuatMultVec (&OPA.quat_var, &OPB.vector_var, &OPC.vector_var); + case OP_MUL_QV_v6p: + QuatMultVec (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_MUL_DQ: + case OP_MUL_DQ_v6p: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too - double scale = OPA_double_var; - QuatScale (&OPB.quat_var, scale, &OPC.quat_var); + double scale = OPA(double); + QuatScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_QD: + case OP_MUL_QD_v6p: { // avoid issues with the likes of x = x * x.s; // makes for faster code, too - double scale = OPB_double_var; - QuatScale (&OPA.quat_var, scale, &OPC.quat_var); + double scale = OPB(double); + QuatScale (&OPA(float), scale, &OPC(float)); } break; - case OP_MUL_FQ: + case OP_MUL_FQ_v6p: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too - float scale = OPA.float_var; - QuatScale (&OPB.quat_var, scale, &OPC.quat_var); + float scale = OPA(float); + QuatScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_QF: + case OP_MUL_QF_v6p: { // avoid issues with the likes of x = x * x.s; // makes for faster code, too - float scale = OPB.float_var; - QuatScale (&OPA.quat_var, scale, &OPC.quat_var); + float scale = OPB(float); + QuatScale (&OPA(float), scale, &OPC(float)); } break; - case OP_CONJ_Q: - QuatConj (&OPA.quat_var, &OPC.quat_var); + case OP_CONJ_Q_v6p: + QuatConj (&OPA(float), &OPC(float)); break; - case OP_DIV_D: - OPC_double_var = OPA_double_var / OPB_double_var; + case OP_DIV_D_v6p: + OPC(double) = OPA(double) / OPB(double); break; - case OP_DIV_F: - OPC.float_var = OPA.float_var / OPB.float_var; + case OP_DIV_F_v6p: + OPC(float) = OPA(float) / OPB(float); break; - case OP_BITAND: - OPC.float_var = (int) OPA.float_var & (int) OPB.float_var; + case OP_BITAND_v6p: + OPC(float) = (int) OPA(float) & (int) OPB(float); break; - case OP_BITOR: - OPC.float_var = (int) OPA.float_var | (int) OPB.float_var; + case OP_BITOR_v6p: + OPC(float) = (int) OPA(float) | (int) OPB(float); break; - case OP_BITXOR_F: - OPC.float_var = (int) OPA.float_var ^ (int) OPB.float_var; + case OP_BITXOR_F_v6p: + OPC(float) = (int) OPA(float) ^ (int) OPB(float); break; - case OP_BITNOT_F: - OPC.float_var = ~ (int) OPA.float_var; + case OP_BITNOT_F_v6p: + OPC(float) = ~ (int) OPA(float); break; - case OP_SHL_F: - OPC.float_var = (int) OPA.float_var << (int) OPB.float_var; + case OP_SHL_F_v6p: + OPC(float) = (int) OPA(float) << (int) OPB(float); break; - case OP_SHR_F: - OPC.float_var = (int) OPA.float_var >> (int) OPB.float_var; + case OP_SHR_F_v6p: + OPC(float) = (int) OPA(float) >> (int) OPB(float); break; - case OP_SHL_I: - OPC.integer_var = OPA.integer_var << OPB.integer_var; + case OP_SHL_I_v6p: + OPC(int) = OPA(int) << OPB(int); break; - case OP_SHR_I: - OPC.integer_var = OPA.integer_var >> OPB.integer_var; + case OP_SHR_I_v6p: + OPC(int) = OPA(int) >> OPB(int); break; - case OP_SHR_U: - OPC.uinteger_var = OPA.uinteger_var >> OPB.integer_var; + case OP_SHR_U_v6p: + OPC(uint) = OPA(uint) >> OPB(int); break; - case OP_GE_F: - OPC.float_var = OPA.float_var >= OPB.float_var; + case OP_GE_F_v6p: + OPC(float) = OPA(float) >= OPB(float); break; - case OP_LE_F: - OPC.float_var = OPA.float_var <= OPB.float_var; + case OP_LE_F_v6p: + OPC(float) = OPA(float) <= OPB(float); break; - case OP_GT_F: - OPC.float_var = OPA.float_var > OPB.float_var; + case OP_GT_F_v6p: + OPC(float) = OPA(float) > OPB(float); break; - case OP_LT_F: - OPC.float_var = OPA.float_var < OPB.float_var; + case OP_LT_F_v6p: + OPC(float) = OPA(float) < OPB(float); break; - case OP_AND: // OPA and OPB have to be float for -0.0 - OPC.integer_var = FNZ (OPA) && FNZ (OPB); + case OP_AND_v6p: // OPA and OPB have to be float for -0.0 + OPC(int) = FNZ (OPA(uint)) && FNZ (OPB(uint)); break; - case OP_OR: // OPA and OPB have to be float for -0.0 - OPC.integer_var = FNZ (OPA) || FNZ (OPB); + case OP_OR_v6p: // OPA and OPB have to be float for -0.0 + OPC(int) = FNZ (OPA(uint)) || FNZ (OPB(uint)); break; - case OP_NOT_F: - OPC.integer_var = !FNZ (OPA); + case OP_NOT_F_v6p: + OPC(int) = !FNZ (OPA(uint)); break; - case OP_NOT_V: - OPC.integer_var = VectorIsZero (&OPA.vector_var); + case OP_NOT_V_v6p: + OPC(int) = VectorIsZero (&OPA(float)); break; - case OP_NOT_Q: - OPC.integer_var = QuatIsZero (&OPA.quat_var); + case OP_NOT_Q_v6p: + OPC(int) = QuatIsZero (&OPA(float)); break; - case OP_NOT_S: - OPC.integer_var = !OPA.string_var || - !*PR_GetString (pr, OPA.string_var); + case OP_NOT_S_v6p: + OPC(int) = !OPA(string) || !*PR_GetString (pr, OPA(string)); break; - case OP_NOT_FN: - OPC.integer_var = !OPA.func_var; + case OP_NOT_FN_v6p: + OPC(int) = !OPA(func); break; - case OP_NOT_ENT: - OPC.integer_var = !OPA.entity_var; + case OP_NOT_ENT_v6p: + OPC(int) = !OPA(entity); break; - case OP_EQ_F: - OPC.integer_var = OPA.float_var == OPB.float_var; + case OP_EQ_F_v6p: + OPC(int) = OPA(float) == OPB(float); break; - case OP_EQ_V: - OPC.integer_var = VectorCompare (&OPA.vector_var, - &OPB.vector_var); + case OP_EQ_V_v6p: + OPC(int) = VectorCompare (&OPA(float), &OPB(float)); break; - case OP_EQ_Q: - OPC.integer_var = QuatCompare (&OPA.quat_var, &OPB.quat_var); + case OP_EQ_Q_v6p: + OPC(int) = QuatCompare (&OPA(float), &OPB(float)); break; - case OP_EQ_E: - OPC.integer_var = OPA.integer_var == OPB.integer_var; + case OP_EQ_E_v6p: + OPC(int) = OPA(field) == OPB(field); break; - case OP_EQ_FN: - OPC.integer_var = OPA.func_var == OPB.func_var; + case OP_EQ_FN_v6p: + OPC(int) = OPA(func) == OPB(func); break; - case OP_NE_F: - OPC.integer_var = OPA.float_var != OPB.float_var; + case OP_NE_F_v6p: + OPC(int) = OPA(float) != OPB(float); break; - case OP_NE_V: - OPC.integer_var = !VectorCompare (&OPA.vector_var, - &OPB.vector_var); + case OP_NE_V_v6p: + OPC(int) = !VectorCompare (&OPA(float), &OPB(float)); break; - case OP_NE_Q: - OPC.integer_var = !QuatCompare (&OPA.quat_var, &OPB.quat_var); + case OP_NE_Q_v6p: + OPC(int) = !QuatCompare (&OPA(float), &OPB(float)); break; - case OP_LE_S: - case OP_GE_S: - case OP_LT_S: - case OP_GT_S: - case OP_NE_S: - case OP_EQ_S: + case OP_LE_S_v6p: + case OP_GE_S_v6p: + case OP_LT_S_v6p: + case OP_GT_S_v6p: + case OP_NE_S_v6p: + case OP_EQ_S_v6p: { - int cmp = strcmp (PR_GetString (pr, OPA.string_var), - PR_GetString (pr, OPB.string_var)); + int cmp = strcmp (PR_GetString (pr, OPA(string)), + PR_GetString (pr, OPB(string))); switch (st->op) { - case OP_LE_S: cmp = (cmp <= 0); break; - case OP_GE_S: cmp = (cmp >= 0); break; - case OP_LT_S: cmp = (cmp < 0); break; - case OP_GT_S: cmp = (cmp > 0); break; - case OP_NE_S: break; - case OP_EQ_S: cmp = !cmp; break; + case OP_LE_S_v6p: cmp = (cmp <= 0); break; + case OP_GE_S_v6p: cmp = (cmp >= 0); break; + case OP_LT_S_v6p: cmp = (cmp < 0); break; + case OP_GT_S_v6p: cmp = (cmp > 0); break; + case OP_NE_S_v6p: break; + case OP_EQ_S_v6p: cmp = !cmp; break; default: break; } - OPC.integer_var = cmp; + OPC(int) = cmp; } break; - case OP_NE_E: - OPC.integer_var = OPA.integer_var != OPB.integer_var; + case OP_NE_E_v6p: + OPC(int) = OPA(entity) != OPB(entity); break; - case OP_NE_FN: - OPC.integer_var = OPA.func_var != OPB.func_var; + case OP_NE_FN_v6p: + OPC(int) = OPA(func) != OPB(func); break; // ================== - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FN: // pointers - case OP_STORE_I: - case OP_STORE_P: - OPB.integer_var = OPA.integer_var; + case OP_STORE_F_v6p: + case OP_STORE_ENT_v6p: + case OP_STORE_FLD_v6p: // integers + case OP_STORE_S_v6p: + case OP_STORE_FN_v6p: // pointers + case OP_STORE_I_v6p: + case OP_STORE_P_v6p: + OPB(int) = OPA(int); break; - case OP_STORE_V: - VectorCopy (&OPA.vector_var, &OPB.vector_var); + case OP_STORE_V_v6p: + VectorCopy (&OPA(float), &OPB(float)); break; - case OP_STORE_Q: - QuatCopy (&OPA.quat_var, &OPB.quat_var); + case OP_STORE_Q_v6p: + QuatCopy (&OPA(float), &OPB(float)); break; - case OP_STORE_D: - OPB_double_var = OPA_double_var; + case OP_STORE_D_v6p: + OPB(double) = OPA(double); break; - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FN: // pointers - case OP_STOREP_I: - case OP_STOREP_P: - pointer = OPB.integer_var; + case OP_STOREP_F_v6p: + case OP_STOREP_ENT_v6p: + case OP_STOREP_FLD_v6p: // integers + case OP_STOREP_S_v6p: + case OP_STOREP_FN_v6p: // pointers + case OP_STOREP_I_v6p: + case OP_STOREP_P_v6p: + pointer = OPB(ptr); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA.integer_var; + ptr->int_var = OPA(int); break; - case OP_STOREP_V: - pointer = OPB.integer_var; + case OP_STOREP_V_v6p: + pointer = OPB(ptr); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA.vector_var, &ptr->vector_var); + VectorCopy (&OPA(float), &ptr->vector_var); break; - case OP_STOREP_Q: - pointer = OPB.integer_var; + case OP_STOREP_Q_v6p: + pointer = OPB(ptr); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA.quat_var, &ptr->quat_var); + QuatCopy (&OPA(float), &ptr->quat_var); break; - case OP_STOREP_D: - pointer = OPB.integer_var; + case OP_STOREP_D_v6p: + pointer = OPB(ptr); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); } ptr = pr->pr_globals + pointer; - *(double *) ptr = OPA_double_var; + *(double *) ptr = OPA(double); break; - case OP_ADDRESS: + case OP_ADDRESS_v6p: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to address an out " "of bounds edict"); - if (OPA.entity_var == 0 && pr->null_bad) + if (OPA(entity) == 0 && pr->null_bad) PR_RunError (pr, "assignment to world entity"); - if (OPB.uinteger_var >= pr->progs->entityfields) + if (OPB(field) >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to address an " "invalid field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - OPC.integer_var = &pr->pr_edict_area[fldofs] - pr->pr_globals; + fldofs = OPA(entity) + OPB(field); + OPC(ptr) = &pr->pr_edict_area[fldofs] - pr->pr_globals; break; - case OP_ADDRESS_VOID: - case OP_ADDRESS_F: - case OP_ADDRESS_V: - case OP_ADDRESS_Q: - case OP_ADDRESS_S: - case OP_ADDRESS_ENT: - case OP_ADDRESS_FLD: - case OP_ADDRESS_FN: - case OP_ADDRESS_I: - case OP_ADDRESS_P: - case OP_ADDRESS_D: - OPC.integer_var = st->a; + case OP_ADDRESS_VOID_v6p: + case OP_ADDRESS_F_v6p: + case OP_ADDRESS_V_v6p: + case OP_ADDRESS_Q_v6p: + case OP_ADDRESS_S_v6p: + case OP_ADDRESS_ENT_v6p: + case OP_ADDRESS_FLD_v6p: + case OP_ADDRESS_FN_v6p: + case OP_ADDRESS_I_v6p: + case OP_ADDRESS_P_v6p: + case OP_ADDRESS_D_v6p: + OPC(int) = st->a; break; - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FN: - case OP_LOAD_I: - case OP_LOAD_P: + case OP_LOAD_F_v6p: + case OP_LOAD_FLD_v6p: + case OP_LOAD_ENT_v6p: + case OP_LOAD_S_v6p: + case OP_LOAD_FN_v6p: + case OP_LOAD_I_v6p: + case OP_LOAD_P_v6p: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var >= pr->progs->entityfields) + if (OPB(field) >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - OPC.integer_var = pr->pr_edict_area[fldofs].integer_var; + fldofs = OPA(entity) + OPB(field); + OPC(int) = pr->pr_edict_area[fldofs].int_var; break; - case OP_LOAD_V: + case OP_LOAD_V_v6p: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var + 2 >= pr->progs->entityfields) + if (OPB(field) + 2 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - memcpy (&OPC, &pr->pr_edict_area[fldofs], 3 * sizeof (OPC)); + fldofs = OPA(entity) + OPB(field); + memcpy (op_c, &pr->pr_edict_area[fldofs], 3 * sizeof (*op_c)); break; - case OP_LOAD_Q: + case OP_LOAD_Q_v6p: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var + 3 >= pr->progs->entityfields) + if (OPB(field) + 3 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - memcpy (&OPC, &pr->pr_edict_area[fldofs], 4 * sizeof (OPC)); + fldofs = OPA(entity) + OPB(field); + memcpy (op_c, &pr->pr_edict_area[fldofs], 4 * sizeof (*op_c)); break; - case OP_LOAD_D: + case OP_LOAD_D_v6p: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var + 1 >= pr->progs->entityfields) + if (OPB(field) + 1 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - memcpy (&OPC, &pr->pr_edict_area[fldofs], sizeof (double)); + fldofs = OPA(entity) + OPB(field); + memcpy (op_c, &pr->pr_edict_area[fldofs], sizeof (double)); break; - case OP_LOADB_F: - case OP_LOADB_S: - case OP_LOADB_ENT: - case OP_LOADB_FLD: - case OP_LOADB_FN: - case OP_LOADB_I: - case OP_LOADB_P: - pointer = OPA.integer_var + OPB.integer_var; + case OP_LOADB_F_v6p: + case OP_LOADB_S_v6p: + case OP_LOADB_ENT_v6p: + case OP_LOADB_FLD_v6p: + case OP_LOADB_FN_v6p: + case OP_LOADB_I_v6p: + case OP_LOADB_P_v6p: + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC.integer_var = ptr->integer_var; + OPC(int) = ptr->int_var; break; - case OP_LOADB_V: - pointer = OPA.integer_var + OPB.integer_var; + case OP_LOADB_V_v6p: + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC(float)); break; - case OP_LOADB_Q: - pointer = OPA.integer_var + OPB.integer_var; + case OP_LOADB_Q_v6p: + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC(float)); break; - case OP_LOADB_D: - pointer = OPA.integer_var + OPB.integer_var; + case OP_LOADB_D_v6p: + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); } ptr = pr->pr_globals + pointer; - OPC_double_var = *(double *) ptr; + OPC(double) = *(double *) ptr; break; - case OP_LOADBI_F: - case OP_LOADBI_S: - case OP_LOADBI_ENT: - case OP_LOADBI_FLD: - case OP_LOADBI_FN: - case OP_LOADBI_I: - case OP_LOADBI_P: - pointer = OPA.integer_var + (short) st->b; + case OP_LOADBI_F_v6p: + case OP_LOADBI_S_v6p: + case OP_LOADBI_ENT_v6p: + case OP_LOADBI_FLD_v6p: + case OP_LOADBI_FN_v6p: + case OP_LOADBI_I_v6p: + case OP_LOADBI_P_v6p: + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC.integer_var = ptr->integer_var; + OPC(int) = ptr->int_var; break; - case OP_LOADBI_V: - pointer = OPA.integer_var + (short) st->b; + case OP_LOADBI_V_v6p: + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC(float)); break; - case OP_LOADBI_Q: - pointer = OPA.integer_var + (short) st->b; + case OP_LOADBI_Q_v6p: + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC(float)); break; - case OP_LOADBI_D: - pointer = OPA.integer_var + (short) st->b; + case OP_LOADBI_D_v6p: + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - OPC_double_var = *(double *) ptr; + OPC(double) = *(double *) ptr; break; - case OP_LEA: - pointer = OPA.integer_var + OPB.integer_var; - OPC.integer_var = pointer; + case OP_LEA_v6p: + pointer = OPA(ptr) + OPB(int); + OPC(ptr) = pointer; break; - case OP_LEAI: - pointer = OPA.integer_var + (short) st->b; - OPC.integer_var = pointer; + case OP_LEAI_v6p: + pointer = OPA(ptr) + (short) st->b; + OPC(ptr) = pointer; break; - case OP_STOREB_F: - case OP_STOREB_S: - case OP_STOREB_ENT: - case OP_STOREB_FLD: - case OP_STOREB_FN: - case OP_STOREB_I: - case OP_STOREB_P: - pointer = OPB.integer_var + OPC.integer_var; + case OP_STOREB_F_v6p: + case OP_STOREB_S_v6p: + case OP_STOREB_ENT_v6p: + case OP_STOREB_FLD_v6p: + case OP_STOREB_FN_v6p: + case OP_STOREB_I_v6p: + case OP_STOREB_P_v6p: + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA.integer_var; + ptr->int_var = OPA(int); break; - case OP_STOREB_V: - pointer = OPB.integer_var + OPC.integer_var; + case OP_STOREB_V_v6p: + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA.vector_var, &ptr->vector_var); + VectorCopy (&OPA(float), &ptr->vector_var); break; - case OP_STOREB_Q: - pointer = OPB.integer_var + OPC.integer_var; + case OP_STOREB_Q_v6p: + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA.quat_var, &ptr->quat_var); + QuatCopy (&OPA(float), &ptr->quat_var); break; - case OP_STOREB_D: - pointer = OPB.integer_var + OPC.integer_var; + case OP_STOREB_D_v6p: + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - *(double *) ptr = OPA_double_var; + *(double *) ptr = OPA(double); break; - case OP_STOREBI_F: - case OP_STOREBI_S: - case OP_STOREBI_ENT: - case OP_STOREBI_FLD: - case OP_STOREBI_FN: - case OP_STOREBI_I: - case OP_STOREBI_P: - pointer = OPB.integer_var + (short) st->c; + case OP_STOREBI_F_v6p: + case OP_STOREBI_S_v6p: + case OP_STOREBI_ENT_v6p: + case OP_STOREBI_FLD_v6p: + case OP_STOREBI_FN_v6p: + case OP_STOREBI_I_v6p: + case OP_STOREBI_P_v6p: + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA.integer_var; + ptr->int_var = OPA(int); break; - case OP_STOREBI_V: - pointer = OPB.integer_var + (short) st->c; + case OP_STOREBI_V_v6p: + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA.vector_var, &ptr->vector_var); + VectorCopy (&OPA(float), &ptr->vector_var); break; - case OP_STOREBI_Q: - pointer = OPB.integer_var + (short) st->c; + case OP_STOREBI_Q_v6p: + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA.quat_var, &ptr->quat_var); + QuatCopy (&OPA(float), &ptr->quat_var); break; - case OP_STOREBI_D: - pointer = OPB.integer_var + (short) st->c; + case OP_STOREBI_D_v6p: + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - *(double *) ptr = OPA_double_var; + *(double *) ptr = OPA(double); break; - case OP_PUSH_F: - case OP_PUSH_FLD: - case OP_PUSH_ENT: - case OP_PUSH_S: - case OP_PUSH_FN: - case OP_PUSH_I: - case OP_PUSH_P: + case OP_PUSH_F_v6p: + case OP_PUSH_FLD_v6p: + case OP_PUSH_ENT_v6p: + case OP_PUSH_S_v6p: + case OP_PUSH_FN_v6p: + case OP_PUSH_I_v6p: + case OP_PUSH_P_v6p: { - pointer_t stack = *pr->globals.stack - 1; + pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); } - stk->integer_var = OPA.integer_var; + stk->int_var = OPA(int); *pr->globals.stack = stack; } break; - case OP_PUSH_V: + case OP_PUSH_V_v6p: { - pointer_t stack = *pr->globals.stack - 3; + pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); } - memcpy (stk, &OPA, 3 * sizeof (OPC)); + memcpy (stk, op_a, 3 * sizeof (*op_c)); *pr->globals.stack = stack; } break; - case OP_PUSH_Q: + case OP_PUSH_Q_v6p: { - pointer_t stack = *pr->globals.stack - 4; + pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); } - memcpy (stk, &OPA, 4 * sizeof (OPC)); + memcpy (stk, op_a, 4 * sizeof (*op_c)); *pr->globals.stack = stack; } break; - case OP_PUSHB_F: - case OP_PUSHB_S: - case OP_PUSHB_ENT: - case OP_PUSHB_FLD: - case OP_PUSHB_FN: - case OP_PUSHB_I: - case OP_PUSHB_P: + case OP_PUSHB_F_v6p: + case OP_PUSHB_S_v6p: + case OP_PUSHB_ENT_v6p: + case OP_PUSHB_FLD_v6p: + case OP_PUSHB_FN_v6p: + case OP_PUSHB_I_v6p: + case OP_PUSHB_P_v6p: { - pointer_t stack = *pr->globals.stack - 1; + pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - stk->integer_var = ptr->integer_var; + stk->int_var = ptr->int_var; *pr->globals.stack = stack; } break; - case OP_PUSHB_V: + case OP_PUSHB_V_v6p: { - pointer_t stack = *pr->globals.stack - 3; + pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack; } break; - case OP_PUSHB_Q: + case OP_PUSHB_Q_v6p: { - pointer_t stack = *pr->globals.stack - 4; + pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&ptr->quat_var, &stk->quat_var); @@ -1154,57 +1213,57 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) } break; - case OP_PUSHBI_F: - case OP_PUSHBI_S: - case OP_PUSHBI_ENT: - case OP_PUSHBI_FLD: - case OP_PUSHBI_FN: - case OP_PUSHBI_I: - case OP_PUSHBI_P: + case OP_PUSHBI_F_v6p: + case OP_PUSHBI_S_v6p: + case OP_PUSHBI_ENT_v6p: + case OP_PUSHBI_FLD_v6p: + case OP_PUSHBI_FN_v6p: + case OP_PUSHBI_I_v6p: + case OP_PUSHBI_P_v6p: { - pointer_t stack = *pr->globals.stack - 1; + pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - stk->integer_var = ptr->integer_var; + stk->int_var = ptr->int_var; *pr->globals.stack = stack; } break; - case OP_PUSHBI_V: + case OP_PUSHBI_V_v6p: { - pointer_t stack = *pr->globals.stack - 3; + pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack; } break; - case OP_PUSHBI_Q: + case OP_PUSHBI_Q_v6p: { - pointer_t stack = *pr->globals.stack - 4; + pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&ptr->quat_var, &stk->quat_var); @@ -1212,97 +1271,97 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) } break; - case OP_POP_F: - case OP_POP_FLD: - case OP_POP_ENT: - case OP_POP_S: - case OP_POP_FN: - case OP_POP_I: - case OP_POP_P: + case OP_POP_F_v6p: + case OP_POP_FLD_v6p: + case OP_POP_ENT_v6p: + case OP_POP_S_v6p: + case OP_POP_FN_v6p: + case OP_POP_I_v6p: + case OP_POP_P_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); } - OPA.integer_var = stk->integer_var; + OPA(int) = stk->int_var; *pr->globals.stack = stack + 1; } break; - case OP_POP_V: + case OP_POP_V_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); } - memcpy (&OPA, stk, 3 * sizeof (OPC)); + memcpy (op_a, stk, 3 * sizeof (*op_c)); *pr->globals.stack = stack + 3; } break; - case OP_POP_Q: + case OP_POP_Q_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); } - memcpy (&OPA, stk, 4 * sizeof (OPC)); + memcpy (op_a, stk, 4 * sizeof (*op_c)); *pr->globals.stack = stack + 4; } break; - case OP_POPB_F: - case OP_POPB_S: - case OP_POPB_ENT: - case OP_POPB_FLD: - case OP_POPB_FN: - case OP_POPB_I: - case OP_POPB_P: + case OP_POPB_F_v6p: + case OP_POPB_S_v6p: + case OP_POPB_ENT_v6p: + case OP_POPB_FLD_v6p: + case OP_POPB_FN_v6p: + case OP_POPB_I_v6p: + case OP_POPB_P_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - ptr->integer_var = stk->integer_var; + ptr->int_var = stk->int_var; *pr->globals.stack = stack + 1; } break; - case OP_POPB_V: + case OP_POPB_V_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&stk->vector_var, &ptr->vector_var); *pr->globals.stack = stack + 3; } break; - case OP_POPB_Q: + case OP_POPB_Q_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&stk->quat_var, &ptr->quat_var); @@ -1310,57 +1369,57 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) } break; - case OP_POPBI_F: - case OP_POPBI_S: - case OP_POPBI_ENT: - case OP_POPBI_FLD: - case OP_POPBI_FN: - case OP_POPBI_I: - case OP_POPBI_P: + case OP_POPBI_F_v6p: + case OP_POPBI_S_v6p: + case OP_POPBI_ENT_v6p: + case OP_POPBI_FLD_v6p: + case OP_POPBI_FN_v6p: + case OP_POPBI_I_v6p: + case OP_POPBI_P_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - ptr->integer_var = stk->integer_var; + ptr->int_var = stk->int_var; *pr->globals.stack = stack + 1; } break; - case OP_POPBI_V: + case OP_POPBI_V_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&stk->vector_var, &ptr->vector_var); *pr->globals.stack = stack + 3; } break; - case OP_POPBI_Q: + case OP_POPBI_Q_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&stk->quat_var, &ptr->quat_var); @@ -1369,111 +1428,111 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) break; // ================== - case OP_IFNOT: - if (!OPA.integer_var) { + case OP_IFNOT_v6p: + if (!OPA(int)) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IF: - if (OPA.integer_var) { + case OP_IF_v6p: + if (OPA(int)) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFBE: - if (OPA.integer_var <= 0) { + case OP_IFBE_v6p: + if (OPA(int) <= 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFB: - if (OPA.integer_var < 0) { + case OP_IFB_v6p: + if (OPA(int) < 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFAE: - if (OPA.integer_var >= 0) { + case OP_IFAE_v6p: + if (OPA(int) >= 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFA: - if (OPA.integer_var > 0) { + case OP_IFA_v6p: + if (OPA(int) > 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_GOTO: + case OP_GOTO_v6p: pr->pr_xstatement += (short)st->a - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; break; - case OP_JUMP: + case OP_JUMP_v6p: if (pr_boundscheck->int_val - && (OPA.uinteger_var >= pr->progs->numstatements)) { + && (OPA(uint) >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); } - pr->pr_xstatement = OPA.uinteger_var - 1; // offset the st++ + pr->pr_xstatement = OPA(uint) - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; break; - case OP_JUMPB: - pointer = st->a + OPB.integer_var; + case OP_JUMPB_v6p: + pointer = st->a + OPB(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - pointer = ptr->integer_var; + pointer = ptr->int_var; if (pr_boundscheck->int_val - && (pointer >= pr->progs->numstatements)) { + && (pointer >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); } pr->pr_xstatement = pointer - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; break; - case OP_RCALL2: - case OP_RCALL3: - case OP_RCALL4: - case OP_RCALL5: - case OP_RCALL6: - case OP_RCALL7: - case OP_RCALL8: - pr->pr_params[1] = &OPC; + case OP_RCALL2_v6p: + case OP_RCALL3_v6p: + case OP_RCALL4_v6p: + case OP_RCALL5_v6p: + case OP_RCALL6_v6p: + case OP_RCALL7_v6p: + case OP_RCALL8_v6p: + pr->pr_params[1] = op_c; goto op_rcall; - case OP_RCALL1: + case OP_RCALL1_v6p: pr->pr_params[1] = pr->pr_real_params[1]; op_rcall: - pr->pr_params[0] = &OPB; - pr->pr_argc = st->op - OP_RCALL1 + 1; + pr->pr_params[0] = op_b; + pr->pr_argc = st->op - OP_RCALL1_v6p + 1; goto op_call; - case OP_CALL0: - case OP_CALL1: - case OP_CALL2: - case OP_CALL3: - case OP_CALL4: - case OP_CALL5: - case OP_CALL6: - case OP_CALL7: - case OP_CALL8: + case OP_CALL0_v6p: + case OP_CALL1_v6p: + case OP_CALL2_v6p: + case OP_CALL3_v6p: + case OP_CALL4_v6p: + case OP_CALL5_v6p: + case OP_CALL6_v6p: + case OP_CALL7_v6p: + case OP_CALL8_v6p: PR_RESET_PARAMS (pr); - pr->pr_argc = st->op - OP_CALL0; + pr->pr_argc = st->op - OP_CALL0_v6p; op_call: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; - PR_CallFunction (pr, OPA.func_var); + PR_CallFunction (pr, OPA(func), pr->pr_return); st = pr->pr_statements + pr->pr_xstatement; break; - case OP_DONE: - case OP_RETURN: + case OP_DONE_v6p: + case OP_RETURN_v6p: if (!st->a) memset (&R_INT (pr), 0, - pr->pr_param_size * sizeof (OPA)); - else if (&R_INT (pr) != &OPA.integer_var) - memcpy (&R_INT (pr), &OPA, - pr->pr_param_size * sizeof (OPA)); + pr->pr_param_size * sizeof (*op_a)); + else if (&R_INT (pr) != &OPA(int)) + memcpy (&R_INT (pr), op_a, + pr->pr_param_size * sizeof (*op_a)); // fallthrough - case OP_RETURN_V: + case OP_RETURN_V_v6p: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; PR_LeaveFunction (pr, pr->pr_depth == exitdepth); @@ -1485,236 +1544,236 @@ op_call: goto exit_program; } break; - case OP_STATE: + case OP_STATE_v6p: { int self = *pr->globals.self; int nextthink = pr->fields.nextthink + self; int frame = pr->fields.frame + self; int think = pr->fields.think + self; - float time = *pr->globals.time + 0.1; + float time = *pr->globals.ftime + 0.1; pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA.float_var; - pr->pr_edict_area[think].func_var = OPB.func_var; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = OPB(func); } break; - case OP_STATE_F: + case OP_STATE_F_v6p: { int self = *pr->globals.self; int nextthink = pr->fields.nextthink + self; int frame = pr->fields.frame + self; int think = pr->fields.think + self; - float time = *pr->globals.time + OPC.float_var; + float time = *pr->globals.ftime + OPC(float); pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA.float_var; - pr->pr_edict_area[think].func_var = OPB.func_var; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = OPB(func); } break; - case OP_ADD_I: - OPC.integer_var = OPA.integer_var + OPB.integer_var; + case OP_ADD_I_v6p: + OPC(int) = OPA(int) + OPB(int); break; - case OP_SUB_I: - OPC.integer_var = OPA.integer_var - OPB.integer_var; + case OP_SUB_I_v6p: + OPC(int) = OPA(int) - OPB(int); break; - case OP_MUL_I: - OPC.integer_var = OPA.integer_var * OPB.integer_var; + case OP_MUL_I_v6p: + OPC(int) = OPA(int) * OPB(int); break; - case OP_DIV_I: - OPC.integer_var = OPA.integer_var / OPB.integer_var; + case OP_DIV_I_v6p: + OPC(int) = OPA(int) / OPB(int); break; - case OP_MOD_I: + case OP_MOD_I_v6p: { // implement true modulo for integers: // 5 mod 3 = 2 // -5 mod 3 = 1 // 5 mod -3 = -1 // -5 mod -3 = -2 - int a = OPA.integer_var; - int b = OPB.integer_var; + int a = OPA(int); + int b = OPB(int); int c = a % b; // % is really remainder and so has the same sign rules // as division: -5 % 3 = -2, so need to add b (3 here) // if c's sign is incorrect, but only if c is non-zero int mask = (a ^ b) >> 31; mask &= ~(!!c + 0) + 1; // +0 to convert bool to int (gcc) - OPC.integer_var = c + (mask & b); + OPC(int) = c + (mask & b); } break; - case OP_REM_I: - OPC.integer_var = OPA.integer_var % OPB.integer_var; + case OP_REM_I_v6p: + OPC(int) = OPA(int) % OPB(int); break; - case OP_MOD_D: + case OP_MOD_D_v6p: { - double a = OPA_double_var; - double b = OPB_double_var; + double a = OPA(double); + double b = OPB(double); // floating point modulo is so much easier :P - OPC_double_var = a - b * floor (a / b); + OPC(double) = a - b * floor (a / b); } break; - case OP_REM_D: + case OP_REM_D_v6p: { - double a = OPA_double_var; - double b = OPB_double_var; - OPC_double_var = a - b * trunc (a / b); + double a = OPA(double); + double b = OPB(double); + OPC(double) = a - b * trunc (a / b); } break; - case OP_MOD_F: + case OP_MOD_F_v6p: { - float a = OPA.float_var; - float b = OPB.float_var; - OPC.float_var = a - b * floorf (a / b); + float a = OPA(float); + float b = OPB(float); + OPC(float) = a - b * floorf (a / b); } break; - case OP_REM_F: + case OP_REM_F_v6p: { - float a = OPA.float_var; - float b = OPB.float_var; - OPC.float_var = a - b * truncf (a / b); + float a = OPA(float); + float b = OPB(float); + OPC(float) = a - b * truncf (a / b); } break; - case OP_CONV_IF: - OPC.float_var = OPA.integer_var; + case OP_CONV_IF_v6p: + OPC(float) = OPA(int); break; - case OP_CONV_FI: - OPC.integer_var = OPA.float_var; + case OP_CONV_FI_v6p: + OPC(int) = OPA(float); break; - case OP_BITAND_I: - OPC.integer_var = OPA.integer_var & OPB.integer_var; + case OP_BITAND_I_v6p: + OPC(int) = OPA(int) & OPB(int); break; - case OP_BITOR_I: - OPC.integer_var = OPA.integer_var | OPB.integer_var; + case OP_BITOR_I_v6p: + OPC(int) = OPA(int) | OPB(int); break; - case OP_BITXOR_I: - OPC.integer_var = OPA.integer_var ^ OPB.integer_var; + case OP_BITXOR_I_v6p: + OPC(int) = OPA(int) ^ OPB(int); break; - case OP_BITNOT_I: - OPC.integer_var = ~OPA.integer_var; + case OP_BITNOT_I_v6p: + OPC(int) = ~OPA(int); break; - case OP_GE_I: - case OP_GE_P: - OPC.integer_var = OPA.integer_var >= OPB.integer_var; + case OP_GE_I_v6p: + case OP_GE_P_v6p: + OPC(int) = OPA(int) >= OPB(int); break; - case OP_GE_U: - OPC.integer_var = OPA.uinteger_var >= OPB.uinteger_var; + case OP_GE_U_v6p: + OPC(int) = OPA(uint) >= OPB(uint); break; - case OP_LE_I: - case OP_LE_P: - OPC.integer_var = OPA.integer_var <= OPB.integer_var; + case OP_LE_I_v6p: + case OP_LE_P_v6p: + OPC(int) = OPA(int) <= OPB(int); break; - case OP_LE_U: - OPC.integer_var = OPA.uinteger_var <= OPB.uinteger_var; + case OP_LE_U_v6p: + OPC(int) = OPA(uint) <= OPB(uint); break; - case OP_GT_I: - case OP_GT_P: - OPC.integer_var = OPA.integer_var > OPB.integer_var; + case OP_GT_I_v6p: + case OP_GT_P_v6p: + OPC(int) = OPA(int) > OPB(int); break; - case OP_GT_U: - OPC.integer_var = OPA.uinteger_var > OPB.uinteger_var; + case OP_GT_U_v6p: + OPC(int) = OPA(uint) > OPB(uint); break; - case OP_LT_I: - case OP_LT_P: - OPC.integer_var = OPA.integer_var < OPB.integer_var; + case OP_LT_I_v6p: + case OP_LT_P_v6p: + OPC(int) = OPA(int) < OPB(int); break; - case OP_LT_U: - OPC.integer_var = OPA.uinteger_var < OPB.uinteger_var; + case OP_LT_U_v6p: + OPC(int) = OPA(uint) < OPB(uint); break; - case OP_AND_I: - OPC.integer_var = OPA.integer_var && OPB.integer_var; + case OP_AND_I_v6p: + OPC(int) = OPA(int) && OPB(int); break; - case OP_OR_I: - OPC.integer_var = OPA.integer_var || OPB.integer_var; + case OP_OR_I_v6p: + OPC(int) = OPA(int) || OPB(int); break; - case OP_NOT_I: - case OP_NOT_P: - OPC.integer_var = !OPA.integer_var; + case OP_NOT_I_v6p: + case OP_NOT_P_v6p: + OPC(int) = !OPA(int); break; - case OP_EQ_I: - case OP_EQ_P: - OPC.integer_var = OPA.integer_var == OPB.integer_var; + case OP_EQ_I_v6p: + case OP_EQ_P_v6p: + OPC(int) = OPA(int) == OPB(int); break; - case OP_NE_I: - case OP_NE_P: - OPC.integer_var = OPA.integer_var != OPB.integer_var; + case OP_NE_I_v6p: + case OP_NE_P_v6p: + OPC(int) = OPA(int) != OPB(int); break; - case OP_MOVEI: - memmove (&OPC, &OPA, st->b * 4); + case OP_MOVEI_v6p: + memmove (op_c, op_a, st->b * 4); break; - case OP_MOVEP: + case OP_MOVEP_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.integer_var, OPB.uinteger_var); - PR_BoundsCheckSize (pr, OPA.integer_var, OPB.uinteger_var); + PR_BoundsCheckSize (pr, OPC(ptr), OPB(uint)); + PR_BoundsCheckSize (pr, OPA(ptr), OPB(uint)); } - memmove (pr->pr_globals + OPC.integer_var, - pr->pr_globals + OPA.integer_var, - OPB.uinteger_var * 4); + memmove (pr->pr_globals + OPC(ptr), + pr->pr_globals + OPA(ptr), + OPB(uint) * 4); break; - case OP_MOVEPI: + case OP_MOVEPI_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.integer_var, st->b); - PR_BoundsCheckSize (pr, OPA.integer_var, st->b); + PR_BoundsCheckSize (pr, OPC(ptr), st->b); + PR_BoundsCheckSize (pr, OPA(ptr), st->b); } - memmove (pr->pr_globals + OPC.integer_var, - pr->pr_globals + OPA.integer_var, + memmove (pr->pr_globals + OPC(ptr), + pr->pr_globals + OPA(ptr), st->b * 4); break; - case OP_MEMSETI: - pr_memset (&OPC, OPA.integer_var, st->b); + case OP_MEMSETI_v6p: + pr_memset (op_c, OPA(ptr), st->b); break; - case OP_MEMSETP: + case OP_MEMSETP_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.pointer_var, OPB.integer_var); + PR_BoundsCheckSize (pr, OPC(ptr), OPB(uint)); } - pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var, - OPB.integer_var); + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), + OPB(uint)); break; - case OP_MEMSETPI: + case OP_MEMSETPI_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.pointer_var, st->b); + PR_BoundsCheckSize (pr, OPC(ptr), st->b); } - pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var, + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), st->b); break; - case OP_GE_D: - OPC.float_var = OPA_double_var >= OPB_double_var; + case OP_GE_D_v6p: + OPC(float) = OPA(double) >= OPB(double); break; - case OP_LE_D: - OPC.float_var = OPA_double_var <= OPB_double_var; + case OP_LE_D_v6p: + OPC(float) = OPA(double) <= OPB(double); break; - case OP_GT_D: - OPC.float_var = OPA_double_var > OPB_double_var; + case OP_GT_D_v6p: + OPC(float) = OPA(double) > OPB(double); break; - case OP_LT_D: - OPC.float_var = OPA_double_var < OPB_double_var; + case OP_LT_D_v6p: + OPC(float) = OPA(double) < OPB(double); break; - case OP_NOT_D: - OPC.integer_var = (op_a[0].integer_var - || (op_a[1].integer_var & ~0x80000000u)); + case OP_NOT_D_v6p: + OPC(int) = (op_a[0].int_var + || (op_a[1].int_var & ~0x80000000u)); break; - case OP_EQ_D: - OPC.integer_var = OPA_double_var == OPB_double_var; + case OP_EQ_D_v6p: + OPC(int) = OPA(double) == OPB(double); break; - case OP_NE_D: - OPC.integer_var = OPA_double_var != OPB_double_var; + case OP_NE_D_v6p: + OPC(int) = OPA(double) != OPB(double); break; - case OP_CONV_ID: - OPC_double_var = OPA.integer_var; + case OP_CONV_ID_v6p: + OPC(double) = OPA(int); break; - case OP_CONV_DI: - OPC.integer_var = OPA_double_var; + case OP_CONV_DI_v6p: + OPC(int) = OPA(double); break; - case OP_CONV_FD: - OPC_double_var = OPA.float_var; + case OP_CONV_FD_v6p: + OPC(double) = OPA(float); break; - case OP_CONV_DF: - OPC.float_var = OPA_double_var; + case OP_CONV_DF_v6p: + OPC(float) = OPA(double); break; // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized /* - case OP_BOUNDCHECK: - if (OPA.integer_var < 0 || OPA.integer_var >= st->b) { + case OP_BOUNDCHECK_v6p: + if (OPA(ptr) >= st->b) { PR_RunError (pr, "Progs boundcheck failed at line number " "%d, value is < 0 or >= %d", st->b, st->c); } @@ -1722,21 +1781,1770 @@ op_call: */ default: - PR_RunError (pr, "Bad opcode %i", st->op); + PR_RunError (pr, "Bad opcode %i", st->op & ~OP_BREAK); } - if (pr->watch && pr->watch->integer_var != old_val.integer_var) { + if (pr->watch && pr->watch->int_var != old_val.int_var) { if (!pr->wp_conditional - || pr->watch->integer_var == pr->wp_val.integer_var) { + || pr->watch->int_var == pr->wp_val.int_var) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.integer_var, pr->watch->integer_var); + old_val.int_var, pr->watch->int_var); } } - old_val.integer_var = pr->watch->integer_var; + old_val.int_var = pr->watch->int_var; } } +exit_program: +} + +#define MM(type) (*((pr_##type##_t *) (mm))) +#define STK(type) (*((pr_##type##_t *) (stk))) + +static pr_type_t * +pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); + pr_ptr_t mm_offs = 0; + + switch (mm_ind) { + case 0: + // regular global access + mm_offs = op_a - pr->pr_globals; + break; + case 1: + // entity.field (equivalent to OP_LOAD_t_v6p) + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; + mm_offs = edict_area + OPA(entity) + OPB(field); + break; + case 2: + // constant indexed pointer: *a + b (supports -ve offset) + mm_offs = OPA(ptr) + (short) st->b; + break; + case 3: + // variable indexed pointer: *a + *b (supports -ve offset) + mm_offs = OPA(ptr) + OPB(int); + break; + } + return pr->pr_globals + mm_offs; +} + +static pr_type_t * +pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); + pr_ptr_t mm_offs = 0; + + switch (mm_ind) { + case 1: + // regular global access + mm_offs = op_a - pr->pr_globals; + break; + case 2: + // constant indexed pointer: *a + b (supports -ve offset) + mm_offs = OPA(ptr) + (short) st->b; + break; + case 3: + // variable indexed pointer: *a + *b (supports -ve offset) + mm_offs = OPA(ptr) + OPB(int); + break; + case 4: + // entity.field (equivalent to OP_LOAD_t_v6p) + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; + mm_offs = edict_area + OPA(entity) + OPB(field); + break; + } + return pr->pr_globals + mm_offs; +} + +static pr_ptr_t __attribute__((pure)) +pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); + pr_ptr_t jump_offs = pr->pr_xstatement; + + switch (jump_ind) { + case 0: + // instruction relative offset + jump_offs = jump_offs + (short) st->a; + break; + case 1: + // variable indexed array: a + *b (only +ve) + jump_offs = (op_a + OPB(uint))->uint_var; + break; + case 2: + // constant indexed pointer: *a + b (supports -ve offset) + jump_offs = OPA(ptr) + (short) st->b; + break; + case 3: + // variable indexed pointer: *a + *b (supports -ve offset) + jump_offs = OPA(ptr) + OPB(int); + break; + } + if (pr_boundscheck->int_val && jump_offs >= pr->progs->statements.count) { + PR_RunError (pr, "out of bounds: %x", jump_offs); + } + return jump_offs - 1; // for st++ +} + +static pr_type_t * +pr_stack_push (progs_t *pr) +{ + // keep the stack 16-byte aligned + pr_ptr_t stack = *pr->globals.stack - 4; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + } + *pr->globals.stack = stack; + return stk; +} + +static pr_type_t * +pr_stack_pop (progs_t *pr) +{ + pr_ptr_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + } + // keep the stack 16-byte aligned + *pr->globals.stack = stack + 4; + return stk; +} + +static void +pr_stack_adjust (progs_t *pr, int mode, int offset) +{ + // keep the stack 16-byte aligned + if (mode || (offset & 3)) { + PR_RunError (pr, "invalid stack adjustment: %d, %d", mode, offset); + } + + pr_ptr_t stack = *pr->globals.stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack + offset, 0); + } + *pr->globals.stack = stack + offset; +} + +static void +pr_with (progs_t *pr, const dstatement_t *st) +{ + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; + pr_type_t *op_b = pr->pr_globals + PR_BASE (pr, st, B) + st->b; + pr_type_t *stk; + pr_uint_t *base = &pr->pr_bases[st->c & 3]; + + switch (st->a) { + // fixed offset + case 0: + // hard-0 base + *base = st->b; + return; + case 1: + // relative to current base (-ve offset) + *base = PR_BASE (pr, st, B) + (pr_short_t) st->b; + return; + case 2: + // relative to stack (-ve offset) + *base = *pr->globals.stack + (pr_short_t) st->b; + return; + case 3: + // relative to edict_area (only +ve) + *base = edict_area + st->b; + return; + + case 4: + // hard-0 base + *base = pr->pr_globals[st->b].pointer_var; + return; + case 5: + *base = OPB(ptr); + return; + case 6: + // relative to stack (-ve offset) + *base = *pr->globals.stack + OPB(int); + return; + case 7: + // relative to edict_area (only +ve) + *base = edict_area + OPB(field); + return; + + case 8: + // pushregs + stk = pr_stack_push (pr); + STK(uivec4) = pr->pr_bases; + return; + case 9: + // popregs + stk = pr_stack_pop (pr); + pr->pr_bases = STK(uivec4); + return; + case 10: + // reset + pr->pr_bases = (pr_uivec4_t) {}; + return; + case 11: + // return pointer + *base = pr->pr_return - pr->pr_globals; + return; + } + PR_RunError (pr, "Invalid with index: %u", st->a); +} + +static pr_ivec4_t +pr_swizzle_f (pr_ivec4_t vec, pr_ushort_t swiz) +{ + goto do_swizzle; +#define swizzle __builtin_shuffle + swizzle_xxxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 0 }); goto negate; + swizzle_yxxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 0 }); goto negate; + swizzle_zxxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 0 }); goto negate; + swizzle_wxxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 0 }); goto negate; + swizzle_xyxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 0 }); goto negate; + swizzle_yyxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 0 }); goto negate; + swizzle_zyxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 0 }); goto negate; + swizzle_wyxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 0 }); goto negate; + swizzle_xzxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 0 }); goto negate; + swizzle_yzxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 0 }); goto negate; + swizzle_zzxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 0 }); goto negate; + swizzle_wzxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 0 }); goto negate; + swizzle_xwxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 0 }); goto negate; + swizzle_ywxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 0 }); goto negate; + swizzle_zwxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 0 }); goto negate; + swizzle_wwxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 0 }); goto negate; + swizzle_xxyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 0 }); goto negate; + swizzle_yxyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 0 }); goto negate; + swizzle_zxyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 0 }); goto negate; + swizzle_wxyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 0 }); goto negate; + swizzle_xyyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 0 }); goto negate; + swizzle_yyyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 0 }); goto negate; + swizzle_zyyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 0 }); goto negate; + swizzle_wyyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 0 }); goto negate; + swizzle_xzyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 0 }); goto negate; + swizzle_yzyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 0 }); goto negate; + swizzle_zzyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 0 }); goto negate; + swizzle_wzyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 0 }); goto negate; + swizzle_xwyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 0 }); goto negate; + swizzle_ywyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 0 }); goto negate; + swizzle_zwyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 0 }); goto negate; + swizzle_wwyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 0 }); goto negate; + swizzle_xxzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 0 }); goto negate; + swizzle_yxzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 0 }); goto negate; + swizzle_zxzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 0 }); goto negate; + swizzle_wxzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 0 }); goto negate; + swizzle_xyzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 0 }); goto negate; + swizzle_yyzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 0 }); goto negate; + swizzle_zyzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 0 }); goto negate; + swizzle_wyzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 0 }); goto negate; + swizzle_xzzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 0 }); goto negate; + swizzle_yzzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 0 }); goto negate; + swizzle_zzzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 0 }); goto negate; + swizzle_wzzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 0 }); goto negate; + swizzle_xwzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 0 }); goto negate; + swizzle_ywzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 0 }); goto negate; + swizzle_zwzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 0 }); goto negate; + swizzle_wwzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 0 }); goto negate; + swizzle_xxwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 0 }); goto negate; + swizzle_yxwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 0 }); goto negate; + swizzle_zxwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 0 }); goto negate; + swizzle_wxwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 0 }); goto negate; + swizzle_xywx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 0 }); goto negate; + swizzle_yywx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 0 }); goto negate; + swizzle_zywx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 0 }); goto negate; + swizzle_wywx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 0 }); goto negate; + swizzle_xzwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 0 }); goto negate; + swizzle_yzwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 0 }); goto negate; + swizzle_zzwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 0 }); goto negate; + swizzle_wzwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 0 }); goto negate; + swizzle_xwwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 0 }); goto negate; + swizzle_ywwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 0 }); goto negate; + swizzle_zwwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 0 }); goto negate; + swizzle_wwwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 0 }); goto negate; + swizzle_xxxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 1 }); goto negate; + swizzle_yxxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 1 }); goto negate; + swizzle_zxxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 1 }); goto negate; + swizzle_wxxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 1 }); goto negate; + swizzle_xyxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 1 }); goto negate; + swizzle_yyxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 1 }); goto negate; + swizzle_zyxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 1 }); goto negate; + swizzle_wyxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 1 }); goto negate; + swizzle_xzxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 1 }); goto negate; + swizzle_yzxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 1 }); goto negate; + swizzle_zzxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 1 }); goto negate; + swizzle_wzxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 1 }); goto negate; + swizzle_xwxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 1 }); goto negate; + swizzle_ywxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 1 }); goto negate; + swizzle_zwxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 1 }); goto negate; + swizzle_wwxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 1 }); goto negate; + swizzle_xxyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 1 }); goto negate; + swizzle_yxyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 1 }); goto negate; + swizzle_zxyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 1 }); goto negate; + swizzle_wxyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 1 }); goto negate; + swizzle_xyyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 1 }); goto negate; + swizzle_yyyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 1 }); goto negate; + swizzle_zyyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 1 }); goto negate; + swizzle_wyyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 1 }); goto negate; + swizzle_xzyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 1 }); goto negate; + swizzle_yzyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 1 }); goto negate; + swizzle_zzyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 1 }); goto negate; + swizzle_wzyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 1 }); goto negate; + swizzle_xwyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 1 }); goto negate; + swizzle_ywyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 1 }); goto negate; + swizzle_zwyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 1 }); goto negate; + swizzle_wwyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 1 }); goto negate; + swizzle_xxzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 1 }); goto negate; + swizzle_yxzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 1 }); goto negate; + swizzle_zxzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 1 }); goto negate; + swizzle_wxzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 1 }); goto negate; + swizzle_xyzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 1 }); goto negate; + swizzle_yyzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 1 }); goto negate; + swizzle_zyzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 1 }); goto negate; + swizzle_wyzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 1 }); goto negate; + swizzle_xzzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 1 }); goto negate; + swizzle_yzzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 1 }); goto negate; + swizzle_zzzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 1 }); goto negate; + swizzle_wzzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 1 }); goto negate; + swizzle_xwzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 1 }); goto negate; + swizzle_ywzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 1 }); goto negate; + swizzle_zwzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 1 }); goto negate; + swizzle_wwzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 1 }); goto negate; + swizzle_xxwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 1 }); goto negate; + swizzle_yxwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 1 }); goto negate; + swizzle_zxwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 1 }); goto negate; + swizzle_wxwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 1 }); goto negate; + swizzle_xywy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 1 }); goto negate; + swizzle_yywy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 1 }); goto negate; + swizzle_zywy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 1 }); goto negate; + swizzle_wywy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 1 }); goto negate; + swizzle_xzwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 1 }); goto negate; + swizzle_yzwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 1 }); goto negate; + swizzle_zzwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 1 }); goto negate; + swizzle_wzwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 1 }); goto negate; + swizzle_xwwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 1 }); goto negate; + swizzle_ywwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 1 }); goto negate; + swizzle_zwwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 1 }); goto negate; + swizzle_wwwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 1 }); goto negate; + swizzle_xxxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 2 }); goto negate; + swizzle_yxxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 2 }); goto negate; + swizzle_zxxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 2 }); goto negate; + swizzle_wxxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 2 }); goto negate; + swizzle_xyxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 2 }); goto negate; + swizzle_yyxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 2 }); goto negate; + swizzle_zyxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 2 }); goto negate; + swizzle_wyxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 2 }); goto negate; + swizzle_xzxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 2 }); goto negate; + swizzle_yzxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 2 }); goto negate; + swizzle_zzxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 2 }); goto negate; + swizzle_wzxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 2 }); goto negate; + swizzle_xwxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 2 }); goto negate; + swizzle_ywxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 2 }); goto negate; + swizzle_zwxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 2 }); goto negate; + swizzle_wwxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 2 }); goto negate; + swizzle_xxyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 2 }); goto negate; + swizzle_yxyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 2 }); goto negate; + swizzle_zxyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 2 }); goto negate; + swizzle_wxyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 2 }); goto negate; + swizzle_xyyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 2 }); goto negate; + swizzle_yyyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 2 }); goto negate; + swizzle_zyyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 2 }); goto negate; + swizzle_wyyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 2 }); goto negate; + swizzle_xzyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 2 }); goto negate; + swizzle_yzyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 2 }); goto negate; + swizzle_zzyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 2 }); goto negate; + swizzle_wzyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 2 }); goto negate; + swizzle_xwyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 2 }); goto negate; + swizzle_ywyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 2 }); goto negate; + swizzle_zwyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 2 }); goto negate; + swizzle_wwyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 2 }); goto negate; + swizzle_xxzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 2 }); goto negate; + swizzle_yxzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 2 }); goto negate; + swizzle_zxzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 2 }); goto negate; + swizzle_wxzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 2 }); goto negate; + swizzle_xyzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 2 }); goto negate; + swizzle_yyzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 2 }); goto negate; + swizzle_zyzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 2 }); goto negate; + swizzle_wyzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 2 }); goto negate; + swizzle_xzzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 2 }); goto negate; + swizzle_yzzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 2 }); goto negate; + swizzle_zzzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 2 }); goto negate; + swizzle_wzzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 2 }); goto negate; + swizzle_xwzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 2 }); goto negate; + swizzle_ywzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 2 }); goto negate; + swizzle_zwzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 2 }); goto negate; + swizzle_wwzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 2 }); goto negate; + swizzle_xxwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 2 }); goto negate; + swizzle_yxwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 2 }); goto negate; + swizzle_zxwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 2 }); goto negate; + swizzle_wxwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 2 }); goto negate; + swizzle_xywz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 2 }); goto negate; + swizzle_yywz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 2 }); goto negate; + swizzle_zywz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 2 }); goto negate; + swizzle_wywz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 2 }); goto negate; + swizzle_xzwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 2 }); goto negate; + swizzle_yzwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 2 }); goto negate; + swizzle_zzwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 2 }); goto negate; + swizzle_wzwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 2 }); goto negate; + swizzle_xwwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 2 }); goto negate; + swizzle_ywwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 2 }); goto negate; + swizzle_zwwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 2 }); goto negate; + swizzle_wwwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 2 }); goto negate; + swizzle_xxxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 3 }); goto negate; + swizzle_yxxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 3 }); goto negate; + swizzle_zxxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 3 }); goto negate; + swizzle_wxxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 3 }); goto negate; + swizzle_xyxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 3 }); goto negate; + swizzle_yyxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 3 }); goto negate; + swizzle_zyxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 3 }); goto negate; + swizzle_wyxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 3 }); goto negate; + swizzle_xzxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 3 }); goto negate; + swizzle_yzxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 3 }); goto negate; + swizzle_zzxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 3 }); goto negate; + swizzle_wzxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 3 }); goto negate; + swizzle_xwxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 3 }); goto negate; + swizzle_ywxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 3 }); goto negate; + swizzle_zwxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 3 }); goto negate; + swizzle_wwxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 3 }); goto negate; + swizzle_xxyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 3 }); goto negate; + swizzle_yxyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 3 }); goto negate; + swizzle_zxyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 3 }); goto negate; + swizzle_wxyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 3 }); goto negate; + swizzle_xyyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 3 }); goto negate; + swizzle_yyyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 3 }); goto negate; + swizzle_zyyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 3 }); goto negate; + swizzle_wyyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 3 }); goto negate; + swizzle_xzyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 3 }); goto negate; + swizzle_yzyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 3 }); goto negate; + swizzle_zzyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 3 }); goto negate; + swizzle_wzyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 3 }); goto negate; + swizzle_xwyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 3 }); goto negate; + swizzle_ywyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 3 }); goto negate; + swizzle_zwyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 3 }); goto negate; + swizzle_wwyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 3 }); goto negate; + swizzle_xxzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 3 }); goto negate; + swizzle_yxzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 3 }); goto negate; + swizzle_zxzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 3 }); goto negate; + swizzle_wxzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 3 }); goto negate; + swizzle_xyzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 3 }); goto negate; + swizzle_yyzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 3 }); goto negate; + swizzle_zyzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 3 }); goto negate; + swizzle_wyzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 3 }); goto negate; + swizzle_xzzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 3 }); goto negate; + swizzle_yzzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 3 }); goto negate; + swizzle_zzzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 3 }); goto negate; + swizzle_wzzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 3 }); goto negate; + swizzle_xwzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 3 }); goto negate; + swizzle_ywzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 3 }); goto negate; + swizzle_zwzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 3 }); goto negate; + swizzle_wwzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 3 }); goto negate; + swizzle_xxww: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 3 }); goto negate; + swizzle_yxww: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 3 }); goto negate; + swizzle_zxww: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 3 }); goto negate; + swizzle_wxww: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 3 }); goto negate; + swizzle_xyww: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 3 }); goto negate; + swizzle_yyww: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 3 }); goto negate; + swizzle_zyww: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 3 }); goto negate; + swizzle_wyww: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 3 }); goto negate; + swizzle_xzww: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 3 }); goto negate; + swizzle_yzww: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 3 }); goto negate; + swizzle_zzww: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 3 }); goto negate; + swizzle_wzww: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 3 }); goto negate; + swizzle_xwww: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 3 }); goto negate; + swizzle_ywww: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 3 }); goto negate; + swizzle_zwww: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 3 }); goto negate; + swizzle_wwww: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 3 }); goto negate; + static void *swizzle_table[256] = { + &&swizzle_xxxx, &&swizzle_yxxx, &&swizzle_zxxx, &&swizzle_wxxx, + &&swizzle_xyxx, &&swizzle_yyxx, &&swizzle_zyxx, &&swizzle_wyxx, + &&swizzle_xzxx, &&swizzle_yzxx, &&swizzle_zzxx, &&swizzle_wzxx, + &&swizzle_xwxx, &&swizzle_ywxx, &&swizzle_zwxx, &&swizzle_wwxx, + &&swizzle_xxyx, &&swizzle_yxyx, &&swizzle_zxyx, &&swizzle_wxyx, + &&swizzle_xyyx, &&swizzle_yyyx, &&swizzle_zyyx, &&swizzle_wyyx, + &&swizzle_xzyx, &&swizzle_yzyx, &&swizzle_zzyx, &&swizzle_wzyx, + &&swizzle_xwyx, &&swizzle_ywyx, &&swizzle_zwyx, &&swizzle_wwyx, + &&swizzle_xxzx, &&swizzle_yxzx, &&swizzle_zxzx, &&swizzle_wxzx, + &&swizzle_xyzx, &&swizzle_yyzx, &&swizzle_zyzx, &&swizzle_wyzx, + &&swizzle_xzzx, &&swizzle_yzzx, &&swizzle_zzzx, &&swizzle_wzzx, + &&swizzle_xwzx, &&swizzle_ywzx, &&swizzle_zwzx, &&swizzle_wwzx, + &&swizzle_xxwx, &&swizzle_yxwx, &&swizzle_zxwx, &&swizzle_wxwx, + &&swizzle_xywx, &&swizzle_yywx, &&swizzle_zywx, &&swizzle_wywx, + &&swizzle_xzwx, &&swizzle_yzwx, &&swizzle_zzwx, &&swizzle_wzwx, + &&swizzle_xwwx, &&swizzle_ywwx, &&swizzle_zwwx, &&swizzle_wwwx, + &&swizzle_xxxy, &&swizzle_yxxy, &&swizzle_zxxy, &&swizzle_wxxy, + &&swizzle_xyxy, &&swizzle_yyxy, &&swizzle_zyxy, &&swizzle_wyxy, + &&swizzle_xzxy, &&swizzle_yzxy, &&swizzle_zzxy, &&swizzle_wzxy, + &&swizzle_xwxy, &&swizzle_ywxy, &&swizzle_zwxy, &&swizzle_wwxy, + &&swizzle_xxyy, &&swizzle_yxyy, &&swizzle_zxyy, &&swizzle_wxyy, + &&swizzle_xyyy, &&swizzle_yyyy, &&swizzle_zyyy, &&swizzle_wyyy, + &&swizzle_xzyy, &&swizzle_yzyy, &&swizzle_zzyy, &&swizzle_wzyy, + &&swizzle_xwyy, &&swizzle_ywyy, &&swizzle_zwyy, &&swizzle_wwyy, + &&swizzle_xxzy, &&swizzle_yxzy, &&swizzle_zxzy, &&swizzle_wxzy, + &&swizzle_xyzy, &&swizzle_yyzy, &&swizzle_zyzy, &&swizzle_wyzy, + &&swizzle_xzzy, &&swizzle_yzzy, &&swizzle_zzzy, &&swizzle_wzzy, + &&swizzle_xwzy, &&swizzle_ywzy, &&swizzle_zwzy, &&swizzle_wwzy, + &&swizzle_xxwy, &&swizzle_yxwy, &&swizzle_zxwy, &&swizzle_wxwy, + &&swizzle_xywy, &&swizzle_yywy, &&swizzle_zywy, &&swizzle_wywy, + &&swizzle_xzwy, &&swizzle_yzwy, &&swizzle_zzwy, &&swizzle_wzwy, + &&swizzle_xwwy, &&swizzle_ywwy, &&swizzle_zwwy, &&swizzle_wwwy, + &&swizzle_xxxz, &&swizzle_yxxz, &&swizzle_zxxz, &&swizzle_wxxz, + &&swizzle_xyxz, &&swizzle_yyxz, &&swizzle_zyxz, &&swizzle_wyxz, + &&swizzle_xzxz, &&swizzle_yzxz, &&swizzle_zzxz, &&swizzle_wzxz, + &&swizzle_xwxz, &&swizzle_ywxz, &&swizzle_zwxz, &&swizzle_wwxz, + &&swizzle_xxyz, &&swizzle_yxyz, &&swizzle_zxyz, &&swizzle_wxyz, + &&swizzle_xyyz, &&swizzle_yyyz, &&swizzle_zyyz, &&swizzle_wyyz, + &&swizzle_xzyz, &&swizzle_yzyz, &&swizzle_zzyz, &&swizzle_wzyz, + &&swizzle_xwyz, &&swizzle_ywyz, &&swizzle_zwyz, &&swizzle_wwyz, + &&swizzle_xxzz, &&swizzle_yxzz, &&swizzle_zxzz, &&swizzle_wxzz, + &&swizzle_xyzz, &&swizzle_yyzz, &&swizzle_zyzz, &&swizzle_wyzz, + &&swizzle_xzzz, &&swizzle_yzzz, &&swizzle_zzzz, &&swizzle_wzzz, + &&swizzle_xwzz, &&swizzle_ywzz, &&swizzle_zwzz, &&swizzle_wwzz, + &&swizzle_xxwz, &&swizzle_yxwz, &&swizzle_zxwz, &&swizzle_wxwz, + &&swizzle_xywz, &&swizzle_yywz, &&swizzle_zywz, &&swizzle_wywz, + &&swizzle_xzwz, &&swizzle_yzwz, &&swizzle_zzwz, &&swizzle_wzwz, + &&swizzle_xwwz, &&swizzle_ywwz, &&swizzle_zwwz, &&swizzle_wwwz, + &&swizzle_xxxw, &&swizzle_yxxw, &&swizzle_zxxw, &&swizzle_wxxw, + &&swizzle_xyxw, &&swizzle_yyxw, &&swizzle_zyxw, &&swizzle_wyxw, + &&swizzle_xzxw, &&swizzle_yzxw, &&swizzle_zzxw, &&swizzle_wzxw, + &&swizzle_xwxw, &&swizzle_ywxw, &&swizzle_zwxw, &&swizzle_wwxw, + &&swizzle_xxyw, &&swizzle_yxyw, &&swizzle_zxyw, &&swizzle_wxyw, + &&swizzle_xyyw, &&swizzle_yyyw, &&swizzle_zyyw, &&swizzle_wyyw, + &&swizzle_xzyw, &&swizzle_yzyw, &&swizzle_zzyw, &&swizzle_wzyw, + &&swizzle_xwyw, &&swizzle_ywyw, &&swizzle_zwyw, &&swizzle_wwyw, + &&swizzle_xxzw, &&swizzle_yxzw, &&swizzle_zxzw, &&swizzle_wxzw, + &&swizzle_xyzw, &&swizzle_yyzw, &&swizzle_zyzw, &&swizzle_wyzw, + &&swizzle_xzzw, &&swizzle_yzzw, &&swizzle_zzzw, &&swizzle_wzzw, + &&swizzle_xwzw, &&swizzle_ywzw, &&swizzle_zwzw, &&swizzle_wwzw, + &&swizzle_xxww, &&swizzle_yxww, &&swizzle_zxww, &&swizzle_wxww, + &&swizzle_xyww, &&swizzle_yyww, &&swizzle_zyww, &&swizzle_wyww, + &&swizzle_xzww, &&swizzle_yzww, &&swizzle_zzww, &&swizzle_wzww, + &&swizzle_xwww, &&swizzle_ywww, &&swizzle_zwww, &&swizzle_wwww, + }; +#undef swizzle + static const pr_ivec4_t neg[16] = { + { 0, 0, 0, 0 }, + { 1<<31, 0, 0, 0 }, + { 0, 1<<31, 0, 0 }, + { 1<<31, 1<<31, 0, 0 }, + { 0, 0, 1<<31, 0 }, + { 1<<31, 0, 1<<31, 0 }, + { 0, 1<<31, 1<<31, 0 }, + { 1<<31, 1<<31, 1<<31, 0 }, + { 0, 0, 0, 1<<31 }, + { 1<<31, 0, 0, 1<<31 }, + { 0, 1<<31, 0, 1<<31 }, + { 1<<31, 1<<31, 0, 1<<31 }, + { 0, 0, 1<<31, 1<<31 }, + { 1<<31, 0, 1<<31, 1<<31 }, + { 0, 1<<31, 1<<31, 1<<31 }, + { 1<<31, 1<<31, 1<<31, 1<<31 }, + }; + static const pr_ivec4_t zero[16] = { + { ~0, ~0, ~0, ~0 }, + { 0, ~0, ~0, ~0 }, + { ~0, 0, ~0, ~0 }, + { 0, 0, ~0, ~0 }, + { ~0, ~0, 0, ~0 }, + { 0, ~0, 0, ~0 }, + { ~0, 0, 0, ~0 }, + { 0, 0, 0, ~0 }, + { ~0, ~0, ~0, 0 }, + { 0, ~0, ~0, 0 }, + { ~0, 0, ~0, 0 }, + { 0, 0, ~0, 0 }, + { ~0, ~0, 0, 0 }, + { 0, ~0, 0, 0 }, + { ~0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + }; + +do_swizzle: + goto *swizzle_table[swiz & 0xff]; +negate: + vec ^= neg[(swiz >> 8) & 0xf]; + vec &= zero[(swiz >> 12) & 0xf]; + return vec; +} + +static pr_lvec4_t +#ifdef _WIN64 +//force gcc to use registers for the parameters to avoid alignment issues +//on the stack (gcc bug as of 11.2) +__attribute__((sysv_abi)) +#endif +pr_swizzle_d (pr_lvec4_t vec, pr_ushort_t swiz) +{ + goto do_swizzle; +#define swizzle __builtin_shuffle + swizzle_xxxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 0 }); goto negate; + swizzle_yxxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 0 }); goto negate; + swizzle_zxxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 0 }); goto negate; + swizzle_wxxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 0 }); goto negate; + swizzle_xyxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 0 }); goto negate; + swizzle_yyxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 0 }); goto negate; + swizzle_zyxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 0 }); goto negate; + swizzle_wyxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 0 }); goto negate; + swizzle_xzxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 0 }); goto negate; + swizzle_yzxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 0 }); goto negate; + swizzle_zzxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 0 }); goto negate; + swizzle_wzxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 0 }); goto negate; + swizzle_xwxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 0 }); goto negate; + swizzle_ywxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 0 }); goto negate; + swizzle_zwxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 0 }); goto negate; + swizzle_wwxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 0 }); goto negate; + swizzle_xxyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 0 }); goto negate; + swizzle_yxyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 0 }); goto negate; + swizzle_zxyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 0 }); goto negate; + swizzle_wxyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 0 }); goto negate; + swizzle_xyyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 0 }); goto negate; + swizzle_yyyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 0 }); goto negate; + swizzle_zyyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 0 }); goto negate; + swizzle_wyyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 0 }); goto negate; + swizzle_xzyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 0 }); goto negate; + swizzle_yzyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 0 }); goto negate; + swizzle_zzyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 0 }); goto negate; + swizzle_wzyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 0 }); goto negate; + swizzle_xwyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 0 }); goto negate; + swizzle_ywyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 0 }); goto negate; + swizzle_zwyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 0 }); goto negate; + swizzle_wwyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 0 }); goto negate; + swizzle_xxzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 0 }); goto negate; + swizzle_yxzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 0 }); goto negate; + swizzle_zxzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 0 }); goto negate; + swizzle_wxzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 0 }); goto negate; + swizzle_xyzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 0 }); goto negate; + swizzle_yyzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 0 }); goto negate; + swizzle_zyzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 0 }); goto negate; + swizzle_wyzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 0 }); goto negate; + swizzle_xzzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 0 }); goto negate; + swizzle_yzzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 0 }); goto negate; + swizzle_zzzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 0 }); goto negate; + swizzle_wzzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 0 }); goto negate; + swizzle_xwzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 0 }); goto negate; + swizzle_ywzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 0 }); goto negate; + swizzle_zwzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 0 }); goto negate; + swizzle_wwzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 0 }); goto negate; + swizzle_xxwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 0 }); goto negate; + swizzle_yxwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 0 }); goto negate; + swizzle_zxwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 0 }); goto negate; + swizzle_wxwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 0 }); goto negate; + swizzle_xywx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 0 }); goto negate; + swizzle_yywx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 0 }); goto negate; + swizzle_zywx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 0 }); goto negate; + swizzle_wywx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 0 }); goto negate; + swizzle_xzwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 0 }); goto negate; + swizzle_yzwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 0 }); goto negate; + swizzle_zzwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 0 }); goto negate; + swizzle_wzwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 0 }); goto negate; + swizzle_xwwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 0 }); goto negate; + swizzle_ywwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 0 }); goto negate; + swizzle_zwwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 0 }); goto negate; + swizzle_wwwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 0 }); goto negate; + swizzle_xxxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 1 }); goto negate; + swizzle_yxxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 1 }); goto negate; + swizzle_zxxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 1 }); goto negate; + swizzle_wxxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 1 }); goto negate; + swizzle_xyxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 1 }); goto negate; + swizzle_yyxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 1 }); goto negate; + swizzle_zyxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 1 }); goto negate; + swizzle_wyxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 1 }); goto negate; + swizzle_xzxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 1 }); goto negate; + swizzle_yzxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 1 }); goto negate; + swizzle_zzxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 1 }); goto negate; + swizzle_wzxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 1 }); goto negate; + swizzle_xwxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 1 }); goto negate; + swizzle_ywxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 1 }); goto negate; + swizzle_zwxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 1 }); goto negate; + swizzle_wwxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 1 }); goto negate; + swizzle_xxyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 1 }); goto negate; + swizzle_yxyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 1 }); goto negate; + swizzle_zxyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 1 }); goto negate; + swizzle_wxyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 1 }); goto negate; + swizzle_xyyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 1 }); goto negate; + swizzle_yyyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 1 }); goto negate; + swizzle_zyyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 1 }); goto negate; + swizzle_wyyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 1 }); goto negate; + swizzle_xzyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 1 }); goto negate; + swizzle_yzyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 1 }); goto negate; + swizzle_zzyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 1 }); goto negate; + swizzle_wzyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 1 }); goto negate; + swizzle_xwyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 1 }); goto negate; + swizzle_ywyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 1 }); goto negate; + swizzle_zwyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 1 }); goto negate; + swizzle_wwyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 1 }); goto negate; + swizzle_xxzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 1 }); goto negate; + swizzle_yxzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 1 }); goto negate; + swizzle_zxzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 1 }); goto negate; + swizzle_wxzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 1 }); goto negate; + swizzle_xyzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 1 }); goto negate; + swizzle_yyzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 1 }); goto negate; + swizzle_zyzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 1 }); goto negate; + swizzle_wyzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 1 }); goto negate; + swizzle_xzzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 1 }); goto negate; + swizzle_yzzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 1 }); goto negate; + swizzle_zzzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 1 }); goto negate; + swizzle_wzzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 1 }); goto negate; + swizzle_xwzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 1 }); goto negate; + swizzle_ywzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 1 }); goto negate; + swizzle_zwzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 1 }); goto negate; + swizzle_wwzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 1 }); goto negate; + swizzle_xxwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 1 }); goto negate; + swizzle_yxwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 1 }); goto negate; + swizzle_zxwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 1 }); goto negate; + swizzle_wxwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 1 }); goto negate; + swizzle_xywy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 1 }); goto negate; + swizzle_yywy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 1 }); goto negate; + swizzle_zywy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 1 }); goto negate; + swizzle_wywy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 1 }); goto negate; + swizzle_xzwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 1 }); goto negate; + swizzle_yzwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 1 }); goto negate; + swizzle_zzwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 1 }); goto negate; + swizzle_wzwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 1 }); goto negate; + swizzle_xwwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 1 }); goto negate; + swizzle_ywwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 1 }); goto negate; + swizzle_zwwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 1 }); goto negate; + swizzle_wwwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 1 }); goto negate; + swizzle_xxxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 2 }); goto negate; + swizzle_yxxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 2 }); goto negate; + swizzle_zxxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 2 }); goto negate; + swizzle_wxxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 2 }); goto negate; + swizzle_xyxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 2 }); goto negate; + swizzle_yyxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 2 }); goto negate; + swizzle_zyxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 2 }); goto negate; + swizzle_wyxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 2 }); goto negate; + swizzle_xzxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 2 }); goto negate; + swizzle_yzxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 2 }); goto negate; + swizzle_zzxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 2 }); goto negate; + swizzle_wzxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 2 }); goto negate; + swizzle_xwxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 2 }); goto negate; + swizzle_ywxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 2 }); goto negate; + swizzle_zwxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 2 }); goto negate; + swizzle_wwxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 2 }); goto negate; + swizzle_xxyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 2 }); goto negate; + swizzle_yxyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 2 }); goto negate; + swizzle_zxyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 2 }); goto negate; + swizzle_wxyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 2 }); goto negate; + swizzle_xyyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 2 }); goto negate; + swizzle_yyyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 2 }); goto negate; + swizzle_zyyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 2 }); goto negate; + swizzle_wyyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 2 }); goto negate; + swizzle_xzyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 2 }); goto negate; + swizzle_yzyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 2 }); goto negate; + swizzle_zzyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 2 }); goto negate; + swizzle_wzyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 2 }); goto negate; + swizzle_xwyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 2 }); goto negate; + swizzle_ywyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 2 }); goto negate; + swizzle_zwyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 2 }); goto negate; + swizzle_wwyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 2 }); goto negate; + swizzle_xxzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 2 }); goto negate; + swizzle_yxzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 2 }); goto negate; + swizzle_zxzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 2 }); goto negate; + swizzle_wxzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 2 }); goto negate; + swizzle_xyzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 2 }); goto negate; + swizzle_yyzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 2 }); goto negate; + swizzle_zyzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 2 }); goto negate; + swizzle_wyzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 2 }); goto negate; + swizzle_xzzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 2 }); goto negate; + swizzle_yzzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 2 }); goto negate; + swizzle_zzzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 2 }); goto negate; + swizzle_wzzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 2 }); goto negate; + swizzle_xwzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 2 }); goto negate; + swizzle_ywzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 2 }); goto negate; + swizzle_zwzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 2 }); goto negate; + swizzle_wwzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 2 }); goto negate; + swizzle_xxwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 2 }); goto negate; + swizzle_yxwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 2 }); goto negate; + swizzle_zxwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 2 }); goto negate; + swizzle_wxwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 2 }); goto negate; + swizzle_xywz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 2 }); goto negate; + swizzle_yywz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 2 }); goto negate; + swizzle_zywz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 2 }); goto negate; + swizzle_wywz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 2 }); goto negate; + swizzle_xzwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 2 }); goto negate; + swizzle_yzwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 2 }); goto negate; + swizzle_zzwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 2 }); goto negate; + swizzle_wzwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 2 }); goto negate; + swizzle_xwwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 2 }); goto negate; + swizzle_ywwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 2 }); goto negate; + swizzle_zwwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 2 }); goto negate; + swizzle_wwwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 2 }); goto negate; + swizzle_xxxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 3 }); goto negate; + swizzle_yxxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 3 }); goto negate; + swizzle_zxxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 3 }); goto negate; + swizzle_wxxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 3 }); goto negate; + swizzle_xyxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 3 }); goto negate; + swizzle_yyxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 3 }); goto negate; + swizzle_zyxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 3 }); goto negate; + swizzle_wyxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 3 }); goto negate; + swizzle_xzxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 3 }); goto negate; + swizzle_yzxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 3 }); goto negate; + swizzle_zzxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 3 }); goto negate; + swizzle_wzxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 3 }); goto negate; + swizzle_xwxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 3 }); goto negate; + swizzle_ywxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 3 }); goto negate; + swizzle_zwxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 3 }); goto negate; + swizzle_wwxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 3 }); goto negate; + swizzle_xxyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 3 }); goto negate; + swizzle_yxyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 3 }); goto negate; + swizzle_zxyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 3 }); goto negate; + swizzle_wxyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 3 }); goto negate; + swizzle_xyyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 3 }); goto negate; + swizzle_yyyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 3 }); goto negate; + swizzle_zyyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 3 }); goto negate; + swizzle_wyyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 3 }); goto negate; + swizzle_xzyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 3 }); goto negate; + swizzle_yzyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 3 }); goto negate; + swizzle_zzyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 3 }); goto negate; + swizzle_wzyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 3 }); goto negate; + swizzle_xwyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 3 }); goto negate; + swizzle_ywyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 3 }); goto negate; + swizzle_zwyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 3 }); goto negate; + swizzle_wwyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 3 }); goto negate; + swizzle_xxzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 3 }); goto negate; + swizzle_yxzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 3 }); goto negate; + swizzle_zxzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 3 }); goto negate; + swizzle_wxzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 3 }); goto negate; + swizzle_xyzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 3 }); goto negate; + swizzle_yyzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 3 }); goto negate; + swizzle_zyzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 3 }); goto negate; + swizzle_wyzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 3 }); goto negate; + swizzle_xzzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 3 }); goto negate; + swizzle_yzzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 3 }); goto negate; + swizzle_zzzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 3 }); goto negate; + swizzle_wzzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 3 }); goto negate; + swizzle_xwzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 3 }); goto negate; + swizzle_ywzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 3 }); goto negate; + swizzle_zwzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 3 }); goto negate; + swizzle_wwzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 3 }); goto negate; + swizzle_xxww: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 3 }); goto negate; + swizzle_yxww: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 3 }); goto negate; + swizzle_zxww: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 3 }); goto negate; + swizzle_wxww: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 3 }); goto negate; + swizzle_xyww: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 3 }); goto negate; + swizzle_yyww: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 3 }); goto negate; + swizzle_zyww: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 3 }); goto negate; + swizzle_wyww: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 3 }); goto negate; + swizzle_xzww: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 3 }); goto negate; + swizzle_yzww: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 3 }); goto negate; + swizzle_zzww: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 3 }); goto negate; + swizzle_wzww: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 3 }); goto negate; + swizzle_xwww: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 3 }); goto negate; + swizzle_ywww: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 3 }); goto negate; + swizzle_zwww: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 3 }); goto negate; + swizzle_wwww: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 3 }); goto negate; + static void *swizzle_table[256] = { + &&swizzle_xxxx, &&swizzle_yxxx, &&swizzle_zxxx, &&swizzle_wxxx, + &&swizzle_xyxx, &&swizzle_yyxx, &&swizzle_zyxx, &&swizzle_wyxx, + &&swizzle_xzxx, &&swizzle_yzxx, &&swizzle_zzxx, &&swizzle_wzxx, + &&swizzle_xwxx, &&swizzle_ywxx, &&swizzle_zwxx, &&swizzle_wwxx, + &&swizzle_xxyx, &&swizzle_yxyx, &&swizzle_zxyx, &&swizzle_wxyx, + &&swizzle_xyyx, &&swizzle_yyyx, &&swizzle_zyyx, &&swizzle_wyyx, + &&swizzle_xzyx, &&swizzle_yzyx, &&swizzle_zzyx, &&swizzle_wzyx, + &&swizzle_xwyx, &&swizzle_ywyx, &&swizzle_zwyx, &&swizzle_wwyx, + &&swizzle_xxzx, &&swizzle_yxzx, &&swizzle_zxzx, &&swizzle_wxzx, + &&swizzle_xyzx, &&swizzle_yyzx, &&swizzle_zyzx, &&swizzle_wyzx, + &&swizzle_xzzx, &&swizzle_yzzx, &&swizzle_zzzx, &&swizzle_wzzx, + &&swizzle_xwzx, &&swizzle_ywzx, &&swizzle_zwzx, &&swizzle_wwzx, + &&swizzle_xxwx, &&swizzle_yxwx, &&swizzle_zxwx, &&swizzle_wxwx, + &&swizzle_xywx, &&swizzle_yywx, &&swizzle_zywx, &&swizzle_wywx, + &&swizzle_xzwx, &&swizzle_yzwx, &&swizzle_zzwx, &&swizzle_wzwx, + &&swizzle_xwwx, &&swizzle_ywwx, &&swizzle_zwwx, &&swizzle_wwwx, + &&swizzle_xxxy, &&swizzle_yxxy, &&swizzle_zxxy, &&swizzle_wxxy, + &&swizzle_xyxy, &&swizzle_yyxy, &&swizzle_zyxy, &&swizzle_wyxy, + &&swizzle_xzxy, &&swizzle_yzxy, &&swizzle_zzxy, &&swizzle_wzxy, + &&swizzle_xwxy, &&swizzle_ywxy, &&swizzle_zwxy, &&swizzle_wwxy, + &&swizzle_xxyy, &&swizzle_yxyy, &&swizzle_zxyy, &&swizzle_wxyy, + &&swizzle_xyyy, &&swizzle_yyyy, &&swizzle_zyyy, &&swizzle_wyyy, + &&swizzle_xzyy, &&swizzle_yzyy, &&swizzle_zzyy, &&swizzle_wzyy, + &&swizzle_xwyy, &&swizzle_ywyy, &&swizzle_zwyy, &&swizzle_wwyy, + &&swizzle_xxzy, &&swizzle_yxzy, &&swizzle_zxzy, &&swizzle_wxzy, + &&swizzle_xyzy, &&swizzle_yyzy, &&swizzle_zyzy, &&swizzle_wyzy, + &&swizzle_xzzy, &&swizzle_yzzy, &&swizzle_zzzy, &&swizzle_wzzy, + &&swizzle_xwzy, &&swizzle_ywzy, &&swizzle_zwzy, &&swizzle_wwzy, + &&swizzle_xxwy, &&swizzle_yxwy, &&swizzle_zxwy, &&swizzle_wxwy, + &&swizzle_xywy, &&swizzle_yywy, &&swizzle_zywy, &&swizzle_wywy, + &&swizzle_xzwy, &&swizzle_yzwy, &&swizzle_zzwy, &&swizzle_wzwy, + &&swizzle_xwwy, &&swizzle_ywwy, &&swizzle_zwwy, &&swizzle_wwwy, + &&swizzle_xxxz, &&swizzle_yxxz, &&swizzle_zxxz, &&swizzle_wxxz, + &&swizzle_xyxz, &&swizzle_yyxz, &&swizzle_zyxz, &&swizzle_wyxz, + &&swizzle_xzxz, &&swizzle_yzxz, &&swizzle_zzxz, &&swizzle_wzxz, + &&swizzle_xwxz, &&swizzle_ywxz, &&swizzle_zwxz, &&swizzle_wwxz, + &&swizzle_xxyz, &&swizzle_yxyz, &&swizzle_zxyz, &&swizzle_wxyz, + &&swizzle_xyyz, &&swizzle_yyyz, &&swizzle_zyyz, &&swizzle_wyyz, + &&swizzle_xzyz, &&swizzle_yzyz, &&swizzle_zzyz, &&swizzle_wzyz, + &&swizzle_xwyz, &&swizzle_ywyz, &&swizzle_zwyz, &&swizzle_wwyz, + &&swizzle_xxzz, &&swizzle_yxzz, &&swizzle_zxzz, &&swizzle_wxzz, + &&swizzle_xyzz, &&swizzle_yyzz, &&swizzle_zyzz, &&swizzle_wyzz, + &&swizzle_xzzz, &&swizzle_yzzz, &&swizzle_zzzz, &&swizzle_wzzz, + &&swizzle_xwzz, &&swizzle_ywzz, &&swizzle_zwzz, &&swizzle_wwzz, + &&swizzle_xxwz, &&swizzle_yxwz, &&swizzle_zxwz, &&swizzle_wxwz, + &&swizzle_xywz, &&swizzle_yywz, &&swizzle_zywz, &&swizzle_wywz, + &&swizzle_xzwz, &&swizzle_yzwz, &&swizzle_zzwz, &&swizzle_wzwz, + &&swizzle_xwwz, &&swizzle_ywwz, &&swizzle_zwwz, &&swizzle_wwwz, + &&swizzle_xxxw, &&swizzle_yxxw, &&swizzle_zxxw, &&swizzle_wxxw, + &&swizzle_xyxw, &&swizzle_yyxw, &&swizzle_zyxw, &&swizzle_wyxw, + &&swizzle_xzxw, &&swizzle_yzxw, &&swizzle_zzxw, &&swizzle_wzxw, + &&swizzle_xwxw, &&swizzle_ywxw, &&swizzle_zwxw, &&swizzle_wwxw, + &&swizzle_xxyw, &&swizzle_yxyw, &&swizzle_zxyw, &&swizzle_wxyw, + &&swizzle_xyyw, &&swizzle_yyyw, &&swizzle_zyyw, &&swizzle_wyyw, + &&swizzle_xzyw, &&swizzle_yzyw, &&swizzle_zzyw, &&swizzle_wzyw, + &&swizzle_xwyw, &&swizzle_ywyw, &&swizzle_zwyw, &&swizzle_wwyw, + &&swizzle_xxzw, &&swizzle_yxzw, &&swizzle_zxzw, &&swizzle_wxzw, + &&swizzle_xyzw, &&swizzle_yyzw, &&swizzle_zyzw, &&swizzle_wyzw, + &&swizzle_xzzw, &&swizzle_yzzw, &&swizzle_zzzw, &&swizzle_wzzw, + &&swizzle_xwzw, &&swizzle_ywzw, &&swizzle_zwzw, &&swizzle_wwzw, + &&swizzle_xxww, &&swizzle_yxww, &&swizzle_zxww, &&swizzle_wxww, + &&swizzle_xyww, &&swizzle_yyww, &&swizzle_zyww, &&swizzle_wyww, + &&swizzle_xzww, &&swizzle_yzww, &&swizzle_zzww, &&swizzle_wzww, + &&swizzle_xwww, &&swizzle_ywww, &&swizzle_zwww, &&swizzle_wwww, + }; +#undef swizzle +#define L(x) UINT64_C(x) + static const pr_lvec4_t neg[16] = { + { INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(0), INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(0), INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63 }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63 }, + }; + static const pr_lvec4_t zero[16] = { + { ~INT64_C(0), ~INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), ~INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), ~INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { ~INT64_C(0), ~INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), INT64_C(0), INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(0) }, + }; + +do_swizzle: + goto *swizzle_table[swiz & 0xff]; +negate: + vec ^= neg[(swiz >> 8) & 0xf]; + vec &= zero[(swiz >> 12) & 0xf]; + return vec; +} + +static void +pr_exec_ruamoko (progs_t *pr, int exitdepth) +{ + int profile, startprofile; + dstatement_t *st; + pr_type_t old_val = {0}; + + // make a stack frame + startprofile = profile = 0; + + st = pr->pr_statements + pr->pr_xstatement; + + if (pr->watch) { + old_val = *pr->watch; + } + + while (1) { + st++; + ++pr->pr_xstatement; + if (pr->pr_xstatement != st - pr->pr_statements) + PR_RunError (pr, "internal error"); + if (++profile > 1000000 && !pr->no_exec_limit) { + PR_RunError (pr, "runaway loop error"); + } + + if (pr->pr_trace) { + if (pr->debug_handler) { + pr->debug_handler (prd_trace, 0, pr->debug_data); + } else { + PR_PrintStatement (pr, st, 1); + } + } + + if (st->op & OP_BREAK) { + if (pr->debug_handler) { + pr->debug_handler (prd_breakpoint, 0, pr->debug_data); + } else { + PR_RunError (pr, "breakpoint hit"); + } + } + + pr_ptr_t st_a = st->a + PR_BASE (pr, st, A); + pr_ptr_t st_b = st->b + PR_BASE (pr, st, B); + pr_ptr_t st_c = st->c + PR_BASE (pr, st, C); + + + pr_type_t *op_a = pr->pr_globals + st_a; + pr_type_t *op_b = pr->pr_globals + st_b; + pr_type_t *op_c = pr->pr_globals + st_c; + + pr_type_t *stk; + pr_type_t *mm; + pr_func_t function; + pr_opcode_e st_op = st->op & OP_MASK; + switch (st_op) { + // 0 0000 + case OP_NOP: + break; + case OP_ADJSTK: + pr_stack_adjust (pr, st->a, (short) st->b); + break; + case OP_LDCONST: + PR_RunError (pr, "OP_LDCONST not implemented"); + break; + case OP_LOAD_B_1: + case OP_LOAD_C_1: + case OP_LOAD_D_1: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_1 + 4) >> 2); + OPC(int) = MM(int); + break; + case OP_LOAD_B_2: + case OP_LOAD_C_2: + case OP_LOAD_D_2: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_2 + 4) >> 2); + OPC(ivec2) = MM(ivec2); + break; + case OP_LOAD_B_3: + case OP_LOAD_C_3: + case OP_LOAD_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_3 + 4) >> 2); + VectorCopy (&MM(int), &OPC(int)); + break; + case OP_LOAD_B_4: + case OP_LOAD_C_4: + case OP_LOAD_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_4 + 4) >> 2); + OPC(ivec4) = MM(ivec4); + break; + // 0 0001 + case OP_STORE_A_1: + case OP_STORE_B_1: + case OP_STORE_C_1: + case OP_STORE_D_1: + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_1) >> 2); + MM(int) = OPC(int); + break; + case OP_STORE_A_2: + case OP_STORE_B_2: + case OP_STORE_C_2: + case OP_STORE_D_2: + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_2) >> 2); + MM(ivec2) = OPC(ivec2); + break; + case OP_STORE_A_3: + case OP_STORE_B_3: + case OP_STORE_C_3: + case OP_STORE_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_3) >> 2); + VectorCopy (&OPC(int), &MM(int)); + break; + case OP_STORE_A_4: + case OP_STORE_B_4: + case OP_STORE_C_4: + case OP_STORE_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_4) >> 2); + MM(ivec4) = OPC(ivec4); + break; + // 0 0010 + case OP_PUSH_A_1: + case OP_PUSH_B_1: + case OP_PUSH_C_1: + case OP_PUSH_D_1: + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_1) >> 2); + stk = pr_stack_push (pr); + STK(int) = MM(int); + break; + case OP_PUSH_A_2: + case OP_PUSH_B_2: + case OP_PUSH_C_2: + case OP_PUSH_D_2: + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_2) >> 2); + stk = pr_stack_push (pr); + STK(ivec2) = MM(ivec2); + break; + case OP_PUSH_A_3: + case OP_PUSH_B_3: + case OP_PUSH_C_3: + case OP_PUSH_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_3) >> 2); + stk = pr_stack_push (pr); + VectorCopy (&MM(int), &STK(int)); + break; + case OP_PUSH_A_4: + case OP_PUSH_B_4: + case OP_PUSH_C_4: + case OP_PUSH_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_4) >> 2); + stk = pr_stack_push (pr); + STK(ivec4) = MM(ivec4); + break; + // 0 0011 + case OP_POP_A_1: + case OP_POP_B_1: + case OP_POP_C_1: + case OP_POP_D_1: + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_1) >> 2); + stk = pr_stack_pop (pr); + MM(int) = STK(int); + break; + case OP_POP_A_2: + case OP_POP_B_2: + case OP_POP_C_2: + case OP_POP_D_2: + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_2) >> 2); + stk = pr_stack_pop (pr); + MM(ivec2) = STK(ivec2); + break; + case OP_POP_A_3: + case OP_POP_B_3: + case OP_POP_C_3: + case OP_POP_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_3) >> 2); + stk = pr_stack_pop (pr); + VectorCopy (&STK(int), &MM(int)); + break; + case OP_POP_A_4: + case OP_POP_B_4: + case OP_POP_C_4: + case OP_POP_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_4) >> 2); + stk = pr_stack_pop (pr); + MM(ivec4) = STK(ivec4); + break; + // 0 0100 + // spare + // 0 0101 + // spare + // 0 0110 + // spare + // 0 0111 + // spare + +#define OP_cmp_1(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_1: \ + OPC(rt) = -(OPA(ct) cmp OPB(ct)); \ + break +#define OP_cmp_2(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_2: \ + OPC(rt) = (OPA(ct) cmp OPB(ct)); \ + break +#define OP_cmp_3(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_3: \ + VectorCompCompare (&OPC(rt), -, &OPA(ct), cmp, &OPB(ct)); \ + break; +#define OP_cmp_4(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_4: \ + OPC(rt) = (OPA(ct) cmp OPB(ct)); \ + break +#define OP_cmp_T(OP, T, rt1, rt2, rt4, cmp, ct1, ct2, ct4) \ + OP_cmp_1 (OP, T, rt1, cmp, ct1); \ + OP_cmp_2 (OP, T, rt2, cmp, ct2); \ + OP_cmp_3 (OP, T, rt1, cmp, ct1); \ + OP_cmp_4 (OP, T, rt4, cmp, ct4) +#define OP_cmp(OP, cmp) \ + OP_cmp_T (OP, I, int, ivec2, ivec4, cmp, int, ivec2, ivec4); \ + OP_cmp_T (OP, F, int, ivec2, ivec4, cmp, float, vec2, vec4); \ + OP_cmp_T (OP, L, long, lvec2, lvec4, cmp, long, lvec2, lvec4); \ + OP_cmp_T (OP, D, long, lvec2, lvec4, cmp, double, dvec2, dvec4) + + // 0 1000 + OP_cmp(EQ, ==); + // 0 1001 + OP_cmp(LT, <); + // 0 1010 + OP_cmp(GT, >); + +#define OP_op_1(OP, T, t, op) \ + case OP_##OP##_##T##_1: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_2(OP, T, t, op) \ + case OP_##OP##_##T##_2: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_3(OP, T, t, op) \ + case OP_##OP##_##T##_3: \ + VectorCompOp (&OPC(t), &OPA(t), op, &OPB(t)); \ + break; +#define OP_op_4(OP, T, t, op) \ + case OP_##OP##_##T##_4: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_T(OP, T, t1, t2, t4, op) \ + OP_op_1 (OP, T, t1, op); \ + OP_op_2 (OP, T, t2, op); \ + OP_op_3 (OP, T, t1, op); \ + OP_op_4 (OP, T, t4, op) + // 0 1011 + OP_op_T (DIV, u, uint, uivec2, uivec4, /); + OP_op_T (DIV, U, ulong, ulvec2, ulvec4, /); + OP_op_T (REM, u, uint, uivec2, uivec4, %); + OP_op_T (REM, U, ulong, ulvec2, ulvec4, %); + // 0 1100 + OP_cmp(NE, !=); + // 0 1101 + OP_cmp(GE, >=); + // 0 1110 + OP_cmp(LE, <=); + // 0 1111 + case OP_LOAD64_B_3: + case OP_LOAD64_C_3: + case OP_LOAD64_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD64_B_3 + 1)); + VectorCopy (&MM(long), &OPC(long)); + break; + case OP_STORE64_A_3: + case OP_STORE64_B_3: + case OP_STORE64_C_3: + case OP_STORE64_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_3)); + VectorCopy (&OPC(long), &MM(long)); + break; + case OP_LOAD64_B_4: + case OP_LOAD64_C_4: + case OP_LOAD64_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD64_B_4 + 1)); + OPC(lvec4) = MM(lvec4); + break; + case OP_STORE64_A_4: + case OP_STORE64_B_4: + case OP_STORE64_C_4: + case OP_STORE64_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_4)); + MM(lvec4) = OPC(lvec4); + break; + // spare + +#define OP_op(OP, op) \ + OP_op_T (OP, I, int, ivec2, ivec4, op); \ + OP_op_T (OP, F, float, vec2, vec4, op); \ + OP_op_T (OP, L, long, lvec2, lvec4, op); \ + OP_op_T (OP, D, double, dvec2, dvec4, op) +#define OP_uop_1(OP, T, t, op) \ + case OP_##OP##_##T##_1: \ + OPC(t) = op (OPA(t)); \ + break +#define OP_uop_2(OP, T, t, op) \ + case OP_##OP##_##T##_2: \ + OPC(t) = op (OPA(t)); \ + break +#define OP_uop_3(OP, T, t, op) \ + case OP_##OP##_##T##_3: \ + VectorCompUop (&OPC(t), op, &OPA(t)); \ + break; +#define OP_uop_4(OP, T, t, op) \ + case OP_##OP##_##T##_4: \ + OPC(t) = op (OPA(t)); \ + break +#define OP_uop_T(OP, T, t1, t2, t4, op) \ + OP_uop_1 (OP, T, t1, op); \ + OP_uop_2 (OP, T, t2, op); \ + OP_uop_3 (OP, T, t1, op); \ + OP_uop_4 (OP, T, t4, op) + + // 1 0000 + OP_op(MUL, *); + // 1 0001 + OP_op(DIV, /); + +// implement remainder (c %) for integers: +// 5 rem 3 = 2 +// -5 rem 3 = -2 +// 5 rem -3 = 2 +// -5 rem -3 = -2 +#define OP_store(d, s) *(d) = s +#define OP_remmod_T(OP, T, n, t, l, f, s) \ + case OP_##OP##_##T##_##n: \ + { \ + __auto_type a = l (&OPA(t)); \ + __auto_type b = l (&OPB(t)); \ + s (&OPC(t), a - b * f(a / b)); \ + } \ + break +#define OP_rem_T(T, n, t, l, f, s) \ + OP_remmod_T(REM, T, n, t, l, f, s) + + // 1 0010 + OP_op_T (REM, I, int, ivec2, ivec4, %); + OP_rem_T (F, 1, float, *, truncf, OP_store); + OP_rem_T (F, 2, vec2, *, vtrunc2f, OP_store); + OP_rem_T (F, 3, float, loadvec3f, vtrunc4f, storevec3f); + OP_rem_T (F, 4, vec4, *, vtrunc4f, OP_store); + OP_op_T (REM, L, long, lvec2, lvec4, %); + OP_rem_T (D, 1, double, *, trunc, OP_store); + OP_rem_T (D, 2, dvec2, *, vtrunc2d, OP_store); + OP_rem_T (D, 3, double, loadvec3d, vtrunc4d, storevec3d); + OP_rem_T (D, 4, dvec4, *, vtrunc4d, OP_store); + +// implement true modulo (python %) for integers: +// 5 mod 3 = 2 +// -5 mod 3 = 1 +// 5 mod -3 = -1 +// -5 mod -3 = -2 +#define OP_mod_Ti(T, n, t, l, m, s) \ + case OP_MOD_##T##_##n: \ + { \ + __auto_type a = l(&OPA(t)); \ + __auto_type b = l(&OPB(t)); \ + __auto_type c = a % b; \ + /* % is really remainder and so has the same sign rules */\ + /* as division: -5 % 3 = -2, so need to add b (3 here) */\ + /* if c's sign is incorrect, but only if c is non-zero */\ + __auto_type mask = m((a ^ b) < 0); \ + mask &= m(c != 0); \ + s(&OPC(t), c + (mask & b)); \ + } \ + break +// floating point modulo is so much easier :P (just use floor instead of trunc) +#define OP_mod_Tf(T, n, t, l, f, s) \ + OP_remmod_T(MOD, T, n, t, l, f, s) + + // 1 0011 + OP_mod_Ti (I, 1, int, *, -, OP_store); + OP_mod_Ti (I, 2, ivec2, *, +, OP_store); + OP_mod_Ti (I, 3, int, loadvec3i1, +, storevec3i); + OP_mod_Ti (I, 4, ivec4, *, +, OP_store); + OP_mod_Tf (F, 1, float, *, floorf, OP_store); + OP_mod_Tf (F, 2, vec2, *, vfloor2f, OP_store); + OP_mod_Tf (F, 3, float, loadvec3f, vfloor4f, storevec3f); + OP_mod_Tf (F, 4, vec4, *, vfloor4f, OP_store); + OP_mod_Ti (L, 1, long, *, -, OP_store); + OP_mod_Ti (L, 2, lvec2, *, +, OP_store); + OP_mod_Ti (L, 3, long, loadvec3l1, +, storevec3l); + OP_mod_Ti (L, 4, lvec4, *, +, OP_store); + OP_mod_Tf (D, 1, double, *, floor, OP_store); + OP_mod_Tf (D, 2, dvec2, *, vfloor2d, OP_store); + OP_mod_Tf (D, 3, double, loadvec3d, vfloor4d, storevec3d); + OP_mod_Tf (D, 4, dvec4, *, vfloor4d, OP_store); + + // 1 0100 + OP_op(ADD, +); + // 1 0101 + OP_op(SUB, -); + // 1 0110 + OP_op_T (SHL, I, int, ivec2, ivec4, <<); + OP_op_T (SHL, L, long, lvec2, lvec4, <<); + case OP_EQ_S: + case OP_LT_S: + case OP_GT_S: + case OP_CMP_S: + case OP_GE_S: + case OP_LE_S: + { + int cmp = strcmp (PR_GetString (pr, OPA(string)), + PR_GetString (pr, OPB(string))); + switch (st_op) { + case OP_EQ_S: cmp = -(cmp == 0); break; + case OP_LT_S: cmp = -(cmp < 0); break; + case OP_GT_S: cmp = -(cmp > 0); break; + case OP_GE_S: cmp = -(cmp >= 0); break; + case OP_LE_S: cmp = -(cmp <= 0); break; + case OP_CMP_S: break; + default: break; + } + OPC(int) = cmp; + } + break; + case OP_ADD_S: + OPC(string) = PR_CatStrings(pr, PR_GetString (pr, OPA(string)), + PR_GetString (pr, OPB(string))); + break; + case OP_NOT_S: + OPC(int) = -(!OPA(string) || !*PR_GetString (pr, OPA(string))); + break; + // 1 0111 + OP_op_T (ASR, I, int, ivec2, ivec4, >>); + OP_op_T (SHR, u, uint, uivec2, uivec4, >>); + OP_op_T (ASR, L, long, lvec2, lvec4, >>); + OP_op_T (SHR, U, ulong, ulvec2, ulvec4, >>); + // 1 1000 + OP_op_T (BITAND, I, int, ivec2, ivec4, &); + OP_op_T (BITOR, I, int, ivec2, ivec4, |); + OP_op_T (BITXOR, I, int, ivec2, ivec4, ^); + OP_uop_T (BITNOT, I, int, ivec2, ivec4, ~); + // 1 1001 + OP_cmp_T (LT, u, int, ivec2, ivec4, <, uint, uivec2, uivec4); + case OP_JUMP_A: + case OP_JUMP_B: + case OP_JUMP_C: + case OP_JUMP_D: + pr->pr_xstatement = pr_jump_mode (pr, st, st_op - OP_JUMP_A); + st = pr->pr_statements + pr->pr_xstatement; + break; + OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); + case OP_RETURN: + int ret_size = (st->c & 0x1f) + 1; // up to 32 words + if (st->c != 0xffff) { + mm = pr_address_mode (pr, st, st->c >> 5); + memcpy (&R_INT (pr), mm, ret_size * sizeof (*op_a)); + } + pr->pr_xfunction->profile += profile - startprofile; + startprofile = profile; + PR_LeaveFunction (pr, pr->pr_depth == exitdepth); + st = pr->pr_statements + pr->pr_xstatement; + if (pr->pr_depth== exitdepth) { + if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) { + pr->pr_trace = false; + } + goto exit_program; + } + break; + case OP_CALL_B: + case OP_CALL_C: + case OP_CALL_D: + mm = pr_call_mode (pr, st, st_op - OP_CALL_B + 1); + function = mm->func_var; + pr->pr_argc = 0; + // op_c specifies the location for the return value if any + pr->pr_xfunction->profile += profile - startprofile; + startprofile = profile; + PR_CallFunction (pr, function, op_c); + st = pr->pr_statements + pr->pr_xstatement; + break; + // 1 1010 + OP_cmp_T (GT, u, int, ivec2, ivec4, >, uint, uivec2, uivec4); + case OP_SWIZZLE_F: + OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b); + break; + case OP_SCALE_F_2: + OPC(vec2) = OPA(vec2) * OPB(float); + break; + case OP_SCALE_F_3: + VectorScale (&OPA(float), OPB(float), &OPC(float)); + break; + case OP_SCALE_F_4: + OPC(vec4) = OPA(vec4) * OPB(float); + break; + OP_cmp_T (GT, U, long, lvec2, lvec4, >, ulong, ulvec2, ulvec4); + case OP_SWIZZLE_D: + OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b); + break; + case OP_SCALE_D_2: + OPC(dvec2) = OPA(dvec2) * OPB(double); + break; + case OP_SCALE_D_3: + VectorScale (&OPA(double), OPB(double), &OPC(double)); + break; + case OP_SCALE_D_4: + OPC(dvec4) = OPA(dvec4) * OPB(double); + break; + // 1 1011 + case OP_CROSS_F: + { + pr_vec4_t a = loadvec3f (&OPA(float)); + pr_vec4_t b = loadvec3f (&OPB(float)); + pr_vec4_t c = crossf (a, b); + storevec3f (&OPC(float), c); + } + break; + case OP_CDOT_F: + OPC(vec2) = dot2f (OPA(vec2), OPB(vec2)); + break; + case OP_VDOT_F: + { + vec_t d = DotProduct (&OPA(float), + &OPB(float)); + VectorSet (d, d, d, &OPC(float)); + } + break; + case OP_QDOT_F: + OPC(vec4) = dotf (OPA(vec4), OPB(vec4)); + break; + case OP_CMUL_F: + OPC(vec2) = cmulf (OPA(vec2), OPB(vec2)); + break; + case OP_QVMUL_F: + { + pr_vec4_t v = loadvec3f (&OPB(float)); + v = qvmulf (OPA(vec4), v); + storevec3f (&OPC(float), v); + } + break; + case OP_VQMUL_F: + { + pr_vec4_t v = loadvec3f (&OPA(float)); + v = vqmulf (v, OPB(vec4)); + storevec3f (&OPC(float), v); + } + break; + case OP_QMUL_F: + OPC(vec4) = qmulf (OPA(vec4), OPB(vec4)); + break; + case OP_CROSS_D: + { + pr_dvec4_t a = loadvec3d (&OPA(double)); + pr_dvec4_t b = loadvec3d (&OPB(double)); + pr_dvec4_t c = crossd (a, b); + storevec3d (&OPC(double), c); + } + break; + case OP_CDOT_D: + OPC(dvec2) = dot2d (OPA(dvec2), OPB(dvec2)); + break; + case OP_VDOT_D: + { + double d = DotProduct (&OPA(double), + &OPB(double)); + VectorSet (d, d, d, &OPC(double)); + } + break; + case OP_QDOT_D: + OPC(dvec4) = dotd (OPA(dvec4), OPB(dvec4)); + break; + case OP_CMUL_D: + OPC(dvec2) = cmuld (OPA(dvec2), OPB(dvec2)); + break; + case OP_QVMUL_D: + { + pr_dvec4_t v = loadvec3d (&OPB(double)); + v = qvmuld (OPA(dvec4), v); + storevec3d (&OPC(double), v); + } + break; + case OP_VQMUL_D: + { + pr_dvec4_t v = loadvec3d (&OPA(double)); + v = vqmuld (v, OPB(dvec4)); + storevec3d (&OPC(double), v); + } + break; + case OP_QMUL_D: + OPC(dvec4) = qmuld (OPA(dvec4), OPB(dvec4)); + break; + // 1 1100 + OP_op_T (BITAND, L, long, lvec2, lvec4, &); + OP_op_T (BITOR, L, long, lvec2, lvec4, |); + OP_op_T (BITXOR, L, long, lvec2, lvec4, ^); + OP_uop_T (BITNOT, L, long, lvec2, lvec4, ~); + // 1 1101 + OP_cmp_T (GE, u, int, ivec2, ivec4, >=, uint, uivec2, uivec4); + case OP_MOVE_I: + memmove (op_c, op_a, st->b * sizeof (pr_type_t)); + break; + case OP_MOVE_P: + memmove (pr->pr_globals + OPC(ptr), pr->pr_globals + OPA(ptr), + OPB(uint) * sizeof (pr_type_t)); + break; + case OP_MOVE_PI: + memmove (pr->pr_globals + OPC(ptr), pr->pr_globals + OPA(ptr), + st->b * sizeof (pr_type_t)); + break; + case OP_STATE_ft: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.ftime + 0.1; + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4); + case OP_MEMSET_I: + pr_memset (op_c, OPA(int), st->b); + break; + case OP_MEMSET_P: + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), OPB(uint)); + break; + case OP_MEMSET_PI: + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), st->b); + break; + case OP_STATE_ftt: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.ftime + OPC(float); + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + // 1 1110 + OP_cmp_T (LE, u, int, ivec2, ivec4, <=, uint, uivec2, uivec4); + case OP_IFZ: + if (!OPC(int)) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFB: + if (OPC(int) < 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFA: + if (OPC(int) > 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_STATE_dt: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + double time = *pr->globals.dtime + 0.1; + *(double *) (&pr->pr_edict_area[nextthink]) = time; + pr->pr_edict_area[frame].int_var = OPA(int); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + OP_cmp_T (LE, U, long, lvec2, lvec4, <=, ulong, ulvec2, ulvec4); + case OP_IFNZ: + if (OPC(int)) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFAE: + if (OPC(int) >= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFBE: + if (OPC(int) <= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_STATE_dtt: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + double time = *pr->globals.dtime + OPC(double); + *(double *) (&pr->pr_edict_area[nextthink]) = time; + pr->pr_edict_area[frame].int_var = OPA(int); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + // 1 1111 + case OP_LEA_A: + case OP_LEA_B: + case OP_LEA_C: + case OP_LEA_D: + mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); + op_c->pointer_var = mm - pr->pr_globals; + break; + case OP_QV4MUL_F: + OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); + break; + case OP_V4QMUL_F: + OPC(vec4) = vqmulf (OPA(vec4), OPB(vec4)); + break; + case OP_QV4MUL_D: + OPC(dvec4) = qvmuld (OPA(dvec4), OPB(dvec4)); + break; + case OP_V4QMUL_D: + OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); + break; + case OP_BITAND_F: + OPC(float) = (int) OPA(float) & (int) OPB(float); + break; + case OP_BITOR_F: + OPC(float) = (int) OPA(float) | (int) OPB(float); + break; + case OP_BITXOR_F: + OPC(float) = (int) OPA(float) ^ (int) OPB(float); + break; + case OP_BITNOT_F: + OPC(float) = ~ (int) OPA(float); + break; + case OP_CONV: + switch (st->b) { +#include "libs/gamecode/pr_convert.cinc" + default: + PR_RunError (pr, "invalid conversion code: %04o", + st->b); + } + break; + case OP_WITH: + pr_with (pr, st); + break; + // 1110 spare +#define OP_hop2(vec, op) ((vec)[0] op (vec)[1]) +#define OP_hop3(vec, op) ((vec)[0] op (vec)[1] op (vec)[2]) +#define OP_hop4(vec, op) ((vec)[0] op (vec)[1] op (vec)[2] op (vec)[3]) + case OP_HOPS: + switch (st->b) { +#include "libs/gamecode/pr_hops.cinc" + default: + PR_RunError (pr, "invalid hops code: %04o", + st->b); + } + break; + default: + PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); + } + if (pr->watch && pr->watch->int_var != old_val.int_var) { + if (!pr->wp_conditional + || pr->watch->int_var == pr->wp_val.int_var) { + if (pr->debug_handler) { + pr->debug_handler (prd_watchpoint, 0, pr->debug_data); + } else { + PR_RunError (pr, "watchpoint hit: %d -> %d", + old_val.int_var, pr->watch->int_var); + } + } + old_val.int_var = pr->watch->int_var; + } + } +exit_program: +} +/* + PR_ExecuteProgram + + The interpretation main loop +*/ +VISIBLE void +PR_ExecuteProgram (progs_t *pr, pr_func_t fnum) +{ + Sys_PushSignalHook (signal_hook, pr); + Sys_PushErrorHandler (error_handler, pr); + + if (pr->debug_handler) { + pr->debug_handler (prd_subenter, &fnum, pr->debug_data); + } + + int exitdepth = pr->pr_depth; + if (!PR_CallFunction (pr, fnum, pr->pr_return)) { + // called a builtin instead of progs code + goto exit_program; + } + if (pr->progs->version < PROG_VERSION) { + pr_exec_quakec (pr, exitdepth); + } else { + pr_exec_ruamoko (pr, exitdepth); + } exit_program: if (pr->debug_handler) { pr->debug_handler (prd_subexit, 0, pr->debug_data); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 55c556aac..c2c3c31d1 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -46,6 +46,8 @@ #include "QF/sys.h" #include "QF/zone.h" +#include "QF/progs/pr_type.h" + #include "compat.h" VISIBLE cvar_t *pr_boundscheck; @@ -58,7 +60,7 @@ function_get_key (const void *f, void *_pr) { progs_t *pr = (progs_t*)_pr; dfunction_t *func = (dfunction_t*)f; - return PR_GetString (pr, func->s_name); + return PR_GetString (pr, func->name); } static const char * @@ -69,6 +71,14 @@ var_get_key (const void *d, void *_pr) return PR_GetString (pr, def->name); } +static const char * +type_get_key (const void *t, void *_pr) +{ + progs_t *pr = (progs_t *) _pr; + __auto_type type = (qfot_type_t *) t; + return PR_GetString (pr, type->encoding); +} + static void file_error (progs_t *pr, const char *path) { @@ -95,13 +105,10 @@ free_progs_mem (progs_t *pr, void *mem) } static int -align_size (int size) +align_size (int size, int align) { - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - size += sizeof (void*) - 1; - size &= ~(sizeof (void*) - 1); + size += align - 1; + size &= ~(align - 1); return size; } @@ -114,9 +121,10 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) dprograms_t progs; byte *base; byte *heap; - pr_def_t *xdefs_def = 0; ddef_t *global_ddefs; ddef_t *field_ddefs; + // absolute minimum alignment is 4 bytes + int alignment = sizeof (void *); if (!pr->file_error) pr->file_error = file_error; @@ -145,6 +153,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) ((int *) &progs)[i] = LittleLong (((int *) &progs)[i]); if (progs.version != PROG_VERSION + && progs.version != PROG_V6P_VERSION && progs.version != PROG_ID_VERSION) { if (progs.version < 0x00fff000) { PR_Error (pr, "%s has unrecognised version number (%u)", @@ -162,31 +171,36 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) PROG_VERSION & 0xfff); } } + if (progs.version == PROG_VERSION) { + // ensure SIMD types can be aligned (qfcc will align them within + // the progs memory map, so the engine needs to ensure the progs memory + // is aligned) + alignment = __alignof__(pr_lvec4_t); + } // Some compilers (eg, FTE) put extra data between the header and the // strings section. What's worse, they de-align the data. - offset_tweak = progs.ofs_strings % sizeof (pr_int_t); + offset_tweak = progs.strings.offset % sizeof (pr_int_t); offset_tweak = (sizeof (pr_int_t) - offset_tweak) % sizeof (pr_int_t); // size of progs themselves pr->progs_size = size + offset_tweak; Sys_MaskPrintf (SYS_dev, "Programs occupy %iK.\n", size / 1024); - pr->progs_size = align_size (pr->progs_size); - pr->zone_size = align_size (pr->zone_size); - pr->stack_size = align_size (pr->stack_size); + pr->progs_size = align_size (pr->progs_size, alignment); + pr->zone_size = align_size (pr->zone_size, alignment); + pr->stack_size = align_size (pr->stack_size, alignment); // size of edict asked for by progs, but at least 1 pr->pr_edict_size = max (1, progs.entityfields); - // round off to next highest multiple of 4 words - // this ensures that progs that try to align vectors and quaternions - // get what they want - pr->pr_edict_size += (4 - 1); - pr->pr_edict_size &= ~(4 - 1); + // edict size is in words + pr->pr_edict_size = align_size (pr->pr_edict_size, alignment / 4); pr->pr_edict_area_size = pr->max_edicts * pr->pr_edict_size; mem_size = pr->pr_edict_area_size * sizeof (pr_type_t); mem_size += pr->progs_size + pr->zone_size + pr->stack_size; + // space for return buffer + mem_size += PR_MAX_RETURN * sizeof (pr_type_t); // +1 for a nul terminator pr->progs = pr->allocate_progs_mem (pr, mem_size + 1); @@ -213,18 +227,22 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->zone = (memzone_t *) heap; } - pr->pr_functions = (dfunction_t *) (base + pr->progs->ofs_functions); - pr->pr_strings = (char *) base + pr->progs->ofs_strings; + pr->pr_functions = (dfunction_t *) (base + pr->progs->functions.offset); + pr->pr_strings = (char *) base + pr->progs->strings.offset; pr->pr_stringsize = (heap - base) + pr->zone_size; - global_ddefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); - field_ddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); - pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements); + global_ddefs = (ddef_t *) (base + pr->progs->globaldefs.offset); + field_ddefs = (ddef_t *) (base + pr->progs->fielddefs.offset); + pr->pr_statements = (dstatement_t *) (base + pr->progs->statements.offset); - pr->pr_globals = (pr_type_t *) (base + pr->progs->ofs_globals); + pr->pr_globals = (pr_type_t *) (base + pr->progs->globals.offset); pr->stack = (pr_type_t *) ((byte *) pr->zone + pr->zone_size); pr->stack_bottom = pr->stack - pr->pr_globals; pr->globals_size = (pr_type_t *) ((byte *) pr->stack + pr->stack_size) - pr->pr_globals; + if (pr->globals.stack && pr->stack_bottom) { + *pr->globals.stack = pr->globals_size; + } + pr->pr_return_buffer = pr->pr_globals + pr->globals_size; if (pr->zone) { PR_Zone_Init (pr); @@ -233,89 +251,105 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) Hash_FlushTable (pr->function_hash); Hash_FlushTable (pr->global_hash); Hash_FlushTable (pr->field_hash); + Hash_FlushTable (pr->type_hash); // byte swap the lumps - for (i = 0; i < pr->progs->numstatements; i++) { + for (i = 0; i < pr->progs->statements.count; i++) { pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op); pr->pr_statements[i].a = LittleShort (pr->pr_statements[i].a); pr->pr_statements[i].b = LittleShort (pr->pr_statements[i].b); pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c); } - for (i = 0; i < pr->progs->numfunctions; i++) { + for (i = 0; i < pr->progs->functions.count; i++) { pr->pr_functions[i].first_statement = LittleLong (pr->pr_functions[i].first_statement); - pr->pr_functions[i].parm_start = - LittleLong (pr->pr_functions[i].parm_start); - pr->pr_functions[i].s_name = LittleLong (pr->pr_functions[i].s_name); - pr->pr_functions[i].s_file = LittleLong (pr->pr_functions[i].s_file); - pr->pr_functions[i].numparms = - LittleLong (pr->pr_functions[i].numparms); + pr->pr_functions[i].params_start = + LittleLong (pr->pr_functions[i].params_start); + pr->pr_functions[i].name = LittleLong (pr->pr_functions[i].name); + pr->pr_functions[i].file = LittleLong (pr->pr_functions[i].file); + pr->pr_functions[i].numparams = + LittleLong (pr->pr_functions[i].numparams); pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals); - if (pr->pr_functions[i].s_name) + if (pr->pr_functions[i].name) Hash_Add (pr->function_hash, &pr->pr_functions[i]); } if (pr->pr_globaldefs) { free (pr->pr_globaldefs); } - pr->pr_globaldefs = calloc (pr->progs->numglobaldefs, sizeof (pr_def_t)); + pr->pr_globaldefs = calloc (pr->progs->globaldefs.count, sizeof (pr_def_t)); - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { pr_ushort_t safe_type = global_ddefs[i].type & ~DEF_SAVEGLOBAL; global_ddefs[i].type = LittleShort (global_ddefs[i].type); global_ddefs[i].ofs = LittleShort (global_ddefs[i].ofs); - global_ddefs[i].s_name = LittleLong (global_ddefs[i].s_name); + global_ddefs[i].name = LittleLong (global_ddefs[i].name); pr->pr_globaldefs[i].type = global_ddefs[i].type; pr->pr_globaldefs[i].size = pr_type_size[safe_type]; pr->pr_globaldefs[i].ofs = global_ddefs[i].ofs; - pr->pr_globaldefs[i].name = global_ddefs[i].s_name; + pr->pr_globaldefs[i].name = global_ddefs[i].name; Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); } if (pr->pr_fielddefs) { free (pr->pr_fielddefs); } - pr->pr_fielddefs = calloc (pr->progs->numfielddefs, sizeof (pr_def_t)); - for (i = 0; i < pr->progs->numfielddefs; i++) { + pr->pr_fielddefs = calloc (pr->progs->fielddefs.count, sizeof (pr_def_t)); + for (i = 0; i < pr->progs->fielddefs.count; i++) { field_ddefs[i].type = LittleShort (field_ddefs[i].type); if (field_ddefs[i].type & DEF_SAVEGLOBAL) PR_Error (pr, "PR_LoadProgs: DEF_SAVEGLOBAL on field def %zd", i); field_ddefs[i].ofs = LittleShort (field_ddefs[i].ofs); - field_ddefs[i].s_name = LittleLong (field_ddefs[i].s_name); + field_ddefs[i].name = LittleLong (field_ddefs[i].name); pr->pr_fielddefs[i].type = field_ddefs[i].type; pr->pr_fielddefs[i].ofs = field_ddefs[i].ofs; - pr->pr_fielddefs[i].name = field_ddefs[i].s_name; + pr->pr_fielddefs[i].name = field_ddefs[i].name; Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]); } - for (i = 0; i < pr->progs->numglobals; i++) + for (i = 0; i < pr->progs->globals.count; i++) ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); - xdefs_def = PR_FindGlobal (pr, ".xdefs"); + pr_def_t *types_def = PR_FindGlobal (pr, ".type_encodings"); + if (types_def) { + __auto_type encodings = &G_STRUCT (pr, qfot_type_encodings_t, + types_def->ofs); + pr->type_encodings = encodings->types; + qfot_type_t *type; + for (pr_ptr_t type_ptr = 4; type_ptr < encodings->size; + type_ptr += type->size) { + type = &G_STRUCT (pr, qfot_type_t, pr->type_encodings + type_ptr); + Hash_Add (pr->type_hash, type); + } + } else { + pr->type_encodings = 0; + } + + pr_def_t *xdefs_def = PR_FindGlobal (pr, ".xdefs"); if (xdefs_def) { pr_xdefs_t *xdefs = &G_STRUCT (pr, pr_xdefs_t, xdefs_def->ofs); xdef_t *xdef = &G_STRUCT (pr, xdef_t, xdefs->xdefs); pr_def_t *def; - for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs; + for (def = pr->pr_globaldefs, i = 0; i < pr->progs->globaldefs.count; i++, xdef++, def++) { def->ofs = xdef->ofs; def->type_encoding = xdef->type; } - for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs; + for (def = pr->pr_fielddefs, i = 0; i < pr->progs->fielddefs.count; i++, xdef++, def++) { def->ofs = xdef->ofs; def->type_encoding = xdef->type; } } else { pr_def_t *def; - for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs; + for (def = pr->pr_globaldefs, i = 0; i < pr->progs->globaldefs.count; i++, def++) { def->size = pr_type_size[def->type & ~DEF_SAVEGLOBAL]; } - for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs; + for (def = pr->pr_fielddefs, i = 0; i < pr->progs->fielddefs.count; i++, def++) { def->size = pr_type_size[def->type & ~DEF_SAVEGLOBAL]; } @@ -363,9 +397,9 @@ pr_run_ctors (progs_t *pr) pr_uint_t fnum; dfunction_t *func; - for (fnum = 0; fnum < pr->progs->numfunctions; fnum++) { + for (fnum = 0; fnum < pr->progs->functions.count; fnum++) { func = pr->pr_functions + fnum; - if (strequal (PR_GetString (pr, func->s_name), ".ctor")) + if (strequal (PR_GetString (pr, func->name), ".ctor")) PR_ExecuteProgram (pr, fnum); } return 1; @@ -478,7 +512,6 @@ PR_Init_Cvars (void) VISIBLE void PR_Init (progs_t *pr) { - PR_Opcode_Init (); // idempotent PR_Resources_Init (pr); PR_Strings_Init (pr); PR_Debug_Init (pr); @@ -488,6 +521,8 @@ PR_Init (progs_t *pr) pr->hashlink_freelist); pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr, pr->hashlink_freelist); + pr->type_hash = Hash_NewTable (1021, type_get_key, 0, pr, + pr->hashlink_freelist); } VISIBLE void diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 2c893b39f..34a36c242 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1,12 +1,12 @@ /* - #FILENAME# + pr_opcode.c - #DESCRIPTION# + Ruamoko instruction set opcode tables. - Copyright (C) 2001 #AUTHOR# + Copyright (C) 2022 Bill Currie - Author: #AUTHOR# - Date: #DATE# + Author: Bill Currie + Date: 2022/1/4 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -31,1764 +31,42 @@ # include "config.h" #endif -#ifdef HAVE_STRING_H -# include "string.h" -#endif -#ifdef HAVE_STRINGS_H -# include "strings.h" -#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; +#define EV_TYPE(type) PR_SIZEOF(type), VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { - 1, // ev_void - 1, // ev_string - 1, // ev_float - 3, // ev_vector - 1, // ev_entity - 1, // ev_field - 1, // ev_func - 1, // ev_pointer - 4, // ev_quat - 1, // ev_integer - 1, // ev_uinteger - 0, // ev_short value in opcode - 2, // ev_double +#include "QF/progs/pr_type_names.h" 0, // ev_invalid not a valid/simple type }; +#define EV_TYPE(type) PR_ALIGNOF(type), +VISIBLE const pr_ushort_t pr_type_alignment[ev_type_count] = { +#include "QF/progs/pr_type_names.h" + 0, // ev_invalid not a valid/simple type +}; + +#define EV_TYPE(type) #type, VISIBLE const char * const pr_type_name[ev_type_count] = { - "void", - "string", - "float", - "vector", - "entity", - "field", - "function", - "pointer", - "quaternion", - "integer", - "uinteger", - "short", - "double", +#include "QF/progs/pr_type_names.h" "invalid", }; -// default format is "%Ga, %Gb, %gc" -// V global_string, contents, void -// G global_string, contents -// g global_string, no contents -// s as short -// O address + short -// P function parameter -// F function (must come before any P) -// R return value -// E entity + field (%Eab) -// -// a operand a -// b operand b -// c operand c -// 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 - ev_entity, ev_field, ev_void, // OP_RETURN, the types are bogus - PROG_ID_VERSION, - "%Va", - }, - - {"*", "mul.d", OP_MUL_D, false, - ev_double, ev_double, ev_double, - PROG_VERSION, - }, - {"*", "mul.f", OP_MUL_F, false, - ev_float, ev_float, ev_float, - PROG_ID_VERSION, - }, - {"*", "mul.v", OP_MUL_V, false, - ev_vector, ev_vector, ev_float, - PROG_ID_VERSION, - }, - {"*", "mul.fv", OP_MUL_FV, false, - ev_float, ev_vector, ev_vector, - PROG_ID_VERSION, - }, - {"*", "mul.vf", OP_MUL_VF, false, - ev_vector, ev_float, ev_vector, - PROG_ID_VERSION, - }, - {"*", "mul.dv", OP_MUL_DV, false, - ev_double, ev_vector, ev_vector, - PROG_ID_VERSION, - }, - {"*", "mul.vd", OP_MUL_VD, false, - ev_vector, ev_double, ev_vector, - PROG_ID_VERSION, - }, - {"*", "mul.q", OP_MUL_Q, false, - ev_quat, ev_quat, ev_quat, - PROG_VERSION, - }, - {"*", "mul.fq", OP_MUL_FQ, false, - ev_float, ev_quat, ev_quat, - PROG_VERSION, - }, - {"*", "mul.qf", OP_MUL_QF, false, - ev_quat, ev_float, ev_quat, - PROG_VERSION, - }, - {"*", "mul.dq", OP_MUL_DQ, false, - ev_double, ev_quat, ev_quat, - PROG_VERSION, - }, - {"*", "mul.qd", OP_MUL_QD, false, - ev_quat, ev_double, ev_quat, - PROG_VERSION, - }, - {"*", "mul.qv", OP_MUL_QV, false, - ev_quat, ev_vector, ev_vector, - PROG_VERSION, - }, - - {"~", "conj.q", OP_CONJ_Q, false, - ev_quat, ev_invalid, ev_quat, - PROG_VERSION, - "%Ga, %gc", - }, - - {"/", "div.f", OP_DIV_F, false, - ev_float, ev_float, ev_float, - PROG_ID_VERSION, - }, - {"/", "div.d", OP_DIV_D, false, - ev_double, ev_double, ev_double, - PROG_VERSION, - }, - {"%", "rem.d", OP_REM_D, false, - ev_double, ev_double, ev_double, - PROG_VERSION, - }, - {"%%", "mod.d", OP_MOD_D, false, - ev_double, ev_double, ev_double, - PROG_VERSION, - }, - - {"+", "add.d", OP_ADD_D, false, - ev_double, ev_double, ev_double, - PROG_VERSION, - }, - {"+", "add.f", OP_ADD_F, false, - ev_float, ev_float, ev_float, - PROG_ID_VERSION, - }, - {"+", "add.v", OP_ADD_V, false, - ev_vector, ev_vector, ev_vector, - PROG_ID_VERSION, - }, - {"+", "add.q", OP_ADD_Q, false, - ev_quat, ev_quat, ev_quat, - PROG_VERSION, - }, - {"+", "add.s", OP_ADD_S, false, - ev_string, ev_string, ev_string, - PROG_VERSION, - }, - - {"-", "sub.d", OP_SUB_D, false, - ev_double, ev_double, ev_double, - PROG_VERSION, - }, - {"-", "sub.f", OP_SUB_F, false, - ev_float, ev_float, ev_float, - PROG_ID_VERSION, - }, - {"-", "sub.v", OP_SUB_V, false, - ev_vector, ev_vector, ev_vector, - PROG_ID_VERSION, - }, - {"-", "sub.q", OP_SUB_Q, false, - ev_quat, ev_quat, ev_quat, - PROG_VERSION, - }, - - {"==", "eq.d", OP_EQ_D, false, - ev_double, ev_double, ev_integer, - PROG_VERSION, - }, - {"==", "eq.f", OP_EQ_F, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - {"==", "eq.v", OP_EQ_V, false, - ev_vector, ev_vector, ev_integer, - PROG_ID_VERSION, - }, - {"==", "eq.q", OP_EQ_Q, false, - ev_quat, ev_quat, ev_integer, - PROG_VERSION, - }, - {"==", "eq.s", OP_EQ_S, false, - ev_string, ev_string, ev_integer, - PROG_ID_VERSION, - }, - {"==", "eq.e", OP_EQ_E, false, - ev_entity, ev_entity, ev_integer, - PROG_ID_VERSION, - }, - {"==", "eq.fn", OP_EQ_FN, false, - ev_func, ev_func, ev_integer, - PROG_ID_VERSION, - }, - - {"!=", "ne.d", OP_NE_D, false, - ev_double, ev_double, ev_integer, - PROG_VERSION, - }, - {"!=", "ne.f", OP_NE_F, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - {"!=", "ne.v", OP_NE_V, false, - ev_vector, ev_vector, ev_integer, - PROG_ID_VERSION, - }, - {"!=", "ne.q", OP_NE_Q, false, - ev_quat, ev_quat, ev_integer, - PROG_VERSION, - }, - {"!=", "ne.s", OP_NE_S, false, - ev_string, ev_string, ev_integer, - PROG_ID_VERSION, - }, - {"!=", "ne.e", OP_NE_E, false, - ev_entity, ev_entity, ev_integer, - PROG_ID_VERSION, - }, - {"!=", "ne.fn", OP_NE_FN, false, - ev_func, ev_func, ev_integer, - PROG_ID_VERSION, - }, - - {"<=", "le.d", OP_LE_D, false, - ev_double, ev_double, ev_integer, - PROG_VERSION, - }, - {"<=", "le.f", OP_LE_F, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - {">=", "ge.d", OP_GE_D, false, - ev_double, ev_double, ev_integer, - PROG_VERSION, - }, - {">=", "ge.f", OP_GE_F, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - {"<=", "le.s", OP_LE_S, false, - ev_string, ev_string, ev_integer, - PROG_VERSION, - }, - {">=", "ge.s", OP_GE_S, false, - ev_string, ev_string, ev_integer, - PROG_VERSION, - }, - {"<", "lt.d", OP_LT_D, false, - ev_double, ev_double, ev_integer, - PROG_VERSION, - }, - {"<", "lt.f", OP_LT_F, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - {">", "gt.d", OP_GT_D, false, - ev_double, ev_double, ev_integer, - PROG_VERSION, - }, - {">", "gt.f", OP_GT_F, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - {"<", "lt.s", OP_LT_S, false, - ev_string, ev_string, ev_integer, - PROG_VERSION, - }, - {">", "gt.s", OP_GT_S, false, - ev_string, ev_string, ev_integer, - PROG_VERSION, - }, - - {".", "load.f", OP_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, - ev_entity, ev_field, ev_double, - PROG_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.v", OP_LOAD_V, false, - ev_entity, ev_field, ev_vector, - PROG_ID_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.q", OP_LOAD_Q, false, - ev_entity, ev_field, ev_quat, - PROG_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.s", OP_LOAD_S, false, - ev_entity, ev_field, ev_string, - PROG_ID_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.ent", OP_LOAD_ENT, false, - ev_entity, ev_field, ev_entity, - PROG_ID_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.fld", OP_LOAD_FLD, false, - ev_entity, ev_field, ev_field, - PROG_ID_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.fn", OP_LOAD_FN, false, - ev_entity, ev_field, ev_func, - PROG_ID_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.i", OP_LOAD_I, false, - ev_entity, ev_field, ev_integer, - PROG_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - {".", "load.p", OP_LOAD_P, false, - ev_entity, ev_field, ev_pointer, - PROG_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - - {".", "loadb.d", OP_LOADB_D, false, - ev_pointer, ev_integer, ev_double, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.f", OP_LOADB_F, false, - ev_pointer, ev_integer, ev_float, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.v", OP_LOADB_V, false, - ev_pointer, ev_integer, ev_vector, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.q", OP_LOADB_Q, false, - ev_pointer, ev_integer, ev_quat, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.s", OP_LOADB_S, false, - ev_pointer, ev_integer, ev_string, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.ent", OP_LOADB_ENT, false, - ev_pointer, ev_integer, ev_entity, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.fld", OP_LOADB_FLD, false, - ev_pointer, ev_integer, ev_field, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.fn", OP_LOADB_FN, false, - ev_pointer, ev_integer, ev_func, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.i", OP_LOADB_I, false, - ev_pointer, ev_integer, ev_integer, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - {".", "loadb.p", OP_LOADB_P, false, - ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, - "*(%Ga + %Gb), %gc", - }, - - {".", "loadbi.d", OP_LOADBI_D, false, - ev_pointer, ev_short, ev_double, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.f", OP_LOADBI_F, false, - ev_pointer, ev_short, ev_float, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.v", OP_LOADBI_V, false, - ev_pointer, ev_short, ev_vector, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.q", OP_LOADBI_Q, false, - ev_pointer, ev_short, ev_quat, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.s", OP_LOADBI_S, false, - ev_pointer, ev_short, ev_string, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.ent", OP_LOADBI_ENT, false, - ev_pointer, ev_short, ev_entity, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.fld", OP_LOADBI_FLD, false, - ev_pointer, ev_short, ev_field, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.fn", OP_LOADBI_FN, false, - ev_pointer, ev_short, ev_func, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.i", OP_LOADBI_I, false, - ev_pointer, ev_short, ev_integer, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - {".", "loadbi.p", OP_LOADBI_P, false, - ev_pointer, ev_short, ev_pointer, - PROG_VERSION, - "*(%Ga + %sb), %gc", - }, - - {"&", "address", OP_ADDRESS, false, - ev_entity, ev_field, ev_pointer, - PROG_ID_VERSION, - "%Ga.%Gb(%Ec), %gc", - }, - - {"&", "address", OP_ADDRESS_VOID, false, - ev_void, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.d", OP_ADDRESS_D, false, - ev_double, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.f", OP_ADDRESS_F, false, - ev_float, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.v", OP_ADDRESS_V, false, - ev_vector, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.q", OP_ADDRESS_Q, false, - ev_quat, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.s", OP_ADDRESS_S, false, - ev_string, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.ent", OP_ADDRESS_ENT, false, - ev_entity, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.fld", OP_ADDRESS_FLD, false, - ev_field, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.fn", OP_ADDRESS_FN, false, - ev_func, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.i", OP_ADDRESS_I, false, - ev_integer, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - {"&", "address.p", OP_ADDRESS_P, false, - ev_pointer, ev_invalid, ev_pointer, - PROG_VERSION, - "%Ga, %gc", - }, - - {"&", "lea", OP_LEA, false, - ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, - "(%Ga + %Gb), %gc", - }, - {"&", "leai", OP_LEAI, false, - ev_pointer, ev_short, ev_pointer, - PROG_VERSION, - "(%Ga + %sb), %gc", - }, - - {"", "conv.if", OP_CONV_IF, false, - ev_integer, ev_invalid, ev_float, - PROG_VERSION, - "%Ga, %gc", - }, - {"", "conv.fi", OP_CONV_FI, false, - ev_float, ev_invalid, ev_integer, - PROG_VERSION, - "%Ga, %gc", - }, - {"", "conv.id", OP_CONV_ID, false, - ev_integer, ev_invalid, ev_double, - PROG_VERSION, - "%Ga, %gc", - }, - {"", "conv.di", OP_CONV_DI, false, - ev_double, ev_invalid, ev_integer, - PROG_VERSION, - "%Ga, %gc", - }, - {"", "conv.fd", OP_CONV_FD, false, - ev_float, ev_invalid, ev_double, - PROG_VERSION, - "%Ga, %gc", - }, - {"", "conv.df", OP_CONV_DF, false, - ev_double, ev_invalid, ev_float, - PROG_VERSION, - "%Ga, %gc", - }, - - {"=", "store.d", OP_STORE_D, true, - ev_double, ev_double, ev_invalid, - PROG_VERSION, - "%Ga, %gb", - }, - {"=", "store.f", OP_STORE_F, true, - ev_float, ev_float, ev_invalid, - PROG_ID_VERSION, - "%Ga, %gb", - }, - {"=", "store.v", OP_STORE_V, true, - ev_vector, ev_vector, ev_invalid, - PROG_ID_VERSION, - "%Ga, %gb", - }, - {"=", "store.q", OP_STORE_Q, true, - ev_quat, ev_quat, ev_invalid, - PROG_VERSION, - "%Ga, %gb", - }, - {"=", "store.s", OP_STORE_S, true, - ev_string, ev_string, ev_invalid, - PROG_ID_VERSION, - "%Ga, %gb", - }, - {"=", "store.ent", OP_STORE_ENT, true, - ev_entity, ev_entity, ev_invalid, - PROG_ID_VERSION, - "%Ga, %gb", - }, - {"=", "store.fld", OP_STORE_FLD, true, - ev_field, ev_field, ev_invalid, - PROG_ID_VERSION, - "%Ga, %gb", - }, - {"=", "store.fn", OP_STORE_FN, true, - ev_func, ev_func, ev_invalid, - PROG_ID_VERSION, - "%Ga, %gb", - }, - {"=", "store.i", OP_STORE_I, true, - ev_integer, ev_integer, ev_invalid, - PROG_VERSION, - "%Ga, %gb", - }, - {"=", "store.p", OP_STORE_P, true, - ev_pointer, ev_pointer, ev_invalid, - PROG_VERSION, - "%Ga, %gb", - }, - - {".=", "storep.d", OP_STOREP_D, true, - ev_double, ev_pointer, ev_invalid, - PROG_ID_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.f", OP_STOREP_F, true, - ev_float, ev_pointer, ev_invalid, - PROG_ID_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.v", OP_STOREP_V, true, - ev_vector, ev_pointer, ev_invalid, - PROG_ID_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.q", OP_STOREP_Q, true, - ev_quat, ev_pointer, ev_invalid, - PROG_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.s", OP_STOREP_S, true, - ev_string, ev_pointer, ev_invalid, - PROG_ID_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.ent", OP_STOREP_ENT, true, - ev_entity, ev_pointer, ev_invalid, - PROG_ID_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.fld", OP_STOREP_FLD, true, - ev_field, ev_pointer, ev_invalid, - PROG_ID_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.fn", OP_STOREP_FN, true, - ev_func, ev_pointer, ev_invalid, - PROG_ID_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.i", OP_STOREP_I, true, - ev_integer, ev_pointer, ev_invalid, - PROG_VERSION, - "%Ga, *%Gb", - }, - {".=", "storep.p", OP_STOREP_P, true, - ev_pointer, ev_pointer, ev_invalid, - PROG_VERSION, - "%Ga, *%Gb", - }, - - {".=", "storeb.d", OP_STOREB_D, true, - ev_double, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.f", OP_STOREB_F, true, - ev_float, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.v", OP_STOREB_V, true, - ev_vector, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.q", OP_STOREB_Q, true, - ev_quat, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.s", OP_STOREB_S, true, - ev_string, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.ent", OP_STOREB_ENT, true, - ev_entity, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.fld", OP_STOREB_FLD, true, - ev_field, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.fn", OP_STOREB_FN, true, - ev_func, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.i", OP_STOREB_I, true, - ev_integer, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - {".=", "storeb.p", OP_STOREB_P, true, - ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, - "%Ga, *(%Gb + %Gc)", - }, - - {".=", "storebi.d", OP_STOREBI_D, true, - ev_double, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.f", OP_STOREBI_F, true, - ev_float, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.v", OP_STOREBI_V, true, - ev_vector, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.q", OP_STOREBI_Q, true, - ev_quat, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.s", OP_STOREBI_S, true, - ev_string, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.ent", OP_STOREBI_ENT, true, - ev_entity, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.fld", OP_STOREBI_FLD, true, - ev_field, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.fn", OP_STOREBI_FN, true, - ev_func, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.i", OP_STOREBI_I, true, - ev_integer, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - {".=", "storebi.p", OP_STOREBI_P, true, - ev_pointer, ev_pointer, ev_short, - PROG_VERSION, - "%Ga, *(%Gb + %sc)", - }, - - {"", "return", OP_RETURN, false, - ev_void, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Ra", - }, - - {"", "return", OP_RETURN_V, false, - ev_invalid, ev_invalid, ev_invalid, - PROG_VERSION, - "", - }, - - {"!", "not.d", OP_NOT_D, false, - ev_double, ev_invalid, ev_integer, - PROG_VERSION, - "%Ga, %gc", - }, - {"!", "not.f", OP_NOT_F, false, - ev_float, ev_invalid, ev_integer, - PROG_ID_VERSION, - "%Ga, %gc", - }, - {"!", "not.v", OP_NOT_V, false, - ev_vector, ev_invalid, ev_integer, - PROG_ID_VERSION, - "%Ga, %gc", - }, - {"!", "not.q", OP_NOT_Q, false, - ev_quat, ev_invalid, ev_integer, - PROG_VERSION, - "%Ga, %gc", - }, - {"!", "not.s", OP_NOT_S, false, - ev_string, ev_invalid, ev_integer, - PROG_ID_VERSION, - "%Ga, %gc", - }, - {"!", "not.ent", OP_NOT_ENT, false, - ev_entity, ev_invalid, ev_integer, - PROG_ID_VERSION, - "%Ga, %gc", - }, - {"!", "not.fn", OP_NOT_FN, false, - ev_func, ev_invalid, ev_integer, - PROG_ID_VERSION, - "%Ga, %gc", - }, - {"!", "not.p", OP_NOT_P, false, - ev_pointer, ev_invalid, ev_integer, - PROG_VERSION, - "%Ga, %gc", - }, - - {"", "if", OP_IF, false, - ev_integer, ev_short, ev_invalid, - PROG_ID_VERSION, - "%Ga branch %sb (%Ob)", - }, - {"", "ifnot", OP_IFNOT, false, - ev_integer, ev_short, ev_invalid, - PROG_ID_VERSION, - "%Ga branch %sb (%Ob)", - }, - {"", "ifbe", OP_IFBE, true, - ev_integer, ev_short, ev_invalid, - PROG_VERSION, - "%Ga branch %sb (%Ob)", - }, - {"", "ifb", OP_IFB, true, - ev_integer, ev_short, ev_invalid, - PROG_VERSION, - "%Ga branch %sb (%Ob)", - }, - {"", "ifae", OP_IFAE, true, - ev_integer, ev_short, ev_invalid, - PROG_VERSION, - "%Ga branch %sb (%Ob)", - }, - {"", "ifa", OP_IFA, true, - ev_integer, ev_short, ev_invalid, - PROG_VERSION, - "%Ga branch %sb (%Ob)", - }, - -// calls returns REG_RETURN - {"", "call0", OP_CALL0, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa ()", - }, - {"", "call1", OP_CALL1, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x)", - }, - {"", "call2", OP_CALL2, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x, %P1x)", - }, - {"", "call3", OP_CALL3, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x, %P1x, %P2x)", - }, - {"", "call4", OP_CALL4, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x, %P1x, %P2x, %P3x)", - }, - {"", "call5", OP_CALL5, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)", - }, - {"", "call6", OP_CALL6, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)", - }, - {"", "call7", OP_CALL7, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)", - }, - {"", "call8", OP_CALL8, false, - ev_func, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", - }, - {"", "rcall1", OP_RCALL1, false, - ev_func, ev_void, ev_invalid, - PROG_VERSION, - "%Fa (%P0b)", - }, - {"", "rcall2", OP_RCALL2, false, - ev_func, ev_void, ev_void, - PROG_VERSION, - "%Fa (%P0b, %P1c)", - }, - {"", "rcall3", OP_RCALL3, false, - ev_func, ev_void, ev_void, - PROG_VERSION, - "%Fa (%P0b, %P1c, %P2x)", - }, - {"", "rcall4", OP_RCALL4, false, - ev_func, ev_void, ev_void, - PROG_VERSION, - "%Fa (%P0b, %P1c, %P2x, %P3x)", - }, - {"", "rcall5", OP_RCALL5, false, - ev_func, ev_void, ev_void, - PROG_VERSION, - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", - }, - {"", "rcall6", OP_RCALL6, false, - ev_func, ev_void, ev_void, - PROG_VERSION, - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", - }, - {"", "rcall7", OP_RCALL7, false, - ev_func, ev_void, ev_void, - PROG_VERSION, - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", - }, - {"", "rcall8", OP_RCALL8, false, - ev_func, ev_void, ev_void, - PROG_VERSION, - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", - }, - - {"", "state", OP_STATE, false, - ev_float, ev_func, ev_invalid, - PROG_ID_VERSION, - "%Ga, %Gb", - }, - - {"", "state.f", OP_STATE_F, false, - ev_float, ev_func, ev_float, - PROG_VERSION, - "%Ga, %Gb, %Gc", - }, - - {"", "goto", OP_GOTO, false, - ev_short, ev_invalid, ev_invalid, - PROG_ID_VERSION, - "branch %sa (%Oa)", - }, - {"", "jump", OP_JUMP, false, - ev_integer, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "jumpb", OP_JUMPB, false, - ev_void, ev_integer, ev_invalid, - PROG_VERSION, - "%Ga[%Gb]", - }, - - {"&&", "and.f", OP_AND, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - {"||", "or.f", OP_OR, false, - ev_float, ev_float, ev_integer, - PROG_ID_VERSION, - }, - - {"<<", "shl.f", OP_SHL_F, false, - ev_float, ev_float, ev_float, - PROG_VERSION, - }, - {">>", "shr.f", OP_SHR_F, false, - ev_float, ev_float, ev_float, - PROG_VERSION, - }, - {"<<", "shl.i", OP_SHL_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {">>", "shr.i", OP_SHR_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {">>", "shr.u", OP_SHR_U, false, - ev_uinteger, ev_integer, ev_uinteger, - PROG_VERSION, - }, - - {"&", "bitand", OP_BITAND, false, - ev_float, ev_float, ev_float, - PROG_ID_VERSION, - }, - {"|", "bitor", OP_BITOR, false, - ev_float, ev_float, ev_float, - PROG_ID_VERSION, - }, - - {"+", "add.i", OP_ADD_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"-", "sub.i", OP_SUB_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"*", "mul.i", OP_MUL_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"/", "div.i", OP_DIV_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"%", "rem.i", OP_REM_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"%%", "mod.i", OP_MOD_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"&", "bitand.i", OP_BITAND_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"|", "bitor.i", OP_BITOR_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - - {"%", "rem.f", OP_REM_F, false, - ev_float, ev_float, ev_float, - PROG_VERSION, - }, - - {"%%", "mod.f", OP_MOD_F, false, - ev_float, ev_float, ev_float, - PROG_VERSION, - }, - - {">=", "ge.i", OP_GE_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"<=", "le.i", OP_LE_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {">", "gt.i", OP_GT_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"<", "lt.i", OP_LT_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - - {"&&", "and.i", OP_AND_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"||", "or.i", OP_OR_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"!", "not.i", OP_NOT_I, false, - ev_integer, ev_invalid, ev_integer, - PROG_VERSION, - "%Ga, %gc", - }, - {"==", "eq.i", OP_EQ_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"!=", "ne.i", OP_NE_I, 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, - PROG_VERSION, - }, - {"~", "bitnot.f", OP_BITNOT_F, false, - ev_float, ev_invalid, ev_float, - PROG_VERSION, - "%Ga, %gc", - }, - {"^", "bitxor.i", OP_BITXOR_I, false, - ev_integer, ev_integer, ev_integer, - PROG_VERSION, - }, - {"~", "bitnot.i", OP_BITNOT_I, false, - ev_integer, ev_invalid, ev_integer, - PROG_VERSION, - "%Ga, %gc", - }, - - {">=", "ge.p", OP_GE_P, false, - ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, - }, - {"<=", "le.p", OP_LE_P, false, - ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, - }, - {">", "gt.p", OP_GT_P, false, - ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, - }, - {"<", "lt.p", OP_LT_P, false, - ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, - }, - {"==", "eq.p", OP_EQ_P, false, - ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, - }, - {"!=", "ne.p", OP_NE_P, false, - ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, - }, - - {"", "movei", OP_MOVEI, true, - ev_void, ev_short, ev_void, - PROG_VERSION, - "%Ga, %sb, %gc", - }, - {"", "movep", OP_MOVEP, true, - ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, - "%Ga, %Gb, %Gc", - }, - {"", "movepi", OP_MOVEPI, true, - ev_pointer, ev_short, ev_pointer, - PROG_VERSION, - "%Ga, %sb, %Gc", - }, - {"", "memseti", OP_MEMSETI, true, - ev_integer, ev_short, ev_void, - PROG_VERSION, - "%Ga, %sb, %gc", - }, - {"", "memsetp", OP_MEMSETP, true, - ev_integer, ev_integer, ev_pointer, - PROG_VERSION, - "%Ga, %Gb, %Gc", - }, - {"", "memsetpi", OP_MEMSETPI, true, - ev_integer, ev_short, ev_pointer, - PROG_VERSION, - "%Ga, %sb, %Gc", - }, - - {"", "push.s", OP_PUSH_S, false, - ev_string, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.f", OP_PUSH_F, false, - ev_float, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.v", OP_PUSH_V, false, - ev_vector, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.ent", OP_PUSH_ENT, false, - ev_entity, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.fld", OP_PUSH_FLD, false, - ev_field, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.fn", OP_PUSH_FN, false, - ev_func, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.p", OP_PUSH_P, false, - ev_pointer, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.q", OP_PUSH_Q, false, - ev_quat, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - {"", "push.i", OP_PUSH_I, false, - ev_integer, ev_invalid, ev_invalid, - PROG_VERSION, - "%Ga", - }, - - {"", "pushb.s", OP_PUSHB_S, false, - ev_pointer, ev_integer, ev_string, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.f", OP_PUSHB_F, false, - ev_pointer, ev_integer, ev_float, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.v", OP_PUSHB_V, false, - ev_pointer, ev_integer, ev_vector, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.ent", OP_PUSHB_ENT, false, - ev_pointer, ev_integer, ev_entity, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.fld", OP_PUSHB_FLD, false, - ev_pointer, ev_integer, ev_field, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.fn", OP_PUSHB_FN, false, - ev_pointer, ev_integer, ev_func, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.p", OP_PUSHB_P, false, - ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.q", OP_PUSHB_Q, false, - ev_pointer, ev_integer, ev_quat, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "pushb.i", OP_PUSHB_I, false, - ev_pointer, ev_integer, ev_integer, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - - {"", "pushbi.s", OP_PUSHBI_S, false, - ev_pointer, ev_short, ev_string, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.f", OP_PUSHBI_F, false, - ev_pointer, ev_short, ev_float, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.v", OP_PUSHBI_V, false, - ev_pointer, ev_short, ev_vector, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.ent", OP_PUSHBI_ENT, false, - ev_pointer, ev_short, ev_entity, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.fld", OP_PUSHBI_FLD, false, - ev_pointer, ev_short, ev_field, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.fn", OP_PUSHBI_FN, false, - ev_pointer, ev_short, ev_func, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.p", OP_PUSHBI_P, false, - ev_pointer, ev_short, ev_pointer, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.q", OP_PUSHBI_Q, false, - ev_pointer, ev_short, ev_quat, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "pushbi.i", OP_PUSHBI_I, false, - ev_pointer, ev_short, ev_integer, - PROG_VERSION, - "*(%Ga + %sb)", - }, - - {"", "pop.s", OP_POP_S, false, - ev_string, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.f", OP_POP_F, false, - ev_float, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.v", OP_POP_V, false, - ev_vector, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.ent", OP_POP_ENT, false, - ev_entity, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.fld", OP_POP_FLD, false, - ev_field, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.fn", OP_POP_FN, false, - ev_func, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.p", OP_POP_P, false, - ev_pointer, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.q", OP_POP_Q, false, - ev_quat, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - {"", "pop.i", OP_POP_I, false, - ev_integer, ev_invalid, ev_invalid, - PROG_VERSION, - "%ga", - }, - - {"", "popb.s", OP_POPB_S, false, - ev_pointer, ev_integer, ev_string, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.f", OP_POPB_F, false, - ev_pointer, ev_integer, ev_float, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.v", OP_POPB_V, false, - ev_pointer, ev_integer, ev_vector, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.ent", OP_POPB_ENT, false, - ev_pointer, ev_integer, ev_entity, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.fld", OP_POPB_FLD, false, - ev_pointer, ev_integer, ev_field, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.fn", OP_POPB_FN, false, - ev_pointer, ev_integer, ev_func, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.p", OP_POPB_P, false, - ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.q", OP_POPB_Q, false, - ev_pointer, ev_integer, ev_quat, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - {"", "popb.i", OP_POPB_I, false, - ev_pointer, ev_integer, ev_integer, - PROG_VERSION, - "*(%Ga + %Gb)", - }, - - {"", "popbi.s", OP_POPBI_S, false, - ev_pointer, ev_short, ev_string, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.f", OP_POPBI_F, false, - ev_pointer, ev_short, ev_float, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.v", OP_POPBI_V, false, - ev_pointer, ev_short, ev_vector, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.ent", OP_POPBI_ENT, false, - ev_pointer, ev_short, ev_entity, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.fld", OP_POPBI_FLD, false, - ev_pointer, ev_short, ev_field, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.fn", OP_POPBI_FN, false, - ev_pointer, ev_short, ev_func, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.p", OP_POPBI_P, false, - ev_pointer, ev_short, ev_pointer, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.q", OP_POPBI_Q, false, - ev_pointer, ev_short, ev_quat, - PROG_VERSION, - "*(%Ga + %sb)", - }, - {"", "popbi.i", OP_POPBI_I, false, - ev_pointer, ev_short, ev_integer, - PROG_VERSION, - "*(%Ga + %sb)", - }, - - // end of table - {0}, +const opcode_t pr_opcodes[512] = { +#include "libs/gamecode/pr_opcode.cinc" }; - -static uintptr_t -opcode_get_hash (const void *op, void *unused) +const opcode_t * +PR_Opcode (pr_ushort_t opcode) { - 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 * -PR_Opcode (pr_short_t opcode) -{ - opcode_t op; - - op.opcode = opcode; - return Hash_FindElement (opcode_table, &op); -} - -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) -{ - pr_int_t address = st - pr->pr_statements; - - address += offset; - if (address < 0 || (pr_uint_t) address >= pr->progs->numstatements) - PR_Error (pr, "PR_Check_Opcodes: invalid branch (statement %ld: %s)", - (long)(st - pr->pr_statements), op->opname); -} - -static int -is_vector_parameter_store (progs_t *pr, dstatement_t *st, - unsigned short operand) -{ - int i; - - if (st->op != OP_STORE_V) - return 0; - if (operand != st->a) - return 0; - for (i = 0; i < MAX_PARMS; i++) - if (st->b == pr->pr_params[i] - pr->pr_globals) - return 1; - return 0; -} - -#define ISDENORM(x) ((x) && !((x) & 0x7f800000)) - -static inline void -check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type, - unsigned short operand, int check_denorm) -{ - const char *msg; - pr_def_t *def; - - switch (type) { - case ev_short: - break; - case ev_invalid: - if (operand) { - msg = "non-zero global index in invalid operand"; - goto error; - } - break; - default: - if (operand + (unsigned) pr_type_size[type] - > pr->progs->numglobals) { - if (operand >= pr->progs->numglobals - || !is_vector_parameter_store (pr, st, operand)) { - msg = "out of bounds global index"; - goto error; - } - } - if (type != ev_float || !check_denorm) - break; - if (!ISDENORM (G_INT (pr, operand)) - || G_UINT(pr, operand) == 0x80000000) - break; - if ((def = PR_GlobalAtOfs (pr, operand)) - && (def->type & ~DEF_SAVEGLOBAL) != ev_float) { - // FTEqcc uses store.f parameters of most types :/ - break; - } - if (!pr->denorm_found) { - pr->denorm_found = 1; - if (pr_boundscheck->int_val) { - Sys_Printf ("DENORMAL floats detected, these progs might " - "not work. Good luck.\n"); - return; - } - msg = "DENORMAL float detected. These progs are probably " - "using qccx arrays and integers. If just simple arrays " - "are being used, then they should work, but if " - "internal.qc is used, they most definitely will NOT. To " - "allow these progs to be used, set pr_boundscheck to 1."; - goto error; - } - break; - } - return; -error: - PR_PrintStatement (pr, st, 0); - PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)", msg, - (long)(st - pr->pr_statements), op->opname); -} - -static void -check_global_size (progs_t *pr, dstatement_t *st, opcode_t *op, - unsigned short size, unsigned short operand) -{ - const char *msg; - if (operand + size > pr->progs->numglobals) { - msg = "out of bounds global index"; - goto error; - } - return; -error: - PR_PrintStatement (pr, st, 0); - PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)", msg, - (long)(st - pr->pr_statements), op->opname); + opcode &= OP_MASK; + return &pr_opcodes[opcode]; } int PR_Check_Opcodes (progs_t *pr) { - opcode_t *op; - dstatement_t *st; - int state_ok = 0; - int pushpop_ok = 0; - pr_uint_t i; - - if (pr->globals.time && pr->globals.self && pr->fields.nextthink != -1 - && pr->fields.think != -1 && pr->fields.frame != -1) { - state_ok = 1; - } - if (pr->globals.stack) { - pushpop_ok = 1; - } - - //FIXME need to decide if I really want to always do static bounds checking - // the only problem is that it slows progs load a little, but it's the only - // way to check for qccx' evil - if (0 && !pr_boundscheck->int_val) { - for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; - st++, i++) { - op = PR_Opcode (st->op); - if (!op) { - PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " - "statement %ld", st->op, - (long)(st - pr->pr_statements)); - } - if ((st->op == OP_STATE || st->op == OP_STATE_F) && !state_ok) { - PR_Error (pr, "PR_Check_Opcodes: %s used with missing fields " - "or globals", op->opname); - } - if ((strequal(op->name, "") || strequal(op->name, "")) - && !pushpop_ok) { - PR_Error (pr, "PR_Check_Opcodes: %s used with missing .stack " - "globals", op->opname); - } - } - } else { - for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; - st++, i++) { - op = PR_Opcode (st->op); - if (!op) { - PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " - "statement %ld", st->op, - (long)(st - pr->pr_statements)); - } - switch (st->op) { - case OP_IF: - case OP_IFNOT: - check_global (pr, st, op, op->type_a, st->a, 1); - check_branch (pr, st, op, st->b); - break; - case OP_GOTO: - check_branch (pr, st, op, st->a); - break; - case OP_DONE: - case OP_RETURN: - check_global (pr, st, op, ev_integer, st->a, 1); - check_global (pr, st, op, ev_void, st->b, 0); - check_global (pr, st, op, ev_void, st->c, 0); - break; - case OP_RCALL1: - check_global (pr, st, op, ev_void, st->c, 1); - case OP_RCALL2: - case OP_RCALL3: - case OP_RCALL4: - case OP_RCALL5: - case OP_RCALL6: - case OP_RCALL7: - case OP_RCALL8: - if (st->op > OP_RCALL1) - check_global (pr, st, op, ev_integer, st->c, 1); - check_global (pr, st, op, ev_integer, st->b, 1); - check_global (pr, st, op, ev_func, st->a, 1); - break; - case OP_STATE: - case OP_STATE_F: - if (!state_ok) { - PR_Error (pr, "PR_Check_Opcodes: %s used with missing " - "fields or globals", op->opname); - } - check_global (pr, st, op, op->type_a, st->a, 1); - check_global (pr, st, op, op->type_b, st->b, 1); - check_global (pr, st, op, op->type_c, st->c, 1); - break; - case OP_MOVEI: - check_global_size (pr, st, op, st->b, st->a); - check_global_size (pr, st, op, st->b, st->c); - break; - case OP_MEMSETI: - check_global_size (pr, st, op, st->b, st->c); - break; - case OP_PUSHB_F: - case OP_PUSHB_S: - case OP_PUSHB_ENT: - case OP_PUSHB_FLD: - case OP_PUSHB_FN: - case OP_PUSHB_I: - case OP_PUSHB_P: - case OP_PUSHB_V: - case OP_PUSHB_Q: - case OP_PUSHBI_F: - case OP_PUSHBI_S: - case OP_PUSHBI_ENT: - case OP_PUSHBI_FLD: - case OP_PUSHBI_FN: - case OP_PUSHBI_I: - case OP_PUSHBI_P: - case OP_PUSHBI_V: - case OP_PUSHBI_Q: - // op->type_c is used for selecting the operator during - // compilation, but is invalid when running - check_global (pr, st, op, op->type_a, st->a, 1); - check_global (pr, st, op, op->type_b, st->b, 1); - check_global (pr, st, op, ev_invalid, st->c, 1); - break; - case OP_POP_F: - case OP_POP_FLD: - case OP_POP_ENT: - case OP_POP_S: - case OP_POP_FN: - case OP_POP_I: - case OP_POP_P: - case OP_POP_V: - case OP_POP_Q: - // don't want to check for denormal floats, otherwise - // OP_POP_* could use the defualt rule - check_global (pr, st, op, op->type_a, st->a, 0); - check_global (pr, st, op, ev_invalid, st->b, 1); - check_global (pr, st, op, ev_invalid, st->c, 1); - break; - case OP_POPB_F: - case OP_POPB_S: - case OP_POPB_ENT: - case OP_POPB_FLD: - case OP_POPB_FN: - case OP_POPB_I: - case OP_POPB_P: - case OP_POPB_V: - case OP_POPB_Q: - case OP_POPBI_F: - case OP_POPBI_S: - case OP_POPBI_ENT: - case OP_POPBI_FLD: - case OP_POPBI_FN: - case OP_POPBI_I: - case OP_POPBI_P: - case OP_POPBI_V: - case OP_POPBI_Q: - // op->type_c is used for selecting the operator during - // compilation, but is invalid when running - check_global (pr, st, op, op->type_a, st->a, 1); - check_global (pr, st, op, op->type_b, st->b, 1); - check_global (pr, st, op, ev_invalid, st->c, 1); - break; - 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); - check_global (pr, st, op, op->type_c, st->c, 0); - break; - } - } + if (pr->progs->version < PROG_VERSION) { + return PR_Check_v6p_Opcodes (pr); } return 1; } diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index cfc170815..182146261 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -76,10 +76,10 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) break; case ev_func: f = pr->pr_functions + val->func_var; - dsprintf (line, "%s", PR_GetString (pr, f->s_name)); + dsprintf (line, "%s", PR_GetString (pr, f->name)); break; case ev_field: - def = PR_FieldAtOfs (pr, val->integer_var); + def = PR_FieldAtOfs (pr, val->int_var); dsprintf (line, "%s", PR_GetString (pr, def->name)); break; case ev_void: @@ -88,13 +88,13 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) case ev_float: dsprintf (line, "%.9g", val->float_var); break; - case ev_integer: - dsprintf (line, "%d", val->integer_var); + case ev_int: + dsprintf (line, "%d", val->int_var); break; case ev_vector: dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&val->vector_var)); break; - case ev_quat: + case ev_quaternion: dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&val->quat_var)); break; default: @@ -118,7 +118,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) pr_type_t *v; if (!ed->free) { - for (i = 0; i < pr->progs->numfielddefs; i++) { + for (i = 0; i < pr->progs->fielddefs.count; i++) { pr_def_t *d = &pr->pr_fielddefs[i]; name = PR_GetString (pr, d->name); @@ -132,7 +132,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; for (j = 0; j < pr_type_size[type]; j++) - if (v[j].integer_var) + if (v[j].int_var) break; if (j == pr_type_size[type]) continue; @@ -162,7 +162,7 @@ ED_GlobalsDict (progs_t *pr) pr_def_t *def; int type; - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { def = &pr->pr_globaldefs[i]; type = def->type; if (!(def->type & DEF_SAVEGLOBAL)) @@ -257,7 +257,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) Sys_Printf ("Can't find field %s\n", s); return false; } - d->integer_var = G_INT (pr, def->ofs); + d->int_var = G_INT (pr, def->ofs); break; case ev_func: diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 6270653d2..008c1abed 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -44,7 +44,7 @@ static const char param_str[] = ".param_0"; pr_def_t * -PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) +PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pr_ptr_t offset) { // fuzzy bsearh unsigned left = 0; @@ -69,15 +69,15 @@ PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) } pr_def_t * -PR_GlobalAtOfs (progs_t * pr, pointer_t ofs) +PR_GlobalAtOfs (progs_t * pr, pr_ptr_t ofs) { - return PR_SearchDefs (pr->pr_globaldefs, pr->progs->numglobaldefs, ofs); + return PR_SearchDefs (pr->pr_globaldefs, pr->progs->globaldefs.count, ofs); } VISIBLE pr_def_t * -PR_FieldAtOfs (progs_t * pr, pointer_t ofs) +PR_FieldAtOfs (progs_t * pr, pr_ptr_t ofs) { - return PR_SearchDefs (pr->pr_fielddefs, pr->progs->numfielddefs, ofs); + return PR_SearchDefs (pr->pr_fielddefs, pr->progs->fielddefs.count, ofs); } VISIBLE pr_def_t * @@ -129,7 +129,7 @@ PR_ResolveGlobals (progs_t *pr) if (!(def = PR_FindGlobal (pr, sym = ".return"))) goto error; pr->pr_return = &pr->pr_globals[def->ofs]; - for (i = 0; i < MAX_PARMS; i++) { + for (i = 0; i < PR_MAX_PARAMS; i++) { param_n[sizeof (param_str) - 2] = i + '0'; if (!(def = PR_FindGlobal (pr, sym = param_n))) goto error; @@ -142,15 +142,16 @@ PR_ResolveGlobals (progs_t *pr) goto error; pr->pr_param_alignment = G_INT (pr, def->ofs); } + pr->null_size = pr->pr_return - pr->pr_globals; memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params)); - if (!pr->globals.time) { + if (!pr->globals.ftime) {//FIXME double time if ((def = PR_FindGlobal (pr, "time"))) - pr->globals.time = &G_FLOAT (pr, def->ofs); + pr->globals.ftime = &G_FLOAT (pr, def->ofs); } if (!pr->globals.self) { if ((def = PR_FindGlobal (pr, ".self")) || (def = PR_FindGlobal (pr, "self"))) - pr->globals.self = &G_INT (pr, def->ofs); + pr->globals.self = &G_UINT (pr, def->ofs); } if (!pr->globals.stack) { if ((def = PR_FindGlobal (pr, ".stack")) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index ba53acac8..b8364d89c 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -164,7 +164,7 @@ free_string_ref (prstr_resources_t *res, strref_t *sr) res->free_string_refs = sr; } -static __attribute__((pure)) string_t +static __attribute__((pure)) pr_string_t string_index (prstr_resources_t *res, strref_t *sr) { long o = (long) (sr - res->static_strings); @@ -234,7 +234,7 @@ PR_LoadStrings (progs_t *pr) { prstr_resources_t *res = PR_Resources_Find (pr, "Strings"); - char *end = pr->pr_strings + pr->progs->numstrings; + char *end = pr->pr_strings + pr->progs->strings.count; char *str = pr->pr_strings; int count = 0; @@ -242,13 +242,16 @@ PR_LoadStrings (progs_t *pr) while (str < end) { count++; - if (*str == '@' && pr->progs->version == PROG_VERSION) { + if (*str == '@' && pr->progs->version == PROG_V6P_VERSION) { if (!strcmp (str, "@float_promoted@")) { pr->float_promoted = 1; } } str += strlen (str) + 1; } + if (pr->progs->version == PROG_VERSION) { + pr->float_promoted = 1; + } res->ds_mem.alloc = pr_strings_alloc; res->ds_mem.free = pr_strings_free; @@ -306,7 +309,7 @@ requeue_strref (prstr_resources_t *res, strref_t *sr) } static inline strref_t * -get_strref (prstr_resources_t *res, string_t num) +get_strref (prstr_resources_t *res, pr_string_t num) { if (num < 0) { strref_t *ref; @@ -325,7 +328,7 @@ get_strref (prstr_resources_t *res, string_t num) } static inline __attribute__((pure)) const char * -get_string (progs_t *pr, string_t num) +get_string (progs_t *pr, pr_string_t num) { __auto_type res = pr->pr_string_resources; if (num < 0) { @@ -353,7 +356,7 @@ get_string (progs_t *pr, string_t num) } VISIBLE qboolean -PR_StringValid (progs_t *pr, string_t num) +PR_StringValid (progs_t *pr, pr_string_t num) { if (num >= 0) { return num < pr->pr_stringsize; @@ -362,7 +365,7 @@ PR_StringValid (progs_t *pr, string_t num) } VISIBLE qboolean -PR_StringMutable (progs_t *pr, string_t num) +PR_StringMutable (progs_t *pr, pr_string_t num) { strref_t *sr; if (num >= 0) { @@ -373,7 +376,7 @@ PR_StringMutable (progs_t *pr, string_t num) } VISIBLE const char * -PR_GetString (progs_t *pr, string_t num) +PR_GetString (progs_t *pr, pr_string_t num) { const char *str; @@ -384,7 +387,7 @@ PR_GetString (progs_t *pr, string_t num) } VISIBLE dstring_t * -PR_GetMutableString (progs_t *pr, string_t num) +PR_GetMutableString (progs_t *pr, pr_string_t num) { strref_t *ref = get_strref (pr->pr_string_resources, num); if (ref) { @@ -421,7 +424,7 @@ pr_strdup (progs_t *pr, const char *s) return new; } -VISIBLE string_t +VISIBLE pr_string_t PR_SetString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -440,7 +443,7 @@ PR_SetString (progs_t *pr, const char *s) return string_index (res, sr); } -VISIBLE string_t +VISIBLE pr_string_t PR_FindString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -456,7 +459,7 @@ PR_FindString (progs_t *pr, const char *s) return 0; } -VISIBLE string_t +VISIBLE pr_string_t PR_SetReturnString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -496,7 +499,7 @@ PR_SetReturnString (progs_t *pr, const char *s) return string_index (res, sr); } -static inline string_t +static inline pr_string_t pr_settempstring (progs_t *pr, prstr_resources_t *res, char *s) { strref_t *sr; @@ -509,7 +512,7 @@ pr_settempstring (progs_t *pr, prstr_resources_t *res, char *s) return string_index (res, sr); } -VISIBLE string_t +VISIBLE pr_string_t PR_CatStrings (progs_t *pr, const char *a, const char *b) { size_t lena; @@ -525,7 +528,7 @@ PR_CatStrings (progs_t *pr, const char *a, const char *b) return pr_settempstring (pr, pr->pr_string_resources, c); } -VISIBLE string_t +VISIBLE pr_string_t PR_SetTempString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -541,7 +544,7 @@ PR_SetTempString (progs_t *pr, const char *s) return pr_settempstring (pr, res, pr_strdup (pr, s)); } -VISIBLE string_t +VISIBLE pr_string_t PR_AllocTempBlock (progs_t *pr, size_t size) { prstr_resources_t *res = pr->pr_string_resources; @@ -549,7 +552,7 @@ PR_AllocTempBlock (progs_t *pr, size_t size) } VISIBLE void -PR_PushTempString (progs_t *pr, string_t num) +PR_PushTempString (progs_t *pr, pr_string_t num) { prstr_resources_t *res = pr->pr_string_resources; strref_t *ref = get_strref (res, num); @@ -569,7 +572,7 @@ PR_PushTempString (progs_t *pr, string_t num) PR_Error (pr, "attempt to push stale temp string"); } -VISIBLE string_t +VISIBLE pr_string_t PR_SetDynamicString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -589,7 +592,7 @@ PR_SetDynamicString (progs_t *pr, const char *s) } VISIBLE void -PR_MakeTempString (progs_t *pr, string_t str) +PR_MakeTempString (progs_t *pr, pr_string_t str) { prstr_resources_t *res = pr->pr_string_resources; strref_t *sr = get_strref (res, str); @@ -610,7 +613,7 @@ PR_MakeTempString (progs_t *pr, string_t str) pr->pr_xtstr = sr; } -VISIBLE string_t +VISIBLE pr_string_t PR_NewMutableString (progs_t *pr) { prstr_resources_t *res = pr->pr_string_resources; @@ -621,7 +624,7 @@ PR_NewMutableString (progs_t *pr) } VISIBLE void -PR_HoldString (progs_t *pr, string_t str) +PR_HoldString (progs_t *pr, pr_string_t str) { prstr_resources_t *res = pr->pr_string_resources; strref_t *sr = get_strref (res, str); @@ -651,7 +654,7 @@ PR_HoldString (progs_t *pr, string_t str) } VISIBLE void -PR_FreeString (progs_t *pr, string_t str) +PR_FreeString (progs_t *pr, pr_string_t str) { prstr_resources_t *res = pr->pr_string_resources; strref_t *sr = get_strref (res, str); diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c new file mode 100644 index 000000000..bc3848de1 --- /dev/null +++ b/libs/gamecode/pr_v6p_opcode.c @@ -0,0 +1,1772 @@ +/* + pr_v6p_opcodes.c + + Opcode table and checking for v6+ progs. + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2001 Bill Currie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include "string.h" +#endif +#ifdef HAVE_STRINGS_H +# include "strings.h" +#endif + +#include "QF/cvar.h" +#include "QF/progs.h" +#include "QF/sys.h" + +#include "QF/progs/pr_comp.h" + +#include "compat.h" + +// default format is "%Ga, %Gb, %gc" +// V global_string, contents, void +// G global_string, contents +// g global_string, no contents +// s as short +// O address + short +// P function parameter +// F function (must come before any P) +// R return value +// E entity + field (%Eab) +// M addressing mode, contents +// m addressing mode, no contents +// takes operand (a,b,c,o (opcode)) and right shift(hex). always masked +// by 3 +// %Mc5 -> contents, operand c, shift right 5 bits +// %mo2 -> no contents, opcode, shift right 2 bits +// %mo0 -> no contents, opcode, no shift +// always uses a and b for the address calculation (Ruamoko convention)) +// +// a operand a +// b operand b +// c operand c +// o opcode +// x place holder for P (padding) +// 0-7 parameter index (for P) +VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { + // OP_DONE_v6p is actually the same as OP_RETURN_v6p, the types are bogus + [OP_DONE_v6p] = {"done", "done", + ev_entity, ev_field, ev_void, + PROG_ID_VERSION, + "%Va", + }, + + [OP_MUL_D_v6p] = {"mul", "mul.d", + ev_double, ev_double, ev_double, + PROG_V6P_VERSION, + }, + [OP_MUL_F_v6p] = {"mul", "mul.f", + ev_float, ev_float, ev_float, + PROG_ID_VERSION, + }, + [OP_MUL_V_v6p] = {"mul", "mul.v", + ev_vector, ev_vector, ev_float, + PROG_ID_VERSION, + }, + [OP_MUL_FV_v6p] = {"scale", "mul.fv", + ev_float, ev_vector, ev_vector, + PROG_ID_VERSION, + }, + [OP_MUL_VF_v6p] = {"scale", "mul.vf", + ev_vector, ev_float, ev_vector, + PROG_ID_VERSION, + }, + [OP_MUL_DV_v6p] = {"mul", "mul.dv", + ev_double, ev_vector, ev_vector, + PROG_ID_VERSION, + }, + [OP_MUL_VD_v6p] = {"mul", "mul.vd", + ev_vector, ev_double, ev_vector, + PROG_ID_VERSION, + }, + [OP_MUL_Q_v6p] = {"mul", "mul.q", + ev_quaternion, ev_quaternion, ev_quaternion, + PROG_V6P_VERSION, + }, + [OP_MUL_FQ_v6p] = {"mul", "mul.fq", + ev_float, ev_quaternion, ev_quaternion, + PROG_V6P_VERSION, + }, + [OP_MUL_QF_v6p] = {"mul", "mul.qf", + ev_quaternion, ev_float, ev_quaternion, + PROG_V6P_VERSION, + }, + [OP_MUL_DQ_v6p] = {"mul", "mul.dq", + ev_double, ev_quaternion, ev_quaternion, + PROG_V6P_VERSION, + }, + [OP_MUL_QD_v6p] = {"mul", "mul.qd", + ev_quaternion, ev_double, ev_quaternion, + PROG_V6P_VERSION, + }, + [OP_MUL_QV_v6p] = {"mul", "mul.qv", + ev_quaternion, ev_vector, ev_vector, + PROG_V6P_VERSION, + }, + + [OP_CONJ_Q_v6p] = {"conj", "conj.q", + ev_quaternion, ev_invalid, ev_quaternion, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + + [OP_DIV_F_v6p] = {"div", "div.f", + ev_float, ev_float, ev_float, + PROG_ID_VERSION, + }, + [OP_DIV_D_v6p] = {"div", "div.d", + ev_double, ev_double, ev_double, + PROG_V6P_VERSION, + }, + [OP_REM_D_v6p] = {"rem", "rem.d", + ev_double, ev_double, ev_double, + PROG_V6P_VERSION, + }, + [OP_MOD_D_v6p] = {"mod", "mod.d", + ev_double, ev_double, ev_double, + PROG_V6P_VERSION, + }, + + [OP_ADD_D_v6p] = {"add", "add.d", + ev_double, ev_double, ev_double, + PROG_V6P_VERSION, + }, + [OP_ADD_F_v6p] = {"add", "add.f", + ev_float, ev_float, ev_float, + PROG_ID_VERSION, + }, + [OP_ADD_V_v6p] = {"add", "add.v", + ev_vector, ev_vector, ev_vector, + PROG_ID_VERSION, + }, + [OP_ADD_Q_v6p] = {"add", "add.q", + ev_quaternion, ev_quaternion, ev_quaternion, + PROG_V6P_VERSION, + }, + [OP_ADD_S_v6p] = {"add", "add.s", + ev_string, ev_string, ev_string, + PROG_V6P_VERSION, + }, + + [OP_SUB_D_v6p] = {"sub", "sub.d", + ev_double, ev_double, ev_double, + PROG_V6P_VERSION, + }, + [OP_SUB_F_v6p] = {"sub", "sub.f", + ev_float, ev_float, ev_float, + PROG_ID_VERSION, + }, + [OP_SUB_V_v6p] = {"sub", "sub.v", + ev_vector, ev_vector, ev_vector, + PROG_ID_VERSION, + }, + [OP_SUB_Q_v6p] = {"sub", "sub.q", + ev_quaternion, ev_quaternion, ev_quaternion, + PROG_V6P_VERSION, + }, + + [OP_EQ_D_v6p] = {"eq", "eq.d", + ev_double, ev_double, ev_int, + PROG_V6P_VERSION, + }, + [OP_EQ_F_v6p] = {"eq", "eq.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + [OP_EQ_V_v6p] = {"eq", "eq.v", + ev_vector, ev_vector, ev_int, + PROG_ID_VERSION, + }, + [OP_EQ_Q_v6p] = {"eq", "eq.q", + ev_quaternion, ev_quaternion, ev_int, + PROG_V6P_VERSION, + }, + [OP_EQ_S_v6p] = {"eq", "eq.s", + ev_string, ev_string, ev_int, + PROG_ID_VERSION, + }, + [OP_EQ_E_v6p] = {"eq", "eq.e", + ev_entity, ev_entity, ev_int, + PROG_ID_VERSION, + }, + [OP_EQ_FN_v6p] = {"eq", "eq.fn", + ev_func, ev_func, ev_int, + PROG_ID_VERSION, + }, + + [OP_NE_D_v6p] = {"ne", "ne.d", + ev_double, ev_double, ev_int, + PROG_V6P_VERSION, + }, + [OP_NE_F_v6p] = {"ne", "ne.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + [OP_NE_V_v6p] = {"ne", "ne.v", + ev_vector, ev_vector, ev_int, + PROG_ID_VERSION, + }, + [OP_NE_Q_v6p] = {"ne", "ne.q", + ev_quaternion, ev_quaternion, ev_int, + PROG_V6P_VERSION, + }, + [OP_NE_S_v6p] = {"cmp", "ne.s", + ev_string, ev_string, ev_int, + PROG_ID_VERSION, + }, + [OP_NE_E_v6p] = {"ne", "ne.e", + ev_entity, ev_entity, ev_int, + PROG_ID_VERSION, + }, + [OP_NE_FN_v6p] = {"ne", "ne.fn", + ev_func, ev_func, ev_int, + PROG_ID_VERSION, + }, + + [OP_LE_D_v6p] = {"le", "le.d", + ev_double, ev_double, ev_int, + PROG_V6P_VERSION, + }, + [OP_LE_F_v6p] = {"le", "le.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + [OP_GE_D_v6p] = {"ge", "ge.d", + ev_double, ev_double, ev_int, + PROG_V6P_VERSION, + }, + [OP_GE_F_v6p] = {"ge", "ge.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + [OP_LE_S_v6p] = {"le", "le.s", + ev_string, ev_string, ev_int, + PROG_V6P_VERSION, + }, + [OP_GE_S_v6p] = {"ge", "ge.s", + ev_string, ev_string, ev_int, + PROG_V6P_VERSION, + }, + [OP_LT_D_v6p] = {"lt", "lt.d", + ev_double, ev_double, ev_int, + PROG_V6P_VERSION, + }, + [OP_LT_F_v6p] = {"lt", "lt.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + [OP_GT_D_v6p] = {"gt", "gt.d", + ev_double, ev_double, ev_int, + PROG_V6P_VERSION, + }, + [OP_GT_F_v6p] = {"gt", "gt.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + [OP_LT_S_v6p] = {"lt", "lt.s", + ev_string, ev_string, ev_int, + PROG_V6P_VERSION, + }, + [OP_GT_S_v6p] = {"gt", "gt.s", + ev_string, ev_string, ev_int, + PROG_V6P_VERSION, + }, + + [OP_LOAD_F_v6p] = {"load", "load.f", + ev_entity, ev_field, ev_float, + PROG_ID_VERSION, + "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible? + }, + [OP_LOAD_D_v6p] = {"load", "load.d", + ev_entity, ev_field, ev_double, + PROG_V6P_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_V_v6p] = {"load", "load.v", + ev_entity, ev_field, ev_vector, + PROG_ID_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_Q_v6p] = {"load", "load.q", + ev_entity, ev_field, ev_quaternion, + PROG_V6P_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_S_v6p] = {"load", "load.s", + ev_entity, ev_field, ev_string, + PROG_ID_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_ENT_v6p] = {"load", "load.ent", + ev_entity, ev_field, ev_entity, + PROG_ID_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_FLD_v6p] = {"load", "load.fld", + ev_entity, ev_field, ev_field, + PROG_ID_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_FN_v6p] = {"load", "load.fn", + ev_entity, ev_field, ev_func, + PROG_ID_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_I_v6p] = {"load", "load.i", + ev_entity, ev_field, ev_int, + PROG_V6P_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + [OP_LOAD_P_v6p] = {"load", "load.p", + ev_entity, ev_field, ev_ptr, + PROG_V6P_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + + [OP_LOADB_D_v6p] = {"load", "loadb.d", + ev_ptr, ev_int, ev_double, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_F_v6p] = {"load", "loadb.f", + ev_ptr, ev_int, ev_float, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_V_v6p] = {"load", "loadb.v", + ev_ptr, ev_int, ev_vector, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_Q_v6p] = {"load", "loadb.q", + ev_ptr, ev_int, ev_quaternion, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_S_v6p] = {"load", "loadb.s", + ev_ptr, ev_int, ev_string, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_ENT_v6p] = {"load", "loadb.ent", + ev_ptr, ev_int, ev_entity, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_FLD_v6p] = {"load", "loadb.fld", + ev_ptr, ev_int, ev_field, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_FN_v6p] = {"load", "loadb.fn", + ev_ptr, ev_int, ev_func, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_I_v6p] = {"load", "loadb.i", + ev_ptr, ev_int, ev_int, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + [OP_LOADB_P_v6p] = {"load", "loadb.p", + ev_ptr, ev_int, ev_ptr, + PROG_V6P_VERSION, + "*(%Ga + %Gb), %gc", + }, + + [OP_LOADBI_D_v6p] = {"load", "loadbi.d", + ev_ptr, ev_short, ev_double, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_F_v6p] = {"load", "loadbi.f", + ev_ptr, ev_short, ev_float, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_V_v6p] = {"load", "loadbi.v", + ev_ptr, ev_short, ev_vector, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_Q_v6p] = {"load", "loadbi.q", + ev_ptr, ev_short, ev_quaternion, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_S_v6p] = {"load", "loadbi.s", + ev_ptr, ev_short, ev_string, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_ENT_v6p] = {"load", "loadbi.ent", + ev_ptr, ev_short, ev_entity, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_FLD_v6p] = {"load", "loadbi.fld", + ev_ptr, ev_short, ev_field, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_FN_v6p] = {"load", "loadbi.fn", + ev_ptr, ev_short, ev_func, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_I_v6p] = {"load", "loadbi.i", + ev_ptr, ev_short, ev_int, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + [OP_LOADBI_P_v6p] = {"load", "loadbi.p", + ev_ptr, ev_short, ev_ptr, + PROG_V6P_VERSION, + "*(%Ga + %sb), %gc", + }, + + [OP_ADDRESS_v6p] = {"lea", "address", + ev_entity, ev_field, ev_ptr, + PROG_ID_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, + + [OP_ADDRESS_VOID_v6p] = {"lea", "address", + ev_void, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_D_v6p] = {"lea", "address.d", + ev_double, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_F_v6p] = {"lea", "address.f", + ev_float, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_V_v6p] = {"lea", "address.v", + ev_vector, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_Q_v6p] = {"lea", "address.q", + ev_quaternion, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_S_v6p] = {"lea", "address.s", + ev_string, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_ENT_v6p] = {"lea", "address.ent", + ev_entity, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_FLD_v6p] = {"lea", "address.fld", + ev_field, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_FN_v6p] = {"lea", "address.fn", + ev_func, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_I_v6p] = {"lea", "address.i", + ev_int, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_ADDRESS_P_v6p] = {"lea", "address.p", + ev_ptr, ev_invalid, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + + [OP_LEA_v6p] = {"lea", "lea", + ev_ptr, ev_int, ev_ptr, + PROG_V6P_VERSION, + "(%Ga + %Gb), %gc", + }, + [OP_LEAI_v6p] = {"lea", "leai", + ev_ptr, ev_short, ev_ptr, + PROG_V6P_VERSION, + "(%Ga + %sb), %gc", + }, + + [OP_CONV_IF_v6p] = {"conv", "conv.if", + ev_int, ev_invalid, ev_float, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_CONV_FI_v6p] = {"conv", "conv.fi", + ev_float, ev_invalid, ev_int, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_CONV_ID_v6p] = {"conv", "conv.id", + ev_int, ev_invalid, ev_double, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_CONV_DI_v6p] = {"conv", "conv.di", + ev_double, ev_invalid, ev_int, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_CONV_FD_v6p] = {"conv", "conv.fd", + ev_float, ev_invalid, ev_double, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_CONV_DF_v6p] = {"conv", "conv.df", + ev_double, ev_invalid, ev_float, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + + [OP_STORE_D_v6p] = {"assign", "store.d", + ev_double, ev_double, ev_invalid, + PROG_V6P_VERSION, + "%Ga, %gb", + }, + [OP_STORE_F_v6p] = {"assign", "store.f", + ev_float, ev_float, ev_invalid, + PROG_ID_VERSION, + "%Ga, %gb", + }, + [OP_STORE_V_v6p] = {"assign", "store.v", + ev_vector, ev_vector, ev_invalid, + PROG_ID_VERSION, + "%Ga, %gb", + }, + [OP_STORE_Q_v6p] = {"assign", "store.q", + ev_quaternion, ev_quaternion, ev_invalid, + PROG_V6P_VERSION, + "%Ga, %gb", + }, + [OP_STORE_S_v6p] = {"assign", "store.s", + ev_string, ev_string, ev_invalid, + PROG_ID_VERSION, + "%Ga, %gb", + }, + [OP_STORE_ENT_v6p] = {"assign", "store.ent", + ev_entity, ev_entity, ev_invalid, + PROG_ID_VERSION, + "%Ga, %gb", + }, + [OP_STORE_FLD_v6p] = {"assign", "store.fld", + ev_field, ev_field, ev_invalid, + PROG_ID_VERSION, + "%Ga, %gb", + }, + [OP_STORE_FN_v6p] = {"assign", "store.fn", + ev_func, ev_func, ev_invalid, + PROG_ID_VERSION, + "%Ga, %gb", + }, + [OP_STORE_I_v6p] = {"assign", "store.i", + ev_int, ev_int, ev_invalid, + PROG_V6P_VERSION, + "%Ga, %gb", + }, + [OP_STORE_P_v6p] = {"assign", "store.p", + ev_ptr, ev_ptr, ev_invalid, + PROG_V6P_VERSION, + "%Ga, %gb", + }, + + [OP_STOREP_D_v6p] = {"store", "storep.d", + ev_double, ev_ptr, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_F_v6p] = {"store", "storep.f", + ev_float, ev_ptr, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_V_v6p] = {"store", "storep.v", + ev_vector, ev_ptr, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_Q_v6p] = {"store", "storep.q", + ev_quaternion, ev_ptr, ev_invalid, + PROG_V6P_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_S_v6p] = {"store", "storep.s", + ev_string, ev_ptr, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_ENT_v6p] = {"store", "storep.ent", + ev_entity, ev_ptr, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_FLD_v6p] = {"store", "storep.fld", + ev_field, ev_ptr, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_FN_v6p] = {"store", "storep.fn", + ev_func, ev_ptr, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_I_v6p] = {"store", "storep.i", + ev_int, ev_ptr, ev_invalid, + PROG_V6P_VERSION, + "%Ga, *%Gb", + }, + [OP_STOREP_P_v6p] = {"store", "storep.p", + ev_ptr, ev_ptr, ev_invalid, + PROG_V6P_VERSION, + "%Ga, *%Gb", + }, + + [OP_STOREB_D_v6p] = {"store", "storeb.d", + ev_double, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_F_v6p] = {"store", "storeb.f", + ev_float, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_V_v6p] = {"store", "storeb.v", + ev_vector, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_Q_v6p] = {"store", "storeb.q", + ev_quaternion, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_S_v6p] = {"store", "storeb.s", + ev_string, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_ENT_v6p] = {"store", "storeb.ent", + ev_entity, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_FLD_v6p] = {"store", "storeb.fld", + ev_field, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_FN_v6p] = {"store", "storeb.fn", + ev_func, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_I_v6p] = {"store", "storeb.i", + ev_int, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + [OP_STOREB_P_v6p] = {"store", "storeb.p", + ev_ptr, ev_ptr, ev_int, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %Gc)", + }, + + [OP_STOREBI_D_v6p] = {"store", "storebi.d", + ev_double, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_F_v6p] = {"store", "storebi.f", + ev_float, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_V_v6p] = {"store", "storebi.v", + ev_vector, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_Q_v6p] = {"store", "storebi.q", + ev_quaternion, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_S_v6p] = {"store", "storebi.s", + ev_string, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_ENT_v6p] = {"store", "storebi.ent", + ev_entity, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_FLD_v6p] = {"store", "storebi.fld", + ev_field, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_FN_v6p] = {"store", "storebi.fn", + ev_func, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_I_v6p] = {"store", "storebi.i", + ev_int, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + [OP_STOREBI_P_v6p] = {"store", "storebi.p", + ev_ptr, ev_ptr, ev_short, + PROG_V6P_VERSION, + "%Ga, *(%Gb + %sc)", + }, + + [OP_RETURN_v6p] = {"return", "return", + ev_void, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Ra", + }, + + [OP_RETURN_V_v6p] = {"return", "return", + ev_invalid, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "", + }, + + [OP_NOT_D_v6p] = {"not", "not.d", + ev_double, ev_invalid, ev_int, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_NOT_F_v6p] = {"not", "not.f", + ev_float, ev_invalid, ev_int, + PROG_ID_VERSION, + "%Ga, %gc", + }, + [OP_NOT_V_v6p] = {"not", "not.v", + ev_vector, ev_invalid, ev_int, + PROG_ID_VERSION, + "%Ga, %gc", + }, + [OP_NOT_Q_v6p] = {"not", "not.q", + ev_quaternion, ev_invalid, ev_int, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_NOT_S_v6p] = {"not", "not.s", + ev_string, ev_invalid, ev_int, + PROG_ID_VERSION, + "%Ga, %gc", + }, + [OP_NOT_ENT_v6p] = {"not", "not.ent", + ev_entity, ev_invalid, ev_int, + PROG_ID_VERSION, + "%Ga, %gc", + }, + [OP_NOT_FN_v6p] = {"not", "not.fn", + ev_func, ev_invalid, ev_int, + PROG_ID_VERSION, + "%Ga, %gc", + }, + [OP_NOT_P_v6p] = {"not", "not.p", + ev_ptr, ev_invalid, ev_int, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + + [OP_IF_v6p] = {"ifnz", "if", + ev_int, ev_short, ev_invalid, + PROG_ID_VERSION, + "%Ga branch %sb (%Ob)", + }, + [OP_IFNOT_v6p] = {"ifz", "ifnot", + ev_int, ev_short, ev_invalid, + PROG_ID_VERSION, + "%Ga branch %sb (%Ob)", + }, + [OP_IFBE_v6p] = {"ifbe", "ifbe", + ev_int, ev_short, ev_invalid, + PROG_V6P_VERSION, + "%Ga branch %sb (%Ob)", + }, + [OP_IFB_v6p] = {"ifb", "ifb", + ev_int, ev_short, ev_invalid, + PROG_V6P_VERSION, + "%Ga branch %sb (%Ob)", + }, + [OP_IFAE_v6p] = {"ifae", "ifae", + ev_int, ev_short, ev_invalid, + PROG_V6P_VERSION, + "%Ga branch %sb (%Ob)", + }, + [OP_IFA_v6p] = {"ifa", "ifa", + ev_int, ev_short, ev_invalid, + PROG_V6P_VERSION, + "%Ga branch %sb (%Ob)", + }, + +// calls returns REG_RETURN + [OP_CALL0_v6p] = {"call0", "call0", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa ()", + }, + [OP_CALL1_v6p] = {"call1", "call1", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x)", + }, + [OP_CALL2_v6p] = {"call2", "call2", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x, %P1x)", + }, + [OP_CALL3_v6p] = {"call3", "call3", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x, %P1x, %P2x)", + }, + [OP_CALL4_v6p] = {"call4", "call4", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x, %P1x, %P2x, %P3x)", + }, + [OP_CALL5_v6p] = {"call5", "call5", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)", + }, + [OP_CALL6_v6p] = {"call6", "call6", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)", + }, + [OP_CALL7_v6p] = {"call7", "call7", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)", + }, + [OP_CALL8_v6p] = {"call8", "call8", + ev_func, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", + }, + [OP_RCALL0_v6p] = {"rcall0", 0, + ev_invalid, ev_invalid, ev_invalid, + ~0, // not a valid instruction + 0, + }, + [OP_RCALL1_v6p] = {"rcall1", "rcall1", + ev_func, ev_void, ev_invalid, + PROG_V6P_VERSION, + "%Fa (%P0b)", + }, + [OP_RCALL2_v6p] = {"rcall2", "rcall2", + ev_func, ev_void, ev_void, + PROG_V6P_VERSION, + "%Fa (%P0b, %P1c)", + }, + [OP_RCALL3_v6p] = {"rcall3", "rcall3", + ev_func, ev_void, ev_void, + PROG_V6P_VERSION, + "%Fa (%P0b, %P1c, %P2x)", + }, + [OP_RCALL4_v6p] = {"rcall4", "rcall4", + ev_func, ev_void, ev_void, + PROG_V6P_VERSION, + "%Fa (%P0b, %P1c, %P2x, %P3x)", + }, + [OP_RCALL5_v6p] = {"rcall5", "rcall5", + ev_func, ev_void, ev_void, + PROG_V6P_VERSION, + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", + }, + [OP_RCALL6_v6p] = {"rcall6", "rcall6", + ev_func, ev_void, ev_void, + PROG_V6P_VERSION, + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", + }, + [OP_RCALL7_v6p] = {"rcall7", "rcall7", + ev_func, ev_void, ev_void, + PROG_V6P_VERSION, + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", + }, + [OP_RCALL8_v6p] = {"rcall8", "rcall8", + ev_func, ev_void, ev_void, + PROG_V6P_VERSION, + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", + }, + + [OP_STATE_v6p] = {"state", "state", + ev_float, ev_func, ev_invalid, + PROG_ID_VERSION, + "%Ga, %Gb", + }, + + [OP_STATE_F_v6p] = {"state", "state.f", + ev_float, ev_func, ev_float, + PROG_V6P_VERSION, + "%Ga, %Gb, %Gc", + }, + + [OP_GOTO_v6p] = {"jump", "goto", + ev_short, ev_invalid, ev_invalid, + PROG_ID_VERSION, + "branch %sa (%Oa)", + }, + [OP_JUMP_v6p] = {"jump", "jump", + ev_int, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_JUMPB_v6p] = {"jump", "jump", + ev_void, ev_int, ev_invalid, + PROG_V6P_VERSION, + "%Ga[%Gb]", + }, + + [OP_AND_v6p] = {"and", "and.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + [OP_OR_v6p] = {"or", "or.f", + ev_float, ev_float, ev_int, + PROG_ID_VERSION, + }, + + [OP_SHL_F_v6p] = {"shl", "shl.f", + ev_float, ev_float, ev_float, + PROG_V6P_VERSION, + }, + [OP_SHR_F_v6p] = {"shr", "shr.f", + ev_float, ev_float, ev_float, + PROG_V6P_VERSION, + }, + [OP_SHL_I_v6p] = {"shl", "shl.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_SHR_I_v6p] = {"shr", "shr.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_SHR_U_v6p] = {"shr", "shr.u", + ev_uint, ev_int, ev_uint, + PROG_V6P_VERSION, + }, + + [OP_BITAND_v6p] = {"bitand", "bitand.f", + ev_float, ev_float, ev_float, + PROG_ID_VERSION, + }, + [OP_BITOR_v6p] = {"bitor", "bitor.f", + ev_float, ev_float, ev_float, + PROG_ID_VERSION, + }, + + [OP_ADD_I_v6p] = {"add", "add.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_SUB_I_v6p] = {"sub", "sub.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_MUL_I_v6p] = {"mul", "mul.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_DIV_I_v6p] = {"div", "div.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_REM_I_v6p] = {"rem", "rem.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_MOD_I_v6p] = {"mod", "mod.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_BITAND_I_v6p] = {"bitand", "bitand.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_BITOR_I_v6p] = {"bitor", "bitor.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + + [OP_REM_F_v6p] = {"rem", "rem.f", + ev_float, ev_float, ev_float, + PROG_V6P_VERSION, + }, + + [OP_MOD_F_v6p] = {"mod", "mod.f", + ev_float, ev_float, ev_float, + PROG_V6P_VERSION, + }, + + [OP_GE_I_v6p] = {"ge", "ge.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_LE_I_v6p] = {"le", "le.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_GT_I_v6p] = {"gt", "gt.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_LT_I_v6p] = {"lt", "lt.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + + [OP_AND_I_v6p] = {"and", "and.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_OR_I_v6p] = {"or", "or.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_NOT_I_v6p] = {"not", "not.i", + ev_int, ev_invalid, ev_int, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_EQ_I_v6p] = {"eq", "eq.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_NE_I_v6p] = {"ne", "ne.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + + [OP_GE_U_v6p] = {"ge", "ge.u", + ev_uint, ev_uint, ev_int, + PROG_V6P_VERSION, + }, + [OP_LE_U_v6p] = {"le", "le.u", + ev_uint, ev_uint, ev_int, + PROG_V6P_VERSION, + }, + [OP_GT_U_v6p] = {"gt", "gt.u", + ev_uint, ev_uint, ev_int, + PROG_V6P_VERSION, + }, + [OP_LT_U_v6p] = {"lt", "lt.u", + ev_uint, ev_uint, ev_int, + PROG_V6P_VERSION, + }, + + [OP_BITXOR_F_v6p] = {"bitxor", "bitxor.f", + ev_float, ev_float, ev_float, + PROG_V6P_VERSION, + }, + [OP_BITNOT_F_v6p] = {"bitnot", "bitnot.f", + ev_float, ev_invalid, ev_float, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + [OP_BITXOR_I_v6p] = {"bitxor", "bitxor.i", + ev_int, ev_int, ev_int, + PROG_V6P_VERSION, + }, + [OP_BITNOT_I_v6p] = {"bitnot", "bitnot.i", + ev_int, ev_invalid, ev_int, + PROG_V6P_VERSION, + "%Ga, %gc", + }, + + [OP_GE_P_v6p] = {"ge", "ge.p", + ev_ptr, ev_ptr, ev_int, + PROG_V6P_VERSION, + }, + [OP_LE_P_v6p] = {"le", "le.p", + ev_ptr, ev_ptr, ev_int, + PROG_V6P_VERSION, + }, + [OP_GT_P_v6p] = {"gt", "gt.p", + ev_ptr, ev_ptr, ev_int, + PROG_V6P_VERSION, + }, + [OP_LT_P_v6p] = {"lt", "lt.p", + ev_ptr, ev_ptr, ev_int, + PROG_V6P_VERSION, + }, + [OP_EQ_P_v6p] = {"eq", "eq.p", + ev_ptr, ev_ptr, ev_int, + PROG_V6P_VERSION, + }, + [OP_NE_P_v6p] = {"ne", "ne.p", + ev_ptr, ev_ptr, ev_int, + PROG_V6P_VERSION, + }, + + [OP_MOVEI_v6p] = {"move", "movei", + ev_void, ev_short, ev_void, + PROG_V6P_VERSION, + "%Ga, %sb, %gc", + }, + [OP_MOVEP_v6p] = {"movep", "movep", + ev_ptr, ev_int, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %Gb, %Gc", + }, + [OP_MOVEPI_v6p] = {"movep", "movepi", + ev_ptr, ev_short, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %sb, %Gc", + }, + [OP_MEMSETI_v6p] = {"memset", "memseti", + ev_int, ev_short, ev_void, + PROG_V6P_VERSION, + "%Ga, %sb, %gc", + }, + [OP_MEMSETP_v6p] = {"memsetp", "memsetp", + ev_int, ev_int, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %Gb, %Gc", + }, + [OP_MEMSETPI_v6p] = {"memsetp", "memsetpi", + ev_int, ev_short, ev_ptr, + PROG_V6P_VERSION, + "%Ga, %sb, %Gc", + }, + + [OP_PUSH_S_v6p] = {"push", "push.s", + ev_string, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_F_v6p] = {"push", "push.f", + ev_float, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_V_v6p] = {"push", "push.v", + ev_vector, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_ENT_v6p] = {"push", "push.ent", + ev_entity, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_FLD_v6p] = {"push", "push.fld", + ev_field, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_FN_v6p] = {"push", "push.fn", + ev_func, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_P_v6p] = {"push", "push.p", + ev_ptr, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_Q_v6p] = {"push", "push.q", + ev_quaternion, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_I_v6p] = {"push", "push.i", + ev_int, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + [OP_PUSH_D_v6p] = {"push", "push.d", + ev_double, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%Ga", + }, + + [OP_PUSHB_S_v6p] = {"push", "pushb.s", + ev_ptr, ev_int, ev_string, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_F_v6p] = {"push", "pushb.f", + ev_ptr, ev_int, ev_float, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_V_v6p] = {"push", "pushb.v", + ev_ptr, ev_int, ev_vector, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_ENT_v6p] = {"push", "pushb.ent", + ev_ptr, ev_int, ev_entity, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_FLD_v6p] = {"push", "pushb.fld", + ev_ptr, ev_int, ev_field, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_FN_v6p] = {"push", "pushb.fn", + ev_ptr, ev_int, ev_func, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_P_v6p] = {"push", "pushb.p", + ev_ptr, ev_int, ev_ptr, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_Q_v6p] = {"push", "pushb.q", + ev_ptr, ev_int, ev_quaternion, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_I_v6p] = {"push", "pushb.i", + ev_ptr, ev_int, ev_int, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_PUSHB_D_v6p] = {"push", "pushb.d", + ev_ptr, ev_int, ev_double, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + + [OP_PUSHBI_S_v6p] = {"push", "pushbi.s", + ev_ptr, ev_short, ev_string, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_F_v6p] = {"push", "pushbi.f", + ev_ptr, ev_short, ev_float, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_V_v6p] = {"push", "pushbi.v", + ev_ptr, ev_short, ev_vector, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_ENT_v6p] = {"push", "pushbi.ent", + ev_ptr, ev_short, ev_entity, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_FLD_v6p] = {"push", "pushbi.fld", + ev_ptr, ev_short, ev_field, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_FN_v6p] = {"push", "pushbi.fn", + ev_ptr, ev_short, ev_func, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_P_v6p] = {"push", "pushbi.p", + ev_ptr, ev_short, ev_ptr, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_Q_v6p] = {"push", "pushbi.q", + ev_ptr, ev_short, ev_quaternion, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_I_v6p] = {"push", "pushbi.i", + ev_ptr, ev_short, ev_int, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_PUSHBI_D_v6p] = {"push", "pushbi.d", + ev_ptr, ev_short, ev_double, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + + [OP_POP_S_v6p] = {"pop", "pop.s", + ev_string, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_F_v6p] = {"pop", "pop.f", + ev_float, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_V_v6p] = {"pop", "pop.v", + ev_vector, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_ENT_v6p] = {"pop", "pop.ent", + ev_entity, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_FLD_v6p] = {"pop", "pop.fld", + ev_field, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_FN_v6p] = {"pop", "pop.fn", + ev_func, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_P_v6p] = {"pop", "pop.p", + ev_ptr, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_Q_v6p] = {"pop", "pop.q", + ev_quaternion, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_I_v6p] = {"pop", "pop.i", + ev_int, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + [OP_POP_D_v6p] = {"pop", "pop.d", + ev_double, ev_invalid, ev_invalid, + PROG_V6P_VERSION, + "%ga", + }, + + [OP_POPB_S_v6p] = {"pop", "popb.s", + ev_ptr, ev_int, ev_string, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_F_v6p] = {"pop", "popb.f", + ev_ptr, ev_int, ev_float, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_V_v6p] = {"pop", "popb.v", + ev_ptr, ev_int, ev_vector, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_ENT_v6p] = {"pop", "popb.ent", + ev_ptr, ev_int, ev_entity, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_FLD_v6p] = {"pop", "popb.fld", + ev_ptr, ev_int, ev_field, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_FN_v6p] = {"pop", "popb.fn", + ev_ptr, ev_int, ev_func, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_P_v6p] = {"pop", "popb.p", + ev_ptr, ev_int, ev_ptr, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_Q_v6p] = {"pop", "popb.q", + ev_ptr, ev_int, ev_quaternion, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_I_v6p] = {"pop", "popb.i", + ev_ptr, ev_int, ev_int, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + [OP_POPB_D_v6p] = {"pop", "popb.d", + ev_ptr, ev_int, ev_double, + PROG_V6P_VERSION, + "*(%Ga + %Gb)", + }, + + [OP_POPBI_S_v6p] = {"pop", "popbi.s", + ev_ptr, ev_short, ev_string, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_F_v6p] = {"pop", "popbi.f", + ev_ptr, ev_short, ev_float, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_V_v6p] = {"pop", "popbi.v", + ev_ptr, ev_short, ev_vector, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_ENT_v6p] = {"pop", "popbi.ent", + ev_ptr, ev_short, ev_entity, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_FLD_v6p] = {"pop", "popbi.fld", + ev_ptr, ev_short, ev_field, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_FN_v6p] = {"pop", "popbi.fn", + ev_ptr, ev_short, ev_func, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_P_v6p] = {"pop", "popbi.p", + ev_ptr, ev_short, ev_ptr, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_Q_v6p] = {"pop", "popbi.q", + ev_ptr, ev_short, ev_quaternion, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_I_v6p] = {"pop", "popbi.i", + ev_ptr, ev_short, ev_int, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + [OP_POPBI_D_v6p] = {"pop", "popbi.d", + ev_ptr, ev_short, ev_double, + PROG_V6P_VERSION, + "*(%Ga + %sb)", + }, + + // end of table + [OP_MEMSETPI_v6p+1] = {0}, //XXX FIXME relies on OP_MEMSETPI_v6p being last +}; + +const v6p_opcode_t * +PR_v6p_Opcode (pr_ushort_t opcode) +{ + size_t opcode_count = sizeof (pr_v6p_opcodes) / sizeof (pr_v6p_opcodes[0]); + if (opcode >= opcode_count - 1) { + return 0; + } + return &pr_v6p_opcodes[opcode]; +} + +static inline void +check_branch (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, short offset) +{ + pr_int_t address = st - pr->pr_statements; + + address += offset; + if (address < 0 || (pr_uint_t) address >= pr->progs->statements.count) + PR_Error (pr, "PR_Check_Opcodes: invalid branch (statement %ld: %s)", + (long)(st - pr->pr_statements), op->opname); +} + +static int +is_vector_parameter_store (progs_t *pr, dstatement_t *st, + unsigned short operand) +{ + int i; + + if ((pr_opcode_v6p_e) st->op != OP_STORE_V_v6p) + return 0; + if (operand != st->a) + return 0; + for (i = 0; i < PR_MAX_PARAMS; i++) + if (st->b == pr->pr_params[i] - pr->pr_globals) + return 1; + return 0; +} + +#define ISDENORM(x) ((x) && !((x) & 0x7f800000)) + +static inline void +check_global (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, etype_t type, + unsigned short operand, int check_denorm) +{ + const char *msg; + pr_def_t *def; + + switch (type) { + case ev_short: + break; + case ev_invalid: + if (operand) { + msg = "non-zero global index in invalid operand"; + goto error; + } + break; + default: + if (operand + (unsigned) pr_type_size[type] + > pr->progs->globals.count) { + if (operand >= pr->progs->globals.count + || !is_vector_parameter_store (pr, st, operand)) { + msg = "out of bounds global index"; + goto error; + } + } + if (type != ev_float || !check_denorm) + break; + if (!ISDENORM (G_INT (pr, operand)) + || G_UINT(pr, operand) == 0x80000000) + break; + if ((def = PR_GlobalAtOfs (pr, operand)) + && (def->type & ~DEF_SAVEGLOBAL) != ev_float) { + // FTEqcc uses store.f parameters of most types :/ + break; + } + if (!pr->denorm_found) { + pr->denorm_found = 1; + if (pr_boundscheck->int_val) { + Sys_Printf ("DENORMAL floats detected, these progs might " + "not work. Good luck.\n"); + return; + } + msg = "DENORMAL float detected. These progs are probably " + "using qccx arrays and integers. If just simple arrays " + "are being used, then they should work, but if " + "internal.qc is used, they most definitely will NOT. To " + "allow these progs to be used, set pr_boundscheck to 1."; + goto error; + } + break; + } + return; +error: + PR_PrintStatement (pr, st, 0); + PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)", msg, + (long)(st - pr->pr_statements), op->opname); +} + +static void +check_global_size (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, + unsigned short size, unsigned short operand) +{ + const char *msg; + if (operand + size > pr->progs->globals.count) { + msg = "out of bounds global index"; + goto error; + } + return; +error: + PR_PrintStatement (pr, st, 0); + PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)", msg, + (long)(st - pr->pr_statements), op->opname); +} + +int +PR_Check_v6p_Opcodes (progs_t *pr) +{ + const v6p_opcode_t *op; + dstatement_t *st; + int state_ok = 0; + int pushpop_ok = 0; + pr_uint_t i; + + if (pr->globals.ftime && pr->globals.self && pr->fields.nextthink != -1 + && pr->fields.think != -1 && pr->fields.frame != -1) { + state_ok = 1; + } + if (pr->globals.stack) { + pushpop_ok = 1; + } + + //FIXME need to decide if I really want to always do static bounds checking + // the only problem is that it slows progs load a little, but it's the only + // way to check for qccx' evil + if (0 && !pr_boundscheck->int_val) { + for (i = 0, st = pr->pr_statements; i < pr->progs->statements.count; + st++, i++) { + pr_opcode_v6p_e st_op = st->op; + op = PR_v6p_Opcode (st_op); + if (!op) { + PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " + "statement %ld", st_op, + (long)(st - pr->pr_statements)); + } + if ((st_op == OP_STATE_v6p || st_op == OP_STATE_F_v6p) + && !state_ok) { + PR_Error (pr, "PR_Check_Opcodes: %s used with missing fields " + "or globals", op->opname); + } + if ((strequal(op->name, "push") || strequal(op->name, "pop")) + && !pushpop_ok) { + PR_Error (pr, "PR_Check_Opcodes: %s used with missing .stack " + "globals", op->opname); + } + } + } else { + for (i = 0, st = pr->pr_statements; i < pr->progs->statements.count; + st++, i++) { + pr_opcode_v6p_e st_op = st->op; + op = PR_v6p_Opcode (st_op); + if (!op) { + PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " + "statement %ld", st_op, + (long)(st - pr->pr_statements)); + } + switch (st_op) { + case OP_IF_v6p: + case OP_IFNOT_v6p: + check_global (pr, st, op, op->type_a, st->a, 1); + check_branch (pr, st, op, st->b); + break; + case OP_GOTO_v6p: + check_branch (pr, st, op, st->a); + break; + case OP_DONE_v6p: + case OP_RETURN_v6p: + check_global (pr, st, op, ev_int, st->a, 1); + check_global (pr, st, op, ev_void, st->b, 0); + check_global (pr, st, op, ev_void, st->c, 0); + break; + case OP_RCALL1_v6p: + check_global (pr, st, op, ev_void, st->c, 1); + case OP_RCALL2_v6p: + case OP_RCALL3_v6p: + case OP_RCALL4_v6p: + case OP_RCALL5_v6p: + case OP_RCALL6_v6p: + case OP_RCALL7_v6p: + case OP_RCALL8_v6p: + if (st_op > OP_RCALL1_v6p) + check_global (pr, st, op, ev_int, st->c, 1); + check_global (pr, st, op, ev_int, st->b, 1); + check_global (pr, st, op, ev_func, st->a, 1); + break; + case OP_STATE_v6p: + case OP_STATE_F_v6p: + if (!state_ok) { + PR_Error (pr, "PR_Check_Opcodes: %s used with missing " + "fields or globals", op->opname); + } + check_global (pr, st, op, op->type_a, st->a, 1); + check_global (pr, st, op, op->type_b, st->b, 1); + check_global (pr, st, op, op->type_c, st->c, 1); + break; + case OP_MOVEI_v6p: + check_global_size (pr, st, op, st->b, st->a); + check_global_size (pr, st, op, st->b, st->c); + break; + case OP_MEMSETI_v6p: + check_global_size (pr, st, op, st->b, st->c); + break; + case OP_PUSHB_F_v6p: + case OP_PUSHB_S_v6p: + case OP_PUSHB_ENT_v6p: + case OP_PUSHB_FLD_v6p: + case OP_PUSHB_FN_v6p: + case OP_PUSHB_I_v6p: + case OP_PUSHB_P_v6p: + case OP_PUSHB_V_v6p: + case OP_PUSHB_Q_v6p: + case OP_PUSHBI_F_v6p: + case OP_PUSHBI_S_v6p: + case OP_PUSHBI_ENT_v6p: + case OP_PUSHBI_FLD_v6p: + case OP_PUSHBI_FN_v6p: + case OP_PUSHBI_I_v6p: + case OP_PUSHBI_P_v6p: + case OP_PUSHBI_V_v6p: + case OP_PUSHBI_Q_v6p: + // op->type_c is used for selecting the operator during + // compilation, but is invalid when running + check_global (pr, st, op, op->type_a, st->a, 1); + check_global (pr, st, op, op->type_b, st->b, 1); + check_global (pr, st, op, ev_invalid, st->c, 1); + break; + case OP_POP_F_v6p: + case OP_POP_FLD_v6p: + case OP_POP_ENT_v6p: + case OP_POP_S_v6p: + case OP_POP_FN_v6p: + case OP_POP_I_v6p: + case OP_POP_P_v6p: + case OP_POP_V_v6p: + case OP_POP_Q_v6p: + // don't want to check for denormal floats, otherwise + // OP_POP__v6p* could use the defualt rule + check_global (pr, st, op, op->type_a, st->a, 0); + check_global (pr, st, op, ev_invalid, st->b, 1); + check_global (pr, st, op, ev_invalid, st->c, 1); + break; + case OP_POPB_F_v6p: + case OP_POPB_S_v6p: + case OP_POPB_ENT_v6p: + case OP_POPB_FLD_v6p: + case OP_POPB_FN_v6p: + case OP_POPB_I_v6p: + case OP_POPB_P_v6p: + case OP_POPB_V_v6p: + case OP_POPB_Q_v6p: + case OP_POPBI_F_v6p: + case OP_POPBI_S_v6p: + case OP_POPBI_ENT_v6p: + case OP_POPBI_FLD_v6p: + case OP_POPBI_FN_v6p: + case OP_POPBI_I_v6p: + case OP_POPBI_P_v6p: + case OP_POPBI_V_v6p: + case OP_POPBI_Q_v6p: + // op->type_c is used for selecting the operator during + // compilation, but is invalid when running + check_global (pr, st, op, op->type_a, st->a, 1); + check_global (pr, st, op, op->type_b, st->b, 1); + check_global (pr, st, op, ev_invalid, st->c, 1); + break; + default: + check_global (pr, st, op, op->type_a, st->a, 1); + check_global (pr, st, op, op->type_b, st->b, + (op - pr_v6p_opcodes) != OP_STORE_F_v6p); + check_global (pr, st, op, op->type_c, st->c, 0); + break; + } + } + } + return 1; +} diff --git a/libs/gamecode/swizzle.py b/libs/gamecode/swizzle.py new file mode 100644 index 000000000..f61d50de5 --- /dev/null +++ b/libs/gamecode/swizzle.py @@ -0,0 +1,183 @@ +def iter(func): + for i in range(4): + for j in range(4): + for k in range(4): + for l in range(4): + func(i, j, k, l) + +def iter16(func): + for i in range(16): + func(i) + +import sys + +coord=['x', 'y', 'z', 'w'] +def label(i, j, k, l): + return f"swizzle_{coord[l]}{coord[k]}{coord[j]}{coord[i]}" + +def print_ref(i, j, k, l): + print(f"\t\t&&{label(i, j, k, l)},") + +def print_op(i, j, k, l): + print(f"\t{label(i, j, k, l)}: vec = swizzle (vec, (pr_ivec4_t) {{ {l}, {k}, {j}, {i} }}); goto negate;") + +def print_data(i, j, k, l): + print(f"\t{{ {l+1:2}, {k+1:2}, {j+1:2}, {i+1:2} }},") + +def print_swizzle_f(i, j, k, l): + swiz = i * 64 + j * 16 + k * 4 + l + addr = (swiz + 1) * 4 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x{swiz:04x}, {addr} }},") + +def print_neg_f(i): + swiz = i * 0x100 + 0xe4 + addr = (i + 1) * 4 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x{swiz:04x}, {addr} }},") + +def print_zero_f(i): + swiz = i * 0x1000 + 0xe4 + addr = (i + 1) * 4 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x{swiz:04x}, {addr} }},") + +def print_swizzle_d(i, j, k, l): + swiz = i * 64 + j * 16 + k * 4 + l + addr = (swiz + 1) * 8 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x{swiz:04x}, {addr} }},") + +def print_neg_d(i): + swiz = i * 0x100 + 0xe4 + addr = (i + 1) * 8 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x{swiz:04x}, {addr} }},") + +def print_zero_d(i): + swiz = i * 0x1000 + 0xe4 + addr = (i + 1) * 8 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x{swiz:04x}, {addr} }},") + +def print_eights(i, j, k, l): + print(f"\t{{ {8:2}, {8:2}, {8:2}, {8:2} }},") + +def print_nines(i): + print(f"\t{{ {9:2}, {9:2}, {9:2}, {9:2} }},") + +def print_neg(n): + x = [1, 2, 3, 4] + for i in range(4): + if n & (1<< i): + x[i] = -x[i] + print(f"\t{{ {x[0]:2}, {x[1]:2}, {x[2]:2}, {x[3]:2} }},") + +def print_zero(z): + x = [1, 2, 3, 4] + for i in range(4): + if z & (1<< i): + x[i] = 0 + print(f"\t{{ {x[0]:2}, {x[1]:2}, {x[2]:2}, {x[3]:2} }},") + +types = ["f", "d"] +tests = ["swizzle", "neg", "zero"] + +if sys.argv[1] == "case": + iter(print_op) + print("\tstatic void *swizzle_table[256] = {") + iter(print_ref) + print("\t};") +elif sys.argv[1] == "test": + print('#include "head.c"') + print() + print("static pr_vec4_t swizzle_f_init[] = {") + print_data(3, 2, 1, 0) + iter(print_eights) + print("};") + print("static pr_vec4_t swizzle_f_expect[] = {") + print_data(3, 2, 1, 0) + iter(print_data) + print("};") + print() + print("static dstatement_t swizzle_f_statements[] = {") + iter(print_swizzle_f) + print("};") + print() + print("static pr_vec4_t neg_f_init[] = {") + print_neg(0) + iter16(print_nines) + print("};") + print() + print("static pr_vec4_t neg_f_expect[] = {") + print_neg(0) + iter16(print_neg) + print("};") + print() + print("static dstatement_t neg_f_statements[] = {") + iter16(print_neg_f) + print("};") + print() + print("static pr_vec4_t zero_f_init[] = {") + print_zero(0) + iter16(print_nines) + print("};") + print() + print("static pr_vec4_t zero_f_expect[] = {") + print_zero(0) + iter16(print_zero) + print("};") + print() + print("static dstatement_t zero_f_statements[] = {") + iter16(print_zero_f) + print("};") + print() + print("static pr_dvec4_t swizzle_d_init[] = {") + print_data(3, 2, 1, 0) + iter(print_eights) + print("};") + print("static pr_dvec4_t swizzle_d_expect[] = {") + print_data(3, 2, 1, 0) + iter(print_data) + print("};") + print() + print("static dstatement_t swizzle_d_statements[] = {") + iter(print_swizzle_d) + print("};") + print() + print("static pr_dvec4_t neg_d_init[] = {") + print_neg(0) + iter16(print_nines) + print("};") + print() + print("static pr_dvec4_t neg_d_expect[] = {") + print_neg(0) + iter16(print_neg) + print("};") + print() + print("static dstatement_t neg_d_statements[] = {") + iter16(print_neg_d) + print("};") + print() + print("static pr_dvec4_t zero_d_init[] = {") + print_zero(0) + iter16(print_nines) + print("};") + print() + print("static pr_dvec4_t zero_d_expect[] = {") + print_zero(0) + iter16(print_zero) + print("};") + print() + print("static dstatement_t zero_d_statements[] = {") + iter16(print_zero_d) + print("};") + print() + print("test_t tests[] = {") + for t in types: + for o in tests: + print("\t{") + print(f'\t\t.desc = "{o} {t}",') + print(f"\t\t.num_globals = num_globals({o}_{t}_init,{o}_{t}_expect),") + print(f"\t\t.num_statements = num_statements({o}_{t}_statements),") + print(f"\t\t.statements = {o}_{t}_statements,") + print(f"\t\t.init_globals = (pr_int_t *) {o}_{t}_init,") + print(f"\t\t.expect_globals = (pr_int_t *) {o}_{t}_expect,") + print("\t},") + print("};") + print() + print('#include "main.c"') diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am new file mode 100644 index 000000000..57793aa4f --- /dev/null +++ b/libs/gamecode/test/Makemodule.am @@ -0,0 +1,196 @@ +libs_gamecode_tests = \ + libs/gamecode/test/test-branch \ + libs/gamecode/test/test-bitops \ + libs/gamecode/test/test-callret \ + libs/gamecode/test/test-conv0 \ + libs/gamecode/test/test-conv1 \ + libs/gamecode/test/test-conv2 \ + libs/gamecode/test/test-conv3 \ + libs/gamecode/test/test-conv4 \ + libs/gamecode/test/test-conv5 \ + libs/gamecode/test/test-conv6 \ + libs/gamecode/test/test-conv7 \ + libs/gamecode/test/test-double \ + libs/gamecode/test/test-float \ + libs/gamecode/test/test-hops \ + libs/gamecode/test/test-int \ + libs/gamecode/test/test-jump \ + libs/gamecode/test/test-lea \ + libs/gamecode/test/test-load \ + libs/gamecode/test/test-load64 \ + libs/gamecode/test/test-long \ + libs/gamecode/test/test-mem \ + libs/gamecode/test/test-scale \ + libs/gamecode/test/test-stack \ + libs/gamecode/test/test-state \ + libs/gamecode/test/test-store \ + libs/gamecode/test/test-store64 \ + libs/gamecode/test/test-string \ + libs/gamecode/test/test-swizzle \ + libs/gamecode/test/test-unsigned \ + libs/gamecode/test/test-vector \ + libs/gamecode/test/test-with + +TESTS += $(libs_gamecode_tests) + +check_PROGRAMS += $(libs_gamecode_tests) + +EXTRA_DIST += head.c main.c + +test_gamecode_libs= \ + libs/gamecode/libQFgamecode.la \ + libs/util/libQFutil.la + +libs_gamecode_test_test_branch_SOURCES= \ + libs/gamecode/test/test-branch.c +libs_gamecode_test_test_branch_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_branch_DEPENDENCIES=$(test_gamecode_libs) + +libs_gamecode_test_test_bitops_SOURCES= \ + libs/gamecode/test/test-bitops.c +libs_gamecode_test_test_bitops_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_bitops_DEPENDENCIES=$(test_gamecode_libs) + +libs_gamecode_test_test_callret_SOURCES= \ + libs/gamecode/test/test-callret.c +libs_gamecode_test_test_callret_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_callret_DEPENDENCIES=$(test_gamecode_libs) + +libs_gamecode_test_test_conv0_SOURCES= \ + libs/gamecode/test/test-conv0.c +libs_gamecode_test_test_conv0_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv0_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv1_SOURCES= \ + libs/gamecode/test/test-conv1.c +libs_gamecode_test_test_conv1_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv1_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv2_SOURCES= \ + libs/gamecode/test/test-conv2.c +libs_gamecode_test_test_conv2_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv2_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv3_SOURCES= \ + libs/gamecode/test/test-conv3.c +libs_gamecode_test_test_conv3_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv3_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv4_SOURCES= \ + libs/gamecode/test/test-conv4.c +libs_gamecode_test_test_conv4_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv4_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv5_SOURCES= \ + libs/gamecode/test/test-conv5.c +libs_gamecode_test_test_conv5_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv5_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv6_SOURCES= \ + libs/gamecode/test/test-conv6.c +libs_gamecode_test_test_conv6_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv6_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv7_SOURCES= \ + libs/gamecode/test/test-conv7.c +libs_gamecode_test_test_conv7_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv7_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_double_SOURCES= \ + libs/gamecode/test/test-double.c +libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_double_DEPENDENCIES=$(test_gamecode_libs) + +libs_gamecode_test_test_float_SOURCES= \ + libs/gamecode/test/test-float.c +libs_gamecode_test_test_float_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_float_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_hops_SOURCES= \ + libs/gamecode/test/test-hops.c +libs_gamecode_test_test_hops_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_hops_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_int_SOURCES= \ + libs/gamecode/test/test-int.c +libs_gamecode_test_test_int_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_int_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_jump_SOURCES= \ + libs/gamecode/test/test-jump.c +libs_gamecode_test_test_jump_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_jump_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_lea_SOURCES= \ + libs/gamecode/test/test-lea.c +libs_gamecode_test_test_lea_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_lea_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_load_SOURCES= \ + libs/gamecode/test/test-load.c +libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_load64_SOURCES= \ + libs/gamecode/test/test-load64.c +libs_gamecode_test_test_load64_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_load64_DEPENDENCIES=$(test_gamecode_libs) + +libs_gamecode_test_test_long_SOURCES= \ + libs/gamecode/test/test-long.c +libs_gamecode_test_test_long_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_long_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_mem_SOURCES= \ + libs/gamecode/test/test-mem.c +libs_gamecode_test_test_mem_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_mem_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_scale_SOURCES= \ + libs/gamecode/test/test-scale.c +libs_gamecode_test_test_scale_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_scale_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_stack_SOURCES= \ + libs/gamecode/test/test-stack.c +libs_gamecode_test_test_stack_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_stack_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_state_SOURCES= \ + libs/gamecode/test/test-state.c +libs_gamecode_test_test_state_LDADD= $(test_gamecode_libs) + +libs_gamecode_test_test_store_SOURCES= \ + libs/gamecode/test/test-store.c +libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_store_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_store64_SOURCES= \ + libs/gamecode/test/test-store64.c +libs_gamecode_test_test_store64_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_store64_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_string_SOURCES= \ + libs/gamecode/test/test-string.c +libs_gamecode_test_test_string_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_string_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_swizzle_SOURCES= \ + libs/gamecode/test/test-swizzle.c +libs_gamecode_test_test_swizzle_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_swizzle_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_unsigned_SOURCES= \ + libs/gamecode/test/test-unsigned.c +libs_gamecode_test_test_unsigned_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_unsigned_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_vector_SOURCES= \ + libs/gamecode/test/test-vector.c +libs_gamecode_test_test_vector_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_vector_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_with_SOURCES= \ + libs/gamecode/test/test-with.c +libs_gamecode_test_test_with_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_with_DEPENDENCIES= $(test_gamecode_libs) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c new file mode 100644 index 000000000..78410dfe5 --- /dev/null +++ b/libs/gamecode/test/head.c @@ -0,0 +1,54 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/progs.h" + +static int verbose = 0; + +// both calculates the number of globals in the test, and ensures that both +// init and expect are the same size (will product a "void value not ignored" +// error if the sizes differ) +#define num_globals(init, expect) \ + __builtin_choose_expr ( \ + sizeof (init) == sizeof (expect), \ + (sizeof (init) / sizeof (init[0])) \ + * (sizeof (init[0]) / sizeof (pr_type_t)), \ + (void) 0\ + ) + +// calculate the numver of statements in the test +#define num_statements(statements) \ + (sizeof (statements) / sizeof (statements[0])) + +#define num_functions(functions) \ + (sizeof (functions) / sizeof (functions[0])) + +#define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) +#define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) + +typedef struct { + const char *desc; + pr_ptr_t edict_area; + pr_uint_t stack_size; + pr_uint_t extra_globals; + pr_uint_t num_globals; + pr_uint_t num_statements; + dstatement_t *statements; + pr_int_t *init_globals; + pr_int_t *expect_globals; + const char *strings; + pr_uint_t string_size; + // pointers/globals for state + double *double_time; + pr_uint_t dtime; + float *float_time; + pr_uint_t ftime; + pr_uint_t self; + // fields for state + pr_uint_t think; + pr_uint_t nextthink; + pr_uint_t frame; + bfunction_t *functions; + pr_uint_t num_functions; +} test_t; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c new file mode 100644 index 000000000..bb0efb2fd --- /dev/null +++ b/libs/gamecode/test/main.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include + +#include "QF/va.h" + +#define num_tests (sizeof (tests) / sizeof (tests[0])) +static int test_enabled[num_tests] = { 0 }; + +#include "getopt.h" + +#include "QF/cmd.h" +#include "QF/cvar.h" + +static bfunction_t test_functions[] = { + {}, // null function + { .first_statement = 0 } +}; +static dprograms_t test_progs = { + .version = PROG_VERSION, +}; +static progs_t test_pr; + +static jmp_buf jump_buffer; + +static void +test_debug_handler (prdebug_t event, void *param, void *data) +{ + progs_t *pr = data; + + switch (event) { + case prd_breakpoint: + if (verbose > 0) { + printf ("debug: %s\n", prdebug_names[event]); + } + longjmp (jump_buffer, 1); + case prd_subenter: + if (verbose > 0) { + printf ("debug: subenter %d\n", *(pr_func_t *) param); + } + case prd_subexit: + break; + case prd_trace: + dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement; + if (verbose > 1) { + printf ("---\n"); + printf ("debug: trace %05x %04x %04x %04x %04x%s\n", + test_pr.pr_xstatement, st->op, st->a, st->b, st->c, + pr->globals.stack ? va (0, " %05x", *pr->globals.stack) + : ""); + printf (" %04x %04x %04x\n", + st->a + PR_BASE (pr, st, A), + st->b + PR_BASE (pr, st, B), + st->c + PR_BASE (pr, st, C)); + } + if (verbose > 0) { + PR_PrintStatement (&test_pr, st, 0); + } + if (pr->globals.stack) { + if (*pr->globals.stack & 3) { + printf ("stack not aligned: %d\n", *pr->globals.stack); + longjmp (jump_buffer, 3); + } + } + break; + case prd_runerror: + printf ("debug: %s: %s\n", prdebug_names[event], (char *)param); + longjmp (jump_buffer, 3); + case prd_watchpoint: + case prd_begin: + case prd_terminate: + case prd_error: + case prd_none: + printf ("debug: unexpected:%s %p\n", prdebug_names[event], param); + longjmp (jump_buffer, 2); + } +} + +static void +setup_test (test_t *test) +{ + memset (&test_pr, 0, sizeof (test_pr)); + PR_Init (&test_pr); + PR_Debug_Init (&test_pr); + test_pr.progs = &test_progs; + test_pr.debug_handler = test_debug_handler; + test_pr.debug_data = &test_pr; + test_pr.pr_trace = 1; + test_pr.pr_trace_depth = -1; + if (test->num_functions && test->functions) { + test_pr.function_table = calloc ((test->num_functions + 2), + sizeof (bfunction_t)); + memcpy (test_pr.function_table, test_functions, + 2 * sizeof (bfunction_t)); + memcpy (test_pr.function_table + 2, test->functions, + test->num_functions * sizeof (bfunction_t)); + } else { + test_pr.function_table = test_functions; + } + + pr_uint_t num_globals = test->num_globals; + num_globals += test->extra_globals + test->stack_size; + + test_pr.globals_size = num_globals; + test_pr.pr_globals = Sys_Alloc (num_globals * sizeof (pr_type_t)); + memcpy (test_pr.pr_globals, test->init_globals, + test->num_globals * sizeof (pr_type_t)); + memset (test_pr.pr_globals + test->num_globals, 0, + test->extra_globals * sizeof (pr_type_t)); + if (test->stack_size) { + pr_ptr_t stack = num_globals - test->stack_size; + test_pr.stack_bottom = stack + 4; + test_pr.globals.stack = (pr_ptr_t *) (test_pr.pr_globals + stack); + *test_pr.globals.stack = num_globals; + } + if (test->edict_area) { + test_pr.pr_edict_area = test_pr.pr_globals + test->edict_area; + } + if (test->double_time || test->float_time) { + test_pr.fields.nextthink = test->nextthink; + test_pr.fields.frame = test->frame; + test_pr.fields.think = test->think; + test_pr.globals.self = (pr_uint_t *) &test_pr.pr_globals[test->self]; + if (test->double_time) { + test_pr.globals.dtime = (double *)&test_pr.pr_globals[test->dtime]; + *test_pr.globals.dtime = *test->double_time; + } + if (test->float_time) { + test_pr.globals.ftime = (float *) &test_pr.pr_globals[test->ftime]; + *test_pr.globals.ftime = *test->float_time; + } + } + + test_progs.statements.count = test->num_statements + 1; + test_pr.pr_statements + = malloc ((test->num_statements + 1) * sizeof (dstatement_t)); + memcpy (test_pr.pr_statements, test->statements, + (test->num_statements + 1) * sizeof (dstatement_t)); + test_pr.pr_statements[test->num_statements] = + (dstatement_t) { OP_BREAK, 0, 0, 0 }; + + test_pr.pr_strings = (char *) test->strings; + test_pr.pr_stringsize = test->string_size; +} + +static int +check_result (test_t *test) +{ + int ret = 0; + + if (memcmp (test_pr.pr_globals, test->expect_globals, + test->num_globals * sizeof (pr_int_t)) == 0) { + ret = 1; + printf ("test #%zd: %s: OK\n", test - tests, test->desc); + } else { + printf ("test #%zd: %s: words differ\n", test - tests, test->desc); + } + return ret; +} + +static int +run_test (test_t *test) +{ + int jump_ret; + int ret = 0; + + setup_test (test); + + if (!(jump_ret = setjmp (jump_buffer))) { + PR_ExecuteProgram (&test_pr, 1); + printf ("returned from progs\n"); + } + if (jump_ret == 1) { + ret = check_result (test); + } else { + printf ("test #%zd: %s: critical failure\n", test - tests, test->desc); + } + + pr_uint_t num_globals = test->num_globals; + num_globals += test->extra_globals + test->stack_size; + if (test->num_functions && test->functions) { + free (test_pr.function_table); + } + Sys_Free (test_pr.pr_globals, num_globals * sizeof (pr_type_t)); + + free (test_pr.pr_statements); + return ret; +} + +int +main (int argc, char **argv) +{ + int c; + size_t i, test; + int pass = 1; + + Cmd_Init_Hash (); + Cvar_Init_Hash (); + Cmd_Init (); + Cvar_Init (); + PR_Init_Cvars (); + pr_boundscheck->int_val = 1; + + while ((c = getopt (argc, argv, "qvt:")) != EOF) { + switch (c) { + case 'q': + verbose--; + break; + case 'v': + verbose++; + break; + case 't': + test = atoi (optarg); + if (test < num_tests) { + test_enabled[test] = 1; + } else { + fprintf (stderr, "Bad test number (0 - %zd)\n", num_tests); + return 1; + } + break; + default: + fprintf (stderr, "-q (quiet) -v (verbose) and/or -t TEST " + "(test number)\n"); + return 1; + } + } + + for (i = 0; i < num_tests; i++) + if (test_enabled[i]) + break; + if (i == num_tests) { + for (i = 0; i < num_tests; i++) + test_enabled[i] = 1; + } + + for (i = 0; i < num_tests; i++) { + if (!test_enabled[i]) + continue; + pass &= run_test (&tests[i]); + } + + return !pass; +} diff --git a/libs/gamecode/test/test-bitops.c b/libs/gamecode/test/test-bitops.c new file mode 100644 index 000000000..b692223d7 --- /dev/null +++ b/libs/gamecode/test/test-bitops.c @@ -0,0 +1,260 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t int_bitop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_bitop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 5, 1, 1, -5}, + { 5, -1, -1, -5}, + { 0, -2, -2, 0}, + { -6, 4, -6, 4}, +}; + +static dstatement_t int_bitop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 24 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 24, -1, 24 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 24 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 24, 1 }, + + { OP(1, 1, 1, OP_BITAND_I_1), 0, 4, 8}, + { OP(1, 1, 1, OP_BITOR_I_1), 0, 4, 12}, + { OP(1, 1, 1, OP_BITXOR_I_1), 0, 4, 16}, + { OP(1, 1, 1, OP_BITNOT_I_1), 0, 4, 20}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t int_bitop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 24 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 24, -2, 24 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 24 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 24, 1 }, + + { OP(1, 1, 1, OP_BITAND_I_2), 0, 4, 8}, + { OP(1, 1, 1, OP_BITOR_I_2), 0, 4, 12}, + { OP(1, 1, 1, OP_BITXOR_I_2), 0, 4, 16}, + { OP(1, 1, 1, OP_BITNOT_I_2), 0, 4, 20}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t int_bitop_3a_statements[] = { + { OP(1, 1, 1, OP_BITAND_I_3), 0, 4, 8}, + { OP(1, 1, 1, OP_BITAND_I_1), 3, 7, 11}, + { OP(1, 1, 1, OP_BITOR_I_3), 0, 4, 12}, + { OP(1, 1, 1, OP_BITOR_I_1), 3, 7, 15}, + { OP(1, 1, 1, OP_BITXOR_I_3), 0, 4, 16}, + { OP(1, 1, 1, OP_BITXOR_I_1), 3, 7, 19}, + { OP(1, 1, 1, OP_BITNOT_I_3), 0, 4, 20}, + { OP(1, 1, 1, OP_BITNOT_I_1), 3, 7, 23}, +}; + +static dstatement_t int_bitop_3b_statements[] = { + { OP(1, 1, 1, OP_BITAND_I_1), 0, 4, 8}, + { OP(1, 1, 1, OP_BITAND_I_3), 1, 5, 9}, + { OP(1, 1, 1, OP_BITOR_I_1), 0, 4, 12}, + { OP(1, 1, 1, OP_BITOR_I_3), 1, 5, 13}, + { OP(1, 1, 1, OP_BITXOR_I_1), 0, 4, 16}, + { OP(1, 1, 1, OP_BITXOR_I_3), 1, 5, 17}, + { OP(1, 1, 1, OP_BITNOT_I_1), 0, 4, 20}, + { OP(1, 1, 1, OP_BITNOT_I_3), 1, 5, 21}, +}; + +static dstatement_t int_bitop_4_statements[] = { + { OP(1, 1, 1, OP_BITAND_I_4), 0, 4, 8}, + { OP(1, 1, 1, OP_BITOR_I_4), 0, 4, 12}, + { OP(1, 1, 1, OP_BITXOR_I_4), 0, 4, 16}, + { OP(1, 1, 1, OP_BITNOT_I_4), 0, 4, 20}, +}; + +static pr_lvec4_t long_bitop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_lvec4_t long_bitop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 5, 1, 1, -5}, + { 5, -1, -1, -5}, + { 0, -2, -2, 0}, + { -6, 4, -6, 4}, +}; + +static dstatement_t long_bitop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 48 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 48, -2, 48 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 48 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 48, 1 }, + + { OP(1, 1, 1, OP_BITAND_L_1), 0, 8, 16}, + { OP(1, 1, 1, OP_BITOR_L_1), 0, 8, 24}, + { OP(1, 1, 1, OP_BITXOR_L_1), 0, 8, 32}, + { OP(1, 1, 1, OP_BITNOT_L_1), 0, 8, 40}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t long_bitop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 48 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 48, -4, 48 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 48 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 48, 1 }, + + { OP(1, 1, 1, OP_BITAND_L_2), 0, 8, 16}, + { OP(1, 1, 1, OP_BITOR_L_2), 0, 8, 24}, + { OP(1, 1, 1, OP_BITXOR_L_2), 0, 8, 32}, + { OP(1, 1, 1, OP_BITNOT_L_2), 0, 8, 40}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t long_bitop_3a_statements[] = { + { OP(1, 1, 1, OP_BITAND_L_3), 0, 8, 16}, + { OP(1, 1, 1, OP_BITAND_L_1), 6, 14, 22}, + { OP(1, 1, 1, OP_BITOR_L_3), 0, 8, 24}, + { OP(1, 1, 1, OP_BITOR_L_1), 6, 14, 30}, + { OP(1, 1, 1, OP_BITXOR_L_3), 0, 8, 32}, + { OP(1, 1, 1, OP_BITXOR_L_1), 6, 14, 38}, + { OP(1, 1, 1, OP_BITNOT_L_3), 0, 8, 40}, + { OP(1, 1, 1, OP_BITNOT_L_1), 6, 14, 46}, +}; + +static dstatement_t long_bitop_3b_statements[] = { + { OP(1, 1, 1, OP_BITAND_L_1), 0, 8, 16}, + { OP(1, 1, 1, OP_BITAND_L_3), 2, 10, 18}, + { OP(1, 1, 1, OP_BITOR_L_1), 0, 8, 24}, + { OP(1, 1, 1, OP_BITOR_L_3), 2, 10, 26}, + { OP(1, 1, 1, OP_BITXOR_L_1), 0, 8, 32}, + { OP(1, 1, 1, OP_BITXOR_L_3), 2, 10, 34}, + { OP(1, 1, 1, OP_BITNOT_L_1), 0, 8, 40}, + { OP(1, 1, 1, OP_BITNOT_L_3), 2, 10, 42}, +}; + +static dstatement_t long_bitop_4_statements[] = { + { OP(1, 1, 1, OP_BITAND_L_4), 0, 8, 16}, + { OP(1, 1, 1, OP_BITOR_L_4), 0, 8, 24}, + { OP(1, 1, 1, OP_BITXOR_L_4), 0, 8, 32}, + { OP(1, 1, 1, OP_BITNOT_L_4), 0, 8, 40}, +}; + +test_t tests[] = { + { + .desc = "int bitop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_1_statements), + .statements = int_bitop_1_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_2_statements), + .statements = int_bitop_2_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_3a_statements), + .statements = int_bitop_3a_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_3b_statements), + .statements = int_bitop_3b_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_4_statements), + .statements = int_bitop_4_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "long bitop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_1_statements), + .statements = long_bitop_1_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_2_statements), + .statements = long_bitop_2_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_3a_statements), + .statements = long_bitop_3a_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_3b_statements), + .statements = long_bitop_3b_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_4_statements), + .statements = long_bitop_4_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-branch.c b/libs/gamecode/test/test-branch.c new file mode 100644 index 000000000..e02f229ba --- /dev/null +++ b/libs/gamecode/test/test-branch.c @@ -0,0 +1,193 @@ +#include "head.c" + +#define DB 0xdeadbeef + +static pr_int_t test_globals_init[] = { + -1, 1, 0, DB, DB, +}; + +static pr_int_t test_globals_expect[] = { + -1, 1, 0, DB, 1, +}; + +static dstatement_t ifz_taken_statements[] = { + { OP_IFZ, 4, 0, 2 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFZ, -2, 0, 2 }, +}; + +static dstatement_t ifb_taken_statements[] = { + { OP_IFB, 4, 0, 0 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFB, -2, 0, 0 }, +}; + +static dstatement_t ifa_taken_statements[] = { + { OP_IFA, 4, 0, 1 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFA, -2, 0, 1 }, +}; + +static dstatement_t ifnz_taken_statements[] = { + { OP_IFNZ, 4, 0, 0 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFNZ, -2, 0, 1 }, +}; + +static dstatement_t ifae_taken_statements[] = { + { OP_IFAE, 4, 0, 1 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFAE, -2, 0, 2 }, +}; + +static dstatement_t ifbe_taken_statements[] = { + { OP_IFBE, 4, 0, 0 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFBE, -2, 0, 2 }, +}; + +static dstatement_t ifz_not_taken_statements[] = { + { OP_IFZ, 3, 0, 0 }, + { OP_IFZ, 2, 0, 1 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifb_not_taken_statements[] = { + { OP_IFB, 3, 0, 2 }, + { OP_IFB, 2, 0, 1 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifa_not_taken_statements[] = { + { OP_IFA, 3, 0, 2 }, + { OP_IFA, 2, 0, 0 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifnz_not_taken_statements[] = { + { OP_IFNZ, 3, 0, 2 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifae_not_taken_statements[] = { + { OP_IFAE, 2, 0, 0 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifbe_not_taken_statements[] = { + { OP_IFBE, 2, 0, 1 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +test_t tests[] = { + { + .desc = "ifz taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifz_taken_statements), + .statements = ifz_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifb taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifb_taken_statements), + .statements = ifb_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifa taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifa_taken_statements), + .statements = ifa_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifnz taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifnz_taken_statements), + .statements = ifnz_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifae taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifae_taken_statements), + .statements = ifae_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifbe taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifbe_taken_statements), + .statements = ifbe_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifz not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifz_not_taken_statements), + .statements = ifz_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifb not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifb_not_taken_statements), + .statements = ifb_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifa not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifa_not_taken_statements), + .statements = ifa_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifnz not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifnz_not_taken_statements), + .statements = ifnz_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifae not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifae_not_taken_statements), + .statements = ifae_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifbe not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifbe_not_taken_statements), + .statements = ifbe_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c new file mode 100644 index 000000000..d90b95efa --- /dev/null +++ b/libs/gamecode/test/test-callret.c @@ -0,0 +1,208 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((float)(x)*(float)(x)) +#define pi_6 0x3f060a92 // pi/6 +#define r3_2 0x3f5db3d7 // sqrt(3)/2 +#define f1_2 0x3f000000 // 1/2 +#define f1 0x3f800000 // 1 +#define f2 0x40000000 // 2 +#define shx 0x3f0c4020 // sinh(pi/6) +#define chx 0x3f91f354 // cosh(pi/6) + +#define DB 0xdeadbeef + +#define STK (32 * 4) // stack ptr just after globals + +static pr_ivec4_t callret_init[32] = { + { 0, pi_6, 2, 0}, + { f1, f2, 0, 0}, + // result + { DB, DB, DB, DB }, + // pre-call with + { DB, DB, DB, DB }, + // post-call with + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, +}; + +static pr_ivec4_t callret_expect[32] = { + // constants + { 0, pi_6, 2, 0 }, + { f1, f2, 0, 0 }, + // result + { r3_2, f1_2, chx, shx }, + // pre-call with: should be all 0 on progs init + { 0, 0, 0, 0 }, + // post-call with; should be restored to pre-call values (in this case, + // progs init) + { 0, 0, 0, 0 }, + { DB, DB, DB, DB }, +}; + +static dstatement_t callret_statements[] = { + { OP_WITH, 8, 0, 0 }, // pushregs + { OP_POP_A_4, 12, 0, 0 }, + { OP_STORE_A_1, 7, 0, STK }, // save stack pointer for check + { OP_PUSH_A_1, 1, 0, 0 }, + { OP_CALL_B, 2, 0, 8 }, + { OP_LEA_C, STK, 4, STK }, // discard param + { OP_SUB_I_1, 7, STK, 7 }, // check stack restored + { OP_WITH, 8, 0, 0 }, // pushregs + { OP_POP_A_4, 16, 0, 0 }, + { OP_BREAK }, +// cos_sin_cosh_sinh: +// calculate cos(x), sin(x), cosh(x) and sinh(x) simultaneously +[32]= + { OP_WITH, 2, 0, 1 }, // put params into reg 1 + { OP_LEA_C, STK, -24, STK }, // reserve 24 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 +#define x 0 // in parameters float +#define xn 0 // in locals vec4 +#define x2 4 // in locals vec4 +#define ac 8 // in locals vec4 +#define fa 12 // in locals vec4 +#define fi 16 // in locals vec4 +#define c 20 // in locals int + { OP(2, 0, 1, OP_STORE_A_1), xn+1,0, x }, // init xn to [1, x, 0, 0] + { OP(2, 0, 0, OP_STORE_A_1), xn, 0, 4 }, + { OP(2, 0, 2, OP_SWIZZLE_F), xn, 0x0044, xn }, // xn -> [1, x, 1, x] + { OP(1, 1, 2, OP_MUL_F_1), x, x, x2 }, // x2 -> [x*x, ?, ?, ?] + { OP(2, 0, 2, OP_SWIZZLE_F), x2, 0x0300, x2},//x2 -> [-x*x, -x*x, x*x, x*x] + { OP(2, 0, 0, OP_STORE_A_1), fa, 0, 4 }, // init factorial + { OP(2, 0, 0, OP_STORE_A_1), fa+1,0, 5 }, + { OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0044, fa }, // fa -> [1, 2, 1, 2] + { OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0000, fi }, // init fi -> [1, 1, 1, 1] + { OP(2, 2, 2, OP_SUB_F_4), ac, ac, ac }, // init acc (output) to 0 + { OP(0, 0, 2, OP_LEA_A), 25, 0, c }, // init count +// loop: + { OP(2, 2, 2, OP_ADD_F_4), ac, xn, ac }, // acc += xn + { OP(2, 2, 2, OP_MUL_F_4), xn, x2, xn }, // xn *= x2 + { OP(2, 2, 2, OP_DIV_F_4), xn, fa, xn }, // xn /= f + { OP(2, 2, 2, OP_ADD_F_4), fa, fi, fa }, // f += inc + { OP(2, 2, 2, OP_DIV_F_4), xn, fa, xn }, // xn /= f + { OP(2, 2, 2, OP_ADD_F_4), fa, fi, fa }, // f += inc + { OP(2, 0, 2, OP_LEA_C), c, -1, c }, // dec count + { OP(0, 0, 2, OP_IFA), -7, 0, c }, // count > 0 + { OP(2, 0, 0, OP_RETURN), ac, 0, 3 }, // size is (c&31)+1 +#undef x +#undef xn +#undef x2 +#undef ac +#undef fa +#undef fi +#undef c +}; + +static pr_ivec4_t call32_init[32] = { + { 0, 2, 0, 0 }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, +}; + +static pr_ivec4_t call32_expect[32] = { + { 0, 2, 0, 0 }, + { 0, 1, 2, 3 }, + { 4, 5, 6, 7 }, + { 8, 9, 10, 11 }, + { 12, 13, 14, 15 }, + { 16, 17, 18, 19 }, + { 20, 21, 22, 23 }, + { 24, 25, 26, 27 }, + { 28, 29, 30, 31 }, +}; + +static dstatement_t call32_statements[] = { + { OP_CALL_B, 1, 0, 4 }, + { OP_BREAK }, +[32]= + { OP_LEA_C, STK, -36, STK }, // reserve 36 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 + { OP(0, 0, 2, OP_LEA_A), 32, 0, 32 }, // init index + { OP(2, 0, 2, OP_LEA_A), 0, 0, 33 }, // init base to array +//loop: + { OP(0, 0, 2, OP_IFBE), 4, 0, 32 }, // if index-- > 0 + { OP(2, 0, 2, OP_LEA_C), 32, -1, 32 }, + { OP(2, 2, 2, OP_STORE_D_1), 33, 32, 32 }, // array[index] = index + { OP(0, 0, 0, OP_JUMP_A), -3, 0, 0 }, + { OP(2, 0, 0, OP_RETURN), 0, 0, 0x1f }, // only bits 0-5 are size +}; + +static pr_ivec4_t callchain_init[32] = { + { 0, 2, 3, 4 }, + { DB, DB, DB, DB }, +}; + +static pr_ivec4_t callchain_expect[32] = { + { 0, 2, 3, 4 }, + { 42, DB, DB, DB }, +}; + +static dstatement_t callchain_statements[] = { + { OP_CALL_B, 1, 0, 4 }, + { OP_BREAK }, +[32]= + { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 + { OP(0, 0, 2, OP_CALL_B), 2, 0, 0 }, + { OP(0, 0, 2, OP_CALL_B), 3, 0, 1 }, + { OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, +[64]= + { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 + { OP(0, 0, 2, OP_LEA_A), 42, 0, 0 }, // init value + { OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, // return value +[96]= + { OP_RETURN, 0, 0, -1 } // void return +}; + +static bfunction_t callret_functions[] = { + { .first_statement = 32 }, + { .first_statement = 64 }, + { .first_statement = 96 }, +}; + +test_t tests[] = { + { + .desc = "callret", + .num_globals = num_globals(callret_init,callret_expect), + .num_statements = num_statements (callret_statements), + .statements = callret_statements, + .init_globals = (pr_int_t *) callret_init, + .expect_globals = (pr_int_t *) callret_expect, + .functions = callret_functions, + .num_functions = num_functions(callret_functions), + .stack_size = 128, + }, + { + .desc = "call32", + .num_globals = num_globals(call32_init,call32_expect), + .num_statements = num_statements (call32_statements), + .statements = call32_statements, + .init_globals = (pr_int_t *) call32_init, + .expect_globals = (pr_int_t *) call32_expect, + .functions = callret_functions, + .num_functions = num_functions(callret_functions), + .stack_size = 128, + }, + { + .desc = "callchain", + .num_globals = num_globals(callchain_init,callchain_expect), + .num_statements = num_statements (callchain_statements), + .statements = callchain_statements, + .init_globals = (pr_int_t *) callchain_init, + .expect_globals = (pr_int_t *) callchain_expect, + .functions = callret_functions, + .num_functions = num_functions(callret_functions), + .stack_size = 128, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c new file mode 100644 index 000000000..3b6e06359 --- /dev/null +++ b/libs/gamecode/test/test-conv0.c @@ -0,0 +1,190 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t int_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 5, -5, 0x80000000, 0x7fffffff}, // int + { 1, -1, 0x80000000, 0x80000000}, // float undef? + { 99, 0x80000000, 256, 0x7fffffff}, // long + { 0x80000000, 0x80000000, 1, -1}, // double undef? + { 5, -5, 0x80000000, 0x7fffffff}, // uint + { 1, 1, 1, 0}, // bool32 + { 99, 0x80000000, 256, 0x7fffffff}, // ulong + { 1, 1, 1, 0}, // bool64 +}; + +static dstatement_t int_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0000, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0010, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0020, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0030, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0040, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0050, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0060, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0070, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t int_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0100, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0110, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0120, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0130, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0140, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0150, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0160, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0170, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t int_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0200, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0200, 51 }, + { OP(1, 1, 1, OP_CONV), 4, 0210, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0010, 55 }, + { OP(2, 1, 1, OP_CONV), 8, 0220, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0020, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0230, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0030, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0240, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0240, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0250, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0050, 71 }, + { OP(2, 1, 1, OP_CONV), 32, 0260, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0060, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0270, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0070, 79 }, +}; + +static dstatement_t int_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0200, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0200, 49 }, + { OP(1, 1, 1, OP_CONV), 4, 0010, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0210, 53 }, + { OP(2, 1, 1, OP_CONV), 8, 0020, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0220, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0030, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0230, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0240, 64 }, + { OP(1, 1, 1, OP_CONV), 25, 0240, 65 }, + { OP(1, 1, 1, OP_CONV), 28, 0050, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0250, 69 }, + { OP(2, 1, 1, OP_CONV), 32, 0060, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0260, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0070, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0270, 77 }, +}; + +static dstatement_t int_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0300, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0310, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0320, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0330, 60 }, + { OP(1, 1, 1, OP_CONV), 28, 0350, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0360, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0370, 76 }, + { OP(1, 1, 1, OP_CONV), 24, 0340, 64 }, +}; + +test_t tests[] = { + { + .desc = "int conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_1_statements), + .statements = int_conv_1_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_2_statements), + .statements = int_conv_2_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_3a_statements), + .statements = int_conv_3a_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_3b_statements), + .statements = int_conv_3b_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_4_statements), + .statements = int_conv_4_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv1.c b/libs/gamecode/test/test-conv1.c new file mode 100644 index 000000000..663604205 --- /dev/null +++ b/libs/gamecode/test/test-conv1.c @@ -0,0 +1,190 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t float_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t float_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0x40a00000, 0xc0a00000, 0xcf000000, 0x4f000000}, // int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, // float + { 0xdf000000, 0x52c70000, 0x43800000, 0x4f000000}, // long + { 0x7149f2ca, 0xf149f2ca, 0x3fc00000, 0xbfc00000}, // double + { 0x40a00000, 0x4f800000, 0x4f000000, 0x4f000000}, // uint + { 0x3f800000, 0x3f800000, 0x3f800000, 0}, // bool32 + { 0x5f000000, 0x52c70000, 0x43800000, 0x4f000000}, // ulong + { 0x3f800000, 0x3f800000, 0x3f800000, 0}, // bool64 +}; + +static dstatement_t float_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0001, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0011, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0021, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0031, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0041, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0051, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0061, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0071, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t float_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0101, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0111, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0121, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0131, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0141, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0151, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0161, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0171, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t float_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0201, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0001, 51 }, + { OP(1, 1, 1, OP_CONV), 4, 0211, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0011, 55 }, + { OP(2, 1, 1, OP_CONV), 8, 0221, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0021, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0231, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0031, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0241, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0041, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0251, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0051, 71 }, + { OP(2, 1, 1, OP_CONV), 32, 0261, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0061, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0271, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0071, 79 }, +}; + +static dstatement_t float_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0001, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0201, 49 }, + { OP(1, 1, 1, OP_CONV), 4, 0011, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0211, 53 }, + { OP(2, 1, 1, OP_CONV), 8, 0021, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0221, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0031, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0231, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0241, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0041, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0051, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0251, 69 }, + { OP(2, 1, 1, OP_CONV), 32, 0061, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0261, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0071, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0271, 77 }, +}; + +static dstatement_t float_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0301, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0311, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0321, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0331, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0341, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0351, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0361, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0371, 76 }, +}; + +test_t tests[] = { + { + .desc = "float conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_1_statements), + .statements = float_conv_1_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_2_statements), + .statements = float_conv_2_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_3a_statements), + .statements = float_conv_3a_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_3b_statements), + .statements = float_conv_3b_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_4_statements), + .statements = float_conv_4_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c new file mode 100644 index 000000000..0dd4f5d41 --- /dev/null +++ b/libs/gamecode/test/test-conv2.c @@ -0,0 +1,206 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t long_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t long_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 5, 0, -5, 0xffffffff}, // int + { 0x80000000, 0xffffffff, 0x7fffffff, 0}, + { 1, 0, -1, -1}, // float + { 0, 0x80000000, 0, 0x80000000}, // undef? + { 99, 0x80000000, 0x80000000, 99}, // long + { 256, 0, 0x7fffffff, 0}, + { 0, 0x80000000, 0, 0x80000000}, // double undef? + { 1, 0, -1, -1}, + { 5, 0, -5, 0}, // uint + { 0x80000000, 0, 0x7fffffff, 0}, + { 1, 0, 1, 0}, // bool32 + { 1, 0, 0, 0}, + { 99, 0x80000000, 0x80000000, 99}, // ulong + { 256, 0, 0x7fffffff, 0}, + { 1, 0, 1, 0}, // bool64 + { 1, 0, 0, 0}, +}; + +static dstatement_t long_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0002, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0012, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0022, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0032, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0042, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0052, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0062, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0072, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t long_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0102, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0112, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0122, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0132, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0142, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0152, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0162, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0172, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t long_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0202, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0002, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0212, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0012, 62 }, + { OP(2, 1, 2, OP_CONV), 8, 0222, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0022, 70 }, + { OP(2, 1, 2, OP_CONV), 16, 0232, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0032, 78 }, + { OP(1, 1, 2, OP_CONV), 24, 0242, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0042, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0252, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0052, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0262, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0062, 102 }, + { OP(2, 1, 2, OP_CONV), 40, 0272, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0072, 110 }, +}; + +static dstatement_t long_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0002, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0202, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0012, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0212, 58 }, + { OP(2, 1, 2, OP_CONV), 8, 0022, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0222, 66 }, + { OP(2, 1, 2, OP_CONV), 16, 0032, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0232, 74 }, + { OP(1, 1, 2, OP_CONV), 24, 0042, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0242, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0052, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0252, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0062, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0262, 98 }, + { OP(2, 1, 2, OP_CONV), 40, 0072, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0272, 106 }, +}; + +static dstatement_t long_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0302, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0312, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0322, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0332, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0342, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0352, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0362, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0372, 104 }, +}; + +test_t tests[] = { + { + .desc = "long conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_1_statements), + .statements = long_conv_1_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_2_statements), + .statements = long_conv_2_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_3a_statements), + .statements = long_conv_3a_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_3b_statements), + .statements = long_conv_3b_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_4_statements), + .statements = long_conv_4_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv3.c b/libs/gamecode/test/test-conv3.c new file mode 100644 index 000000000..7ea316d8b --- /dev/null +++ b/libs/gamecode/test/test-conv3.c @@ -0,0 +1,206 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t double_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t double_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0x00000000, 0x40140000, 0x00000000, 0xc0140000}, // int + { 0x00000000, 0xc1e00000, 0xffc00000, 0x41dfffff}, + { 0x00000000, 0x3ff80000, 0x00000000, 0xbff80000}, // float + { 0x40000000, 0x46293e59, 0x40000000, 0xc6293e59}, + { 0x00000000, 0xc3e00000, 0x00000000, 0x4258e000}, // long + { 0x00000000, 0x40700000, 0xffc00000, 0x41dfffff}, + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, // double + { 0, 0x3ff80000, 0, 0xbff80000}, + { 0x00000000, 0x40140000, 0xff600000, 0x41efffff}, // uint + { 0x00000000, 0x41e00000, 0xffc00000, 0x41dfffff}, + { 0x00000000, 0x3ff00000, 0x00000000, 0x3ff00000}, // bool32 + { 0x00000000, 0x3ff00000, 0x00000000, 0x00000000}, + { 0x00000000, 0x43e00000, 0x00000000, 0x4258e000}, // long + { 0x00000000, 0x40700000, 0xffc00000, 0x41dfffff}, + { 0x00000000, 0x3ff00000, 0x00000000, 0x3ff00000}, // bool64 + { 0x00000000, 0x3ff00000, 0x00000000, 0x00000000}, +}; + +static dstatement_t double_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0003, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0013, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0023, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0033, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0043, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0053, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0063, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0073, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t double_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0103, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0113, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0123, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0133, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0143, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0153, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0163, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0173, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t double_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0203, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0003, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0213, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0013, 62 }, + { OP(2, 1, 2, OP_CONV), 8, 0223, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0023, 70 }, + { OP(2, 1, 2, OP_CONV), 16, 0233, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0033, 78 }, + { OP(1, 1, 2, OP_CONV), 24, 0243, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0043, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0253, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0053, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0263, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0063, 102 }, + { OP(2, 1, 2, OP_CONV), 40, 0273, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0073, 110 }, +}; + +static dstatement_t double_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0003, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0203, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0013, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0213, 58 }, + { OP(2, 1, 2, OP_CONV), 8, 0023, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0223, 66 }, + { OP(2, 1, 2, OP_CONV), 16, 0033, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0233, 74 }, + { OP(1, 1, 2, OP_CONV), 24, 0043, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0243, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0053, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0253, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0063, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0263, 98 }, + { OP(2, 1, 2, OP_CONV), 40, 0073, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0273, 106 }, +}; + +static dstatement_t double_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0303, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0313, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0323, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0333, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0343, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0353, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0363, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0373, 104 }, +}; + +test_t tests[] = { + { + .desc = "double conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_1_statements), + .statements = double_conv_1_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_2_statements), + .statements = double_conv_2_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_3a_statements), + .statements = double_conv_3a_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_3b_statements), + .statements = double_conv_3b_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_4_statements), + .statements = double_conv_4_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c new file mode 100644 index 000000000..246b4bec3 --- /dev/null +++ b/libs/gamecode/test/test-conv4.c @@ -0,0 +1,190 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t uint_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t uint_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 5, -5, 0x80000000, 0x7fffffff}, // int + { 1, 0xffffffff, 0, 0}, // float undef? + { 99, 0x80000000, 256, 0x7fffffff}, // long + { 0, 0, 1, 0xffffffff}, // double undef? + { 5, -5, 0x80000000, 0x7fffffff}, // uint + { 1, 1, 1, 0}, // bool32 + { 99, 0x80000000, 256, 0x7fffffff}, // ulong + { 1, 1, 1, 0}, // bool64 +}; + +static dstatement_t uint_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0004, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0014, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0024, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0034, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0044, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0054, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0064, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0074, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t uint_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0104, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0114, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0124, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0134, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0144, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0154, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0164, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0174, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t uint_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0204, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0004, 51 }, + { OP(1, 1, 1, OP_CONV), 4, 0214, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0014, 55 }, + { OP(2, 1, 1, OP_CONV), 8, 0224, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0024, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0234, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0034, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0244, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0044, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0254, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0054, 71 }, + { OP(2, 1, 1, OP_CONV), 32, 0264, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0064, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0274, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0074, 79 }, +}; + +static dstatement_t uint_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0004, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0204, 49 }, + { OP(1, 1, 1, OP_CONV), 4, 0014, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0214, 53 }, + { OP(2, 1, 1, OP_CONV), 8, 0024, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0224, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0034, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0234, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0044, 64 }, + { OP(1, 1, 1, OP_CONV), 25, 0244, 65 }, + { OP(1, 1, 1, OP_CONV), 28, 0054, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0254, 69 }, + { OP(2, 1, 1, OP_CONV), 32, 0064, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0264, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0074, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0274, 77 }, +}; + +static dstatement_t uint_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0304, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0314, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0324, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0334, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0344, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0354, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0364, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0374, 76 }, +}; + +test_t tests[] = { + { + .desc = "uint conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_1_statements), + .statements = uint_conv_1_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_2_statements), + .statements = uint_conv_2_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_3a_statements), + .statements = uint_conv_3a_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_3b_statements), + .statements = uint_conv_3b_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_4_statements), + .statements = uint_conv_4_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv5.c b/libs/gamecode/test/test-conv5.c new file mode 100644 index 000000000..fe75e0ff2 --- /dev/null +++ b/libs/gamecode/test/test-conv5.c @@ -0,0 +1,190 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t bool32_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t bool32_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { -1, -1, -1, -1}, // int + { -1, -1, -1, -1}, // float + { -1, -1, -1, -1}, // long + { -1, -1, -1, -1}, // double + { -1, -1, -1, -1}, // uint + { ~0, 1, 0x80000000, 0}, // bool32 + { -1, -1, -1, -1}, // ulong + { -1, -1, -1, 0}, // bool64 +}; + +static dstatement_t bool32_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0005, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0015, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0025, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0035, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0045, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0055, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0065, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0075, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t bool32_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0105, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0115, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0125, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0135, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0145, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0155, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0165, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0175, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t bool32_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0205, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0005, 51 }, + { OP(1, 1, 1, OP_CONV), 4, 0215, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0015, 55 }, + { OP(2, 1, 1, OP_CONV), 8, 0225, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0025, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0235, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0035, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0245, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0045, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0255, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0055, 71 }, + { OP(2, 1, 1, OP_CONV), 32, 0265, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0065, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0275, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0075, 79 }, +}; + +static dstatement_t bool32_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0005, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0205, 49 }, + { OP(1, 1, 1, OP_CONV), 4, 0015, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0215, 53 }, + { OP(2, 1, 1, OP_CONV), 8, 0025, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0225, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0035, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0235, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0045, 64 }, + { OP(1, 1, 1, OP_CONV), 25, 0245, 65 }, + { OP(1, 1, 1, OP_CONV), 28, 0055, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0255, 69 }, + { OP(2, 1, 1, OP_CONV), 32, 0065, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0265, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0075, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0275, 77 }, +}; + +static dstatement_t bool32_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0305, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0315, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0325, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0335, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0345, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0355, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0365, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0375, 76 }, +}; + +test_t tests[] = { + { + .desc = "bool32 conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_1_statements), + .statements = bool32_conv_1_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_2_statements), + .statements = bool32_conv_2_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_3a_statements), + .statements = bool32_conv_3a_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_3b_statements), + .statements = bool32_conv_3b_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_4_statements), + .statements = bool32_conv_4_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c new file mode 100644 index 000000000..b32cfc537 --- /dev/null +++ b/libs/gamecode/test/test-conv6.c @@ -0,0 +1,206 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t ulong_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t ulong_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 5, 0, -5, 0xffffffff}, // int + { 0x80000000, 0xffffffff, 0x7fffffff, 0}, + { 1, 0, -1, -1}, // float + { 0, 0, 0, 0x80000000}, // undef? + { 99, 0x80000000, 0x80000000, 99}, // long + { 256, 0, 0x7fffffff, 0}, + { 0, 0, 0, 0x80000000}, // double undef? + { 1, 0, -1, -1}, + { 5, 0, -5, 0}, // uint + { 0x80000000, 0, 0x7fffffff, 0}, + { 1, 0, 1, 0}, // bool32 + { 1, 0, 0, 0}, + { 99, 0x80000000, 0x80000000, 99}, // ulong + { 256, 0, 0x7fffffff, 0}, + { 1, 0, 1, 0}, // bool64 + { 1, 0, 0, 0}, +}; + +static dstatement_t ulong_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0006, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0016, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0026, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0036, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0046, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0056, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0066, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0076, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t ulong_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0106, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0116, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0126, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0136, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0146, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0156, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0166, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0176, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t ulong_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0206, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0006, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0216, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0016, 62 }, + { OP(2, 1, 2, OP_CONV), 8, 0226, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0026, 70 }, + { OP(2, 1, 2, OP_CONV), 16, 0236, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0036, 78 }, + { OP(1, 1, 2, OP_CONV), 24, 0246, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0046, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0256, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0056, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0266, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0066, 102 }, + { OP(2, 1, 2, OP_CONV), 40, 0276, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0076, 110 }, +}; + +static dstatement_t ulong_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0006, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0206, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0016, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0216, 58 }, + { OP(2, 1, 2, OP_CONV), 8, 0026, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0226, 66 }, + { OP(2, 1, 2, OP_CONV), 16, 0036, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0236, 74 }, + { OP(1, 1, 2, OP_CONV), 24, 0046, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0246, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0056, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0256, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0066, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0266, 98 }, + { OP(2, 1, 2, OP_CONV), 40, 0076, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0276, 106 }, +}; + +static dstatement_t ulong_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0306, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0316, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0326, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0336, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0346, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0356, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0366, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0376, 104 }, +}; + +test_t tests[] = { + { + .desc = "ulong conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_1_statements), + .statements = ulong_conv_1_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_2_statements), + .statements = ulong_conv_2_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_3a_statements), + .statements = ulong_conv_3a_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_3b_statements), + .statements = ulong_conv_3b_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_4_statements), + .statements = ulong_conv_4_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv7.c b/libs/gamecode/test/test-conv7.c new file mode 100644 index 000000000..cbc2306e0 --- /dev/null +++ b/libs/gamecode/test/test-conv7.c @@ -0,0 +1,206 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t bool64_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t bool64_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // int + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // float + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // long + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // double + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // uint + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // bool32 + { 0xffffffff, 0xffffffff, 0, 0}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // ulong + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { ~0, ~0, ~0, 0}, // bool64 + { 0, ~0, 0, 0}, +}; + +static dstatement_t bool64_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0007, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0017, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0027, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0037, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0047, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0057, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0067, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0077, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t bool64_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0107, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0117, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0127, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0137, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0147, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0157, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0167, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0177, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, +}; + +static dstatement_t bool64_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0207, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0007, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0217, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0017, 62 }, + { OP(2, 1, 2, OP_CONV), 8, 0227, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0027, 70 }, + { OP(2, 1, 2, OP_CONV), 16, 0237, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0037, 78 }, + { OP(1, 1, 2, OP_CONV), 24, 0247, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0047, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0257, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0057, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0267, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0067, 102 }, + { OP(2, 1, 2, OP_CONV), 40, 0277, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0077, 110 }, +}; + +static dstatement_t bool64_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0007, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0207, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0017, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0217, 58 }, + { OP(2, 1, 2, OP_CONV), 8, 0027, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0227, 66 }, + { OP(2, 1, 2, OP_CONV), 16, 0037, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0237, 74 }, + { OP(1, 1, 2, OP_CONV), 24, 0047, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0247, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0057, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0257, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0067, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0267, 98 }, + { OP(2, 1, 2, OP_CONV), 40, 0077, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0277, 106 }, +}; + +static dstatement_t bool64_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0307, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0317, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0327, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0337, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0347, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0357, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0367, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0377, 104 }, +}; + +test_t tests[] = { + { + .desc = "bool64 conv 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_1_statements), + .statements = bool64_conv_1_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_2_statements), + .statements = bool64_conv_2_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_3a_statements), + .statements = bool64_conv_3a_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_3b_statements), + .statements = bool64_conv_3b_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_4_statements), + .statements = bool64_conv_4_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-double.c b/libs/gamecode/test/test-double.c new file mode 100644 index 000000000..33bd4ff7a --- /dev/null +++ b/libs/gamecode/test/test-double.c @@ -0,0 +1,333 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((x)*(x)) + +static pr_dvec4_t double_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_dvec4_t double_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 5.0/3, -5.0/3, -5.0/3, 5.0/3}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t double_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_D_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_D_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_D_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_D_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_D_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_D_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_D_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_D_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_DIV_D_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_D_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_REM_D_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_D_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_MOD_D_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_D_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_ADD_D_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_D_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_SUB_D_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_D_1), 6, 14, 62 }, +}; + +static dstatement_t double_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_D_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_DIV_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_D_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_REM_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_D_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_MOD_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_D_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_ADD_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_D_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_SUB_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_D_3), 2, 10, 58 }, +}; + +static dstatement_t double_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_D_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_D_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_D_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_D_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_D_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_D_4), 0, 8, 56 }, +}; + +static pr_dvec4_t double_cossin_init[] = { + { 1, 2, 3, 4 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 1, 2, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { 0, 0, 0, 0 }, // 16: x2 -> [xx, xx] + // { } // 20: xn +}; + +static pr_dvec4_t double_cossin_expect[] = { + { 0.8660254037844386, 0.49999999999999994, 0, 0 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 25, 26, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { -sq(M_PI/6), -sq(M_PI/6), 0, 0 }, // 16: x2 -> [xx, xx] +}; + +static dstatement_t double_cossin_statements[] = { + { OP(0, 0, 0, OP_STORE_A_2), 42, 0, 8 }, // init xn -> [?, x] + { OP(0, 0, 0, OP_STORE_A_2), 40, 0, 16 }, // init xn -> [1, x] + { OP(0, 0, 0, OP_SWIZZLE_D), 8,0xc000, 32 }, // init x2 -> [x, x, 0, 0] + { OP(0, 0, 0, OP_MUL_D_2), 32, 32, 32 }, // x2 -> [x*x, x*x, 0, 0] + { OP(0, 0, 0, OP_SWIZZLE_D), 32,0xc3e4, 32 }, // init x2 -> -x2 + { OP(0, 0, 0, OP_SUB_D_4), 0, 0, 0 }, // init acc (output) to 0 +// loop: + { OP(0, 0, 0, OP_ADD_D_2), 0, 40, 0 }, // acc += xn + { OP(0, 0, 0, OP_MUL_D_2), 40, 32, 40 }, // xn *= x2 + { OP(0, 0, 0, OP_DIV_D_2), 40, 16, 40 }, // xn /= f + { OP(0, 0, 0, OP_ADD_D_2), 16, 24, 16 }, // f += inc + { OP(0, 0, 0, OP_DIV_D_2), 40, 16, 40 }, // xn /= f + { OP(0, 0, 0, OP_ADD_D_2), 16, 24, 16 }, // f += inc + { OP(0, 0, 0, OP_LT_D_1), 16, 30, 46 }, // f0 < fmax + { OP(0, 0, 0, OP_IFNZ), -7, 0, 46 }, // f0 < fmax +}; + +static pr_dvec4_t double_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +// 5.0 as 64-bit int +#define F 0x4014000000000000l +#define mF 0xc014000000000000l +static pr_lvec4_t double_cmpop_expect[] = { + { F, mF, F, mF}, + { F, F, mF, mF}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t double_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_D_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_D_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_D_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_D_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_D_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_D_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_D_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_D_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_LT_D_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_D_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_GT_D_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_D_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_NE_D_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_D_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_GE_D_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_D_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_LE_D_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_D_1), 6, 14, 62 }, +}; + +static dstatement_t double_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_D_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_LT_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_D_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_GT_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_D_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_NE_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_D_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_GE_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_D_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_LE_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_D_3), 2, 10, 58 }, +}; + +static dstatement_t double_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_D_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_D_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_D_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_D_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_D_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_D_4), 0, 8, 56 }, +}; + +test_t tests[] = { + { + .desc = "double binop 1", + .extra_globals = 8 * 1, + .num_globals = num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_1_statements), + .statements = double_binop_1_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 2", + .extra_globals = 8 * 1, + .num_globals = num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_2_statements), + .statements = double_binop_2_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 3a", + .extra_globals = 8 * 1, + .num_globals = num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_3a_statements), + .statements = double_binop_3a_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 3b", + .extra_globals = 8 * 1, + .num_globals = num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_3b_statements), + .statements = double_binop_3b_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 4", + .extra_globals = 8 * 1, + .num_globals = num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_4_statements), + .statements = double_binop_4_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double cos sin", + .extra_globals = 8 * 1, + .num_globals = num_globals(double_cossin_init,double_cossin_expect), + .num_statements = num_statements (double_cossin_statements), + .statements = double_cossin_statements, + .init_globals = (pr_int_t *) double_cossin_init, + .expect_globals = (pr_int_t *) double_cossin_expect, + }, + { + .desc = "double cmpop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_1_statements), + .statements = double_cmpop_1_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_2_statements), + .statements = double_cmpop_2_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_3a_statements), + .statements = double_cmpop_3a_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_3b_statements), + .statements = double_cmpop_3b_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_4_statements), + .statements = double_cmpop_4_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-float.c b/libs/gamecode/test/test-float.c new file mode 100644 index 000000000..576518128 --- /dev/null +++ b/libs/gamecode/test/test-float.c @@ -0,0 +1,333 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((float)(x)*(float)(x)) + +static pr_vec4_t float_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_vec4_t float_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 1.666666627, -1.666666627, -1.666666627, 1.666666627}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t float_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_F_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_F_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_F_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_F_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_F_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_F_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_F_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_F_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_DIV_F_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_F_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_REM_F_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_F_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_MOD_F_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_F_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_ADD_F_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_F_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_SUB_F_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_F_1), 3, 7, 31 }, +}; + +static dstatement_t float_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_F_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_DIV_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_F_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_REM_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_F_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_MOD_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_F_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_ADD_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_F_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_SUB_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_F_3), 1, 5, 29 }, +}; + +static dstatement_t float_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_F_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_F_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_F_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_F_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_F_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_F_4), 0, 4, 28 }, +}; + +static pr_vec4_t float_cossin_init[] = { + { 1, 2, 3, 4 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 1, 2, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { 0, 0, 0, 0 }, // 16: x2 -> [xx, xx] + // { } // 20: xn +}; + +static pr_vec4_t float_cossin_expect[] = { + { 0.866025388, 0.5, 0, 0 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 25, 26, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { -sq(M_PI/6), -sq(M_PI/6), 0, 0 }, // 16: x2 -> [xx, xx] +}; + +static dstatement_t float_cossin_statements[] = { + { OP(0, 0, 0, OP_STORE_A_1), 21, 0, 4 }, // init xn -> [?, x] + { OP(0, 0, 0, OP_STORE_A_1), 20, 0, 8 }, // init xn -> [1, x] + { OP(0, 0, 0, OP_SWIZZLE_F), 4, 0xc000, 16 },// init x2 -> [x, x, 0, 0] + { OP(0, 0, 0, OP_MUL_F_2), 16, 16, 16 }, // x2 -> [x*x, x*x, 0, 0] + { OP(0, 0, 0, OP_SWIZZLE_F), 16, 0xc3e4, 16 },// init x2 -> -x2 + { OP(0, 0, 0, OP_SUB_F_4), 0, 0, 0 }, // init acc (output) to 0 +// loop: + { OP(0, 0, 0, OP_ADD_F_2), 0, 20, 0 }, // acc += xn + { OP(0, 0, 0, OP_MUL_F_2), 20, 16, 20 }, // xn *= x2 + { OP(0, 0, 0, OP_DIV_F_2), 20, 8, 20 }, // xn /= f + { OP(0, 0, 0, OP_ADD_F_2), 8, 12, 8 }, // f += inc + { OP(0, 0, 0, OP_DIV_F_2), 20, 8, 20 }, // xn /= f + { OP(0, 0, 0, OP_ADD_F_2), 8, 12, 8 }, // f += inc + { OP(0, 0, 0, OP_LT_F_1), 8, 15, 23 }, // f0 < fmax + { OP(0, 0, 0, OP_IFNZ), -7, 0, 23 }, // f0 < fmax +}; + +static pr_vec4_t float_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +// 5.0 as 32-bit int +#define F 0x40a00000 +#define mF 0xc0a00000 +static pr_ivec4_t float_cmpop_expect[] = { + { F, mF, F, mF}, + { F, F, mF, mF}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t float_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_F_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_F_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_F_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_F_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_F_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_F_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_F_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_F_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_LT_F_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_F_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_GT_F_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_F_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_NE_F_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_F_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_GE_F_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_F_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_LE_F_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_F_1), 3, 7, 31 }, +}; + +static dstatement_t float_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_F_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_LT_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_F_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_GT_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_F_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_NE_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_F_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_GE_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_F_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_LE_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_F_3), 1, 5, 29 }, +}; + +static dstatement_t float_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_F_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_F_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_F_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_F_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_F_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_F_4), 0, 4, 28 }, +}; + +test_t tests[] = { + { + .desc = "float binop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_1_statements), + .statements = float_binop_1_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_2_statements), + .statements = float_binop_2_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_3a_statements), + .statements = float_binop_3a_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_3b_statements), + .statements = float_binop_3b_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_4_statements), + .statements = float_binop_4_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float cos sin", + .extra_globals = 4 * 1, + .num_globals = num_globals (float_cossin_init, float_cossin_expect), + .num_statements = num_statements (float_cossin_statements), + .statements = float_cossin_statements, + .init_globals = (pr_int_t *) float_cossin_init, + .expect_globals = (pr_int_t *) float_cossin_expect, + }, + { + .desc = "float cmpop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_1_statements), + .statements = float_cmpop_1_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_2_statements), + .statements = float_cmpop_2_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_3a_statements), + .statements = float_cmpop_3a_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_3b_statements), + .statements = float_cmpop_3b_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_4_statements), + .statements = float_cmpop_4_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-hops.c b/libs/gamecode/test/test-hops.c new file mode 100644 index 000000000..34d14fe2d --- /dev/null +++ b/libs/gamecode/test/test-hops.c @@ -0,0 +1,166 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_uivec4_t uint_hop_init[7] = { + { 0x0000ff00, 0x0000f0f0, 0x0000cccc, 0x0000aaaa }, +}; + +static pr_uivec4_t uint_hop_expect[] = { + { 0x0000ff00, 0x0000f0f0, 0x0000cccc, 0x0000aaaa }, + { 0x00008888, 0x0000eeee, 0x00006666, 0x00017776 }, + { 0xffff7777, 0xffff1111, 0xffff9999, 0 }, + { 0x00008080, 0x0000fefe, 0x00009696, 0x00026866 }, + { 0xffff7f7f, 0xffff0101, 0xffff6969, 0 }, + { 0x00008000, 0x0000fffe, 0x00006996, 0x00036766 }, + { 0xffff7fff, 0xffff0001, 0xffff9669, 0 }, +}; + +static dstatement_t uint_hop_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 4, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 12, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 20, 3 }, + + { OP(0, 0, 1, OP_HOPS), 2, 010, 0 }, + { OP(0, 0, 1, OP_HOPS), 2, 011, 1 }, + { OP(0, 0, 1, OP_HOPS), 2, 012, 2 }, + { OP(0, 0, 1, OP_HOPS), 2, 013, 3 }, + { OP(0, 0, 1, OP_HOPS), 2, 014, 4 }, + { OP(0, 0, 1, OP_HOPS), 2, 015, 5 }, + { OP(0, 0, 1, OP_HOPS), 2, 016, 6 }, + + { OP(0, 0, 2, OP_HOPS), 1, 020, 0 }, + { OP(0, 0, 2, OP_HOPS), 1, 021, 1 }, + { OP(0, 0, 2, OP_HOPS), 1, 022, 2 }, + { OP(0, 0, 2, OP_HOPS), 1, 023, 3 }, + { OP(0, 0, 2, OP_HOPS), 1, 024, 4 }, + { OP(0, 0, 2, OP_HOPS), 1, 025, 5 }, + { OP(0, 0, 2, OP_HOPS), 1, 026, 6 }, + + { OP(0, 0, 3, OP_HOPS), 0, 030, 0 }, + { OP(0, 0, 3, OP_HOPS), 0, 031, 1 }, + { OP(0, 0, 3, OP_HOPS), 0, 032, 2 }, + { OP(0, 0, 3, OP_HOPS), 0, 033, 3 }, + { OP(0, 0, 3, OP_HOPS), 0, 034, 4 }, + { OP(0, 0, 3, OP_HOPS), 0, 035, 5 }, + { OP(0, 0, 3, OP_HOPS), 0, 036, 6 }, +}; + +static pr_ulvec4_t ulong_hop_init[7] = { + { UINT64_C(0x00ff00000000), UINT64_C(0x0f0f00000000), + UINT64_C(0x333300000000), UINT64_C(0x555500000000) }, +}; + +static pr_ulvec4_t ulong_hop_expect[] = { + { UINT64_C(0x000000ff00000000), UINT64_C(0x00000f0f00000000), + UINT64_C(0x0000333300000000), UINT64_C(0x0000555500000000) }, + { UINT64_C(0x0000111100000000), UINT64_C(0x0000777700000000), + UINT64_C(0x0000666600000000), UINT64_C(0x0000888800000000) }, + { UINT64_C(0xffffeeeeffffffff), UINT64_C(0xffff8888ffffffff), + UINT64_C(0xffff9999ffffffff), 0 }, + { UINT64_C(0x0000010100000000), UINT64_C(0x00007f7f00000000), + UINT64_C(0x0000696900000000), UINT64_C(0x0000979700000000) }, + { UINT64_C(0xfffffefeffffffff), UINT64_C(0xffff8080ffffffff), + UINT64_C(0xffff9696ffffffff), 0 }, + { UINT64_C(0x0000000100000000), UINT64_C(0x00007fff00000000), + UINT64_C(0x0000699600000000), UINT64_C(0x0000989600000000) }, + { UINT64_C(0xfffffffeffffffff), UINT64_C(0xffff8000ffffffff), + UINT64_C(0xffff9669ffffffff), 0 }, +}; + +static dstatement_t ulong_hop_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 8, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 24, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 40, 3 }, + + { OP(0, 0, 1, OP_HOPS), 4, 050, 0 }, + { OP(0, 0, 1, OP_HOPS), 4, 051, 2 }, + { OP(0, 0, 1, OP_HOPS), 4, 052, 4 }, + { OP(0, 0, 1, OP_HOPS), 4, 053, 6 }, + { OP(0, 0, 1, OP_HOPS), 4, 054, 8 }, + { OP(0, 0, 1, OP_HOPS), 4, 055, 10 }, + { OP(0, 0, 1, OP_HOPS), 4, 056, 12 }, + + { OP(0, 0, 2, OP_HOPS), 2, 060, 0 }, + { OP(0, 0, 2, OP_HOPS), 2, 061, 2 }, + { OP(0, 0, 2, OP_HOPS), 2, 062, 4 }, + { OP(0, 0, 2, OP_HOPS), 2, 063, 6 }, + { OP(0, 0, 2, OP_HOPS), 2, 064, 8 }, + { OP(0, 0, 2, OP_HOPS), 2, 065, 10 }, + { OP(0, 0, 2, OP_HOPS), 2, 066, 12 }, + + { OP(0, 0, 3, OP_HOPS), 0, 070, 0 }, + { OP(0, 0, 3, OP_HOPS), 0, 071, 2 }, + { OP(0, 0, 3, OP_HOPS), 0, 072, 4 }, + { OP(0, 0, 3, OP_HOPS), 0, 073, 6 }, + { OP(0, 0, 3, OP_HOPS), 0, 074, 8 }, + { OP(0, 0, 3, OP_HOPS), 0, 075, 10 }, + { OP(0, 0, 3, OP_HOPS), 0, 076, 12 }, +}; + +static pr_vec4_t float_hop_init[2] = { + { 1, 2, 3, 4 }, +}; + +static pr_vec4_t float_hop_expect[] = { + { 1, 2, 3, 4 }, + { 3, 6, 10, 0 }, +}; + +static dstatement_t float_hop_statements[] = { + { OP(0, 0, 0, OP_HOPS), 0, 017, 4 }, + { OP(0, 0, 0, OP_HOPS), 0, 027, 5 }, + { OP(0, 0, 0, OP_HOPS), 0, 037, 6 }, +}; + +static pr_dvec4_t double_hop_init[2] = { + { 1, 2, 3, 4 }, +}; + +static pr_dvec4_t double_hop_expect[] = { + { 1, 2, 3, 4 }, + { 3, 6, 10, 0 }, +}; + +static dstatement_t double_hop_statements[] = { + { OP(0, 0, 0, OP_HOPS), 0, 057, 8 }, + { OP(0, 0, 0, OP_HOPS), 0, 067, 10 }, + { OP(0, 0, 0, OP_HOPS), 0, 077, 12 }, +}; + +test_t tests[] = { + { + .desc = "uint hops", + .num_globals = num_globals(uint_hop_init,uint_hop_expect), + .num_statements = num_statements (uint_hop_statements), + .statements = uint_hop_statements, + .init_globals = (pr_int_t *) uint_hop_init, + .expect_globals = (pr_int_t *) uint_hop_expect, + }, + { + .desc = "ulong hops", + .num_globals = num_globals(ulong_hop_init,ulong_hop_expect), + .num_statements = num_statements (ulong_hop_statements), + .statements = ulong_hop_statements, + .init_globals = (pr_int_t *) ulong_hop_init, + .expect_globals = (pr_int_t *) ulong_hop_expect, + }, + { + .desc = "float hops", + .num_globals = num_globals(float_hop_init,float_hop_expect), + .num_statements = num_statements (float_hop_statements), + .statements = float_hop_statements, + .init_globals = (pr_int_t *) float_hop_init, + .expect_globals = (pr_int_t *) float_hop_expect, + }, + { + .desc = "double hops", + .num_globals = num_globals(double_hop_init,double_hop_expect), + .num_statements = num_statements (double_hop_statements), + .statements = double_hop_statements, + .init_globals = (pr_int_t *) double_hop_init, + .expect_globals = (pr_int_t *) double_hop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-int.c b/libs/gamecode/test/test-int.c new file mode 100644 index 000000000..6ca0dc928 --- /dev/null +++ b/libs/gamecode/test/test-int.c @@ -0,0 +1,284 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t int_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 1, -1, -1, 1}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t int_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_I_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_I_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_I_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_I_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_I_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_I_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_I_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_I_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_DIV_I_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_I_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_REM_I_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_I_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_MOD_I_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_I_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_ADD_I_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_I_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_SUB_I_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_I_1), 3, 7, 31 }, +}; + +static dstatement_t int_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_I_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_DIV_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_I_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_REM_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_I_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_MOD_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_I_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_ADD_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_I_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_SUB_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_I_3), 1, 5, 29 }, +}; + +static dstatement_t int_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_I_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_I_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_I_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_I_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_I_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_I_4), 0, 4, 28 }, +}; + +static pr_ivec4_t int_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t int_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_I_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_I_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_I_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_I_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_I_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_I_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_I_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_I_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_LT_I_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_I_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_GT_I_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_I_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_NE_I_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_I_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_GE_I_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_I_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_LE_I_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_I_1), 3, 7, 31 }, +}; + +static dstatement_t int_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_I_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_LT_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_I_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_GT_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_I_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_NE_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_I_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_GE_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_I_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_LE_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_I_3), 1, 5, 29 }, +}; + +static dstatement_t int_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_I_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_I_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_I_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_I_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_I_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_I_4), 0, 4, 28 }, +}; + +test_t tests[] = { + { + .desc = "int binop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_1_statements), + .statements = int_binop_1_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_2_statements), + .statements = int_binop_2_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_3a_statements), + .statements = int_binop_3a_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_3b_statements), + .statements = int_binop_3b_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_4_statements), + .statements = int_binop_4_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int cmpop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_1_statements), + .statements = int_cmpop_1_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_2_statements), + .statements = int_cmpop_2_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_3a_statements), + .statements = int_cmpop_3a_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_3b_statements), + .statements = int_cmpop_3b_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_4_statements), + .statements = int_cmpop_4_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-jump.c b/libs/gamecode/test/test-jump.c new file mode 100644 index 000000000..d05d6b92b --- /dev/null +++ b/libs/gamecode/test/test-jump.c @@ -0,0 +1,77 @@ +#include "head.c" + +#define DB 0xdeadbeef + +static pr_int_t test_globals_init[] = { + DB, 1, 2, 3, DB, +}; + +static pr_int_t test_globals_expect[] = { + DB, 1, 2, 3, 1, +}; + +static dstatement_t jump_A_statements[] = { + { OP(0, 0, 0, OP_JUMP_A), 4, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, + { OP(0, 0, 0, OP_JUMP_A), 2, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -2, 0, 0 }, +}; + +static dstatement_t jump_B_statements[] = { + { OP(0, 0, 0, OP_JUMP_B), 1, 2, 0 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, +}; + +static dstatement_t jump_C_statements[] = { + { OP(0, 0, 0, OP_JUMP_C), 1, 2, 0 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, +}; + +static dstatement_t jump_D_statements[] = { + { OP(0, 0, 0, OP_JUMP_D), 1, 2, 0 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, +}; + +test_t tests[] = { + { + .desc = "jump A", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_A_statements), + .statements = jump_A_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "jump B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_B_statements), + .statements = jump_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "jump C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_C_statements), + .statements = jump_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "jump D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_D_statements), + .statements = jump_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-lea.c b/libs/gamecode/test/test-lea.c new file mode 100644 index 000000000..33e148c16 --- /dev/null +++ b/libs/gamecode/test/test-lea.c @@ -0,0 +1,40 @@ +#include "head.c" + +static pr_int_t lea_globals_init[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + + 0, 0, 0, 0, +}; + +static pr_int_t lea_globals_expect[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + + 7, 34, 26, 88, +}; + +static dstatement_t lea_statements[] = { + {OP(0, 0, 0, OP_LEA_A), 7, 9, 12}, + {OP(0, 0, 0, OP_LEA_C), 2, 6, 13}, + {OP(0, 0, 0, OP_LEA_D), 2, 6, 14}, + {OP(0, 0, 0, OP_LEA_B), 4, 2, 15}, +}; + +test_t tests[] = { + { + .desc = "lea", + .num_globals = num_globals (lea_globals_init, lea_globals_expect), + .num_statements = num_statements (lea_statements), + .statements = lea_statements, + .init_globals = lea_globals_init, + .expect_globals = lea_globals_expect, + .edict_area = 28, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-load.c b/libs/gamecode/test/test-load.c new file mode 100644 index 000000000..986a58163 --- /dev/null +++ b/libs/gamecode/test/test-load.c @@ -0,0 +1,87 @@ +#include "head.c" + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static dstatement_t load_B_statements[] = { + {OP(0, 0, 0, OP_LOAD_B_4), 7, 9, 12}, + {OP(0, 0, 0, OP_LOAD_B_3), 7, 8, 16}, + {OP(0, 0, 0, OP_LOAD_B_1), 7, 7, 19}, + {OP(0, 0, 0, OP_LOAD_B_2), 7, 6, 20}, + {OP(0, 0, 0, OP_LOAD_B_2), 7, 5, 22}, +}; + +static dstatement_t load_C_statements[] = { + {OP(0, 0, 0, OP_LOAD_C_4), 2, 4, 12}, + {OP(0, 0, 0, OP_LOAD_C_3), 2, 1, 16}, + {OP(0, 0, 0, OP_LOAD_C_1), 2, 0, 19}, + {OP(0, 0, 0, OP_LOAD_C_2), 2, -2, 20}, + {OP(0, 0, 0, OP_LOAD_C_2), 2, -4, 22}, +}; + +static dstatement_t load_D_statements[] = { + {OP(0, 0, 0, OP_LOAD_D_4), 2, 9, 12}, + {OP(0, 0, 0, OP_LOAD_D_3), 2, 8, 16}, + {OP(0, 0, 0, OP_LOAD_D_1), 2, 7, 19}, + {OP(0, 0, 0, OP_LOAD_D_2), 2, 6, 20}, + {OP(0, 0, 0, OP_LOAD_D_2), 2, 5, 22}, +}; + +test_t tests[] = { + { + .desc = "load B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load_B_statements), + .statements = load_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, + }, + { + .desc = "load C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load_C_statements), + .statements = load_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "load D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load_D_statements), + .statements = load_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-load64.c b/libs/gamecode/test/test-load64.c new file mode 100644 index 000000000..abb6052eb --- /dev/null +++ b/libs/gamecode/test/test-load64.c @@ -0,0 +1,89 @@ +#include "head.c" + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // destination data + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + // source data + 21, 22, 23, 24, 17, 18, 19, 20, + 15, 16, 9, 10, 11, 12, 13, 14, + 1, 2, 3, 4, 5, 6, 7, 8, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // destination data +/*16*/ 1, 2, 3, 4, 5, 6, 7, 8, +/*24*/ 9, 10, 11, 12, 13, 14, 15, 16, +/*32*/ 17, 18, 19, 20, 21, 22, 23, 24, + // source data +/*40*/ 21, 22, 23, 24, 17, 18, 19, 20, +/*48*/ 15, 16, 9, 10, 11, 12, 13, 14, +/*56*/ 1, 2, 3, 4, 5, 6, 7, 8, +}; + +static dstatement_t load64_B_statements[] = { + {OP(0, 0, 0, OP_LOAD64_B_4), 7, 9, 16}, + {OP(0, 0, 0, OP_LOAD64_B_3), 7, 8, 24}, + {OP(0, 0, 0, OP_LOAD_B_2), 7, 7, 30}, + {OP(0, 0, 0, OP_LOAD_B_4), 7, 6, 32}, + {OP(0, 0, 0, OP_LOAD_B_4), 7, 5, 36}, +}; + +static dstatement_t load64_C_statements[] = { + {OP(0, 0, 0, OP_LOAD64_C_4), 2, 8, 16}, + {OP(0, 0, 0, OP_LOAD64_C_3), 2, 2, 24}, + {OP(0, 0, 0, OP_LOAD_C_2), 2, 0, 30}, + {OP(0, 0, 0, OP_LOAD_C_4), 2, -4, 32}, + {OP(0, 0, 0, OP_LOAD_C_4), 2, -8, 36}, +}; + +static dstatement_t load64_D_statements[] = { + {OP(0, 0, 0, OP_LOAD64_D_4), 2, 9, 16}, + {OP(0, 0, 0, OP_LOAD64_D_3), 2, 8, 24}, + {OP(0, 0, 0, OP_LOAD_D_2), 2, 7, 30}, + {OP(0, 0, 0, OP_LOAD_D_4), 2, 6, 32}, + {OP(0, 0, 0, OP_LOAD_D_4), 2, 5, 36}, +}; + +test_t tests[] = { + { + .desc = "load64 B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load64_B_statements), + .statements = load64_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 48, + }, + { + .desc = "load64 C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load64_C_statements), + .statements = load64_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "load64 D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load64_D_statements), + .statements = load64_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-long.c b/libs/gamecode/test/test-long.c new file mode 100644 index 000000000..b5b021e17 --- /dev/null +++ b/libs/gamecode/test/test-long.c @@ -0,0 +1,286 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((x)*(x)) + +static pr_lvec4_t long_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_lvec4_t long_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 5.0/3, -5.0/3, -5.0/3, 5.0/3}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t long_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_L_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_L_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_L_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_L_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_L_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_L_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_L_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_L_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_DIV_L_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_L_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_REM_L_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_L_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_MOD_L_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_L_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_ADD_L_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_L_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_SUB_L_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_L_1), 6, 14, 62 }, +}; + +static dstatement_t long_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_L_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_DIV_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_L_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_REM_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_L_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_MOD_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_L_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_ADD_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_L_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_SUB_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_L_3), 2, 10, 58 }, +}; + +static dstatement_t long_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_L_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_L_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_L_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_L_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_L_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_L_4), 0, 8, 56 }, +}; + +static pr_lvec4_t long_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_lvec4_t long_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t long_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_L_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_L_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_L_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_L_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_L_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_L_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_L_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_L_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_LT_L_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_L_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_GT_L_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_L_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_NE_L_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_L_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_GE_L_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_L_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_LE_L_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_L_1), 6, 14, 62 }, +}; + +static dstatement_t long_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_L_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_LT_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_L_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_GT_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_L_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_NE_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_L_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_GE_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_L_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_LE_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_L_3), 2, 10, 58 }, +}; + +static dstatement_t long_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_L_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_L_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_L_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_L_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_L_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_L_4), 0, 8, 56 }, +}; + +test_t tests[] = { + { + .desc = "long binop 1", + .extra_globals = 8 * 1, + .num_globals = num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_1_statements), + .statements = long_binop_1_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 2", + .extra_globals = 8 * 1, + .num_globals = num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_2_statements), + .statements = long_binop_2_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 3a", + .extra_globals = 8 * 1, + .num_globals = num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_3a_statements), + .statements = long_binop_3a_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 3b", + .extra_globals = 8 * 1, + .num_globals = num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_3b_statements), + .statements = long_binop_3b_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 4", + .extra_globals = 8 * 1, + .num_globals = num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_4_statements), + .statements = long_binop_4_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long cmpop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_1_statements), + .statements = long_cmpop_1_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_2_statements), + .statements = long_cmpop_2_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_3a_statements), + .statements = long_cmpop_3a_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_3b_statements), + .statements = long_cmpop_3b_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_4_statements), + .statements = long_cmpop_4_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-mem.c b/libs/gamecode/test/test-mem.c new file mode 100644 index 000000000..1bba532e8 --- /dev/null +++ b/libs/gamecode/test/test-mem.c @@ -0,0 +1,51 @@ +#include "head.c" + +#define DB 0xdeadbeef + +static pr_int_t mem_globals_init[] = { + 0, 8, 68, 9, 80, 112, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 0, 0, 68, 6, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 + + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, +}; + +static pr_int_t mem_globals_expect[] = { + 0, 8, 68, 9, 80, 112, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, // 0 + 0, 0, 68, 6, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 + + DB, 0, 0, 0, 0, 0, DB, DB, 9, 9, DB, DB, DB, DB, DB, DB, // 32 + 1, 2, 3, 4, 5, 6, 7, 8, DB, DB, DB, DB, 5, 6, 7, 8, // 48 + DB, DB, DB, DB, 1, 2, 1, 2, 3, 4, 5, 6, DB, DB, DB, DB, // 64 + 68, 68, 68, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, // 80 + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, // 96 + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, DB, // 112 +}; + +static dstatement_t mem_statements[] = { + {OP(0, 0, 0, OP_MEMSET_I), 0, 5, 33}, + {OP(0, 0, 0, OP_MEMSET_I), 3, 2, 40}, + {OP(0, 0, 0, OP_MOVE_I), 8, 8, 48}, + {OP(0, 0, 0, OP_MOVE_I), 12, 4, 60}, + {OP(0, 0, 0, OP_MOVE_PI), 1, 8, 2}, + {OP(0, 0, 0, OP_MEMSET_P), 2, 10, 4}, + {OP(0, 0, 0, OP_MEMSET_PI), 1, 15, 5}, + {OP(0, 0, 0, OP_MOVE_P), 18, 19, 20}, +}; + +test_t tests[] = { + { + .desc = "mem", + .num_globals = num_globals (mem_globals_init, mem_globals_expect), + .num_statements = num_statements (mem_statements), + .statements = mem_statements, + .init_globals = mem_globals_init, + .expect_globals = mem_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-scale.c b/libs/gamecode/test/test-scale.c new file mode 100644 index 000000000..4117fd718 --- /dev/null +++ b/libs/gamecode/test/test-scale.c @@ -0,0 +1,68 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_vec4_t float_scale_init[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 0, 0, -1, -2}, + { 0, 0, 0, -3}, + { 0, 0, 0, 0}, +}; + +static pr_vec4_t float_scale_expect[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 15, 20, -1, -2}, + { 15, 20, 65, -3}, + { 15, 20, 65, 425}, +}; + +static dstatement_t float_scale_statements[] = { + { OP(1, 1, 1, OP_SCALE_F_2), 4, 0, 8 }, + { OP(1, 1, 1, OP_SCALE_F_3), 4, 0, 12 }, + { OP(1, 1, 1, OP_SCALE_F_4), 4, 0, 16 }, +}; + +static pr_dvec4_t double_scale_init[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 0, 0, -1, -2}, + { 0, 0, 0, -3}, + { 0, 0, 0, 0}, +}; + +static pr_dvec4_t double_scale_expect[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 15, 20, -1, -2}, + { 15, 20, 65, -3}, + { 15, 20, 65, 425}, +}; + +static dstatement_t double_scale_statements[] = { + { OP(1, 1, 1, OP_SCALE_D_2), 8, 0, 16 }, + { OP(1, 1, 1, OP_SCALE_D_3), 8, 0, 24 }, + { OP(1, 1, 1, OP_SCALE_D_4), 8, 0, 32 }, +}; + +test_t tests[] = { + { + .desc = "float scale", + .num_globals = num_globals(float_scale_init,float_scale_expect), + .num_statements = num_statements (float_scale_statements), + .statements = float_scale_statements, + .init_globals = (pr_int_t *) float_scale_init, + .expect_globals = (pr_int_t *) float_scale_expect, + }, + { + .desc = "double scale", + .num_globals = num_globals(double_scale_init,double_scale_expect), + .num_statements = num_statements (double_scale_statements), + .statements = double_scale_statements, + .init_globals = (pr_int_t *) double_scale_init, + .expect_globals = (pr_int_t *) double_scale_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-stack.c b/libs/gamecode/test/test-stack.c new file mode 100644 index 000000000..eba5a06d8 --- /dev/null +++ b/libs/gamecode/test/test-stack.c @@ -0,0 +1,233 @@ +#include "head.c" + +static pr_int_t test_globals_init1[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +static pr_int_t test_globals_expect1[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static pr_int_t test_globals_init2[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static pr_int_t test_globals_expect2[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static dstatement_t stack_AA_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_A_2), 24, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 26, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 28, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 29, 0, 0}, + {OP(0, 0, 0, OP_POP_A_4), 32, 0, 0}, +}; + +static dstatement_t stack_AB_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_B_2), 7, 5, 0}, + {OP(0, 0, 0, OP_POP_B_2), 7, 6, 0}, + {OP(0, 0, 0, OP_POP_B_1), 7, 7, 0}, + {OP(0, 0, 0, OP_POP_B_3), 7, 8, 0}, + {OP(0, 0, 0, OP_POP_B_4), 7, 9, 0}, +}; + +static dstatement_t stack_AC_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_C_2), 2, -4, 0}, + {OP(0, 0, 0, OP_POP_C_2), 2, -2, 0}, + {OP(0, 0, 0, OP_POP_C_1), 2, 0, 0}, + {OP(0, 0, 0, OP_POP_C_3), 2, 1, 0}, + {OP(0, 0, 0, OP_POP_C_4), 2, 4, 0}, +}; + +static dstatement_t stack_AD_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_D_2), 2, 5, 0}, + {OP(0, 0, 0, OP_POP_D_2), 2, 6, 0}, + {OP(0, 0, 0, OP_POP_D_1), 2, 7, 0}, + {OP(0, 0, 0, OP_POP_D_3), 2, 8, 0}, + {OP(0, 0, 0, OP_POP_D_4), 2, 9, 0}, +}; + +static dstatement_t stack_BA_statements[] = { + {OP(0, 0, 0, OP_PUSH_B_2), 7, 5, 0}, + {OP(0, 0, 0, OP_PUSH_B_2), 7, 6, 0}, + {OP(0, 0, 0, OP_PUSH_B_1), 7, 7, 0}, + {OP(0, 0, 0, OP_PUSH_B_3), 7, 8, 0}, + {OP(0, 0, 0, OP_PUSH_B_4), 7, 9, 0}, + + {OP(0, 0, 0, OP_POP_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 22, 0, 0}, +}; + +static dstatement_t stack_CA_statements[] = { + {OP(0, 0, 0, OP_PUSH_C_2), 2, -4, 0}, + {OP(0, 0, 0, OP_PUSH_C_2), 2, -2, 0}, + {OP(0, 0, 0, OP_PUSH_C_1), 2, 0, 0}, + {OP(0, 0, 0, OP_PUSH_C_3), 2, 1, 0}, + {OP(0, 0, 0, OP_PUSH_C_4), 2, 4, 0}, + + {OP(0, 0, 0, OP_POP_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 22, 0, 0}, +}; + +static dstatement_t stack_DA_statements[] = { + {OP(0, 0, 0, OP_PUSH_D_2), 2, 5, 0}, + {OP(0, 0, 0, OP_PUSH_D_2), 2, 6, 0}, + {OP(0, 0, 0, OP_PUSH_D_1), 2, 7, 0}, + {OP(0, 0, 0, OP_PUSH_D_3), 2, 8, 0}, + {OP(0, 0, 0, OP_PUSH_D_4), 2, 9, 0}, + + {OP(0, 0, 0, OP_POP_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 22, 0, 0}, +}; + +test_t tests[] = { + { + .desc = "stack push A pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AA_statements), + .statements = stack_AA_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + }, + { + .desc = "stack push A pop B", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AB_statements), + .statements = stack_AB_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, + }, + { + .desc = "stack push A pop C", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AC_statements), + .statements = stack_AC_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + }, + { + .desc = "stack push A pop D", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AD_statements), + .statements = stack_AD_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + }, + { + .desc = "stack push B pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init2, test_globals_expect2), + .num_statements = num_statements (stack_BA_statements), + .statements = stack_BA_statements, + .init_globals = test_globals_init2, + .expect_globals = test_globals_expect2, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, + }, + { + .desc = "stack push C pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init2, test_globals_expect2), + .num_statements = num_statements (stack_CA_statements), + .statements = stack_CA_statements, + .init_globals = test_globals_init2, + .expect_globals = test_globals_expect2, + }, + { + .desc = "stack push D pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init2, test_globals_expect2), + .num_statements = num_statements (stack_DA_statements), + .statements = stack_DA_statements, + .init_globals = test_globals_init2, + .expect_globals = test_globals_expect2, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-state.c b/libs/gamecode/test/test-state.c new file mode 100644 index 000000000..f7a45076d --- /dev/null +++ b/libs/gamecode/test/test-state.c @@ -0,0 +1,99 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define DB 0xdeadbeef + +static float float_time = 1; + +static pr_ivec4_t float_state_init[] = { + { 0, 0, DB, DB }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +#define f1 0x3f800000 +#define f11 0x3f8ccccd +#define f2 0x40000000 +static pr_ivec4_t float_state_expect[] = { + { 0, 8, f1, DB }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 10, 20, f11, 0 }, + { 11, 21, f2, 0 }, +}; + +static dstatement_t float_state_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 1 }, + { OP(0, 0, 0, OP_STATE_ft), 4, 6, 0 }, + { OP(0, 0, 0, OP_LEA_A), 8, 0, 1 }, + { OP(0, 0, 0, OP_STATE_ftt), 5, 7, 2 }, +}; + +static double double_time = 1; + +static pr_ivec4_t double_state_init[] = { + { 0, 0, DB, DB }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +#define d1l 0x00000000 +#define d1h 0x3ff00000 +#define d11l 0x9999999a +#define d11h 0x3ff19999 +#define d2l 0x00000000 +#define d2h 0x40000000 +static pr_ivec4_t double_state_expect[] = { + { 0, 8, d1l, d1h }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 10, 20, d11l, d11h }, + { 11, 21, d2l, d2h }, +}; + +static dstatement_t double_state_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 1 }, + { OP(0, 0, 0, OP_STATE_dt), 4, 6, 0 }, + { OP(0, 0, 0, OP_LEA_A), 8, 0, 1 }, + { OP(0, 0, 0, OP_STATE_dtt), 5, 7, 2 }, +}; + +test_t tests[] = { + { + .desc = "float state", + .num_globals = num_globals(float_state_init,float_state_expect), + .num_statements = num_statements (float_state_statements), + .statements = float_state_statements, + .init_globals = (pr_int_t *) float_state_init, + .expect_globals = (pr_int_t *) float_state_expect, + .self = 1, + .ftime = 2, + .float_time = &float_time, + .edict_area = 8, + .frame = 0, + .think = 1, + .nextthink = 2, + }, + { + .desc = "double state", + .num_globals = num_globals(double_state_init,double_state_expect), + .num_statements = num_statements (double_state_statements), + .statements = double_state_statements, + .init_globals = (pr_int_t *) double_state_init, + .expect_globals = (pr_int_t *) double_state_expect, + .self = 1, + .dtime = 2, + .double_time = &double_time, + .edict_area = 8, + .frame = 0, + .think = 1, + .nextthink = 2, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-store.c b/libs/gamecode/test/test-store.c new file mode 100644 index 000000000..5ed5147b8 --- /dev/null +++ b/libs/gamecode/test/test-store.c @@ -0,0 +1,103 @@ +#include "head.c" + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static dstatement_t store_A_statements[] = { + {OP(0, 0, 0, OP_STORE_A_4), 32, 0, 12}, + {OP(0, 0, 0, OP_STORE_A_3), 29, 0, 16}, + {OP(0, 0, 0, OP_STORE_A_1), 28, 0, 19}, + {OP(0, 0, 0, OP_STORE_A_2), 26, 0, 20}, + {OP(0, 0, 0, OP_STORE_A_2), 24, 0, 22}, +}; + +static dstatement_t store_B_statements[] = { + {OP(0, 0, 0, OP_STORE_B_4), 7, 9, 12}, + {OP(0, 0, 0, OP_STORE_B_3), 7, 8, 16}, + {OP(0, 0, 0, OP_STORE_B_1), 7, 7, 19}, + {OP(0, 0, 0, OP_STORE_B_2), 7, 6, 20}, + {OP(0, 0, 0, OP_STORE_B_2), 7, 5, 22}, +}; + +static dstatement_t store_C_statements[] = { + {OP(0, 0, 0, OP_STORE_C_4), 2, 4, 12}, + {OP(0, 0, 0, OP_STORE_C_3), 2, 1, 16}, + {OP(0, 0, 0, OP_STORE_C_1), 2, 0, 19}, + {OP(0, 0, 0, OP_STORE_C_2), 2, -2, 20}, + {OP(0, 0, 0, OP_STORE_C_2), 2, -4, 22}, +}; + +static dstatement_t store_D_statements[] = { + {OP(0, 0, 0, OP_STORE_D_4), 2, 9, 12}, + {OP(0, 0, 0, OP_STORE_D_3), 2, 8, 16}, + {OP(0, 0, 0, OP_STORE_D_1), 2, 7, 19}, + {OP(0, 0, 0, OP_STORE_D_2), 2, 6, 20}, + {OP(0, 0, 0, OP_STORE_D_2), 2, 5, 22}, +}; + +test_t tests[] = { + { + .desc = "store A", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_A_statements), + .statements = store_A_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_B_statements), + .statements = store_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, + }, + { + .desc = "store C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_C_statements), + .statements = store_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_D_statements), + .statements = store_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-store64.c b/libs/gamecode/test/test-store64.c new file mode 100644 index 000000000..d8dfd2018 --- /dev/null +++ b/libs/gamecode/test/test-store64.c @@ -0,0 +1,105 @@ +#include "head.c" + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // source data +/*16*/ 1, 2, 3, 4, 5, 6, 7, 8, +/*24*/ 9, 10, 11, 12, 13, 14, 15, 16, +/*32*/ 17, 18, 19, 20, 21, 22, 23, 24, + // destination data + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // source data +/*16*/ 1, 2, 3, 4, 5, 6, 7, 8, +/*24*/ 9, 10, 11, 12, 13, 14, 15, 16, +/*32*/ 17, 18, 19, 20, 21, 22, 23, 24, + // destination data +/*40*/ 21, 22, 23, 24, 17, 18, 19, 20, +/*48*/ 15, 16, 9, 10, 11, 12, 13, 14, +/*56*/ 1, 2, 3, 4, 5, 6, 7, 8, +}; + +static dstatement_t store64_A_statements[] = { + {OP(0, 0, 0, OP_STORE64_A_4), 56, 0, 16}, + {OP(0, 0, 0, OP_STORE64_A_3), 50, 0, 24}, + {OP(0, 0, 0, OP_STORE_A_2), 48, 0, 30}, + {OP(0, 0, 0, OP_STORE_A_4), 44, 0, 32}, + {OP(0, 0, 0, OP_STORE_A_4), 40, 0, 36}, +}; + +static dstatement_t store64_B_statements[] = { + {OP(0, 0, 0, OP_STORE64_B_4), 7, 9, 16}, + {OP(0, 0, 0, OP_STORE64_B_3), 7, 8, 24}, + {OP(0, 0, 0, OP_STORE_B_2), 7, 7, 30}, + {OP(0, 0, 0, OP_STORE_B_4), 7, 6, 32}, + {OP(0, 0, 0, OP_STORE_B_4), 7, 5, 36}, +}; + +static dstatement_t store64_C_statements[] = { + {OP(0, 0, 0, OP_STORE64_C_4), 2, 8, 16}, + {OP(0, 0, 0, OP_STORE64_C_3), 2, 2, 24}, + {OP(0, 0, 0, OP_STORE_C_2), 2, 0, 30}, + {OP(0, 0, 0, OP_STORE_C_4), 2, -4, 32}, + {OP(0, 0, 0, OP_STORE_C_4), 2, -8, 36}, +}; + +static dstatement_t store64_D_statements[] = { + {OP(0, 0, 0, OP_STORE64_D_4), 2, 9, 16}, + {OP(0, 0, 0, OP_STORE64_D_3), 2, 8, 24}, + {OP(0, 0, 0, OP_STORE_D_2), 2, 7, 30}, + {OP(0, 0, 0, OP_STORE_D_4), 2, 6, 32}, + {OP(0, 0, 0, OP_STORE_D_4), 2, 5, 36}, +}; + +test_t tests[] = { + { + .desc = "store64 A", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_A_statements), + .statements = store64_A_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store64 B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_B_statements), + .statements = store64_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 48, + }, + { + .desc = "store64 C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_C_statements), + .statements = store64_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store64 D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_D_statements), + .statements = store64_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-string.c b/libs/gamecode/test/test-string.c new file mode 100644 index 000000000..ceb716570 --- /dev/null +++ b/libs/gamecode/test/test-string.c @@ -0,0 +1,84 @@ +#include "head.c" + +const char test_strings[] = + "\0" + "abc\0" + "def\0" + "abc\0"; + +static pr_int_t string_globals_init[] = { + 0, 1, 5, 9, // string pointers + 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static pr_int_t string_globals_expect[] = { + 0, 1, 5, 9, // string pointers + 0, 0, 8, 0, + +// "\0" "abc" "def" "abc" + -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, // eq + 0, -1, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, // lt + 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, // gt + 0,-97,-100,-97, 97, 0, -3, 0, 100, 3, 0, 3, 97, 0, -3, 0, // cmp + -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, // ge + -1, -1, -1, -1, 0, -1, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, // le + -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // not +}; + +static dstatement_t string_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 24, 0, 6 }, // init k +// for (i = 4; i-- > 0; ) { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 4 }, + { OP(0, 0, 0, OP_IFA), 2, 0, 4 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_C), 4, -1, 4 }, // dec i + + { OP(0, 0, 0, OP_WITH), 4, 4, 1 }, // load i + +// for (j = 4; j-- > 0; ) { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 5 }, // init j + + { OP(0, 0, 0, OP_IFA), 2, 0, 5 }, + { OP(0, 0, 0, OP_JUMP_A), -6, 0, 0 }, + { OP(0, 0, 0, OP_LEA_C), 5, -1, 5 }, // dec j + + { OP(0, 0, 0, OP_WITH), 4, 5, 2 }, // load j + + { OP(0, 0, 0, OP_LEA_C), 6, -1, 6 }, // dec k + { OP(0, 0, 0, OP_WITH), 4, 6, 3 }, // load k + + // i j k + { OP(1, 2, 3, OP_EQ_S), 0, 0, 0 }, + { OP(1, 2, 3, OP_LT_S), 0, 0, 16 }, + { OP(1, 2, 3, OP_GT_S), 0, 0, 32 }, + { OP(1, 2, 3, OP_CMP_S), 0, 0, 48 }, + { OP(1, 2, 3, OP_GE_S), 0, 0, 64 }, + { OP(1, 2, 3, OP_LE_S), 0, 0, 80 }, + { OP(1, 2, 3, OP_NOT_S), 0, 0, 96 }, + +// } + { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, +// } +}; + +test_t tests[] = { + { + .desc = "string", + .num_globals = num_globals (string_globals_init, string_globals_expect), + .num_statements = num_statements (string_statements), + .statements = string_statements, + .init_globals = string_globals_init, + .expect_globals = string_globals_expect, + .strings = test_strings, + .string_size = sizeof (test_strings), + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-swizzle.c b/libs/gamecode/test/test-swizzle.c new file mode 100644 index 000000000..c47acbb5c --- /dev/null +++ b/libs/gamecode/test/test-swizzle.c @@ -0,0 +1,1846 @@ +#include "head.c" + +static pr_vec4_t swizzle_f_init[] = { + { 1, 2, 3, 4 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, +}; +static pr_vec4_t swizzle_f_expect[] = { + { 1, 2, 3, 4 }, + { 1, 1, 1, 1 }, + { 2, 1, 1, 1 }, + { 3, 1, 1, 1 }, + { 4, 1, 1, 1 }, + { 1, 2, 1, 1 }, + { 2, 2, 1, 1 }, + { 3, 2, 1, 1 }, + { 4, 2, 1, 1 }, + { 1, 3, 1, 1 }, + { 2, 3, 1, 1 }, + { 3, 3, 1, 1 }, + { 4, 3, 1, 1 }, + { 1, 4, 1, 1 }, + { 2, 4, 1, 1 }, + { 3, 4, 1, 1 }, + { 4, 4, 1, 1 }, + { 1, 1, 2, 1 }, + { 2, 1, 2, 1 }, + { 3, 1, 2, 1 }, + { 4, 1, 2, 1 }, + { 1, 2, 2, 1 }, + { 2, 2, 2, 1 }, + { 3, 2, 2, 1 }, + { 4, 2, 2, 1 }, + { 1, 3, 2, 1 }, + { 2, 3, 2, 1 }, + { 3, 3, 2, 1 }, + { 4, 3, 2, 1 }, + { 1, 4, 2, 1 }, + { 2, 4, 2, 1 }, + { 3, 4, 2, 1 }, + { 4, 4, 2, 1 }, + { 1, 1, 3, 1 }, + { 2, 1, 3, 1 }, + { 3, 1, 3, 1 }, + { 4, 1, 3, 1 }, + { 1, 2, 3, 1 }, + { 2, 2, 3, 1 }, + { 3, 2, 3, 1 }, + { 4, 2, 3, 1 }, + { 1, 3, 3, 1 }, + { 2, 3, 3, 1 }, + { 3, 3, 3, 1 }, + { 4, 3, 3, 1 }, + { 1, 4, 3, 1 }, + { 2, 4, 3, 1 }, + { 3, 4, 3, 1 }, + { 4, 4, 3, 1 }, + { 1, 1, 4, 1 }, + { 2, 1, 4, 1 }, + { 3, 1, 4, 1 }, + { 4, 1, 4, 1 }, + { 1, 2, 4, 1 }, + { 2, 2, 4, 1 }, + { 3, 2, 4, 1 }, + { 4, 2, 4, 1 }, + { 1, 3, 4, 1 }, + { 2, 3, 4, 1 }, + { 3, 3, 4, 1 }, + { 4, 3, 4, 1 }, + { 1, 4, 4, 1 }, + { 2, 4, 4, 1 }, + { 3, 4, 4, 1 }, + { 4, 4, 4, 1 }, + { 1, 1, 1, 2 }, + { 2, 1, 1, 2 }, + { 3, 1, 1, 2 }, + { 4, 1, 1, 2 }, + { 1, 2, 1, 2 }, + { 2, 2, 1, 2 }, + { 3, 2, 1, 2 }, + { 4, 2, 1, 2 }, + { 1, 3, 1, 2 }, + { 2, 3, 1, 2 }, + { 3, 3, 1, 2 }, + { 4, 3, 1, 2 }, + { 1, 4, 1, 2 }, + { 2, 4, 1, 2 }, + { 3, 4, 1, 2 }, + { 4, 4, 1, 2 }, + { 1, 1, 2, 2 }, + { 2, 1, 2, 2 }, + { 3, 1, 2, 2 }, + { 4, 1, 2, 2 }, + { 1, 2, 2, 2 }, + { 2, 2, 2, 2 }, + { 3, 2, 2, 2 }, + { 4, 2, 2, 2 }, + { 1, 3, 2, 2 }, + { 2, 3, 2, 2 }, + { 3, 3, 2, 2 }, + { 4, 3, 2, 2 }, + { 1, 4, 2, 2 }, + { 2, 4, 2, 2 }, + { 3, 4, 2, 2 }, + { 4, 4, 2, 2 }, + { 1, 1, 3, 2 }, + { 2, 1, 3, 2 }, + { 3, 1, 3, 2 }, + { 4, 1, 3, 2 }, + { 1, 2, 3, 2 }, + { 2, 2, 3, 2 }, + { 3, 2, 3, 2 }, + { 4, 2, 3, 2 }, + { 1, 3, 3, 2 }, + { 2, 3, 3, 2 }, + { 3, 3, 3, 2 }, + { 4, 3, 3, 2 }, + { 1, 4, 3, 2 }, + { 2, 4, 3, 2 }, + { 3, 4, 3, 2 }, + { 4, 4, 3, 2 }, + { 1, 1, 4, 2 }, + { 2, 1, 4, 2 }, + { 3, 1, 4, 2 }, + { 4, 1, 4, 2 }, + { 1, 2, 4, 2 }, + { 2, 2, 4, 2 }, + { 3, 2, 4, 2 }, + { 4, 2, 4, 2 }, + { 1, 3, 4, 2 }, + { 2, 3, 4, 2 }, + { 3, 3, 4, 2 }, + { 4, 3, 4, 2 }, + { 1, 4, 4, 2 }, + { 2, 4, 4, 2 }, + { 3, 4, 4, 2 }, + { 4, 4, 4, 2 }, + { 1, 1, 1, 3 }, + { 2, 1, 1, 3 }, + { 3, 1, 1, 3 }, + { 4, 1, 1, 3 }, + { 1, 2, 1, 3 }, + { 2, 2, 1, 3 }, + { 3, 2, 1, 3 }, + { 4, 2, 1, 3 }, + { 1, 3, 1, 3 }, + { 2, 3, 1, 3 }, + { 3, 3, 1, 3 }, + { 4, 3, 1, 3 }, + { 1, 4, 1, 3 }, + { 2, 4, 1, 3 }, + { 3, 4, 1, 3 }, + { 4, 4, 1, 3 }, + { 1, 1, 2, 3 }, + { 2, 1, 2, 3 }, + { 3, 1, 2, 3 }, + { 4, 1, 2, 3 }, + { 1, 2, 2, 3 }, + { 2, 2, 2, 3 }, + { 3, 2, 2, 3 }, + { 4, 2, 2, 3 }, + { 1, 3, 2, 3 }, + { 2, 3, 2, 3 }, + { 3, 3, 2, 3 }, + { 4, 3, 2, 3 }, + { 1, 4, 2, 3 }, + { 2, 4, 2, 3 }, + { 3, 4, 2, 3 }, + { 4, 4, 2, 3 }, + { 1, 1, 3, 3 }, + { 2, 1, 3, 3 }, + { 3, 1, 3, 3 }, + { 4, 1, 3, 3 }, + { 1, 2, 3, 3 }, + { 2, 2, 3, 3 }, + { 3, 2, 3, 3 }, + { 4, 2, 3, 3 }, + { 1, 3, 3, 3 }, + { 2, 3, 3, 3 }, + { 3, 3, 3, 3 }, + { 4, 3, 3, 3 }, + { 1, 4, 3, 3 }, + { 2, 4, 3, 3 }, + { 3, 4, 3, 3 }, + { 4, 4, 3, 3 }, + { 1, 1, 4, 3 }, + { 2, 1, 4, 3 }, + { 3, 1, 4, 3 }, + { 4, 1, 4, 3 }, + { 1, 2, 4, 3 }, + { 2, 2, 4, 3 }, + { 3, 2, 4, 3 }, + { 4, 2, 4, 3 }, + { 1, 3, 4, 3 }, + { 2, 3, 4, 3 }, + { 3, 3, 4, 3 }, + { 4, 3, 4, 3 }, + { 1, 4, 4, 3 }, + { 2, 4, 4, 3 }, + { 3, 4, 4, 3 }, + { 4, 4, 4, 3 }, + { 1, 1, 1, 4 }, + { 2, 1, 1, 4 }, + { 3, 1, 1, 4 }, + { 4, 1, 1, 4 }, + { 1, 2, 1, 4 }, + { 2, 2, 1, 4 }, + { 3, 2, 1, 4 }, + { 4, 2, 1, 4 }, + { 1, 3, 1, 4 }, + { 2, 3, 1, 4 }, + { 3, 3, 1, 4 }, + { 4, 3, 1, 4 }, + { 1, 4, 1, 4 }, + { 2, 4, 1, 4 }, + { 3, 4, 1, 4 }, + { 4, 4, 1, 4 }, + { 1, 1, 2, 4 }, + { 2, 1, 2, 4 }, + { 3, 1, 2, 4 }, + { 4, 1, 2, 4 }, + { 1, 2, 2, 4 }, + { 2, 2, 2, 4 }, + { 3, 2, 2, 4 }, + { 4, 2, 2, 4 }, + { 1, 3, 2, 4 }, + { 2, 3, 2, 4 }, + { 3, 3, 2, 4 }, + { 4, 3, 2, 4 }, + { 1, 4, 2, 4 }, + { 2, 4, 2, 4 }, + { 3, 4, 2, 4 }, + { 4, 4, 2, 4 }, + { 1, 1, 3, 4 }, + { 2, 1, 3, 4 }, + { 3, 1, 3, 4 }, + { 4, 1, 3, 4 }, + { 1, 2, 3, 4 }, + { 2, 2, 3, 4 }, + { 3, 2, 3, 4 }, + { 4, 2, 3, 4 }, + { 1, 3, 3, 4 }, + { 2, 3, 3, 4 }, + { 3, 3, 3, 4 }, + { 4, 3, 3, 4 }, + { 1, 4, 3, 4 }, + { 2, 4, 3, 4 }, + { 3, 4, 3, 4 }, + { 4, 4, 3, 4 }, + { 1, 1, 4, 4 }, + { 2, 1, 4, 4 }, + { 3, 1, 4, 4 }, + { 4, 1, 4, 4 }, + { 1, 2, 4, 4 }, + { 2, 2, 4, 4 }, + { 3, 2, 4, 4 }, + { 4, 2, 4, 4 }, + { 1, 3, 4, 4 }, + { 2, 3, 4, 4 }, + { 3, 3, 4, 4 }, + { 4, 3, 4, 4 }, + { 1, 4, 4, 4 }, + { 2, 4, 4, 4 }, + { 3, 4, 4, 4 }, + { 4, 4, 4, 4 }, +}; + +static dstatement_t swizzle_f_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0000, 4 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0001, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0002, 12 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0003, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0004, 20 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0005, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0006, 28 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0007, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0008, 36 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0009, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000a, 44 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000b, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000c, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000d, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000e, 60 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000f, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0010, 68 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0011, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0012, 76 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0013, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0014, 84 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0015, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0016, 92 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0017, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0018, 100 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0019, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001a, 108 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001b, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001c, 116 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001d, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001e, 124 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001f, 128 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0020, 132 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0021, 136 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0022, 140 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0023, 144 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0024, 148 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0025, 152 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0026, 156 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0027, 160 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0028, 164 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0029, 168 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002a, 172 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002b, 176 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002c, 180 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002d, 184 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002e, 188 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002f, 192 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0030, 196 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0031, 200 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0032, 204 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0033, 208 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0034, 212 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0035, 216 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0036, 220 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0037, 224 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0038, 228 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0039, 232 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003a, 236 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003b, 240 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003c, 244 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003d, 248 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003e, 252 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003f, 256 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0040, 260 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0041, 264 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0042, 268 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0043, 272 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0044, 276 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0045, 280 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0046, 284 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0047, 288 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0048, 292 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0049, 296 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004a, 300 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004b, 304 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004c, 308 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004d, 312 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004e, 316 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004f, 320 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0050, 324 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0051, 328 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0052, 332 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0053, 336 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0054, 340 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0055, 344 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0056, 348 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0057, 352 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0058, 356 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0059, 360 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005a, 364 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005b, 368 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005c, 372 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005d, 376 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005e, 380 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005f, 384 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0060, 388 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0061, 392 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0062, 396 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0063, 400 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0064, 404 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0065, 408 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0066, 412 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0067, 416 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0068, 420 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0069, 424 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006a, 428 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006b, 432 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006c, 436 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006d, 440 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006e, 444 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006f, 448 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0070, 452 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0071, 456 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0072, 460 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0073, 464 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0074, 468 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0075, 472 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0076, 476 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0077, 480 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0078, 484 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0079, 488 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007a, 492 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007b, 496 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007c, 500 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007d, 504 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007e, 508 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007f, 512 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0080, 516 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0081, 520 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0082, 524 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0083, 528 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0084, 532 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0085, 536 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0086, 540 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0087, 544 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0088, 548 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0089, 552 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008a, 556 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008b, 560 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008c, 564 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008d, 568 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008e, 572 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008f, 576 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0090, 580 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0091, 584 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0092, 588 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0093, 592 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0094, 596 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0095, 600 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0096, 604 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0097, 608 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0098, 612 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0099, 616 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009a, 620 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009b, 624 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009c, 628 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009d, 632 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009e, 636 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009f, 640 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a0, 644 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a1, 648 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a2, 652 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a3, 656 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a4, 660 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a5, 664 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a6, 668 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a7, 672 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a8, 676 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a9, 680 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00aa, 684 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ab, 688 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ac, 692 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ad, 696 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ae, 700 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00af, 704 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b0, 708 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b1, 712 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b2, 716 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b3, 720 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b4, 724 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b5, 728 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b6, 732 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b7, 736 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b8, 740 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b9, 744 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ba, 748 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bb, 752 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bc, 756 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bd, 760 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00be, 764 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bf, 768 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c0, 772 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c1, 776 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c2, 780 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c3, 784 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c4, 788 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c5, 792 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c6, 796 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c7, 800 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c8, 804 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c9, 808 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ca, 812 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cb, 816 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cc, 820 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cd, 824 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ce, 828 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cf, 832 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d0, 836 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d1, 840 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d2, 844 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d3, 848 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d4, 852 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d5, 856 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d6, 860 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d7, 864 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d8, 868 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d9, 872 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00da, 876 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00db, 880 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00dc, 884 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00dd, 888 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00de, 892 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00df, 896 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e0, 900 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e1, 904 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e2, 908 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e3, 912 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e4, 916 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e5, 920 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e6, 924 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e7, 928 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e8, 932 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e9, 936 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ea, 940 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00eb, 944 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ec, 948 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ed, 952 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ee, 956 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ef, 960 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f0, 964 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f1, 968 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f2, 972 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f3, 976 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f4, 980 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f5, 984 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f6, 988 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f7, 992 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f8, 996 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f9, 1000 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fa, 1004 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fb, 1008 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fc, 1012 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fd, 1016 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fe, 1020 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ff, 1024 }, +}; + +static pr_vec4_t neg_f_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_vec4_t neg_f_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { -1, 2, 3, 4 }, + { 1, -2, 3, 4 }, + { -1, -2, 3, 4 }, + { 1, 2, -3, 4 }, + { -1, 2, -3, 4 }, + { 1, -2, -3, 4 }, + { -1, -2, -3, 4 }, + { 1, 2, 3, -4 }, + { -1, 2, 3, -4 }, + { 1, -2, 3, -4 }, + { -1, -2, 3, -4 }, + { 1, 2, -3, -4 }, + { -1, 2, -3, -4 }, + { 1, -2, -3, -4 }, + { -1, -2, -3, -4 }, +}; + +static dstatement_t neg_f_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e4, 4 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x01e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x02e4, 12 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x03e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x04e4, 20 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x05e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x06e4, 28 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x07e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x08e4, 36 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x09e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0ae4, 44 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0be4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0ce4, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0de4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0ee4, 60 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0fe4, 64 }, +}; + +static pr_vec4_t zero_f_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_vec4_t zero_f_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { 0, 2, 3, 4 }, + { 1, 0, 3, 4 }, + { 0, 0, 3, 4 }, + { 1, 2, 0, 4 }, + { 0, 2, 0, 4 }, + { 1, 0, 0, 4 }, + { 0, 0, 0, 4 }, + { 1, 2, 3, 0 }, + { 0, 2, 3, 0 }, + { 1, 0, 3, 0 }, + { 0, 0, 3, 0 }, + { 1, 2, 0, 0 }, + { 0, 2, 0, 0 }, + { 1, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static dstatement_t zero_f_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e4, 4 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x10e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x20e4, 12 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x30e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x40e4, 20 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x50e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x60e4, 28 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x70e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x80e4, 36 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x90e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xa0e4, 44 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xb0e4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xc0e4, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xd0e4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xe0e4, 60 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xf0e4, 64 }, +}; + +static pr_dvec4_t swizzle_d_init[] = { + { 1, 2, 3, 4 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, +}; +static pr_dvec4_t swizzle_d_expect[] = { + { 1, 2, 3, 4 }, + { 1, 1, 1, 1 }, + { 2, 1, 1, 1 }, + { 3, 1, 1, 1 }, + { 4, 1, 1, 1 }, + { 1, 2, 1, 1 }, + { 2, 2, 1, 1 }, + { 3, 2, 1, 1 }, + { 4, 2, 1, 1 }, + { 1, 3, 1, 1 }, + { 2, 3, 1, 1 }, + { 3, 3, 1, 1 }, + { 4, 3, 1, 1 }, + { 1, 4, 1, 1 }, + { 2, 4, 1, 1 }, + { 3, 4, 1, 1 }, + { 4, 4, 1, 1 }, + { 1, 1, 2, 1 }, + { 2, 1, 2, 1 }, + { 3, 1, 2, 1 }, + { 4, 1, 2, 1 }, + { 1, 2, 2, 1 }, + { 2, 2, 2, 1 }, + { 3, 2, 2, 1 }, + { 4, 2, 2, 1 }, + { 1, 3, 2, 1 }, + { 2, 3, 2, 1 }, + { 3, 3, 2, 1 }, + { 4, 3, 2, 1 }, + { 1, 4, 2, 1 }, + { 2, 4, 2, 1 }, + { 3, 4, 2, 1 }, + { 4, 4, 2, 1 }, + { 1, 1, 3, 1 }, + { 2, 1, 3, 1 }, + { 3, 1, 3, 1 }, + { 4, 1, 3, 1 }, + { 1, 2, 3, 1 }, + { 2, 2, 3, 1 }, + { 3, 2, 3, 1 }, + { 4, 2, 3, 1 }, + { 1, 3, 3, 1 }, + { 2, 3, 3, 1 }, + { 3, 3, 3, 1 }, + { 4, 3, 3, 1 }, + { 1, 4, 3, 1 }, + { 2, 4, 3, 1 }, + { 3, 4, 3, 1 }, + { 4, 4, 3, 1 }, + { 1, 1, 4, 1 }, + { 2, 1, 4, 1 }, + { 3, 1, 4, 1 }, + { 4, 1, 4, 1 }, + { 1, 2, 4, 1 }, + { 2, 2, 4, 1 }, + { 3, 2, 4, 1 }, + { 4, 2, 4, 1 }, + { 1, 3, 4, 1 }, + { 2, 3, 4, 1 }, + { 3, 3, 4, 1 }, + { 4, 3, 4, 1 }, + { 1, 4, 4, 1 }, + { 2, 4, 4, 1 }, + { 3, 4, 4, 1 }, + { 4, 4, 4, 1 }, + { 1, 1, 1, 2 }, + { 2, 1, 1, 2 }, + { 3, 1, 1, 2 }, + { 4, 1, 1, 2 }, + { 1, 2, 1, 2 }, + { 2, 2, 1, 2 }, + { 3, 2, 1, 2 }, + { 4, 2, 1, 2 }, + { 1, 3, 1, 2 }, + { 2, 3, 1, 2 }, + { 3, 3, 1, 2 }, + { 4, 3, 1, 2 }, + { 1, 4, 1, 2 }, + { 2, 4, 1, 2 }, + { 3, 4, 1, 2 }, + { 4, 4, 1, 2 }, + { 1, 1, 2, 2 }, + { 2, 1, 2, 2 }, + { 3, 1, 2, 2 }, + { 4, 1, 2, 2 }, + { 1, 2, 2, 2 }, + { 2, 2, 2, 2 }, + { 3, 2, 2, 2 }, + { 4, 2, 2, 2 }, + { 1, 3, 2, 2 }, + { 2, 3, 2, 2 }, + { 3, 3, 2, 2 }, + { 4, 3, 2, 2 }, + { 1, 4, 2, 2 }, + { 2, 4, 2, 2 }, + { 3, 4, 2, 2 }, + { 4, 4, 2, 2 }, + { 1, 1, 3, 2 }, + { 2, 1, 3, 2 }, + { 3, 1, 3, 2 }, + { 4, 1, 3, 2 }, + { 1, 2, 3, 2 }, + { 2, 2, 3, 2 }, + { 3, 2, 3, 2 }, + { 4, 2, 3, 2 }, + { 1, 3, 3, 2 }, + { 2, 3, 3, 2 }, + { 3, 3, 3, 2 }, + { 4, 3, 3, 2 }, + { 1, 4, 3, 2 }, + { 2, 4, 3, 2 }, + { 3, 4, 3, 2 }, + { 4, 4, 3, 2 }, + { 1, 1, 4, 2 }, + { 2, 1, 4, 2 }, + { 3, 1, 4, 2 }, + { 4, 1, 4, 2 }, + { 1, 2, 4, 2 }, + { 2, 2, 4, 2 }, + { 3, 2, 4, 2 }, + { 4, 2, 4, 2 }, + { 1, 3, 4, 2 }, + { 2, 3, 4, 2 }, + { 3, 3, 4, 2 }, + { 4, 3, 4, 2 }, + { 1, 4, 4, 2 }, + { 2, 4, 4, 2 }, + { 3, 4, 4, 2 }, + { 4, 4, 4, 2 }, + { 1, 1, 1, 3 }, + { 2, 1, 1, 3 }, + { 3, 1, 1, 3 }, + { 4, 1, 1, 3 }, + { 1, 2, 1, 3 }, + { 2, 2, 1, 3 }, + { 3, 2, 1, 3 }, + { 4, 2, 1, 3 }, + { 1, 3, 1, 3 }, + { 2, 3, 1, 3 }, + { 3, 3, 1, 3 }, + { 4, 3, 1, 3 }, + { 1, 4, 1, 3 }, + { 2, 4, 1, 3 }, + { 3, 4, 1, 3 }, + { 4, 4, 1, 3 }, + { 1, 1, 2, 3 }, + { 2, 1, 2, 3 }, + { 3, 1, 2, 3 }, + { 4, 1, 2, 3 }, + { 1, 2, 2, 3 }, + { 2, 2, 2, 3 }, + { 3, 2, 2, 3 }, + { 4, 2, 2, 3 }, + { 1, 3, 2, 3 }, + { 2, 3, 2, 3 }, + { 3, 3, 2, 3 }, + { 4, 3, 2, 3 }, + { 1, 4, 2, 3 }, + { 2, 4, 2, 3 }, + { 3, 4, 2, 3 }, + { 4, 4, 2, 3 }, + { 1, 1, 3, 3 }, + { 2, 1, 3, 3 }, + { 3, 1, 3, 3 }, + { 4, 1, 3, 3 }, + { 1, 2, 3, 3 }, + { 2, 2, 3, 3 }, + { 3, 2, 3, 3 }, + { 4, 2, 3, 3 }, + { 1, 3, 3, 3 }, + { 2, 3, 3, 3 }, + { 3, 3, 3, 3 }, + { 4, 3, 3, 3 }, + { 1, 4, 3, 3 }, + { 2, 4, 3, 3 }, + { 3, 4, 3, 3 }, + { 4, 4, 3, 3 }, + { 1, 1, 4, 3 }, + { 2, 1, 4, 3 }, + { 3, 1, 4, 3 }, + { 4, 1, 4, 3 }, + { 1, 2, 4, 3 }, + { 2, 2, 4, 3 }, + { 3, 2, 4, 3 }, + { 4, 2, 4, 3 }, + { 1, 3, 4, 3 }, + { 2, 3, 4, 3 }, + { 3, 3, 4, 3 }, + { 4, 3, 4, 3 }, + { 1, 4, 4, 3 }, + { 2, 4, 4, 3 }, + { 3, 4, 4, 3 }, + { 4, 4, 4, 3 }, + { 1, 1, 1, 4 }, + { 2, 1, 1, 4 }, + { 3, 1, 1, 4 }, + { 4, 1, 1, 4 }, + { 1, 2, 1, 4 }, + { 2, 2, 1, 4 }, + { 3, 2, 1, 4 }, + { 4, 2, 1, 4 }, + { 1, 3, 1, 4 }, + { 2, 3, 1, 4 }, + { 3, 3, 1, 4 }, + { 4, 3, 1, 4 }, + { 1, 4, 1, 4 }, + { 2, 4, 1, 4 }, + { 3, 4, 1, 4 }, + { 4, 4, 1, 4 }, + { 1, 1, 2, 4 }, + { 2, 1, 2, 4 }, + { 3, 1, 2, 4 }, + { 4, 1, 2, 4 }, + { 1, 2, 2, 4 }, + { 2, 2, 2, 4 }, + { 3, 2, 2, 4 }, + { 4, 2, 2, 4 }, + { 1, 3, 2, 4 }, + { 2, 3, 2, 4 }, + { 3, 3, 2, 4 }, + { 4, 3, 2, 4 }, + { 1, 4, 2, 4 }, + { 2, 4, 2, 4 }, + { 3, 4, 2, 4 }, + { 4, 4, 2, 4 }, + { 1, 1, 3, 4 }, + { 2, 1, 3, 4 }, + { 3, 1, 3, 4 }, + { 4, 1, 3, 4 }, + { 1, 2, 3, 4 }, + { 2, 2, 3, 4 }, + { 3, 2, 3, 4 }, + { 4, 2, 3, 4 }, + { 1, 3, 3, 4 }, + { 2, 3, 3, 4 }, + { 3, 3, 3, 4 }, + { 4, 3, 3, 4 }, + { 1, 4, 3, 4 }, + { 2, 4, 3, 4 }, + { 3, 4, 3, 4 }, + { 4, 4, 3, 4 }, + { 1, 1, 4, 4 }, + { 2, 1, 4, 4 }, + { 3, 1, 4, 4 }, + { 4, 1, 4, 4 }, + { 1, 2, 4, 4 }, + { 2, 2, 4, 4 }, + { 3, 2, 4, 4 }, + { 4, 2, 4, 4 }, + { 1, 3, 4, 4 }, + { 2, 3, 4, 4 }, + { 3, 3, 4, 4 }, + { 4, 3, 4, 4 }, + { 1, 4, 4, 4 }, + { 2, 4, 4, 4 }, + { 3, 4, 4, 4 }, + { 4, 4, 4, 4 }, +}; + +static dstatement_t swizzle_d_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0000, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0001, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0002, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0003, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0004, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0005, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0006, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0007, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0008, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0009, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000a, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000b, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000c, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000d, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000e, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000f, 128 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0010, 136 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0011, 144 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0012, 152 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0013, 160 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0014, 168 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0015, 176 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0016, 184 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0017, 192 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0018, 200 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0019, 208 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001a, 216 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001b, 224 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001c, 232 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001d, 240 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001e, 248 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001f, 256 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0020, 264 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0021, 272 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0022, 280 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0023, 288 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0024, 296 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0025, 304 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0026, 312 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0027, 320 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0028, 328 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0029, 336 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002a, 344 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002b, 352 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002c, 360 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002d, 368 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002e, 376 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002f, 384 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0030, 392 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0031, 400 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0032, 408 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0033, 416 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0034, 424 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0035, 432 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0036, 440 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0037, 448 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0038, 456 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0039, 464 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003a, 472 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003b, 480 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003c, 488 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003d, 496 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003e, 504 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003f, 512 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0040, 520 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0041, 528 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0042, 536 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0043, 544 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0044, 552 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0045, 560 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0046, 568 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0047, 576 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0048, 584 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0049, 592 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004a, 600 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004b, 608 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004c, 616 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004d, 624 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004e, 632 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004f, 640 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0050, 648 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0051, 656 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0052, 664 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0053, 672 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0054, 680 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0055, 688 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0056, 696 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0057, 704 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0058, 712 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0059, 720 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005a, 728 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005b, 736 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005c, 744 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005d, 752 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005e, 760 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005f, 768 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0060, 776 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0061, 784 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0062, 792 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0063, 800 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0064, 808 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0065, 816 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0066, 824 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0067, 832 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0068, 840 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0069, 848 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006a, 856 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006b, 864 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006c, 872 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006d, 880 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006e, 888 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006f, 896 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0070, 904 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0071, 912 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0072, 920 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0073, 928 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0074, 936 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0075, 944 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0076, 952 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0077, 960 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0078, 968 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0079, 976 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007a, 984 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007b, 992 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007c, 1000 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007d, 1008 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007e, 1016 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007f, 1024 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0080, 1032 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0081, 1040 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0082, 1048 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0083, 1056 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0084, 1064 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0085, 1072 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0086, 1080 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0087, 1088 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0088, 1096 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0089, 1104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008a, 1112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008b, 1120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008c, 1128 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008d, 1136 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008e, 1144 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008f, 1152 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0090, 1160 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0091, 1168 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0092, 1176 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0093, 1184 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0094, 1192 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0095, 1200 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0096, 1208 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0097, 1216 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0098, 1224 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0099, 1232 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009a, 1240 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009b, 1248 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009c, 1256 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009d, 1264 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009e, 1272 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009f, 1280 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a0, 1288 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a1, 1296 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a2, 1304 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a3, 1312 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a4, 1320 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a5, 1328 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a6, 1336 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a7, 1344 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a8, 1352 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a9, 1360 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00aa, 1368 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ab, 1376 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ac, 1384 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ad, 1392 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ae, 1400 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00af, 1408 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b0, 1416 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b1, 1424 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b2, 1432 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b3, 1440 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b4, 1448 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b5, 1456 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b6, 1464 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b7, 1472 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b8, 1480 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b9, 1488 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ba, 1496 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bb, 1504 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bc, 1512 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bd, 1520 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00be, 1528 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bf, 1536 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c0, 1544 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c1, 1552 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c2, 1560 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c3, 1568 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c4, 1576 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c5, 1584 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c6, 1592 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c7, 1600 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c8, 1608 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c9, 1616 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ca, 1624 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cb, 1632 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cc, 1640 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cd, 1648 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ce, 1656 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cf, 1664 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d0, 1672 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d1, 1680 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d2, 1688 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d3, 1696 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d4, 1704 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d5, 1712 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d6, 1720 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d7, 1728 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d8, 1736 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d9, 1744 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00da, 1752 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00db, 1760 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00dc, 1768 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00dd, 1776 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00de, 1784 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00df, 1792 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e0, 1800 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e1, 1808 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e2, 1816 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e3, 1824 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e4, 1832 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e5, 1840 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e6, 1848 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e7, 1856 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e8, 1864 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e9, 1872 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ea, 1880 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00eb, 1888 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ec, 1896 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ed, 1904 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ee, 1912 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ef, 1920 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f0, 1928 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f1, 1936 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f2, 1944 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f3, 1952 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f4, 1960 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f5, 1968 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f6, 1976 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f7, 1984 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f8, 1992 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f9, 2000 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fa, 2008 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fb, 2016 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fc, 2024 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fd, 2032 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fe, 2040 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ff, 2048 }, +}; + +static pr_dvec4_t neg_d_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_dvec4_t neg_d_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { -1, 2, 3, 4 }, + { 1, -2, 3, 4 }, + { -1, -2, 3, 4 }, + { 1, 2, -3, 4 }, + { -1, 2, -3, 4 }, + { 1, -2, -3, 4 }, + { -1, -2, -3, 4 }, + { 1, 2, 3, -4 }, + { -1, 2, 3, -4 }, + { 1, -2, 3, -4 }, + { -1, -2, 3, -4 }, + { 1, 2, -3, -4 }, + { -1, 2, -3, -4 }, + { 1, -2, -3, -4 }, + { -1, -2, -3, -4 }, +}; + +static dstatement_t neg_d_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x01e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x02e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x03e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x04e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x05e4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x06e4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x07e4, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x08e4, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x09e4, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0ae4, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0be4, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0ce4, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0de4, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0ee4, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0fe4, 128 }, +}; + +static pr_dvec4_t zero_d_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_dvec4_t zero_d_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { 0, 2, 3, 4 }, + { 1, 0, 3, 4 }, + { 0, 0, 3, 4 }, + { 1, 2, 0, 4 }, + { 0, 2, 0, 4 }, + { 1, 0, 0, 4 }, + { 0, 0, 0, 4 }, + { 1, 2, 3, 0 }, + { 0, 2, 3, 0 }, + { 1, 0, 3, 0 }, + { 0, 0, 3, 0 }, + { 1, 2, 0, 0 }, + { 0, 2, 0, 0 }, + { 1, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static dstatement_t zero_d_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x10e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x20e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x30e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x40e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x50e4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x60e4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x70e4, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x80e4, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x90e4, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xa0e4, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xb0e4, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xc0e4, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xd0e4, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xe0e4, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xf0e4, 128 }, +}; + +test_t tests[] = { + { + .desc = "swizzle f", + .num_globals = num_globals(swizzle_f_init,swizzle_f_expect), + .num_statements = num_statements(swizzle_f_statements), + .statements = swizzle_f_statements, + .init_globals = (pr_int_t *) swizzle_f_init, + .expect_globals = (pr_int_t *) swizzle_f_expect, + }, + { + .desc = "neg f", + .num_globals = num_globals(neg_f_init,neg_f_expect), + .num_statements = num_statements(neg_f_statements), + .statements = neg_f_statements, + .init_globals = (pr_int_t *) neg_f_init, + .expect_globals = (pr_int_t *) neg_f_expect, + }, + { + .desc = "zero f", + .num_globals = num_globals(zero_f_init,zero_f_expect), + .num_statements = num_statements(zero_f_statements), + .statements = zero_f_statements, + .init_globals = (pr_int_t *) zero_f_init, + .expect_globals = (pr_int_t *) zero_f_expect, + }, + { + .desc = "swizzle d", + .num_globals = num_globals(swizzle_d_init,swizzle_d_expect), + .num_statements = num_statements(swizzle_d_statements), + .statements = swizzle_d_statements, + .init_globals = (pr_int_t *) swizzle_d_init, + .expect_globals = (pr_int_t *) swizzle_d_expect, + }, + { + .desc = "neg d", + .num_globals = num_globals(neg_d_init,neg_d_expect), + .num_statements = num_statements(neg_d_statements), + .statements = neg_d_statements, + .init_globals = (pr_int_t *) neg_d_init, + .expect_globals = (pr_int_t *) neg_d_expect, + }, + { + .desc = "zero d", + .num_globals = num_globals(zero_d_init,zero_d_expect), + .num_statements = num_statements(zero_d_statements), + .statements = zero_d_statements, + .init_globals = (pr_int_t *) zero_d_init, + .expect_globals = (pr_int_t *) zero_d_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-unsigned.c b/libs/gamecode/test/test-unsigned.c new file mode 100644 index 000000000..66f68e482 --- /dev/null +++ b/libs/gamecode/test/test-unsigned.c @@ -0,0 +1,776 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_uivec4_t uint_divop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_uivec4_t uint_divop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 1, 0x55555553, 0, 0}, + { 2, 2, 5, -5}, +}; + +static dstatement_t uint_divop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_DIV_u_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_REM_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t uint_divop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_DIV_u_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_REM_u_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t uint_divop_3a_statements[] = { + { OP(1, 1, 1, OP_DIV_u_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_u_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_REM_u_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_u_1), 3, 7, 15 }, +}; + +static dstatement_t uint_divop_3b_statements[] = { + { OP(1, 1, 1, OP_DIV_u_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_u_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_REM_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_u_3), 1, 5, 13 }, +}; + +static dstatement_t uint_divop_4_statements[] = { + { OP(1, 1, 1, OP_DIV_u_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_REM_u_4), 0, 4, 12 }, +}; + +static pr_uivec4_t uint_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_uivec4_t uint_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, // no unsigned EQ (redundant) + { 0, 0, -1, 0}, + { 0, -1, 0, 0}, + { 0, 0, 0, 0}, // no unsigned NE (redundant) + { -1, -1, 0, -1}, + { -1, 0, -1, -1}, +}; + +static dstatement_t uint_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_u_1), 0, 4, 16 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_u_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t uint_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_u_2), 0, 4, 16 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_u_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t uint_cmpop_3a_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_u_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_GT_u_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_u_1), 3, 7, 19 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_u_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_LE_u_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_u_1), 3, 7, 31 }, +}; + +static dstatement_t uint_cmpop_3b_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_u_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_GT_u_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_u_3), 1, 5, 17 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_u_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_LE_u_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_u_3), 1, 5, 29 }, +}; + +static dstatement_t uint_cmpop_4_statements[] = { + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_u_4), 0, 4, 16 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_u_4), 0, 4, 28 }, +}; + +static pr_ulvec4_t ulong_divop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ulvec4_t ulong_divop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 1, UINT64_C(0x5555555555555553), 0, 0}, + { 2, 2, 5, -5}, +}; + +static dstatement_t ulong_divop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_DIV_U_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_REM_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t ulong_divop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_DIV_U_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_REM_U_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t ulong_divop_3a_statements[] = { + { OP(1, 1, 1, OP_DIV_U_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_U_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_REM_U_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_U_1), 6, 14, 30 }, +}; + +static dstatement_t ulong_divop_3b_statements[] = { + { OP(1, 1, 1, OP_DIV_U_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_U_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_REM_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_U_3), 2, 10, 26 }, +}; + +static dstatement_t ulong_divop_4_statements[] = { + { OP(1, 1, 1, OP_DIV_U_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_REM_U_4), 0, 8, 24 }, +}; + +static pr_ulvec4_t ulong_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ulvec4_t ulong_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, // no unsigned EQ (redundant) + { 0, 0, -1, 0}, + { 0, -1, 0, 0}, + { 0, 0, 0, 0}, // no unsigned NE (redundant) + { -1, -1, 0, -1}, + { -1, 0, -1, -1}, +}; + +static dstatement_t ulong_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_U_1), 0, 8, 32 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_U_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t ulong_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_U_2), 0, 8, 32 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_U_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t ulong_cmpop_3a_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_U_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_GT_U_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_U_1), 6, 14, 38 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_U_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_LE_U_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_U_1), 6, 14, 62 }, +}; + +static dstatement_t ulong_cmpop_3b_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_U_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_GT_U_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_U_3), 2, 10, 34 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_U_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_LE_U_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_U_3), 2, 10, 58 }, +}; + +static dstatement_t ulong_cmpop_4_statements[] = { + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_U_4), 0, 8, 32 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_U_4), 0, 8, 56 }, +}; + +static pr_uivec4_t uint_shiftop_init[] = { + { 0x12345678, 0x9abcdef0, 0x80000001, 0xaaaa5555 }, + { 12, 16, 9, 1 }, + { 20, 16, 23, 31 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static pr_uivec4_t uint_shiftop_expect[] = { + { 0x12345678, 0x9abcdef0, 0x80000001, 0xaaaa5555 }, + { 12, 16, 9, 1 },//a + { 20, 16, 23, 31 },//b + { 0x45678000, 0xdef00000, 0x00000200, 0x5554aaaa },//shl a + { 0x67800000, 0xdef00000, 0x00800000, 0x80000000 },//shl b + { 0x00012345, 0x00009abc, 0x00400000, 0x55552aaa },//shr a + { 0x00000123, 0x00009abc, 0x00000100, 0x00000001 },//shr b + { 0x00012345, 0xffff9abc, 0xffc00000, 0xd5552aaa },//asr a + { 0x00000123, 0xffff9abc, 0xffffff00, 0xffffffff },//asr b +}; + +static dstatement_t uint_shiftop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 36 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 36, -1, 36 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 36 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 36, 1 }, + { OP(1, 1, 1, OP_SHL_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t uint_shiftop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 36 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 36, -2, 36 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 36 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 36, 1 }, + { OP(1, 1, 1, OP_SHL_I_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHR_u_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_ASR_I_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t uint_shiftop_3a_statements[] = { + { OP(1, 1, 1, OP_SHL_I_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_SHL_I_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHL_I_1), 3, 11, 19 }, + { OP(1, 1, 1, OP_SHR_u_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_SHR_u_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHR_u_1), 3, 11, 27 }, + { OP(1, 1, 1, OP_ASR_I_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_1), 3, 7, 31 }, + { OP(1, 1, 1, OP_ASR_I_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_ASR_I_1), 3, 11, 35 }, +}; + +static dstatement_t uint_shiftop_3b_statements[] = { + { OP(1, 1, 1, OP_SHL_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_SHL_I_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHL_I_3), 1, 9, 17 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHR_u_3), 1, 9, 25 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_3), 1, 5, 29 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_ASR_I_3), 1, 9, 33 }, +}; + +static dstatement_t uint_shiftop_4_statements[] = { + { OP(1, 1, 1, OP_SHL_I_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHR_u_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_ASR_I_4), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_4), 0, 8, 32 }, +}; + +static pr_ulvec4_t ulong_shiftop_init[] = { + { UINT64_C(0x123456789abcdef0), UINT64_C(0x9abcdef012345678), + UINT64_C(0x8000000180000001), UINT64_C(0xaaaa5555aaaa5555) }, + { 12, 16, 9, 1 }, + { 52, 48, 55, 63 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static pr_ulvec4_t ulong_shiftop_expect[] = { + { UINT64_C(0x123456789abcdef0), UINT64_C(0x9abcdef012345678), + UINT64_C(0x8000000180000001), UINT64_C(0xaaaa5555aaaa5555) }, + { 12, 16, 9, 1 },//a + { 52, 48, 55, 63 },//b + { UINT64_C(0x456789abcdef0000), UINT64_C(0xdef0123456780000), + UINT64_C(0x0000030000000200), UINT64_C(0x5554aaab5554aaaa) },//shl a + { UINT64_C(0xef00000000000000), UINT64_C(0x5678000000000000), + UINT64_C(0x0080000000000000), UINT64_C(0x8000000000000000) },//shl b + { UINT64_C(0x000123456789abcd), UINT64_C(0x00009abcdef01234), + UINT64_C(0x0040000000c00000), UINT64_C(0x55552aaad5552aaa) },//shr a + { UINT64_C(0x0000000000000123), UINT64_C(0x0000000000009abc), + UINT64_C(0x0000000000000100), UINT64_C(0x0000000000000001) },//shr b + { UINT64_C(0x000123456789abcd), UINT64_C(0xffff9abcdef01234), + UINT64_C(0xffc0000000c00000), UINT64_C(0xd5552aaad5552aaa) },//asr a + { UINT64_C(0x0000000000000123), UINT64_C(0xffffffffffff9abc), + UINT64_C(0xffffffffffffff00), UINT64_C(0xffffffffffffffff) },//asr b +}; + +static dstatement_t ulong_shiftop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 72 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 72, -2, 72 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 72 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 72, 1 }, + { OP(1, 1, 1, OP_SHL_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_1), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 16, 48 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 16, 64 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t ulong_shiftop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 72 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 72, -4, 72 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 72 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 72, 1 }, + { OP(1, 1, 1, OP_SHL_L_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_2), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHR_U_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_2), 0, 16, 48 }, + { OP(1, 1, 1, OP_ASR_L_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_2), 0, 16, 64 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t ulong_shiftop_3a_statements[] = { + { OP(1, 1, 1, OP_SHL_L_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_SHL_L_3), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHL_L_1), 6, 22, 38 }, + { OP(1, 1, 1, OP_SHR_U_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_SHR_U_3), 0, 16, 48 }, + { OP(1, 1, 1, OP_SHR_U_1), 6, 22, 54 }, + { OP(1, 1, 1, OP_ASR_L_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_1), 6, 14, 62 }, + { OP(1, 1, 1, OP_ASR_L_3), 0, 16, 64 }, + { OP(1, 1, 1, OP_ASR_L_1), 6, 22, 70 }, +}; + +static dstatement_t ulong_shiftop_3b_statements[] = { + { OP(1, 1, 1, OP_SHL_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_SHL_L_1), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHL_L_3), 2, 18, 34 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 16, 48 }, + { OP(1, 1, 1, OP_SHR_U_3), 2, 18, 50 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_3), 2, 10, 58 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 16, 64 }, + { OP(1, 1, 1, OP_ASR_L_3), 2, 18, 66 }, +}; + +static dstatement_t ulong_shiftop_4_statements[] = { + { OP(1, 1, 1, OP_SHL_L_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_4), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHR_U_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_4), 0, 16, 48 }, + { OP(1, 1, 1, OP_ASR_L_4), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_4), 0, 16, 64 }, +}; + +test_t tests[] = { + { + .desc = "uint divop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_1_statements), + .statements = uint_divop_1_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_2_statements), + .statements = uint_divop_2_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_3a_statements), + .statements = uint_divop_3a_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_3b_statements), + .statements = uint_divop_3b_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_4_statements), + .statements = uint_divop_4_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint cmpop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_1_statements), + .statements = uint_cmpop_1_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_2_statements), + .statements = uint_cmpop_2_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_3a_statements), + .statements = uint_cmpop_3a_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_3b_statements), + .statements = uint_cmpop_3b_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_4_statements), + .statements = uint_cmpop_4_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "ulong divop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_1_statements), + .statements = ulong_divop_1_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_2_statements), + .statements = ulong_divop_2_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_3a_statements), + .statements = ulong_divop_3a_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_3b_statements), + .statements = ulong_divop_3b_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_4_statements), + .statements = ulong_divop_4_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong cmpop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_1_statements), + .statements = ulong_cmpop_1_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_2_statements), + .statements = ulong_cmpop_2_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_3a_statements), + .statements = ulong_cmpop_3a_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_3b_statements), + .statements = ulong_cmpop_3b_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_4_statements), + .statements = ulong_cmpop_4_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "uint shiftop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_1_statements), + .statements = uint_shiftop_1_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_2_statements), + .statements = uint_shiftop_2_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_3a_statements), + .statements = uint_shiftop_3a_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_3b_statements), + .statements = uint_shiftop_3b_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_4_statements), + .statements = uint_shiftop_4_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "ulong shiftop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_1_statements), + .statements = ulong_shiftop_1_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_2_statements), + .statements = ulong_shiftop_2_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_3a_statements), + .statements = ulong_shiftop_3a_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_3b_statements), + .statements = ulong_shiftop_3b_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_4_statements), + .statements = ulong_shiftop_4_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-vector.c b/libs/gamecode/test/test-vector.c new file mode 100644 index 000000000..f80253886 --- /dev/null +++ b/libs/gamecode/test/test-vector.c @@ -0,0 +1,170 @@ +#include "head.c" + +static pr_vec4_t float_globals_init[] = { + {3, 4, 5, 12}, + {0, 0, 0, 0}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + + {2, 3, 4, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 7}, + + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 0}, + + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, +}; + +static pr_vec4_t float_globals_expect[] = { + {3, 4, 5, 12}, + {63, 63, -33, 56}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + + {32, 32, 32, 7}, + {-3, 6, -3, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + + {2, 3, 4, 0}, + {70, 70, 70, 70}, + {24, 48, 48, -6}, + {36, 102, 120, 7}, + + {52, 70, 136, 7}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, + {-1, -2, -3, 4}, + + {-1, -2, -3, 4}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, +}; + +static dstatement_t float_vector_statements[] = { + { OP(0, 0, 0, OP_CDOT_F), 0, 2, 4 }, + { OP(0, 0, 0, OP_CMUL_F), 0, 2, 6 }, + { OP(0, 0, 0, OP_VDOT_F), 8, 12, 16 }, + { OP(0, 0, 0, OP_CROSS_F), 8, 12, 20 }, + { OP(0, 0, 0, OP_QDOT_F), 24, 28, 36 }, + { OP(0, 0, 0, OP_QMUL_F), 24, 28, 40 }, + { OP(0, 0, 0, OP_QVMUL_F), 24, 32, 44 }, + { OP(0, 0, 0, OP_VQMUL_F), 32, 24, 48 }, + + { OP(0, 0, 0, OP_QMUL_F), 24, 32, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 60 }, + { OP(0, 0, 0, OP_QMUL_F), 52, 60, 52 }, + + { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 64 }, + { OP(0, 0, 0, OP_QMUL_F), 64, 32, 56 }, + { OP(0, 0, 0, OP_QMUL_F), 56, 24, 56 }, + + { OP(0, 0, 0, OP_QV4MUL_F), 24, 32, 68 }, + { OP(0, 0, 0, OP_V4QMUL_F), 32, 24, 72 }, +}; + +static pr_dvec4_t double_globals_init[] = { + {3, 4, 5, 12}, + {0, 0, 0, 0}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + + {2, 3, 4, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 7}, + + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 0}, + + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, +}; + +static pr_dvec4_t double_globals_expect[] = { + {3, 4, 5, 12}, + {63, 63, -33, 56}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + + {32, 32, 32, 7}, + {-3, 6, -3, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + + {2, 3, 4, 0}, + {70, 70, 70, 70}, + {24, 48, 48, -6}, + {36, 102, 120, 7}, + + {52, 70, 136, 7}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, + {-1, -2, -3, 4}, + + {-1, -2, -3, 4}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, +}; + +static dstatement_t double_vector_statements[] = { + { OP(0, 0, 0, OP_CDOT_D), 0, 4, 8 }, + { OP(0, 0, 0, OP_CMUL_D), 0, 4, 12 }, + { OP(0, 0, 0, OP_VDOT_D), 16, 24, 32 }, + { OP(0, 0, 0, OP_CROSS_D), 16, 24, 40 }, + { OP(0, 0, 0, OP_QDOT_D), 48, 56, 72 }, + { OP(0, 0, 0, OP_QMUL_D), 48, 56, 80 }, + { OP(0, 0, 0, OP_QVMUL_D), 48, 64, 88 }, + { OP(0, 0, 0, OP_VQMUL_D), 64, 48, 96 }, + + { OP(0, 0, 0, OP_QMUL_D), 48, 64, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 48, 0x07e4, 120 }, + { OP(0, 0, 0, OP_QMUL_D), 104, 120, 104 }, + + { OP(0, 0, 0, OP_SWIZZLE_D), 48, 0x07e4, 128 }, + { OP(0, 0, 0, OP_QMUL_D), 128, 64, 112 }, + { OP(0, 0, 0, OP_QMUL_D), 112, 48, 112 }, + + { OP(0, 0, 0, OP_QV4MUL_D), 48, 64, 136 }, + { OP(0, 0, 0, OP_V4QMUL_D), 64, 48, 144 }, +}; + +test_t tests[] = { + { + .desc = "float vector", + .num_globals = num_globals(float_globals_init, float_globals_expect), + .num_statements = num_statements (float_vector_statements), + .statements = float_vector_statements, + .init_globals = (pr_int_t *) float_globals_init, + .expect_globals = (pr_int_t *) float_globals_expect, + }, + { + .desc = "double vector", + .num_globals = num_globals(double_globals_init,double_globals_expect), + .num_statements = num_statements (double_vector_statements), + .statements = double_vector_statements, + .init_globals = (pr_int_t *) double_globals_init, + .expect_globals = (pr_int_t *) double_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-with.c b/libs/gamecode/test/test-with.c new file mode 100644 index 000000000..f86637360 --- /dev/null +++ b/libs/gamecode/test/test-with.c @@ -0,0 +1,307 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define DB 0xdeadbeef + +static pr_ivec4_t pushregs_init[] = { + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t pushregs_expect[] = { + { 0, 0, 0, 0}, // initial base regs should all be 0 +}; + +static dstatement_t pushregs_statements[] = { + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 0, 0, 0 }, +}; + +static pr_ivec4_t popregs_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t popregs_expect[] = { + { 4, 5, 6, 7}, + { 7, 6, 5, 4}, +}; + +static dstatement_t popregs_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 9, 0, 0 }, // popregs + { OP(3, 0, 0, OP_LEA_A), 0, 0, 0 }, + { OP(2, 0, 1, OP_LEA_A), 0, 0, 0 }, + { OP(1, 0, 2, OP_LEA_A), 0, 0, 0 }, + { OP(0, 0, 3, OP_LEA_A), 0, 0, 0 }, +}; + +static pr_ivec4_t with_0_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_0_expect[] = { + { 4, 5, 6, 7}, + { 0, 1, 6, 7}, + { 4, 5, 0, 1}, + { 0, 0, 0, 0}, +}; + +static dstatement_t with_0_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 9, 0, 0 }, // popregs + { OP(0, 0, 0, OP_WITH), 0, 0, 0 }, // set reg 0 to 0 + { OP(0, 0, 0, OP_WITH), 0, 1, 1 }, // set reg 1 to 1 + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 9, 0, 0 }, // popregs + { OP(0, 0, 0, OP_WITH), 0, 0, 2 }, // set reg 2 to 0 + { OP(0, 0, 0, OP_WITH), 0, 1, 3 }, // set reg 3 to 1 + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(2, 0, 0, OP_POP_A_4), 8, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 10, 0, 0 }, // reset + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(2, 0, 0, OP_POP_A_4), 12, 0, 0 }, +}; + +static pr_ivec4_t with_1_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_1_expect[] = { + { 4, 5, 6, 7}, + { 0, 4, 6, 2}, +}; + +static dstatement_t with_1_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 4, 1 }, + { OP(0, 1, 0, OP_WITH), 1, 2, 2 }, + { OP(0, 1, 0, OP_WITH), 1, -2, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_2_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_2_expect[] = { + { 4, 5, 6, 7}, + { 0, 44, 48, 40}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static dstatement_t with_2_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, // so something is on the stack + { OP(0, 0, 0, OP_WITH), 2, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 2, 4, 2 }, + { OP(0, 1, 0, OP_WITH), 2, -4, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_3_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_3_expect[] = { + { 4, 5, 6, 7}, + { 0, 64, 68, 65596}, // edict-area relative is only +ve +}; + +static dstatement_t with_3_statements[] = { + { OP(0, 0, 0, OP_WITH), 3, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 3, 4, 2 }, + { OP(0, 1, 0, OP_WITH), 3, -4, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_4_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_4_expect[] = { + { 4, 5, 6, 7}, + { 0, 4, 5, 6}, +}; + +static dstatement_t with_4_statements[] = { + { OP(0, 0, 0, OP_WITH), 4, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 4, 1, 2 }, + { OP(0, 1, 0, OP_WITH), 4, 2, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_5_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_5_expect[] = { + { 4, 5, 6, 7}, + { 0, 2, 6, 7}, +}; + +static dstatement_t with_5_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 2, 1 }, + { OP(0, 1, 0, OP_WITH), 5, 0, 2 }, + { OP(0, 1, 0, OP_WITH), 5, 1, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_6_init[] = { + { 4, 5, 6, -4}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_6_expect[] = { + { 4, 5, 6, -4}, + { 0, 44, 48, 40}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static dstatement_t with_6_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, // so something is on the stack + { OP(0, 0, 0, OP_WITH), 2, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 6, 0, 2 }, + { OP(0, 1, 0, OP_WITH), 6, 3, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_7_init[] = { + { 4, 5, 6, -4}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_7_expect[] = { + { 4, 5, 6, -4}, + { 0, 2, 70, 60}, // edict-area relative is only +ve, but 32-bit wrap +}; + +static dstatement_t with_7_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 2, 1 }, + { OP(0, 1, 0, OP_WITH), 7, 0, 2 }, + { OP(0, 1, 0, OP_WITH), 7, 1, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +test_t tests[] = { + { + .desc = "pushregs", + .num_globals = num_globals(pushregs_init,pushregs_expect), + .num_statements = num_statements (pushregs_statements), + .statements = pushregs_statements, + .init_globals = (pr_int_t *) pushregs_init, + .expect_globals = (pr_int_t *) pushregs_expect, + .stack_size = 32, + }, + { + .desc = "popregs", + .num_globals = num_globals(popregs_init,popregs_expect), + .num_statements = num_statements (popregs_statements), + .statements = popregs_statements, + .init_globals = (pr_int_t *) popregs_init, + .expect_globals = (pr_int_t *) popregs_expect, + .stack_size = 32, + }, + { + .desc = "with 0", + .num_globals = num_globals(with_0_init,with_0_expect), + .num_statements = num_statements (with_0_statements), + .statements = with_0_statements, + .init_globals = (pr_int_t *) with_0_init, + .expect_globals = (pr_int_t *) with_0_expect, + .stack_size = 32, + }, + { + .desc = "with 1", + .num_globals = num_globals(with_1_init,with_1_expect), + .num_statements = num_statements (with_1_statements), + .statements = with_1_statements, + .init_globals = (pr_int_t *) with_1_init, + .expect_globals = (pr_int_t *) with_1_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 2", + .num_globals = num_globals(with_2_init,with_2_expect), + .num_statements = num_statements (with_2_statements), + .statements = with_2_statements, + .init_globals = (pr_int_t *) with_2_init, + .expect_globals = (pr_int_t *) with_2_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 3", + .num_globals = num_globals(with_3_init,with_3_expect), + .num_statements = num_statements (with_3_statements), + .statements = with_3_statements, + .init_globals = (pr_int_t *) with_3_init, + .expect_globals = (pr_int_t *) with_3_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 4", + .num_globals = num_globals(with_4_init,with_4_expect), + .num_statements = num_statements (with_4_statements), + .statements = with_4_statements, + .init_globals = (pr_int_t *) with_4_init, + .expect_globals = (pr_int_t *) with_4_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 5", + .num_globals = num_globals(with_5_init,with_5_expect), + .num_statements = num_statements (with_5_statements), + .statements = with_5_statements, + .init_globals = (pr_int_t *) with_5_init, + .expect_globals = (pr_int_t *) with_5_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 6", + .num_globals = num_globals(with_6_init,with_6_expect), + .num_statements = num_statements (with_6_statements), + .statements = with_6_statements, + .init_globals = (pr_int_t *) with_6_init, + .expect_globals = (pr_int_t *) with_6_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 7", + .num_globals = num_globals(with_7_init,with_7_expect), + .num_statements = num_statements (with_7_statements), + .statements = with_7_statements, + .init_globals = (pr_int_t *) with_7_init, + .expect_globals = (pr_int_t *) with_7_expect, + .stack_size = 32, + .edict_area = 64, + }, +}; + +#include "main.c" diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 2b1c6c5b4..8c0deb4e8 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -48,8 +48,8 @@ typedef struct bi_gib_builtin_s { struct bi_gib_builtin_s *next; gib_builtin_t *builtin; - progs_t *pr; - func_t func; + progs_t *pr; + pr_func_t func; } bi_gib_builtin_t; typedef struct bi_gib_resources_s { @@ -86,7 +86,7 @@ bi_gib_builtin_f (void) pr_list = PR_Zone_Malloc (builtin->pr, GIB_Argc() * sizeof (pr_type_t)); for (i = 0; i < GIB_Argc(); i++) - pr_list[i].integer_var = PR_SetTempString (builtin->pr, GIB_Argv(i)); + pr_list[i].int_var = PR_SetTempString (builtin->pr, GIB_Argv(i)); PR_RESET_PARAMS (builtin->pr); P_INT (builtin->pr, 0) = GIB_Argc(); @@ -117,7 +117,7 @@ bi_GIB_Builtin_Add (progs_t *pr) bi_gib_resources_t *res = PR_Resources_Find (pr, "GIB"); bi_gib_builtin_t *builtin; const char *name = P_GSTRING (pr, 0); - func_t func = P_FUNCTION (pr, 1); + pr_func_t func = P_FUNCTION (pr, 1); if (GIB_Builtin_Exists (name)) { R_INT (pr) = 0; @@ -175,12 +175,15 @@ bi_GIB_Handle_Get (progs_t *pr) // R_INT (pr) = 0; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"GIB_Builtin_Add", bi_GIB_Builtin_Add, -1}, - {"GIB_Return", bi_GIB_Return, -1}, - {"GIB_Handle_New", bi_GIB_Handle_New, -1}, - {"GIB_Handle_Free", bi_GIB_Handle_Free, -1}, - {"GIB_Handle_Get", bi_GIB_Handle_Get, -1}, + bi(GIB_Builtin_Add, 2, p(string), p(func)), + bi(GIB_Return, 1, p(string)), + bi(GIB_Handle_New, 0),//FIXME + bi(GIB_Handle_Free, 0),//FIXME + bi(GIB_Handle_Get, 0),//FIXME {0} }; @@ -190,11 +193,10 @@ GIB_Progs_Init (progs_t *pr) bi_gib_resources_t *res = malloc (sizeof (bi_gib_resources_t)); res->builtins = 0; - PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear); - bi_gib_builtins = Hash_NewTable (1021, bi_gib_builtin_get_key, bi_gib_builtin_free, 0, pr->hashlink_freelist); - PR_RegisterBuiltins (pr, builtins); + PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/models/trace.c b/libs/models/trace.c index 1fcecb47b..d65a06c9a 100644 --- a/libs/models/trace.c +++ b/libs/models/trace.c @@ -120,7 +120,7 @@ init_box (const trace_t *trace, clipbox_t *box, const vec3_t vel) //FIXME rotated box for (i = 0; i < 3; i++) u[i] = (vel[i] >= 0 ? 1 : -1); - VectorCompMult (u, trace->extents, p); + VectorCompMult (p, u, trace->extents); for (i = 0; i < 3; i++) { box->portals[i].planenum = i; box->portals[i].next[0] = 0; @@ -153,17 +153,17 @@ init_box (const trace_t *trace, clipbox_t *box, const vec3_t vel) box->edges[i].points[j][a] = s[k] * u[i] * box->edges[i].points[j - 1][b]; } - VectorCompMult (box->points[i].points[j - 1], trace->extents, - box->points[i].points[j - 1]); - VectorCompMult (box->edges[i].points[j - 1], trace->extents, - box->edges[i].points[j - 1]); + VectorCompMult (box->points[i].points[j - 1], + box->points[i].points[j - 1], trace->extents); + VectorCompMult (box->edges[i].points[j - 1], + box->edges[i].points[j - 1], trace->extents); VectorScale (box->edges[i].points[j - 1], 2, box->edges[i].points[j - 1]); } - VectorCompMult (box->points[i].points[3], trace->extents, - box->points[i].points[3]); - VectorCompMult (box->edges[i].points[3], trace->extents, - box->edges[i].points[3]); + VectorCompMult (box->points[i].points[3], + box->points[i].points[3], trace->extents); + VectorCompMult (box->edges[i].points[3], + box->edges[i].points[3], trace->extents); VectorScale (box->edges[i].points[3], 2, box->edges[i].points[3]); } @@ -566,8 +566,8 @@ portal_intersect (trace_t *trace, clipport_t *portal, plane_t *plane, vec3_t p1, p2, imp, dist; vec_t t1, t2, frac; - VectorCompMult (trace->extents, verts[i][0], p1); - VectorCompMult (trace->extents, verts[i][1], p2); + VectorCompMult (p1, trace->extents, verts[i][0]); + VectorCompMult (p2, trace->extents, verts[i][1]); t1 = PlaneDiff (p1, plane) + o_n; t2 = PlaneDiff (p2, plane) + o_n; // if both ends of the box edge are on the same side (or touching) the diff --git a/libs/net/net_main.c b/libs/net/net_main.c index 9d8a34e09..e534c4156 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -78,7 +78,7 @@ PollProcedure slistPollProcedure = { NULL, 0.0, Slist_Poll }; static sizebuf_t _net_message_message; static qmsg_t _net_message = { 0, 0, &_net_message_message }; qmsg_t *net_message = &_net_message; -int net_activeconnections = 0; +unsigned net_activeconnections = 0; int messagesSent = 0; int messagesReceived = 0; @@ -197,7 +197,7 @@ NET_Listen_f (void) static void MaxPlayers_f (void) { - int n; + unsigned n; if (Cmd_Argc () != 2) { Sys_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients); @@ -710,7 +710,7 @@ int NET_SendToAll (sizebuf_t *data, double blocktime) { double start; - int i; + unsigned i; int count = 0; qboolean state1[MAX_SCOREBOARD]; /* can we send */ qboolean state2[MAX_SCOREBOARD]; /* did we send */ diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 3f9cf50b1..9aa10ef31 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -652,7 +652,7 @@ _Datagram_CheckNewConnections (void) if (command == CCREQ_PLAYER_INFO) { int playerNumber; int activeNumber; - int clientNumber; + unsigned clientNumber; client_t *client; playerNumber = MSG_ReadByte (net_message); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index cc7a7d8b9..1b03f1bad 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -54,17 +54,18 @@ VISIBLE const char *pr_gametype = ""; /* BUILT-IN FUNCTIONS */ VISIBLE char * -PF_VarString (progs_t *pr, int first) +PF_VarString (progs_t *pr, int first, int argc) { char *out, *dst; const char *src; int len, i; + pr_type_t **argv = pr->pr_params; - for (len = 0, i = first; i < pr->pr_argc; i++) - len += strlen (P_GSTRING (pr, i)); + for (len = 0, i = first; i < argc; i++) + len += strlen (PR_GetString (pr, argv[i]->string_var)); dst = out = Hunk_TempAlloc (0, len + 1); - for (i = first; i < pr->pr_argc; i++) { - src = P_GSTRING (pr, i); + for (i = first; i < argc; i++) { + src = PR_GetString (pr, argv[i]->string_var); while (*src) *dst++ = *src++; } @@ -249,11 +250,11 @@ PF_fabs (progs_t *pr) entity (entity start, .(...) fld, ... match) find */ static void -PF_Find (progs_t *pr) +PF_find (progs_t *pr) { const char *s = 0, *t; // ev_string int i; // ev_vector - int e, f; + pr_uint_t e, f; etype_t type; pr_def_t *field_def; edict_t *ed; @@ -295,7 +296,7 @@ PF_Find (progs_t *pr) continue; RETURN_EDICT (pr, ed); return; - case ev_integer: + case ev_int: case ev_entity: if (P_INT (pr, 2) != E_INT (ed, f)) continue; @@ -352,7 +353,7 @@ PF_eprint (progs_t *pr) static void PF_dprint (progs_t *pr) { - Sys_Printf ("%s", PF_VarString (pr, 0)); + Sys_Printf ("%s", PF_VarString (pr, 0, 1)); } /* @@ -394,7 +395,7 @@ PF_ceil (progs_t *pr) static void PF_nextent (progs_t *pr) { - int i; + pr_uint_t i; edict_t *ent; i = P_EDICTNUM (pr, 0); @@ -420,7 +421,7 @@ PF_nextent (progs_t *pr) #endif /* - integer (float f) ftoi + int (float f) ftoi */ static void PF_ftoi (progs_t *pr) @@ -453,7 +454,7 @@ PF_ftos (progs_t *pr) } /* - float (integer i) itof + float (int i) itof */ static void PF_itof (progs_t *pr) @@ -462,7 +463,7 @@ PF_itof (progs_t *pr) } /* - string (integer i) itos + string (int i) itos */ static void PF_itos (progs_t *pr) @@ -484,7 +485,7 @@ PF_stof (progs_t *pr) } /* - integer (string s) stoi + int (string s) stoi */ static void PF_stoi (progs_t *pr) @@ -557,7 +558,7 @@ PF_charcount (progs_t *pr) string () gametype */ static void -PR_gametype (progs_t *pr) +PF_gametype (progs_t *pr) { RETURN_STRING (pr, pr_gametype); } @@ -585,46 +586,48 @@ PF_PR_FindFunction (progs_t *pr) #define QF (PR_RANGE_QF << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"break", PF_break, 6}, - {"random", PF_random, 7}, - {"normalize", PF_normalize, 9}, - {"vlen", PF_vlen, 12}, - {"vectoyaw", PF_vectoyaw, 13}, - {"find", PF_Find, 18}, - {"dprint", PF_dprint, 25}, - {"ftos", PF_ftos, 26}, - {"vtos", PF_vtos, 27}, - {"coredump", PF_coredump, 28}, - {"traceon", PF_traceon, 29}, - {"traceoff", PF_traceoff, 30}, - {"eprint", PF_eprint, 31}, - {"rint", PF_rint, 36}, - {"floor", PF_floor, 37}, - {"ceil", PF_ceil, 38}, - {"fabs", PF_fabs, 43}, - {"cvar", PF_cvar, 45}, - {"nextent", PF_nextent, 47}, - {"vectoangles", PF_vectoangles, 51}, - {"cvar_set", PF_cvar_set, 72}, - {"stof", PF_stof, 81}, + bi(break, 6, 0), + bi(random, 7, 0), + bi(normalize, 9, 1, p(vector)), + bi(vlen, 12, 1, p(vector)), + bi(vectoyaw, 13, 1, p(vector)), + bi(find, 18, -3, p(entity), p(field)), + bi(dprint, 25, -1), + bi(ftos, 26, 1, p(float)), + bi(vtos, 27, 1, p(vector)), + bi(coredump, 28, 0), + bi(traceon, 29, 0), + bi(traceoff, 30, 0), + bi(eprint, 31, 1, p(entity)), + bi(rint, 36, 1, p(float)), + bi(floor, 37, 1, p(float)), + bi(ceil, 38, 1, p(float)), + bi(fabs, 43, 1, p(float)), + bi(cvar, 45, 1, p(string)), + bi(nextent, 47, 1, p(entity)), + bi(vectoangles, 51, 1, p(vector)), + bi(cvar_set, 72, 2, p(string), p(string)), + bi(stof, 81, 1, p(string)), - {"charcount", PF_charcount, QF 101}, - {"ftoi", PF_ftoi, QF 110}, - {"itof", PF_itof, QF 111}, - {"itos", PF_itos, QF 112}, - {"stoi", PF_stoi, QF 113}, - {"stov", PF_stov, QF 114}, - {"gametype", PR_gametype, QF 115}, + bi(charcount, QF 101, 2, p(string), p(string)), + bi(ftoi, QF 110, 1, p(float)), + bi(itof, QF 111, 1, p(int)), + bi(itos, QF 112, 1, p(int)), + bi(stoi, QF 113, 1, p(string)), + bi(stov, QF 114, 1, p(string)), + bi(gametype, QF 115, 0), - {"PR_SetField", PF_PR_SetField, -1}, - {"PR_FindFunction", PF_PR_FindFunction, -1}, + bi(PR_SetField, -1, 3, p(entity), p(string), p(string)), + bi(PR_FindFunction, -1, 1, p(string)), {0} }; VISIBLE void PR_Cmds_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_cbuf.c b/libs/ruamoko/rua_cbuf.c index 5d1bbc095..7f96f4783 100644 --- a/libs/ruamoko/rua_cbuf.c +++ b/libs/ruamoko/rua_cbuf.c @@ -93,11 +93,14 @@ bi_cbuf_clear (progs_t *pr, void *data) { } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Cbuf_AddText", bi_Cbuf_AddText, -1}, - {"Cbuf_InsertText", bi_Cbuf_InsertText, -1}, - {"Cbuf_Execute", bi_Cbuf_Execute, -1}, - {"Cbuf_Execute_Sets", bi_Cbuf_Execute_Sets, -1}, + bi(Cbuf_AddText, 1, p(string)), + bi(Cbuf_InsertText, 1, p(string)), + bi(Cbuf_Execute, 0), + bi(Cbuf_Execute_Sets, 0), {0} }; @@ -106,7 +109,7 @@ RUA_Cbuf_Init (progs_t *pr, int secure) { cbuf_resources_t *res = calloc (sizeof (cbuf_resources_t), 1); PR_Resources_Register (pr, "Cbuf", res, bi_cbuf_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } VISIBLE void diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 8efcfb2a5..c325e3c3a 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -50,7 +50,7 @@ typedef struct bi_cmd_s { struct bi_cmd_s *next; char *name; progs_t *pr; - func_t func; + pr_func_t func; } bi_cmd_t; typedef struct { @@ -90,7 +90,7 @@ bi_Cmd_AddCommand (progs_t *pr) cmd_resources_t *res = PR_Resources_Find (pr, "Cmd"); bi_cmd_t *cmd = malloc (sizeof (bi_cmd_t)); char *name = strdup (P_GSTRING (pr, 0)); - func_t func = P_FUNCTION (pr, 1); + pr_func_t func = P_FUNCTION (pr, 1); if (!cmd || !name || !Cmd_AddCommand (name, bi_cmd_f, "CSQC command")) { if (name) @@ -145,11 +145,13 @@ bi_Cmd_Args (progs_t *pr) //Cmd_ExecuteString //Cmd_ForwardToServer +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Cmd_AddCommand", bi_Cmd_AddCommand, -1}, - {"Cmd_Argc", bi_Cmd_Argc, -1}, - {"Cmd_Argv", bi_Cmd_Argv, -1}, - {"Cmd_Args", bi_Cmd_Args, -1}, + bi(Cmd_AddCommand, 2, p(string), p(func)), + bi(Cmd_Argc, 0), + bi(Cmd_Argv, 1, p(int)), + bi(Cmd_Args, 1, p(int)), {0} }; @@ -159,11 +161,11 @@ RUA_Cmd_Init (progs_t *pr, int secure) cmd_resources_t *res = calloc (1, sizeof (cmd_resources_t)); res->cmds = 0; - PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); if (!bi_cmds) bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, pr->hashlink_freelist); - PR_RegisterBuiltins (pr, builtins); + PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index dbb652817..12cc3fca1 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -232,18 +232,21 @@ bi_Cvar_Toggle (progs_t *pr) Cvar_Set (var, var->int_val ? "0" : "1"); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Cvar_MakeAlias", bi_Cvar_MakeAlias, -1}, - {"Cvar_RemoveAlias", bi_Cvar_RemoveAlias, -1}, - {"Cvar_SetFloat", bi_Cvar_SetFloat, -1}, - {"Cvar_SetInteger", bi_Cvar_SetInteger, -1}, - {"Cvar_SetVector", bi_Cvar_SetVector, -1}, - {"Cvar_SetString", bi_Cvar_SetString, -1}, - {"Cvar_GetFloat", bi_Cvar_GetFloat, -1}, - {"Cvar_GetInteger", bi_Cvar_GetInteger, -1}, - {"Cvar_GetVector", bi_Cvar_GetVector, -1}, - {"Cvar_GetString", bi_Cvar_GetString, -1}, - {"Cvar_Toggle", bi_Cvar_Toggle, -1}, + bi(Cvar_MakeAlias, 2, p(string), p(string)), + bi(Cvar_RemoveAlias, 1, p(string)), + bi(Cvar_SetFloat, 2, p(string), p(float)), + bi(Cvar_SetInteger, 2, p(string), p(int)), + bi(Cvar_SetVector, 2, p(string), p(vector)), + bi(Cvar_SetString, 2, p(string), p(string)), + bi(Cvar_GetFloat, 1, p(string)), + bi(Cvar_GetInteger, 1, p(string)), + bi(Cvar_GetVector, 1, p(string)), + bi(Cvar_GetString, 1, p(string)), + bi(Cvar_Toggle, 1, p(string)), {0} }; @@ -254,6 +257,5 @@ RUA_Cvar_Init (progs_t *pr, int secure) res->aliases = 0; PR_Resources_Register (pr, "Cvar", res, bi_cvar_clear); - - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 6448e0b1c..c4939e1e7 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -49,11 +49,11 @@ typedef struct bi_hashtab_s { struct bi_hashtab_s **prev; progs_t *pr; hashtab_t *tab; - func_t gk; - func_t gh; - func_t cmp; - func_t f; - pointer_t ud; + pr_func_t gk; + pr_func_t gh; + pr_func_t cmp; + pr_func_t f; + pr_ptr_t ud; } bi_hashtab_t; typedef struct { @@ -95,48 +95,59 @@ static const char * bi_get_key (const void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->gk); - return PR_GetString (ht->pr, R_STRING (ht->pr)); + pr_string_t string = R_STRING (ht->pr); + PR_PopFrame (ht->pr); + return PR_GetString (ht->pr, string); } static uintptr_t bi_get_hash (const void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->gh); - return R_INT (ht->pr); + int hash = R_INT (ht->pr); + PR_PopFrame (ht->pr); + return hash; } static int bi_compare (const void *key1, const void *key2, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key1); P_INT (ht->pr, 1) = (intptr_t) (key2); P_INT (ht->pr, 2) = ht->ud; ht->pr->pr_argc = 3; PR_ExecuteProgram (ht->pr, ht->cmp); - return R_INT (ht->pr); + int cmp = R_INT (ht->pr); + PR_PopFrame (ht->pr); + return cmp; } static void bi_free (void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->f); + PR_PopFrame (ht->pr); } static void @@ -259,7 +270,7 @@ bi_Hash_FindList (progs_t *pr) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].integer_var = (intptr_t) *l; + pr_list[count++].int_var = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -278,7 +289,7 @@ bi_Hash_FindElementList (progs_t *pr) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].integer_var = (intptr_t) *l; + pr_list[count++].int_var = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -334,7 +345,7 @@ bi_Hash_GetList (progs_t *pr) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].integer_var = (intptr_t) *l; + pr_list[count++].int_var = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -359,24 +370,26 @@ bi_hash_clear (progs_t *pr, void *data) table_reset (res); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Hash_NewTable", bi_Hash_NewTable, -1}, - {"Hash_SetHashCompare", bi_Hash_SetHashCompare, -1}, - {"Hash_DelTable", bi_Hash_DelTable, -1}, - {"Hash_FlushTable", bi_Hash_FlushTable, -1}, - {"Hash_Add", bi_Hash_Add, -1}, - {"Hash_AddElement", bi_Hash_AddElement, -1}, - {"Hash_Find", bi_Hash_Find, -1}, - {"Hash_FindElement", bi_Hash_FindElement, -1}, - {"Hash_FindList", bi_Hash_FindList, -1}, - {"Hash_FindElementList", bi_Hash_FindElementList, -1}, - {"Hash_Del", bi_Hash_Del, -1}, - {"Hash_DelElement", bi_Hash_DelElement, -1}, - {"Hash_Free", bi_Hash_Free, -1}, - {"Hash_String", bi_Hash_String, -1}, - {"Hash_Buffer", bi_Hash_Buffer, -1}, - {"Hash_GetList", bi_Hash_GetList, -1}, - {"Hash_Stats", bi_Hash_Stats, -1}, + bi(Hash_NewTable, 4, p(int), p(func), p(func), p(ptr)), + bi(Hash_SetHashCompare, 3, p(ptr), p(func), p(func)), + bi(Hash_DelTable, 1, p(ptr)), + bi(Hash_FlushTable, 1, p(ptr)), + bi(Hash_Add, 2, p(ptr), p(ptr)), + bi(Hash_AddElement, 2, p(ptr), p(ptr)), + bi(Hash_Find, 2, p(ptr), p(string)), + bi(Hash_FindElement, 2, p(ptr), p(ptr)), + bi(Hash_FindList, 2, p(ptr), p(string)), + bi(Hash_FindElementList, 2, p(ptr), p(ptr)), + bi(Hash_Del, 2, p(ptr), p(string)), + bi(Hash_DelElement, 2, p(ptr), p(ptr)), + bi(Hash_Free, 2, p(ptr), p(ptr)), + bi(Hash_String, 1, p(string)), + bi(Hash_Buffer, 2, p(ptr), p(int)), + bi(Hash_GetList, 1, p(ptr)), + bi(Hash_Stats, 1, p(ptr)), {0} }; @@ -387,5 +400,5 @@ RUA_Hash_Init (progs_t *pr, int secure) res->tabs = 0; PR_Resources_Register (pr, "Hash", res, bi_hash_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 3cd3156a2..406ce18bc 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -46,8 +46,8 @@ typedef struct rua_in_cookie_s { size_t users; progs_t *pr; - func_t func; - pointer_t data; + pr_func_t func; + pr_ptr_t data; } rua_in_cookie_t; typedef struct input_resources_s { @@ -193,7 +193,7 @@ bi_IN_GetButtonInfo (progs_t *pr) } static rua_in_cookie_t * -make_cookie (progs_t *pr, func_t func, pointer_t data) +make_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) { input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { @@ -212,7 +212,7 @@ make_cookie (progs_t *pr, func_t func, pointer_t data) } static rua_in_cookie_t * -find_cookie (progs_t *pr, func_t func, pointer_t data) +find_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) { input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { @@ -236,8 +236,8 @@ static void rua_add_axis_listener (progs_t *pr, axis_listener_t listener) { in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = make_cookie (pr, func, data); IN_AxisAddListener (axis, listener, cookie); } @@ -246,8 +246,8 @@ static void rua_remove_axis_listener (progs_t *pr, axis_listener_t listener) { in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = find_cookie (pr, func, data); if (cookie) { IN_AxisRemoveListener (axis, listener, cookie); @@ -259,8 +259,8 @@ static void rua_add_button_listener (progs_t *pr, button_listener_t listener) { in_button_t *button = &P_STRUCT (pr, in_button_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = make_cookie (pr, func, data); IN_ButtonAddListener (button, listener, cookie); } @@ -269,8 +269,8 @@ static void rua_remove_button_listener (progs_t *pr, button_listener_t listener) { in_button_t *button = &P_STRUCT (pr, in_button_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = find_cookie (pr, func, data); if (cookie) { IN_ButtonRemoveListener (button, listener, cookie); @@ -283,6 +283,7 @@ rua_listener_func (rua_in_cookie_t *cookie, const void *input) { progs_t *pr = cookie->pr; PR_PushFrame (pr); + PR_RESET_PARAMS (pr); P_POINTER (pr, 0) = cookie->data; P_POINTER (pr, 1) = PR_SetPointer (pr, input);//FIXME check input pr->pr_argc = 2; @@ -407,56 +408,58 @@ secured (progs_t *pr) PR_RunError (pr, "Secured function called"); } -#define bi(x) {#x, secured, -1} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } +#define bi(x,np,params...) {#x, secured, -1, np, {params}} static builtin_t secure_builtins[] = { - bi(IN_CreateButton), - bi(IN_CreateAxis), - bi(IN_LoadConfig), + bi(IN_CreateButton, 2, p(string), p(string)), + bi(IN_CreateAxis, 2, p(string), p(string)), + bi(IN_LoadConfig, 1, p(ptr)), {0} }; #undef bi -#define bi(x) {#x, bi_##x, -1} +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} static builtin_t insecure_builtins[] = { - bi(IN_CreateButton), - bi(IN_CreateAxis), - bi(IN_LoadConfig), + bi(IN_CreateButton, 2, p(string), p(string)), + bi(IN_CreateAxis, 2, p(string), p(string)), + bi(IN_LoadConfig, 1, p(ptr)), {0} }; static builtin_t builtins[] = { - bi(IN_FindDeviceId), - bi(IN_GetDeviceName), - bi(IN_GetDeviceId), - bi(IN_AxisInfo), - bi(IN_ButtonInfo), - bi(IN_GetAxisName), - bi(IN_GetButtonName), - bi(IN_GetAxisNumber), - bi(IN_GetButtonNumber), - bi(IN_ProcessEvents), - bi(IN_ClearStates), - bi(IN_GetAxisInfo), - bi(IN_GetButtonInfo), + bi(IN_FindDeviceId, 1, p(string)), + bi(IN_GetDeviceName, 1, p(int)), + bi(IN_GetDeviceId, 1, p(int)), + bi(IN_AxisInfo, 0), //FIXME + bi(IN_ButtonInfo, 0), //FIXME + bi(IN_GetAxisName, 2, p(int), p(int)), + bi(IN_GetButtonName, 2, p(int), p(int)), + bi(IN_GetAxisNumber, 2, p(int), p(string)), + bi(IN_GetButtonNumber, 2, p(int), p(string)), + bi(IN_ProcessEvents, 0), + bi(IN_ClearStates, 0), + bi(IN_GetAxisInfo, 3, p(int), p(int), p(ptr)), + bi(IN_GetButtonInfo, 3, p(int), p(int), p(ptr)), {"IN_ButtonAddListener|^{tag in_button_s=}^(v^v^{tag in_button_s=})^v", - rua_IN_ButtonAddListener_func, -1}, + rua_IN_ButtonAddListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_ButtonRemoveListener|^{tag in_button_s=}^(v^v^{tag in_button_s=})^v", - rua_IN_ButtonRemoveListener_func, -1}, + rua_IN_ButtonRemoveListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisAddListener|^{tag in_axis_s=}^(v^v^{tag in_axis_s=})^v", - rua_IN_AxisAddListener_func, -1}, + rua_IN_AxisAddListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisRemoveListener|^{tag in_axis_s=}^(v^v^{tag in_axis_s=})^v", - rua_IN_AxisRemoveListener_func, -1}, + rua_IN_AxisRemoveListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_ButtonAddListener|^{tag in_button_s=}(@@:.)@", - rua_IN_ButtonAddListener_method, -1}, + rua_IN_ButtonAddListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_ButtonRemoveListener|^{tag in_button_s=}(@@:.)@", - rua_IN_ButtonRemoveListener_method, -1}, + rua_IN_ButtonRemoveListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisAddListener|^{tag in_axis_s=}(@@:.)@", - rua_IN_AxisAddListener_method, -1}, + rua_IN_AxisAddListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisRemoveListener|^{tag in_axis_s=}(@@:.)@", - rua_IN_AxisRemoveListener_method, -1}, + rua_IN_AxisRemoveListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, - bi(IMT_CreateContext), - bi(IMT_GetContext), - bi(IMT_SetContext), + bi(IMT_CreateContext, 1, p(string)), + bi(IMT_GetContext, 0), + bi(IMT_SetContext, 1, p(int)), {0} }; @@ -495,17 +498,17 @@ void RUA_Input_Init (progs_t *pr, int secure) { input_resources_t *res = calloc (sizeof (input_resources_t), 1); - PR_Resources_Register (pr, "input", res, bi_input_clear); res->cookie_super = new_memsuper (); res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, &res->hash_links); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); + PR_Resources_Register (pr, "input", res, bi_input_clear); if (secure & 2) { - PR_RegisterBuiltins (pr, secure_builtins); + PR_RegisterBuiltins (pr, secure_builtins, res); } else { - PR_RegisterBuiltins (pr, insecure_builtins); + PR_RegisterBuiltins (pr, insecure_builtins, res); } - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_keys.c b/libs/ruamoko/rua_keys.c index 11747304e..d6e9acaa8 100644 --- a/libs/ruamoko/rua_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -165,18 +165,21 @@ bi_Key_StringToKeynum (progs_t *pr) R_INT (pr) = Key_StringToKeynum (keyname); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Key_keydown", bi_Key_keydown, -1}, - {"Key_SetBinding", bi_Key_SetBinding, -1}, - {"Key_LookupBinding", bi_Key_LookupBinding, -1}, - {"Key_CountBinding", bi_Key_CountBinding, -1}, - {"Key_KeynumToString", bi_Key_KeynumToString, -1}, - {"Key_StringToKeynum", bi_Key_StringToKeynum, -1}, + bi(Key_keydown, 1, p(int)), + bi(Key_SetBinding, 3, p(string), p(int), p(string)), + bi(Key_LookupBinding, 3, p(string), p(int), p(string)), + bi(Key_CountBinding, 2, p(string), p(string)), + bi(Key_KeynumToString, 1, p(int)), + bi(Key_StringToKeynum, 1, p(string)), {0} }; void RUA_Key_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_math.c b/libs/ruamoko/rua_math.c index f6926fa65..2d7e09398 100644 --- a/libs/ruamoko/rua_math.c +++ b/libs/ruamoko/rua_math.c @@ -321,57 +321,59 @@ bi_atanh (progs_t *pr) R_DOUBLE (pr) = log ((1 + y) / (1 - y)) / 2; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"sin|f", bi_sinf, -1}, - {"cos|f", bi_cosf, -1}, - {"tan|f", bi_tanf, -1}, - {"asin|f", bi_asinf, -1}, - {"acos|f", bi_acosf, -1}, - {"atan|f", bi_atanf, -1}, - {"atan2|ff",bi_atan2f, -1}, - {"exp|f", bi_expf, -1}, - {"log|f", bi_logf, -1}, - {"log2|f", bi_log2f, -1}, - {"log10|f", bi_log10f, -1}, - {"pow|ff", bi_powf, -1}, - {"sqrt|f", bi_sqrtf, -1}, - {"cbrt|f", bi_cbrtf, -1}, - {"hypot|ff",bi_hypotf, -1}, - {"sinh|f", bi_sinhf, -1}, - {"cosh|f", bi_coshf, -1}, - {"tanh|f", bi_tanhf, -1}, - {"asinh|f", bi_asinhf, -1}, - {"acosh|f", bi_acoshf, -1}, - {"atanh|f", bi_atanhf, -1}, - {"floor|d", bi_floor, -1}, // float version in pr_cmds - {"ceil|d", bi_ceil, -1}, // float version in pr_cmds - {"fabs|d", bi_fabs, -1}, // float version in pr_cmds - {"sin|d", bi_sin, -1}, - {"cos|d", bi_cos, -1}, - {"tan|d", bi_tan, -1}, - {"asin|d", bi_asin, -1}, - {"acos|d", bi_acos, -1}, - {"atan|d", bi_atan, -1}, - {"atan2|dd",bi_atan2, -1}, - {"exp|d", bi_exp, -1}, - {"log|d", bi_log, -1}, - {"log2|d", bi_log2, -1}, - {"log10|d", bi_log10, -1}, - {"pow|dd", bi_pow, -1}, - {"sqrt|d", bi_sqrt, -1}, - {"cbrt|d", bi_cbrt, -1}, - {"hypot|dd",bi_hypot, -1}, - {"sinh|d", bi_sinh, -1}, - {"cosh|d", bi_cosh, -1}, - {"tanh|d", bi_tanh, -1}, - {"asinh|d", bi_asinh, -1}, - {"acosh|d", bi_acosh, -1}, - {"atanh|d", bi_atanh, -1}, + {"sin|f", bi_sinf, -1, 1, {p(float)}}, + {"cos|f", bi_cosf, -1, 1, {p(float)}}, + {"tan|f", bi_tanf, -1, 1, {p(float)}}, + {"asin|f", bi_asinf, -1, 1, {p(float)}}, + {"acos|f", bi_acosf, -1, 1, {p(float)}}, + {"atan|f", bi_atanf, -1, 1, {p(float)}}, + {"atan2|ff",bi_atan2f, -1, 2, {p(float), p(float)}}, + {"exp|f", bi_expf, -1, 1, {p(float)}}, + {"log|f", bi_logf, -1, 1, {p(float)}}, + {"log2|f", bi_log2f, -1, 1, {p(float)}}, + {"log10|f", bi_log10f, -1, 1, {p(float)}}, + {"pow|ff", bi_powf, -1, 2, {p(float), p(float)}}, + {"sqrt|f", bi_sqrtf, -1, 1, {p(float)}}, + {"cbrt|f", bi_cbrtf, -1, 1, {p(float)}}, + {"hypot|ff",bi_hypotf, -1, 2, {p(float), p(float)}}, + {"sinh|f", bi_sinhf, -1, 1, {p(float)}}, + {"cosh|f", bi_coshf, -1, 1, {p(float)}}, + {"tanh|f", bi_tanhf, -1, 1, {p(float)}}, + {"asinh|f", bi_asinhf, -1, 1, {p(float)}}, + {"acosh|f", bi_acoshf, -1, 1, {p(float)}}, + {"atanh|f", bi_atanhf, -1, 1, {p(float)}}, + {"floor|d", bi_floor, -1, 1, {p(double)}}, // float version in pr_cmds + {"ceil|d", bi_ceil, -1, 1, {p(double)}}, // float version in pr_cmds + {"fabs|d", bi_fabs, -1, 1, {p(double)}}, // float version in pr_cmds + {"sin|d", bi_sin, -1, 1, {p(double)}}, + {"cos|d", bi_cos, -1, 1, {p(double)}}, + {"tan|d", bi_tan, -1, 1, {p(double)}}, + {"asin|d", bi_asin, -1, 1, {p(double)}}, + {"acos|d", bi_acos, -1, 1, {p(double)}}, + {"atan|d", bi_atan, -1, 1, {p(double)}}, + {"atan2|dd",bi_atan2, -1, 2, {p(double), p(double)}}, + {"exp|d", bi_exp, -1, 1, {p(double)}}, + {"log|d", bi_log, -1, 1, {p(double)}}, + {"log2|d", bi_log2, -1, 1, {p(double)}}, + {"log10|d", bi_log10, -1, 1, {p(double)}}, + {"pow|dd", bi_pow, -1, 2, {p(double), p(double)}}, + {"sqrt|d", bi_sqrt, -1, 1, {p(double)}}, + {"cbrt|d", bi_cbrt, -1, 1, {p(double)}}, + {"hypot|dd",bi_hypot, -1, 2, {p(double), p(double)}}, + {"sinh|d", bi_sinh, -1, 1, {p(double)}}, + {"cosh|d", bi_cosh, -1, 1, {p(double)}}, + {"tanh|d", bi_tanh, -1, 1, {p(double)}}, + {"asinh|d", bi_asinh, -1, 1, {p(double)}}, + {"acosh|d", bi_acosh, -1, 1, {p(double)}}, + {"atanh|d", bi_atanh, -1, 1, {p(double)}}, {0} }; void RUA_Math_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index 6c503914f..c55c495c1 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -145,14 +145,15 @@ bi_mtwist_clear (progs_t *pr, void *data) state_reset (res); } -#define bi(x) {#x, bi_##x, -1} +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - bi(mtwist_new), - bi(mtwist_delete), - bi(mtwist_seed), - bi(mtwist_rand), - bi(mtwist_rand_0_1), - bi(mtwist_rand_m1_1), + bi(mtwist_new, 1, p(int)), + bi(mtwist_delete, 1, p(ptr)), + bi(mtwist_seed, 2, p(ptr), p(int)), + bi(mtwist_rand, 1, p(ptr)), + bi(mtwist_rand_0_1, 1, p(ptr)), + bi(mtwist_rand_m1_1, 1, p(ptr)), {0} }; @@ -162,5 +163,5 @@ RUA_Mersenne_Init (progs_t *pr, int secure) mtwist_resources_t *res = calloc (1, sizeof (mtwist_resources_t)); PR_Resources_Register (pr, "Mersenne Twister", res, bi_mtwist_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index e16525053..c2420ed99 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -396,46 +396,49 @@ bi_MsgBuf_ReadUTF8 (progs_t *pr) R_INT (pr) = MSG_ReadUTF8 (&mb->msg); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"MsgBuf_New", bi_MsgBuf_New, -1}, - {"MsgBuf_Delete", bi_MsgBuf_Delete, -1}, - {"MsgBuf_FromFile", bi_MsgBuf_FromFile, -1}, - {"MsgBuf_MaxSize", bi_MsgBuf_MaxSize, -1}, - {"MsgBuf_CurSize", bi_MsgBuf_CurSize, -1}, - {"MsgBuf_ReadCount", bi_MsgBuf_ReadCount, -1}, - {"MsgBuf_DataPtr", bi_MsgBuf_DataPtr, -1}, + bi(MsgBuf_New, 1, p(int)), + bi(MsgBuf_Delete, 1, p(ptr)), + bi(MsgBuf_FromFile, 2, p(ptr), p(ptr)), + bi(MsgBuf_MaxSize, 1, p(ptr)), + bi(MsgBuf_CurSize, 1, p(ptr)), + bi(MsgBuf_ReadCount, 1, p(ptr)), + bi(MsgBuf_DataPtr, 1, p(ptr)), - {"MsgBuf_Clear", bi_MsgBuf_Clear, -1}, - {"MsgBuf_WriteByte", bi_MsgBuf_WriteByte, -1}, - {"MsgBuf_WriteShort", bi_MsgBuf_WriteShort, -1}, - {"MsgBuf_WriteLong", bi_MsgBuf_WriteLong, -1}, - {"MsgBuf_WriteFloat", bi_MsgBuf_WriteFloat, -1}, - {"MsgBuf_WriteString", bi_MsgBuf_WriteString, -1}, -// {"MsgBuf_WriteBytes", bi_MsgBuf_WriteBytes, -1}, - {"MsgBuf_WriteCoord", bi_MsgBuf_WriteCoord, -1}, - {"MsgBuf_WriteCoordV", bi_MsgBuf_WriteCoordV, -1}, - {"MsgBuf_WriteCoordAngleV", bi_MsgBuf_WriteCoordAngleV, -1}, - {"MsgBuf_WriteAngle", bi_MsgBuf_WriteAngle, -1}, - {"MsgBuf_WriteAngleV", bi_MsgBuf_WriteAngleV, -1}, - {"MsgBuf_WriteAngle16", bi_MsgBuf_WriteAngle16, -1}, - {"MsgBuf_WriteAngle16V", bi_MsgBuf_WriteAngle16V, -1}, - {"MsgBuf_WriteUTF8", bi_MsgBuf_WriteUTF8, -1}, + bi(MsgBuf_Clear, 1, p(ptr)), + bi(MsgBuf_WriteByte, 2, p(ptr), p(int)), + bi(MsgBuf_WriteShort, 2, p(ptr), p(int)), + bi(MsgBuf_WriteLong, 2, p(ptr), p(int)), + bi(MsgBuf_WriteFloat, 2, p(ptr), p(float)), + bi(MsgBuf_WriteString, 2, p(ptr), p(string)), +// bi(MsgBuf_WriteBytes, _, _), + bi(MsgBuf_WriteCoord, 2, p(ptr), p(float)), + bi(MsgBuf_WriteCoordV, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteCoordAngleV, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteAngle, 2, p(ptr), p(float)), + bi(MsgBuf_WriteAngleV, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteAngle16, 2, p(ptr), p(float)), + bi(MsgBuf_WriteAngle16V, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteUTF8, 2, p(ptr), p(int)), - {"MsgBuf_BeginReading", bi_MsgBuf_BeginReading, -1}, - {"MsgBuf_ReadByte", bi_MsgBuf_ReadByte, -1}, - {"MsgBuf_ReadShort", bi_MsgBuf_ReadShort, -1}, - {"MsgBuf_ReadLong", bi_MsgBuf_ReadLong, -1}, - {"MsgBuf_ReadFloat", bi_MsgBuf_ReadFloat, -1}, - {"MsgBuf_ReadString", bi_MsgBuf_ReadString, -1}, -// {"MsgBuf_ReadBytes", bi_MsgBuf_ReadBytes, -1}, - {"MsgBuf_ReadCoord", bi_MsgBuf_ReadCoord, -1}, - {"MsgBuf_ReadCoordV", bi_MsgBuf_ReadCoordV, -1}, - {"MsgBuf_ReadCoordAngleV", bi_MsgBuf_ReadCoordAngleV, -1}, - {"MsgBuf_ReadAngle", bi_MsgBuf_ReadAngle, -1}, - {"MsgBuf_ReadAngleV", bi_MsgBuf_ReadAngleV, -1}, - {"MsgBuf_ReadAngle16", bi_MsgBuf_ReadAngle16, -1}, - {"MsgBuf_ReadAngle16V", bi_MsgBuf_ReadAngle16V, -1}, - {"MsgBuf_ReadUTF8", bi_MsgBuf_ReadUTF8, -1}, + bi(MsgBuf_BeginReading, 1, p(ptr)), + bi(MsgBuf_ReadByte, 1, p(ptr)), + bi(MsgBuf_ReadShort, 1, p(ptr)), + bi(MsgBuf_ReadLong, 1, p(ptr)), + bi(MsgBuf_ReadFloat, 1, p(ptr)), + bi(MsgBuf_ReadString, 1, p(ptr)), +// bi(MsgBuf_ReadBytes, _, _), + bi(MsgBuf_ReadCoord, 1, p(ptr)), + bi(MsgBuf_ReadCoordV, 1, p(ptr)), + bi(MsgBuf_ReadCoordAngleV, 2, p(ptr), p(ptr)), + bi(MsgBuf_ReadAngle, 1, p(ptr)), + bi(MsgBuf_ReadAngleV, 1, p(ptr)), + bi(MsgBuf_ReadAngle16, 1, p(ptr)), + bi(MsgBuf_ReadAngle16V, 1, p(ptr)), + bi(MsgBuf_ReadUTF8, 1, p(ptr)), {0} }; @@ -445,5 +448,5 @@ RUA_MsgBuf_Init (progs_t *pr, int secure) msgbuf_resources_t *res = calloc (sizeof (msgbuf_resources_t), 1); PR_Resources_Register (pr, "MsgBuf", res, bi_msgbuf_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 4bed1de5d..8f2601066 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -48,16 +48,49 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" -#include "QF/pr_obj.h" #include "QF/progs.h" #include "QF/ruamoko.h" #include "QF/sys.h" +#include "QF/progs/pr_obj.h" +#include "QF/progs/pr_type.h" + #include "compat.h" #include "rua_internal.h" #define always_inline inline __attribute__((__always_inline__)) +/* Macros to help with setting up to call a function, and cleaning up + * afterwards. The problem is that PR_CallFunction saves the CURRENT stack + * pointer, which has been adjusted by PR_SetupParams in order to push + * the function arguments. + * + * RUA_CALL_BEGIN and RUA_CALL_END must be used in pairs and this is enforced + * by the unbalanced {}s in the macros. + */ +#define RUA_CALL_BEGIN(pr, argc) \ + { \ + pr_ptr_t saved_stack = 0; \ + int call_depth = (pr)->pr_depth; \ + if ((pr)->globals.stack) { \ + saved_stack = *(pr)->globals.stack; \ + } \ + PR_SetupParams (pr, argc, 1); \ + (pr)->pr_argc = argc; + +#define RUA_CALL_END(pr, imp) \ + if (PR_CallFunction ((pr), (imp), (pr)->pr_return)) { \ + /* the call is to a progs function so a frame was pushed, */ \ + /* ensure the stack pointer is restored on return */ \ + /* if there's no stack, then the following is effectively a */ \ + /* noop */ \ + (pr)->pr_stack[call_depth].stack_ptr = saved_stack; \ + } else if ((pr)->globals.stack) { \ + /* the call was to a builtin, restore the stack */ \ + *(pr)->globals.stack = saved_stack; \ + } \ + } + typedef struct obj_list_s { struct obj_list_s *next; void *data; @@ -67,7 +100,7 @@ typedef struct dtable_s { struct dtable_s *next; struct dtable_s **prev; size_t size; - func_t *imp; + pr_func_t *imp; } dtable_t; typedef struct probj_resources_s { @@ -75,10 +108,11 @@ typedef struct probj_resources_s { unsigned selector_index; unsigned selector_index_max; obj_list **selector_sels; - string_t *selector_names; + pr_string_t *selector_names; + pr_int_t *selector_argc; PR_RESMAP (dtable_t) dtables; dtable_t *dtable_list; - func_t obj_forward; + pr_func_t obj_forward; pr_sel_t *forward_selector; dstring_t *msg; hashtab_t *selector_hash; @@ -422,7 +456,7 @@ object_is_instance (probj_t *probj, pr_id_t *object) return 0; } -static string_t +static pr_string_t object_get_class_name (probj_t *probj, pr_id_t *object) { progs_t *pr = probj->pr; @@ -445,7 +479,7 @@ object_get_class_name (probj_t *probj, pr_id_t *object) //==================================================================== static void -finish_class (probj_t *probj, pr_class_t *class, pointer_t object_ptr) +finish_class (probj_t *probj, pr_class_t *class, pr_ptr_t object_ptr) { progs_t *pr = probj->pr; pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); @@ -462,7 +496,7 @@ finish_class (probj_t *probj, pr_class_t *class, pointer_t object_ptr) meta->super_class = val->class_pointer; class->super_class = PR_SetPointer (pr, val); } else { - pointer_t *ml = &meta->methods; + pr_ptr_t *ml = &meta->methods; while (*ml) ml = &G_STRUCT (pr, pr_method_list_t, *ml).method_next; *ml = class->methods; @@ -484,10 +518,13 @@ add_sel_name (probj_t *probj, const char *name) probj->selector_sels = realloc (probj->selector_sels, size * sizeof (obj_list *)); probj->selector_names = realloc (probj->selector_names, - size * sizeof (string_t)); + size * sizeof (pr_string_t)); + probj->selector_argc = realloc (probj->selector_argc, + size * sizeof (pr_int_t)); for (i = probj->selector_index_max; i < size; i++) { probj->selector_sels[i] = 0; probj->selector_names[i] = 0; + probj->selector_argc[i] = 0; } probj->selector_index_max = size; } @@ -541,6 +578,15 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, l->next = probj->selector_sels[index]; probj->selector_sels[index] = l; + if (sel->sel_types && pr->type_encodings) { + const char *enc = PR_GetString (pr, sel->sel_types); + __auto_type type = (qfot_type_t *) Hash_Find (pr->type_hash, enc); + if (type->meta != ty_basic || type->type != ev_func) { + PR_RunError (pr, "selector type encoing is not a function"); + } + probj->selector_argc[index] = type->func.num_params; + } + if (is_new) Hash_Add (probj->selector_hash, (void *) index); done: @@ -804,7 +850,7 @@ obj_find_message (probj_t *probj, pr_class_t *class, pr_sel_t *selector) pr_sel_t *sel; int i; int dev = developer->int_val; - string_t *names; + pr_string_t *names; if (dev & SYS_rua_msg) { names = probj->selector_names; @@ -935,7 +981,7 @@ obj_install_dispatch_table_for_class (probj_t *probj, pr_class_t *class) dtable = dtable_new (probj); class->dtable = dtable_index (probj, dtable); dtable->size = probj->selector_index + 1; - dtable->imp = calloc (dtable->size, sizeof (func_t)); + dtable->imp = calloc (dtable->size, sizeof (pr_func_t)); if (super) { dtable_t *super_dtable = get_dtable (probj, __FUNCTION__, super->dtable); @@ -956,10 +1002,10 @@ obj_check_dtable_installed (probj_t *probj, pr_class_t *class) return get_dtable (probj, __FUNCTION__, class->dtable); } -static func_t +static pr_func_t get_imp (probj_t *probj, pr_class_t *class, pr_sel_t *sel) { - func_t imp = 0; + pr_func_t imp = 0; if (class->dtable) { dtable_t *dtable = get_dtable (probj, __FUNCTION__, class->dtable); @@ -984,7 +1030,7 @@ obj_reponds_to (probj_t *probj, pr_id_t *obj, pr_sel_t *sel) progs_t *pr = probj->pr; pr_class_t *class; dtable_t *dtable; - func_t imp = 0; + pr_func_t imp = 0; class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); dtable = obj_check_dtable_installed (probj, class); @@ -995,7 +1041,7 @@ obj_reponds_to (probj_t *probj, pr_id_t *obj, pr_sel_t *sel) return imp != 0; } -static func_t +static pr_func_t obj_msg_lookup (probj_t *probj, pr_id_t *receiver, pr_sel_t *op) { progs_t *pr = probj->pr; @@ -1014,7 +1060,7 @@ obj_msg_lookup (probj_t *probj, pr_id_t *receiver, pr_sel_t *op) return get_imp (probj, class, op); } -static func_t +static pr_func_t obj_msg_lookup_super (probj_t *probj, pr_super_t *super, pr_sel_t *op) { progs_t *pr = probj->pr; @@ -1040,7 +1086,7 @@ obj_verror (probj_t *probj, pr_id_t *object, int code, const char *fmt, int coun } static void -dump_ivars (probj_t *probj, pointer_t _ivars) +dump_ivars (probj_t *probj, pr_ptr_t _ivars) { progs_t *pr = probj->pr; pr_ivar_list_t *ivars; @@ -1062,8 +1108,8 @@ obj_init_statics (probj_t *probj) { progs_t *pr = probj->pr; obj_list **cell = &probj->uninitialized_statics; - pointer_t *ptr; - pointer_t *inst; + pr_ptr_t *ptr; + pr_ptr_t *inst; Sys_MaskPrintf (SYS_rua_obj, "Initializing statics\n"); while (*cell) { @@ -1109,7 +1155,7 @@ rua___obj_exec_class (progs_t *pr) pr_module_t *module = &P_STRUCT (pr, pr_module_t, 0); pr_symtab_t *symtab; pr_sel_t *sel; - pointer_t *ptr; + pr_ptr_t *ptr; int i; obj_list **cell; @@ -1215,7 +1261,7 @@ rua___obj_exec_class (progs_t *pr) if (*ptr) { Sys_MaskPrintf (SYS_rua_obj, "Static instances lists: %x\n", *ptr); probj->uninitialized_statics - = list_cons (&G_STRUCT (pr, pointer_t, *ptr), + = list_cons (&G_STRUCT (pr, pr_ptr_t, *ptr), probj->uninitialized_statics); } if (probj->uninitialized_statics) { @@ -1259,7 +1305,7 @@ rua___obj_forward (progs_t *pr) pr_sel_t *fwd_sel = probj->forward_selector; pr_sel_t *err_sel; pr_class_t *class =&G_STRUCT (pr, pr_class_t, obj->class_pointer); - func_t imp; + pr_func_t imp; if (!fwd_sel) { //FIXME sel_register_typed_name is really not the way to go about @@ -1270,39 +1316,53 @@ rua___obj_forward (progs_t *pr) if (obj_reponds_to (probj, obj, fwd_sel)) { imp = get_imp (probj, class, fwd_sel); // forward:(SEL) sel :(@va_list) args - // args is full param list - //FIXME oh for a stack - size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); - size_t size = pr->pr_argc * parm_size; - string_t args_block = PR_AllocTempBlock (pr, size); + // args is full param list as a va_list + pr_string_t args_block = 0; + int argc; + pr_type_t *argv; + if (pr->globals.stack) { + argv = pr->pr_params[0]; + argc = probj->selector_argc[sel->sel_id]; + if (argc < 0) { + // -ve values indicate varargs functions and is the ones + // complement of the number of real parameters before the + // ellipsis. However, Ruamoko ISA progs pass va_list through + // ... so in the end, a -ve value indicates the total number + // of arguments (including va_list) passed to the function. + argc = -argc; + } + } else { + size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); + size_t size = pr->pr_argc * parm_size; + args_block = PR_AllocTempBlock (pr, size); - int argc = pr->pr_argc; - __auto_type argv = (pr_type_t *) PR_GetString (pr, args_block); - // can't memcpy all params because 0 and 1 could be anywhere - memcpy (argv + 0, &P_INT (pr, 0), 4 * sizeof (pr_type_t)); - memcpy (argv + 4, &P_INT (pr, 1), 4 * sizeof (pr_type_t)); - memcpy (argv + 8, &P_INT (pr, 2), (argc - 2) * parm_size); + argc = pr->pr_argc; + argv = (pr_type_t *) PR_GetString (pr, args_block); + // can't memcpy all params because 0 and 1 could be anywhere + memcpy (argv + 0, &P_INT (pr, 0), 4 * sizeof (pr_type_t)); + memcpy (argv + 4, &P_INT (pr, 1), 4 * sizeof (pr_type_t)); + memcpy (argv + 8, &P_INT (pr, 2), (argc - 2) * parm_size); + } - PR_RESET_PARAMS (pr); + RUA_CALL_BEGIN (pr, 4); P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, fwd_sel); P_POINTER (pr, 2) = PR_SetPointer (pr, sel); P_PACKED (pr, pr_va_list_t, 3).count = argc; P_PACKED (pr, pr_va_list_t, 3).list = PR_SetPointer (pr, argv); - PR_PushTempString (pr, args_block); - PR_CallFunction (pr, imp); + if (args_block) { + PR_PushTempString (pr, args_block); + } + RUA_CALL_END (pr, imp); return; } - //FIXME ditto err_sel = sel_register_typed_name (probj, "doesNotRecognize:", "", 0); if (obj_reponds_to (probj, obj, err_sel)) { - imp = get_imp (probj, class, err_sel); - PR_RESET_PARAMS (pr); + RUA_CALL_BEGIN (pr, 3) P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetPointer (pr, sel); - pr->pr_argc = 3; - PR_CallFunction (pr, imp); + RUA_CALL_END (pr, get_imp (probj, class, err_sel)) return; } @@ -1311,16 +1371,13 @@ rua___obj_forward (progs_t *pr) PR_GetString (pr, class->name), PR_GetString (pr, probj->selector_names[sel->sel_id])); - //FIXME ditto err_sel = sel_register_typed_name (probj, "error:", "", 0); if (obj_reponds_to (probj, obj, err_sel)) { - imp = get_imp (probj, class, err_sel); - PR_RESET_PARAMS (pr); + RUA_CALL_BEGIN (pr, 3) P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetTempString (pr, probj->msg->str); - pr->pr_argc = 3; - PR_CallFunction (pr, imp); + RUA_CALL_END (pr, get_imp (probj, class, err_sel)) return; } @@ -1371,7 +1428,7 @@ static void rua_obj_set_error_handler (progs_t *pr) { //probj_t *probj = pr->pr_objective_resources; - //func_t func = P_INT (pr, 0); + //pr_func_t func = P_INT (pr, 0); //arglist //XXX PR_RunError (pr, "%s, not implemented", __FUNCTION__); @@ -1401,17 +1458,17 @@ static void rua_obj_msg_sendv (progs_t *pr) { probj_t *probj = pr->pr_objective_resources; - pointer_t obj = P_POINTER (pr, 0); + pr_ptr_t obj = P_POINTER (pr, 0); pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); - pointer_t sel = P_POINTER (pr, 1); + pr_ptr_t sel = P_POINTER (pr, 1); pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); - func_t imp = obj_msg_lookup (probj, receiver, op); + pr_func_t imp = obj_msg_lookup (probj, receiver, op); __auto_type args = &P_PACKED (pr, pr_va_list_t, 2); int count = args->count; pr_type_t *params = G_GPOINTER (pr, args->list); - if (count < 2 || count > MAX_PARMS) { + if (count < 2 || count > PR_MAX_PARAMS) { PR_RunError (pr, "bad args count in obj_msg_sendv: %d", count); } if (pr_boundscheck->int_val) { @@ -1424,40 +1481,40 @@ rua_obj_msg_sendv (progs_t *pr) PR_GetString (pr, probj->selector_names[op->sel_id])); } - pr->pr_argc = count; + RUA_CALL_BEGIN (pr, count) // skip over the first two parameters because receiver and op will // replace them count -= 2; params += 2 * pr->pr_param_size; - PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = obj; P_POINTER (pr, 1) = sel; if (count) { memcpy (&P_INT (pr, 2), params, count * sizeof (pr_type_t) * pr->pr_param_size); } - PR_CallFunction (pr, imp); + RUA_CALL_END (pr, imp) } static void rua_obj_increment_retaincount (progs_t *pr) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = ++(*--obj).integer_var; + R_INT (pr) = ++(*--obj).int_var; } static void rua_obj_decrement_retaincount (progs_t *pr) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = --(*--obj).integer_var; + R_INT (pr) = --(*--obj).int_var; } static void rua_obj_get_retaincount (progs_t *pr) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = (*--obj).integer_var; + R_INT (pr) = (*--obj).int_var; } static void @@ -1529,12 +1586,15 @@ rua_obj_msgSend (progs_t *pr) probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0); pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1); - func_t imp; + pr_func_t imp; if (!self) { R_INT (pr) = P_INT (pr, 0); return; } + if (P_UINT (pr, 0) >= pr->globals_size) { + PR_RunError (pr, "invalid self: %x", P_UINT (pr, 0)); + } if (!_cmd) PR_RunError (pr, "null selector"); imp = obj_msg_lookup (probj, self, _cmd); @@ -1543,7 +1603,7 @@ rua_obj_msgSend (progs_t *pr) PR_GetString (pr, object_get_class_name (probj, self)), PR_GetString (pr, probj->selector_names[_cmd->sel_id])); - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); } static void @@ -1552,7 +1612,7 @@ rua_obj_msgSend_super (progs_t *pr) probj_t *probj = pr->pr_objective_resources; pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0); pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1); - func_t imp; + pr_func_t imp; imp = obj_msg_lookup_super (probj, super, _cmd); if (!imp) { @@ -1561,9 +1621,11 @@ rua_obj_msgSend_super (progs_t *pr) PR_GetString (pr, object_get_class_name (probj, self)), PR_GetString (pr, probj->selector_names[_cmd->sel_id])); } - pr->pr_params[0] = pr->pr_real_params[0]; + if (pr->progs->version < PROG_VERSION) { + pr->pr_params[0] = pr->pr_real_params[0]; + } P_POINTER (pr, 0) = super->self; - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); } static void @@ -1678,12 +1740,12 @@ rua_class_pose_as (progs_t *pr) { pr_class_t *impostor = &P_STRUCT (pr, pr_class_t, 0); pr_class_t *superclass = &P_STRUCT (pr, pr_class_t, 1); - pointer_t *subclass; + pr_ptr_t *subclass; subclass = &superclass->subclass_list; while (*subclass) { pr_class_t *sub = &P_STRUCT (pr, pr_class_t, *subclass); - pointer_t nextSub = sub->sibling_class; + pr_ptr_t nextSub = sub->sibling_class; if (sub != impostor) { sub->sibling_class = impostor->subclass_list; sub->super_class = P_POINTER (pr, 0); // impostor @@ -2077,73 +2139,76 @@ rua_PR_FindGlobal (progs_t *pr) //==================================================================== +#define bi(x,np,params...) {#x, rua_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t obj_methods [] = { - {"__obj_exec_class", rua___obj_exec_class, -1}, - {"__obj_forward", rua___obj_forward, -1}, - {"__obj_responds_to", rua___obj_responds_to, -1}, + bi(__obj_exec_class, 1, p(ptr)), + bi(__obj_forward, -3, p(ptr), p(ptr)), + bi(__obj_responds_to, 2, p(ptr), p(ptr)), - {"obj_error", rua_obj_error, -1}, - {"obj_verror", rua_obj_verror, -1}, - {"obj_set_error_handler", rua_obj_set_error_handler, -1}, - {"obj_msg_lookup", rua_obj_msg_lookup, -1}, - {"obj_msg_lookup_super", rua_obj_msg_lookup_super, -1}, - {"obj_msg_sendv", rua_obj_msg_sendv, -1}, - {"obj_increment_retaincount", rua_obj_increment_retaincount, -1}, - {"obj_decrement_retaincount", rua_obj_decrement_retaincount, -1}, - {"obj_get_retaincount", rua_obj_get_retaincount, -1}, - {"obj_malloc", rua_obj_malloc, -1}, - {"obj_atomic_malloc", rua_obj_atomic_malloc, -1}, - {"obj_valloc", rua_obj_valloc, -1}, - {"obj_realloc", rua_obj_realloc, -1}, - {"obj_calloc", rua_obj_calloc, -1}, - {"obj_free", rua_obj_free, -1}, - {"obj_get_uninstalled_dtable", rua_obj_get_uninstalled_dtable, -1}, - {"obj_msgSend", rua_obj_msgSend, -1}, - {"obj_msgSend_super", rua_obj_msgSend_super, -1}, + bi(obj_error, -4, p(ptr), p(int), p(string)), + bi(obj_verror, 4, p(ptr), p(int), p(string), P(1, 2)), + bi(obj_set_error_handler, 1, p(func)), + bi(obj_msg_lookup, 2, p(ptr), p(ptr)), + bi(obj_msg_lookup_super, 2, p(ptr), p(ptr)), + bi(obj_msg_sendv, 3, p(ptr), p(ptr), P(1, 2)), + bi(obj_increment_retaincount, 1, p(ptr)), + bi(obj_decrement_retaincount, 1, p(ptr)), + bi(obj_get_retaincount, 1, p(ptr)), + bi(obj_malloc, 1, p(int)), + bi(obj_atomic_malloc, 1, p(int)), + bi(obj_valloc, 1, p(int)), + bi(obj_realloc, 2, p(ptr), p(int)), + bi(obj_calloc, 2, p(int), p(int)), + bi(obj_free, 1, p(ptr)), + bi(obj_get_uninstalled_dtable, 0), + bi(obj_msgSend, 2, p(ptr), p(ptr)),//magic + bi(obj_msgSend_super, 2, p(ptr), p(ptr)),//magic - {"obj_get_class", rua_obj_get_class, -1}, - {"obj_lookup_class", rua_obj_lookup_class, -1}, - {"obj_next_class", rua_obj_next_class, -1}, + bi(obj_get_class, 1, p(string)), + bi(obj_lookup_class, 1, p(string)), + bi(obj_next_class, 1, p(ptr)), - {"sel_get_name", rua_sel_get_name, -1}, - {"sel_get_type", rua_sel_get_type, -1}, - {"sel_get_uid", rua_sel_get_uid, -1}, - {"sel_register_name", rua_sel_register_name, -1}, - {"sel_is_mapped", rua_sel_is_mapped, -1}, + bi(sel_get_name, 1, p(ptr)), + bi(sel_get_type, 1, p(ptr)), + bi(sel_get_uid, 1, p(string)), + bi(sel_register_name, 1, p(string)), + bi(sel_is_mapped, 1, p(ptr)), - {"class_get_class_method", rua_class_get_class_method, -1}, - {"class_get_instance_method", rua_class_get_instance_method, -1}, - {"class_pose_as", rua_class_pose_as, -1}, - {"class_create_instance", rua_class_create_instance, -1}, - {"class_get_class_name", rua_class_get_class_name, -1}, - {"class_get_instance_size", rua_class_get_instance_size, -1}, - {"class_get_meta_class", rua_class_get_meta_class, -1}, - {"class_get_super_class", rua_class_get_super_class, -1}, - {"class_get_version", rua_class_get_version, -1}, - {"class_is_class", rua_class_is_class, -1}, - {"class_is_meta_class", rua_class_is_meta_class, -1}, - {"class_set_version", rua_class_set_version, -1}, - {"class_get_gc_object_type", rua_class_get_gc_object_type, -1}, - {"class_ivar_set_gcinvisible", rua_class_ivar_set_gcinvisible, -1}, + bi(class_get_class_method, 2, p(ptr), p(ptr)), + bi(class_get_instance_method, 2, p(ptr), p(ptr)), + bi(class_pose_as, 2, p(ptr), p(ptr)), + bi(class_create_instance, 1, p(ptr)), + bi(class_get_class_name, 1, p(ptr)), + bi(class_get_instance_size, 1, p(ptr)), + bi(class_get_meta_class, 1, p(ptr)), + bi(class_get_super_class, 1, p(ptr)), + bi(class_get_version, 1, p(ptr)), + bi(class_is_class, 1, p(ptr)), + bi(class_is_meta_class, 1, p(ptr)), + bi(class_set_version, 2, p(ptr), p(int)), + bi(class_get_gc_object_type, 1, p(ptr)), + bi(class_ivar_set_gcinvisible, 3, p(ptr), p(string), p(int)), - {"method_get_imp", rua_method_get_imp, -1}, - {"get_imp", rua_get_imp, -1}, + bi(method_get_imp, 1, p(ptr)), + bi(get_imp, 1, p(ptr), p(ptr)), - {"object_copy", rua_object_copy, -1}, - {"object_dispose", rua_object_dispose, -1}, - {"object_get_class", rua_object_get_class, -1}, - {"object_get_class_name", rua_object_get_class_name, -1}, - {"object_get_meta_class", rua_object_get_meta_class, -1}, - {"object_get_super_class", rua_object_get_super_class, -1}, - {"object_is_class", rua_object_is_class, -1}, - {"object_is_instance", rua_object_is_instance, -1}, - {"object_is_meta_class", rua_object_is_meta_class, -1}, + bi(object_copy, 1, p(ptr)), + bi(object_dispose, 1, p(ptr)), + bi(object_get_class, 1, p(ptr)), + bi(object_get_class_name, 1, p(ptr)), + bi(object_get_meta_class, 1, p(ptr)), + bi(object_get_super_class, 1, p(ptr)), + bi(object_is_class, 1, p(ptr)), + bi(object_is_instance, 1, p(ptr)), + bi(object_is_meta_class, 1, p(ptr)), - {"_i_Object__hash", rua__i_Object__hash, -1}, - {"_i_Object_error_error_", rua__i_Object_error_error_, -1}, - {"_c_Object__conformsToProtocol_", rua__c_Object__conformsToProtocol_, -1}, + bi(_i_Object__hash, 2, p(ptr), p(ptr)), + bi(_i_Object_error_error_, -4, p(ptr), p(ptr), p(string)), + bi(_c_Object__conformsToProtocol_, 3, p(ptr), p(ptr), p(ptr)), - {"PR_FindGlobal", rua_PR_FindGlobal, -1},//FIXME + bi(PR_FindGlobal, 1, p(string)),//FIXME {0} }; @@ -2156,7 +2221,7 @@ rua_init_finish (progs_t *pr) class_list = (pr_class_t **) Hash_GetList (probj->classes); if (*class_list) { pr_class_t *object_class; - pointer_t object_ptr; + pr_ptr_t object_ptr; object_class = Hash_Find (probj->classes, "Object"); if (object_class && !object_class->super_class) @@ -2241,19 +2306,18 @@ RUA_Obj_Init (progs_t *pr, int secure) load_methods_compare); PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup); - - PR_RegisterBuiltins (pr, obj_methods); + PR_RegisterBuiltins (pr, obj_methods, probj); PR_AddLoadFunc (pr, rua_obj_init_runtime); } -func_t -RUA_Obj_msg_lookup (progs_t *pr, pointer_t _self, pointer_t __cmd) +pr_func_t +RUA_Obj_msg_lookup (progs_t *pr, pr_ptr_t _self, pr_ptr_t __cmd) { probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &G_STRUCT (pr, pr_id_t, _self); pr_sel_t *_cmd = &G_STRUCT (pr, pr_sel_t, __cmd); - func_t imp; + pr_func_t imp; if (!self) return 0; diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 2899eec5f..4aae2db06 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -444,28 +444,30 @@ plist_compare (const void *k1, const void *k2, void *unused) return pl1->plitem == pl2->plitem; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"PL_GetFromFile", bi_PL_GetFromFile, -1}, - {"PL_GetPropertyList", bi_PL_GetPropertyList, -1}, - {"PL_WritePropertyList", bi_PL_WritePropertyList, -1}, - {"PL_Type", bi_PL_Type, -1}, - {"PL_Line", bi_PL_Line, -1}, - {"PL_String", bi_PL_String, -1}, - {"PL_ObjectForKey", bi_PL_ObjectForKey, -1}, - {"PL_RemoveObjectForKey", bi_PL_RemoveObjectForKey, -1}, - {"PL_ObjectAtIndex", bi_PL_ObjectAtIndex, -1}, - {"PL_D_AllKeys", bi_PL_D_AllKeys, -1}, - {"PL_D_NumKeys", bi_PL_D_NumKeys, -1}, - {"PL_D_AddObject", bi_PL_D_AddObject, -1}, - {"PL_A_AddObject", bi_PL_A_AddObject, -1}, - {"PL_A_NumObjects", bi_PL_A_NumObjects, -1}, - {"PL_A_InsertObjectAtIndex", bi_PL_A_InsertObjectAtIndex, -1}, - {"PL_RemoveObjectAtIndex", bi_PL_RemoveObjectAtIndex, -1}, - {"PL_NewDictionary", bi_PL_NewDictionary, -1}, - {"PL_NewArray", bi_PL_NewArray, -1}, - {"PL_NewData", bi_PL_NewData, -1}, - {"PL_NewString", bi_PL_NewString, -1}, - {"PL_Free", bi_PL_Free, -1}, + bi(PL_GetFromFile, 1, p(ptr)), + bi(PL_GetPropertyList, 1, p(string)), + bi(PL_WritePropertyList, 1, p(ptr)), + bi(PL_Type, 1, p(ptr)), + bi(PL_Line, 1, p(ptr)), + bi(PL_String, 1, p(ptr)), + bi(PL_ObjectForKey, 2, p(ptr), p(string)), + bi(PL_RemoveObjectForKey, 2, p(ptr), p(string)), + bi(PL_ObjectAtIndex, 2, p(ptr), p(int)), + bi(PL_D_AllKeys, 1, p(ptr)), + bi(PL_D_NumKeys, 1, p(ptr)), + bi(PL_D_AddObject, 3, p(ptr), p(string), p(ptr)), + bi(PL_A_AddObject, 2, p(ptr), p(ptr)), + bi(PL_A_NumObjects, 1, p(ptr)), + bi(PL_A_InsertObjectAtIndex, 3, p(ptr), p(ptr), p(int)), + bi(PL_RemoveObjectAtIndex, 2, p(ptr), p(int)), + bi(PL_NewDictionary, 0), + bi(PL_NewArray, 0), + bi(PL_NewData, 2, p(ptr), p(int)), + bi(PL_NewString, 1, p(string)), + bi(PL_Free, 1, p(ptr)), {0} }; @@ -477,5 +479,5 @@ RUA_Plist_Init (progs_t *pr, int secure) Hash_SetHashCompare (res->plist_tab, plist_get_hash, plist_compare); PR_Resources_Register (pr, "plist", res, bi_plist_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 8c6c45ef1..1fee454dc 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -213,7 +213,7 @@ bi_Qreadstring (progs_t *pr) int handle = P_INT (pr, 0); int len = P_INT (pr, 1); qfile_t *h = get_handle (pr, __FUNCTION__, handle); - string_t str = PR_NewMutableString (pr); + pr_string_t str = PR_NewMutableString (pr); dstring_t *dstr = PR_GetMutableString (pr, str); dstr->size = len + 1; @@ -346,35 +346,40 @@ bi_Qfilesize (progs_t *pr) R_INT (pr) = Qfilesize (h->file); } +#define bi(x,np,params...) {#x, secured, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t secure_builtins[] = { - {"Qrename", secured, -1}, - {"Qremove", secured, -1}, - {"Qopen", secured, -1}, + bi(Qrename, 2, p(string), p(string)), + bi(Qremove, 1, p(string)), + bi(Qopen, 2, p(string), p(string)), {0} }; +#undef bi +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} static builtin_t insecure_builtins[] = { - {"Qrename", bi_Qrename, -1}, - {"Qremove", bi_Qremove, -1}, - {"Qopen", bi_Qopen, -1}, + bi(Qrename, 2, p(string), p(string)), + bi(Qremove, 1, p(string)), + bi(Qopen, 2, p(string), p(string)), {0} }; static builtin_t builtins[] = { - {"Qclose", bi_Qclose, -1}, - {"Qgetline", bi_Qgetline, -1}, - {"Qreadstring", bi_Qreadstring, -1}, - {"Qread", bi_Qread, -1}, - {"Qwrite", bi_Qwrite, -1}, - {"Qputs", bi_Qputs, -1}, -// {"Qgets", bi_Qgets, -1}, - {"Qgetc", bi_Qgetc, -1}, - {"Qputc", bi_Qputc, -1}, - {"Qseek", bi_Qseek, -1}, - {"Qtell", bi_Qtell, -1}, - {"Qflush", bi_Qflush, -1}, - {"Qeof", bi_Qeof, -1}, - {"Qfilesize", bi_Qfilesize, -1}, + bi(Qclose, 1, p(ptr)), + bi(Qgetline, 1, p(ptr)), + bi(Qreadstring, 2, p(ptr), p(int)), + bi(Qread, 3, p(ptr), p(ptr), p(int)), + bi(Qwrite, 3, p(ptr), p(ptr), p(int)), + bi(Qputs, 2, p(ptr), p(string)), +// bi(Qgets, _, _), + bi(Qgetc, 1, p(ptr)), + bi(Qputc, 2, p(ptr), p(int)), + bi(Qseek, 3, p(ptr), p(int), p(int)), + bi(Qtell, 1, p(ptr)), + bi(Qflush, 1, p(ptr)), + bi(Qeof, 1, p(ptr)), + bi(Qfilesize, 1, p(ptr)), {0} }; @@ -385,9 +390,9 @@ RUA_QFile_Init (progs_t *pr, int secure) PR_Resources_Register (pr, "QFile", res, bi_qfile_clear); if (secure) { - PR_RegisterBuiltins (pr, secure_builtins); + PR_RegisterBuiltins (pr, secure_builtins, res); } else { - PR_RegisterBuiltins (pr, insecure_builtins); + PR_RegisterBuiltins (pr, insecure_builtins, res); } - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_qfs.c b/libs/ruamoko/rua_qfs.c index 4a3eebb59..8f36c4528 100644 --- a/libs/ruamoko/rua_qfs.c +++ b/libs/ruamoko/rua_qfs.c @@ -45,7 +45,7 @@ typedef struct { int count; - pointer_t list; + pr_ptr_t list; } qfslist_t; static void @@ -155,7 +155,7 @@ bi_QFS_Filelist (progs_t *pr) { filelist_t *filelist = QFS_FilelistNew (); qfslist_t *list; - string_t *strings; + pr_string_t *strings; int i; QFS_FilelistFill (filelist, P_GSTRING (pr, 0), P_GSTRING (pr, 1), @@ -163,7 +163,7 @@ bi_QFS_Filelist (progs_t *pr) list = PR_Zone_Malloc (pr, sizeof (list) + filelist->count * 4); list->count = filelist->count; - strings = (string_t *) (list + 1); + strings = (pr_string_t *) (list + 1); list->list = PR_SetPointer (pr, strings); for (i = 0; i < filelist->count; i++) strings[i] = PR_SetDynamicString (pr, filelist->list[i]); @@ -174,7 +174,7 @@ static void bi_QFS_FilelistFree (progs_t *pr) { qfslist_t *list = &P_STRUCT (pr, qfslist_t, 0); - string_t *strings = &G_STRUCT (pr, string_t, list->list); + pr_string_t *strings = &G_STRUCT (pr, pr_string_t, list->list); int i; for (i = 0; i < list->count; i++) @@ -188,21 +188,23 @@ bi_QFS_GetDirectory (progs_t *pr) RETURN_STRING (pr, qfs_gamedir->dir.def); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"QFS_Open", bi_QFS_Open, -1}, - {"QFS_WOpen", bi_QFS_WOpen, -1}, - {"QFS_Rename", bi_QFS_Rename, -1}, - {"QFS_LoadFile", bi_QFS_LoadFile, -1}, - {"QFS_OpenFile", bi_QFS_OpenFile, -1}, - {"QFS_WriteFile", bi_QFS_WriteFile, -1}, - {"QFS_Filelist", bi_QFS_Filelist, -1}, - {"QFS_FilelistFree", bi_QFS_FilelistFree, -1}, - {"QFS_GetDirectory", bi_QFS_GetDirectory, -1}, + bi(QFS_Open, 2, p(string), p(string)), + bi(QFS_WOpen, 2, p(string), p(int)), + bi(QFS_Rename, 2, p(string), p(string)), + bi(QFS_LoadFile, 1, p(string)), + bi(QFS_OpenFile, 1, p(string)), + bi(QFS_WriteFile, 3, p(string), p(ptr), p(int)), + bi(QFS_Filelist, 3, p(string), p(string), p(int)), + bi(QFS_FilelistFree, 1, p(ptr)), + bi(QFS_GetDirectory, 0), {0} }; void RUA_QFS_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c index 24a8a894d..5a1c906ad 100644 --- a/libs/ruamoko/rua_runtime.c +++ b/libs/ruamoko/rua_runtime.c @@ -56,7 +56,7 @@ bi_va_copy (progs_t *pr) __auto_type src_list = &G_STRUCT (pr, pr_type_t, src_args->list); size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); size_t size = src_args->count * parm_size; - string_t dst_list_block = 0; + pr_string_t dst_list_block = 0; pr_type_t *dst_list = 0; if (size) { @@ -69,13 +69,16 @@ bi_va_copy (progs_t *pr) R_PACKED (pr, pr_va_list_t).list = PR_SetPointer (pr, dst_list); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"va_copy", bi_va_copy, -1}, + bi(va_copy, 1, P(1, 2)), {0} }; void RUA_Runtime_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index 4723bfcbe..8cafdb387 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -46,7 +46,7 @@ typedef struct { script_t script; - string_t dstr; + pr_string_t dstr; progs_t *pr; } rua_script_t; @@ -187,15 +187,17 @@ bi_Script_NoQuoteLines (progs_t *pr) script->script.no_quote_lines = P_INT (pr, 1); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Script_New", bi_Script_New, -1}, - {"Script_Delete", bi_Script_Delete, -1}, - {"Script_Start", bi_Script_Start, -1}, - {"Script_TokenAvailable", bi_Script_TokenAvailable, -1}, - {"Script_GetToken", bi_Script_GetToken, -1}, - {"Script_UngetToken", bi_Script_UngetToken, -1}, - {"Script_Error", bi_Script_Error, -1}, - {"Script_NoQuoteLines", bi_Script_NoQuoteLines, -1}, + bi(Script_New, 0), + bi(Script_Delete, 1, p(ptr)), + bi(Script_Start, 3, p(ptr), p(string), p(string)), + bi(Script_TokenAvailable, 2, p(ptr), p(int)), + bi(Script_GetToken, 2, p(ptr), p(int)), + bi(Script_UngetToken, 1, p(ptr)), + bi(Script_Error, 1, p(ptr)), + bi(Script_NoQuoteLines, 1, p(ptr)), {0} }; @@ -205,6 +207,5 @@ RUA_Script_Init (progs_t *pr, int secure) script_resources_t *res = calloc (1, sizeof (script_resources_t)); PR_Resources_Register (pr, "Script", res, bi_script_clear); - - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 4e8b752b5..c8a0f2672 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -40,9 +40,10 @@ #include #include "QF/progs.h" -#include "QF/pr_obj.h" #include "QF/set.h" +#include "QF/progs/pr_obj.h" + #include "rua_internal.h" typedef struct { @@ -177,6 +178,15 @@ bi_set_del_iter (progs_t *pr) del_set_iter (pr, set_iter); } +static void +bi_set_iter_element (progs_t *pr) +{ + bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, P_INT (pr, 0)); + + R_INT (pr) = set_iter->iter->element; + +} + static void bi_set_new (progs_t *pr) { @@ -209,111 +219,177 @@ bi_set_delete (progs_t *pr) res_set_free (res, set); } +static void +rua_set_add (progs_t *pr, pr_int_t setid, pr_uint_t element) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_add (set->set, element); +} + static void bi_set_add (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_add (set->set, P_UINT (pr, 1)); + rua_set_add (pr, P_INT (pr, 0), P_UINT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_remove (progs_t *pr, pr_int_t setid, pr_uint_t element) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_remove (set->set, element); +} + static void bi_set_remove (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_remove (set->set, P_UINT (pr, 1)); + rua_set_remove (pr, P_INT (pr, 0), P_UINT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_invert (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_invert (set->set); +} + static void bi_set_invert (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_invert (set->set); + rua_set_invert (pr, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_union (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_union (dst->set, src->set); +} + static void bi_set_union (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_union (set1->set, set2->set); + rua_set_union (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_intersection (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_intersection (dst->set, src->set); +} + static void bi_set_intersection (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_intersection (set1->set, set2->set); + rua_set_intersection (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_difference (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_difference (dst->set, src->set); +} + static void bi_set_difference (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_difference (set1->set, set2->set); + rua_set_difference (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_reverse_difference (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_reverse_difference (dst->set, src->set); +} + static void bi_set_reverse_difference (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_reverse_difference (set1->set, set2->set); + rua_set_reverse_difference (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_assign (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_assign (dst->set, src->set); +} + static void bi_set_assign (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_assign (set1->set, set2->set); + rua_set_assign (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_empty (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_empty (set->set); +} + static void bi_set_empty (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_empty (set->set); + rua_set_empty (pr, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_everything (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_everything (set->set); +} + static void bi_set_everything (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_everything (set->set); + rua_set_everything (pr, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } static void -bi_set_is_empty (progs_t *pr) +rua_set_is_empty (progs_t *pr, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + bi_set_t *set = get_set (pr, __FUNCTION__, setid); R_INT (pr) = set_is_empty (set->set); } static void -bi_set_is_everything (progs_t *pr) +bi_set_is_empty (progs_t *pr) +{ + rua_set_is_empty (pr, P_INT (pr, 0)); +} + +static void +rua_set_is_everything (progs_t *pr, pr_int_t setid) { bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); @@ -321,55 +397,97 @@ bi_set_is_everything (progs_t *pr) } static void -bi_set_is_disjoint (progs_t *pr) +bi_set_is_everything (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_everything (pr, P_INT (pr, 0)); +} + +static void +rua_set_is_disjoint (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +{ + bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); R_INT (pr) = set_is_disjoint (set1->set, set2->set); } static void -bi_set_is_intersecting (progs_t *pr) +bi_set_is_disjoint (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_disjoint (pr, P_INT (pr, 0), P_INT (pr, 1)); +} + +static void +rua_set_is_intersecting (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +{ + bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); R_INT (pr) = set_is_intersecting (set1->set, set2->set); } static void -bi_set_is_equivalent (progs_t *pr) +bi_set_is_intersecting (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_intersecting (pr, P_INT (pr, 0), P_INT (pr, 1)); +} + +static void +rua_set_is_equivalent (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +{ + bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); R_INT (pr) = set_is_equivalent (set1->set, set2->set); } +static void +bi_set_is_equivalent (progs_t *pr) +{ + rua_set_is_equivalent (pr, P_INT (pr, 0), P_INT (pr, 1)); +} + +static void +rua_set_is_subset (progs_t *pr, pr_int_t setid, pr_int_t subid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *sub = get_set (pr, __FUNCTION__, subid); + + R_INT (pr) = set_is_subset (set->set, sub->set); +} + static void bi_set_is_subset (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_subset (pr, P_INT (pr, 0), P_INT (pr, 1)); +} - R_INT (pr) = set_is_subset (set1->set, set2->set); +static void +rua_set_is_member (progs_t *pr, pr_int_t setid, pr_uint_t element) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + R_INT (pr) = set_is_member (set->set, element); } static void bi_set_is_member (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + rua_set_is_member (pr, P_INT (pr, 0), P_UINT (pr, 1)); +} - R_INT (pr) = set_is_member (set->set, P_UINT (pr, 1)); +static void +rua_set_count (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + R_INT (pr) = set_count (set->set); } static void bi_set_count (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - R_INT (pr) = set_count (set->set); + rua_set_count (pr, P_INT (pr, 0)); } static void @@ -412,15 +530,21 @@ bi_set_next (progs_t *pr) } static void -bi_set_as_string (progs_t *pr) +rua_set_as_string (progs_t *pr, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + bi_set_t *set = get_set (pr, __FUNCTION__, setid); RETURN_STRING (pr, set_as_string (set->set)); } static void -bi_i_SetIterator__element (progs_t *pr) +bi_set_as_string (progs_t *pr) +{ + rua_set_as_string (pr, P_INT (pr, 0)); +} + +static void +bi__i_SetIterator__element (progs_t *pr) { pr_set_iter_t *iter_obj = &P_STRUCT (pr, pr_set_iter_t, 0); bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, iter_obj->iter); @@ -429,234 +553,183 @@ bi_i_SetIterator__element (progs_t *pr) } static void -bi_i_Set__add_ (progs_t *pr) +bi__i_Set__add_ (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - P_INT (pr, 1) = P_INT (pr, 2); - bi_set_add (pr); + rua_set_add (pr, set_obj->set, P_UINT (pr, 2)); R_INT (pr) = set_ptr; } static void -bi_i_Set__remove_ (progs_t *pr) +bi__i_Set__remove_ (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - P_INT (pr, 1) = P_INT (pr, 2); - bi_set_remove (pr); + rua_set_remove (pr, set_obj->set, P_UINT (pr, 2)); R_INT (pr) = set_ptr; } static void -bi_i_Set__invert (progs_t *pr) +bi__i_Set__invert (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_invert (pr); + rua_set_invert (pr, set_obj->set); R_INT (pr) = set_ptr; } static void -bi_i_Set__union_ (progs_t *pr) +bi__i_Set__union_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_union (pr); + rua_set_union (pr, dst_obj->set, src_obj->set); +} + +static void +bi__i_Set__intersection_ (progs_t *pr) +{ + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + + rua_set_intersection (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi_i_Set__intersection_ (progs_t *pr) +bi__i_Set__difference_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_intersection (pr); + rua_set_difference (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi_i_Set__difference_ (progs_t *pr) +bi__i_Set__reverse_difference_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_difference (pr); + rua_set_reverse_difference (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi_i_Set__reverse_difference_ (progs_t *pr) +bi__i_Set__assign_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_reverse_difference (pr); + rua_set_assign (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi_i_Set__assign_ (progs_t *pr) +bi__i_Set__empty (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_assign (pr); - R_INT (pr) = dst_ptr; -} - -static void -bi_i_Set__empty (progs_t *pr) -{ - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_empty (pr); + rua_set_empty (pr, set_obj->set); R_INT (pr) = set_ptr; } static void -bi_i_Set__everything (progs_t *pr) +bi__i_Set__everything (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_everything (pr); + rua_set_everything (pr, set_obj->set); R_INT (pr) = set_ptr; } static void -bi_i_Set__is_empty (progs_t *pr) +bi__i_Set__is_empty (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_is_empty (pr); + rua_set_is_empty (pr, set_obj->set); } static void -bi_i_Set__is_everything (progs_t *pr) +bi__i_Set__is_everything (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_is_everything (pr); + rua_set_is_everything (pr, set_obj->set); } static void -bi_i_Set__is_disjoint_ (progs_t *pr) +bi__i_Set__is_disjoint_ (progs_t *pr) { pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_disjoint (pr); + rua_set_is_disjoint (pr, s1_obj->set, s2_obj->set); } static void -bi_i_Set__is_intersecting_ (progs_t *pr) +bi__i_Set__is_intersecting_ (progs_t *pr) { pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_intersecting (pr); + rua_set_is_intersecting (pr, s1_obj->set, s2_obj->set); } static void -bi_i_Set__is_equivalent_ (progs_t *pr) +bi__i_Set__is_equivalent_ (progs_t *pr) { pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_equivalent (pr); + rua_set_is_equivalent (pr, s1_obj->set, s2_obj->set); } static void -bi_i_Set__is_subset_ (progs_t *pr) +bi__i_Set__is_subset_ (progs_t *pr) { - pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); - pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); + pr_set_t *sub_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_subset (pr); + rua_set_is_subset (pr, set_obj->set, sub_obj->set); } static void -bi_i_Set__is_member_ (progs_t *pr) +bi__i_Set__is_member_ (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - P_UINT (pr, 1) = P_UINT (pr, 2); - bi_set_is_member (pr); + rua_set_is_member (pr, set_obj->set, P_UINT (pr, 2)); } static void -bi_i_Set__size (progs_t *pr) +bi__i_Set__size (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_count (pr); + rua_set_count (pr, set_obj->set); } static void -bi_i_Set__as_string (progs_t *pr) +bi__i_Set__as_string (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_as_string (pr); + rua_set_as_string (pr, set_obj->set); } static void @@ -676,53 +749,56 @@ res_set_clear (progs_t *pr, void *data) res_set_iter_reset (res); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"set_del_iter", bi_set_del_iter, -1}, - {"set_new", bi_set_new, -1}, - {"set_delete", bi_set_delete, -1}, - {"set_add", bi_set_add, -1}, - {"set_remove", bi_set_remove, -1}, - {"set_invert", bi_set_invert, -1}, - {"set_union", bi_set_union, -1}, - {"set_intersection", bi_set_intersection, -1}, - {"set_difference", bi_set_difference, -1}, - {"set_reverse_difference", bi_set_reverse_difference, -1}, - {"set_assign", bi_set_assign, -1}, - {"set_empty", bi_set_empty, -1}, - {"set_everything", bi_set_everything, -1}, - {"set_is_empty", bi_set_is_empty, -1}, - {"set_is_everything", bi_set_is_everything, -1}, - {"set_is_disjoint", bi_set_is_disjoint, -1}, - {"set_is_intersecting", bi_set_is_intersecting, -1}, - {"set_is_equivalent", bi_set_is_equivalent, -1}, - {"set_is_subset", bi_set_is_subset, -1}, - {"set_is_member", bi_set_is_member, -1}, - {"set_count", bi_set_count, -1}, - {"set_first", bi_set_first, -1}, - {"set_next", bi_set_next, -1}, - {"set_as_string", bi_set_as_string, -1}, + bi(set_del_iter, 1, p(ptr)), + bi(set_iter_element, 1, p(ptr)), + bi(set_new, 0), + bi(set_delete, 1, p(ptr)), + bi(set_add, 2, p(ptr), p(uint)), + bi(set_remove, 2, p(ptr), p(uint)), + bi(set_invert, 1, p(ptr)), + bi(set_union, 2, p(ptr), p(ptr)), + bi(set_intersection, 2, p(ptr), p(ptr)), + bi(set_difference, 2, p(ptr), p(ptr)), + bi(set_reverse_difference, 2, p(ptr), p(ptr)), + bi(set_assign, 2, p(ptr), p(ptr)), + bi(set_empty, 1, p(ptr)), + bi(set_everything, 1, p(ptr)), + bi(set_is_empty, 1, p(ptr)), + bi(set_is_everything, 1, p(ptr)), + bi(set_is_disjoint, 2, p(ptr), p(ptr)), + bi(set_is_intersecting, 2, p(ptr), p(ptr)), + bi(set_is_equivalent, 2, p(ptr), p(ptr)), + bi(set_is_subset, 2, p(ptr), p(ptr)), + bi(set_is_member, 2, p(ptr), p(uint)), + bi(set_count, 1, p(ptr)), + bi(set_first, 1, p(ptr)), + bi(set_next, 1, p(ptr)), + bi(set_as_string, 1, p(ptr)), - {"_i_SetIterator__element", bi_i_SetIterator__element, -1}, + bi(_i_SetIterator__element, 2, p(ptr), p(ptr)), - {"_i_Set__add_", bi_i_Set__add_, -1}, - {"_i_Set__remove_", bi_i_Set__remove_, -1}, - {"_i_Set__invert", bi_i_Set__invert, -1}, - {"_i_Set__union_", bi_i_Set__union_, -1}, - {"_i_Set__intersection_", bi_i_Set__intersection_, -1}, - {"_i_Set__difference_", bi_i_Set__difference_, -1}, - {"_i_Set__reverse_difference_", bi_i_Set__reverse_difference_, -1}, - {"_i_Set__assign_", bi_i_Set__assign_, -1}, - {"_i_Set__empty", bi_i_Set__empty, -1}, - {"_i_Set__everything", bi_i_Set__everything, -1}, - {"_i_Set__is_empty", bi_i_Set__is_empty, -1}, - {"_i_Set__is_everything", bi_i_Set__is_everything, -1}, - {"_i_Set__is_disjoint_", bi_i_Set__is_disjoint_, -1}, - {"_i_Set__is_intersecting_", bi_i_Set__is_intersecting_, -1}, - {"_i_Set__is_equivalent_", bi_i_Set__is_equivalent_, -1}, - {"_i_Set__is_subset_", bi_i_Set__is_subset_, -1}, - {"_i_Set__is_member_", bi_i_Set__is_member_, -1}, - {"_i_Set__size", bi_i_Set__size, -1}, - {"_i_Set__as_string", bi_i_Set__as_string, -1}, + bi(_i_Set__add_, 3, p(ptr), p(ptr), p(uint)), + bi(_i_Set__remove_, 3, p(ptr), p(ptr), p(uint)), + bi(_i_Set__invert, 2, p(ptr), p(ptr)), + bi(_i_Set__union_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__intersection_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__difference_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__reverse_difference_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__assign_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__empty, 2, p(ptr), p(ptr)), + bi(_i_Set__everything, 2, p(ptr), p(ptr)), + bi(_i_Set__is_empty, 2, p(ptr), p(ptr)), + bi(_i_Set__is_everything, 2, p(ptr), p(ptr)), + bi(_i_Set__is_disjoint_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_intersecting_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_equivalent_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_subset_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_member_, 3, p(ptr), p(ptr), p(uint)), + bi(_i_Set__size, 2, p(ptr), p(ptr)), + bi(_i_Set__as_string, 2, p(ptr), p(ptr)), {0} }; @@ -734,5 +810,5 @@ RUA_Set_Init (progs_t *pr, int secure) res->sets = 0; PR_Resources_Register (pr, "Set", res, res_set_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_stdlib.c b/libs/ruamoko/rua_stdlib.c index 8c375e405..50fd1cc04 100644 --- a/libs/ruamoko/rua_stdlib.c +++ b/libs/ruamoko/rua_stdlib.c @@ -56,7 +56,7 @@ typedef struct { progs_t *pr; - func_t func; + pr_func_t func; } function_t; static int @@ -72,12 +72,15 @@ rua_compare (const void *a, const void *b, void *_f) { function_t *f = _f; + PR_PushFrame (f->pr); PR_RESET_PARAMS (f->pr); P_POINTER (f->pr, 0) = PR_SetPointer (f->pr, a); P_POINTER (f->pr, 1) = PR_SetPointer (f->pr, b); f->pr->pr_argc = 2; PR_ExecuteProgram (f->pr, f->func); - return R_INT (f->pr); + int cmp = R_INT (f->pr); + PR_PopFrame (f->pr); + return cmp; } static void @@ -87,7 +90,7 @@ bi_bsearch (progs_t *pr) const void *array = P_GPOINTER (pr, 1); size_t nmemb = P_INT (pr, 2); size_t size = P_INT (pr, 3) * sizeof (pr_int_t); - func_t cmp = P_FUNCTION (pr, 4); + pr_func_t cmp = P_FUNCTION (pr, 4); void *p = 0; if (!cmp) { @@ -106,7 +109,7 @@ bi_fbsearch (progs_t *pr) const void *array = P_GPOINTER (pr, 1); size_t nmemb = P_INT (pr, 2); size_t size = P_INT (pr, 3) * sizeof (pr_int_t); - func_t cmp = P_FUNCTION (pr, 4); + pr_func_t cmp = P_FUNCTION (pr, 4); void *p = 0; if (!cmp) { @@ -124,7 +127,7 @@ bi_qsort (progs_t *pr) void *array = P_GPOINTER (pr, 0); size_t nmemb = P_INT (pr, 1); size_t size = P_INT (pr, 2) * sizeof (pr_int_t); - func_t cmp = P_FUNCTION (pr, 3); + pr_func_t cmp = P_FUNCTION (pr, 3); if (!cmp) { qsort (array, nmemb, size, int_compare); @@ -156,17 +159,20 @@ bi_prefixsumf (progs_t *pr) } } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"bsearch", bi_bsearch, -1}, - {"fbsearch", bi_fbsearch, -1}, - {"qsort", bi_qsort, -1}, - {"prefixsum|^ii", bi_prefixsumi, -1}, - {"prefixsum|^fi", bi_prefixsumf, -1}, + bi(bsearch, 4, p(ptr), p(ptr), p(int), p(int), p(func)), + bi(fbsearch, 4, p(ptr), p(ptr), p(int), p(int), p(func)), + bi(qsort, 3, p(ptr), p(int), p(int), p(func)), + {"prefixsum|^ii", bi_prefixsumi, -1, 2, {p(ptr), p(int)}}, + {"prefixsum|^fi", bi_prefixsumf, -1, 2, {p(ptr), p(int)}}, {0} }; void RUA_Stdlib_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 754d1627e..f5ccd6d86 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -60,16 +60,36 @@ bi_strlen (progs_t *pr) R_INT (pr) = strlen(s); } +void +RUA_Sprintf (progs_t *pr, dstring_t *dstr, const char *func, int fmt_arg) +{ + const char *fmt = P_GSTRING (pr, fmt_arg); + int count = pr->pr_argc - (fmt_arg + 1); + pr_type_t **args = pr->pr_params + (fmt_arg + 1); + + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, (fmt_arg + 1)); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } + + PR_Sprintf (pr, dstr, func, fmt, count, args); +} + static void bi_sprintf (progs_t *pr) { - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; dstring_t *dstr; dstr = dstring_newstr (); - PR_Sprintf (pr, dstr, "bi_sprintf", fmt, count, args); + RUA_Sprintf (pr, dstr, "sprintf", 0); RETURN_STRING (pr, dstr->str); dstring_delete (dstr); } @@ -108,7 +128,7 @@ bi_str_free (progs_t *pr) static void bi_str_hold (progs_t *pr) { - string_t str = P_STRING (pr, 0); + pr_string_t str = P_STRING (pr, 0); PR_HoldString (pr, str); R_STRING (pr) = str; } @@ -155,17 +175,10 @@ bi_str_clear (progs_t *pr) } static void -bi_str_mid (progs_t *pr) +str_mid (progs_t *pr, const char *str, int pos, int end, int size) { - const char *str = P_GSTRING (pr, 0); - int pos = P_INT (pr, 1); - int end = P_INT (pr, 2); - int size = strlen (str); char *temp; - if (pr->pr_argc == 2) - end = size; - R_STRING (pr) = 0; if (pos < 0) pos += size; @@ -185,6 +198,27 @@ bi_str_mid (progs_t *pr) RETURN_STRING (pr, temp); } +static void +bi_str_mid_2 (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + int pos = P_INT (pr, 1); + int size = strlen (str); + + str_mid (pr, str, pos, size, size); +} + +static void +bi_str_mid_3 (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + int pos = P_INT (pr, 1); + int end = P_INT (pr, 2); + int size = strlen (str); + + str_mid (pr, str, pos, end, size); +} + static void bi_str_str (progs_t *pr) { @@ -281,30 +315,33 @@ bi_str_upper (progs_t *pr) RETURN_STRING (pr, upper); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"strlen", bi_strlen, -1}, - {"sprintf", bi_sprintf, -1}, - {"vsprintf", bi_vsprintf, -1}, - {"str_new", bi_str_new, -1}, - {"str_free", bi_str_free, -1}, - {"str_hold", bi_str_hold, -1}, - {"str_valid", bi_str_valid, -1}, - {"str_mutable", bi_str_mutable, -1}, - {"str_copy", bi_str_copy, -1}, - {"str_cat", bi_str_cat, -1}, - {"str_clear", bi_str_clear, -1}, - {"str_mid|*i", bi_str_mid, -1}, - {"str_mid|*ii", bi_str_mid, -1}, - {"str_str", bi_str_str, -1}, - {"str_char", bi_str_char, -1}, - {"str_quote", bi_str_quote, -1}, - {"str_lower", bi_str_lower, -1}, - {"str_upper", bi_str_upper, -1}, + bi(strlen, 1, p(string)), + bi(sprintf, -2, p(string)), + bi(vsprintf, 2, p(string), P(1, 2)), + bi(str_new, 0), + bi(str_free, 1, p(string)), + bi(str_hold, 1, p(string)), + bi(str_valid, 1, p(string)), + bi(str_mutable, 1, p(string)), + bi(str_copy, 2, p(string), p(string)), + bi(str_cat, 2, p(string), p(string)), + bi(str_clear, 1, p(string)), + {"str_mid|*i", bi_str_mid_2, -1, 2, {p(string), p(int)}}, + {"str_mid|*ii", bi_str_mid_3, -1, 3, {p(string), p(int), p(int)}}, + bi(str_str, 2, p(string), p(string)), + bi(str_char, 2, p(string), p(int)), + bi(str_quote, 1, p(string)), + bi(str_lower, 1, p(string)), + bi(str_upper, 1, p(string)), {0} }; void RUA_String_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 9ecba1804..1efbb2f2a 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -350,7 +350,7 @@ double_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, { double a = *(double *) val1->value; double b = *(double *) val2->value; - *(double *) result->value = a - b * truncf (a / b); + *(double *) result->value = a - b * trunc (a / b); } static void @@ -364,7 +364,7 @@ double_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, // -5 mod -3 = -2 double a = *(double *) val1->value; double b = *(double *) val2->value; - *(double *) result->value = a - b * floorf (a / b); + *(double *) result->value = a - b * floor (a / b); } CASTOP (double, int) @@ -425,7 +425,7 @@ vector_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, vec4f_t a = *(vec4f_t *) val1->value; vec4f_t b = *(vec4f_t *) val2->value; __auto_type c = (vec4f_t *) result->value; - *c = a - b * vtruncf (a / b); + *c = a - b * vtrunc4f (a / b); } static void @@ -440,7 +440,7 @@ vector_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, vec4f_t a = *(vec4f_t *) val1->value; vec4f_t b = *(vec4f_t *) val2->value; __auto_type c = (vec4f_t *) result->value; - *c = a - b * vfloorf (a / b); + *c = a - b * vfloor4f (a / b); } static void diff --git a/libs/util/simd.c b/libs/util/simd.c index f10c97acd..352a4169a 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -32,13 +32,21 @@ #include +#define IMPLEMENT_VEC2F_Funcs +#define IMPLEMENT_VEC2D_Funcs +#define IMPLEMENT_VEC2I_Funcs #define IMPLEMENT_VEC4F_Funcs #define IMPLEMENT_VEC4D_Funcs +#define IMPLEMENT_VEC4I_Funcs #define IMPLEMENT_MAT4F_Funcs #include "QF/mathlib.h" +#include "QF/simd/vec2d.h" +#include "QF/simd/vec2f.h" +#include "QF/simd/vec2i.h" #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" +#include "QF/simd/vec4i.h" #include "QF/simd/mat4f.h" #include "QF/set.h" #include "QF/sys.h" diff --git a/libs/util/sys.c b/libs/util/sys.c index 25120aed2..bd985428f 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -431,7 +431,7 @@ Sys_LongTime (void) VISIBLE int64_t Sys_TimeBase (void) { - return __INT64_C (4294967296000000); + return INT64_C (4294967296000000); } VISIBLE double diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 188239e11..7fa5a5f98 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -1,6 +1,7 @@ libs_util_tests = \ libs/util/test/test-bary \ libs/util/test/test-baryvf \ + libs/util/test/test-bitop \ libs/util/test/test-bsearch \ libs/util/test/test-cexpr \ libs/util/test/test-cmem \ @@ -36,6 +37,10 @@ libs_util_test_test_baryvf_SOURCES=libs/util/test/test-baryvf.c libs_util_test_test_baryvf_LDADD=libs/util/libQFutil.la libs_util_test_test_baryvf_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_bitop_SOURCES=libs/util/test/test-bitop.c +libs_util_test_test_bitop_LDADD=libs/util/libQFutil.la +libs_util_test_test_bitop_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_bsearch_SOURCES=libs/util/test/test-bsearch.c libs_util_test_test_bsearch_LDADD=libs/util/libQFutil.la libs_util_test_test_bsearch_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-bitop.c b/libs/util/test/test-bitop.c new file mode 100644 index 000000000..795d023f5 --- /dev/null +++ b/libs/util/test/test-bitop.c @@ -0,0 +1,55 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/math/bitop.h" + +struct { + uint32_t value; + uint32_t expect; +} tests [] = { + {BITOP_RUP(1), 1}, + {BITOP_RUP(2), 2}, + {BITOP_RUP(3), 4}, + {BITOP_RUP(4), 4}, + {BITOP_RUP(5), 8}, + {BITOP_RUP(7), 8}, + {BITOP_RUP(8), 8}, + {BITOP_RUP(0x40000000), 0x40000000}, + {BITOP_RUP(0x40000001), 0x80000000}, + {BITOP_LOG2(1), 0}, + {BITOP_LOG2(2), 1}, + {BITOP_LOG2(3), 2}, + {BITOP_LOG2(4), 2}, + {BITOP_LOG2(5), 3}, + {BITOP_LOG2(7), 3}, + {BITOP_LOG2(8), 3}, + {BITOP_LOG2(9), 4}, + {BITOP_LOG2(15), 4}, + {BITOP_LOG2(16), 4}, + {BITOP_LOG2(17), 5}, + {BITOP_LOG2(31), 5}, + {BITOP_LOG2(32), 5}, + {BITOP_LOG2(33), 6}, + {BITOP_LOG2(0x40000000), 30}, + {BITOP_LOG2(0x40000001), 31}, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) + +int +main (int argc, const char **argv) +{ + size_t i; + int res = 0; + + for (i = 0; i < num_tests; i++) { + if (tests[i].value != tests[i].expect) { + res |= 1; + printf ("test %d failed\n", (int) i); + printf ("expect: %8x\n", tests[i].expect); + printf ("got : %8x\n", tests[i].value); + } + } + return res; +} diff --git a/libs/util/test/test-mat3.c b/libs/util/test/test-mat3.c index 903c4de9f..9134fb9c2 100644 --- a/libs/util/test/test-mat3.c +++ b/libs/util/test/test-mat3.c @@ -99,7 +99,7 @@ test_transform (const vec3_t angles, const vec3_t scale) VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); Mat3Init (rotation, scale, mat); @@ -132,7 +132,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale) VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); Mat3Init (rotation, scale, mat); @@ -141,7 +141,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale) VectorCopy (v, y); QuatMultVec (rot, y, y); VectorShear (sh, y, y); - VectorCompMult (sc, y, y);//scale + VectorCompMult (y, sc, y);//scale for (i = 0; i < 3; i++) if (!compare (x[i], y[i])) diff --git a/libs/util/test/test-mat4.c b/libs/util/test/test-mat4.c index 1bd7afcc9..cd30c0990 100644 --- a/libs/util/test/test-mat4.c +++ b/libs/util/test/test-mat4.c @@ -114,7 +114,7 @@ test_transform (const vec3_t angles, const vec3_t scale, VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); VectorAdd (x, translation, x); @@ -148,7 +148,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale, VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); VectorAdd (translation, x, x); @@ -158,7 +158,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale, VectorCopy (v, y); QuatMultVec (rot, y, y); VectorShear (sh, y, y); - VectorCompMult (sc, y, y);//scale + VectorCompMult (y, sc, y);//scale VectorAdd (tr, y, y); for (i = 0; i < 3; i++) diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index ae2fd6547..7cba48f3b 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -48,7 +48,6 @@ #define s05 0.70710678118654757 -#ifdef __AVX2__ typedef struct { int line; vec4d_t (*op) (vec4d_t a, vec4d_t b); @@ -57,7 +56,6 @@ typedef struct { vec4d_t expect; vec4d_t ulp_errors; } vec4d_test_t; -#endif typedef struct { int line; @@ -94,41 +92,39 @@ typedef struct { mat4f_t ulp_errors; } mq4f_test_t; -#ifdef __AVX2__ static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) { - return vtruncd (v); + return vtrunc4d (v); } static vec4d_t tvceild (vec4d_t v, vec4d_t ignore) { - return vceild (v); + return vceil4d (v); } static vec4d_t tvfloord (vec4d_t v, vec4d_t ignore) { - return vfloord (v); + return vfloor4d (v); } static vec4d_t tqconjd (vec4d_t v, vec4d_t ignore) { return qconjd (v); } -#endif static vec4f_t tvtruncf (vec4f_t v, vec4f_t ignore) { - return vtruncf (v); + return vtrunc4f (v); } static vec4f_t tvceilf (vec4f_t v, vec4f_t ignore) { - return vceilf (v); + return vceil4f (v); } static vec4f_t tvfloorf (vec4f_t v, vec4f_t ignore) { - return vfloorf (v); + return vfloor4f (v); } static vec4f_t tqconjf (vec4f_t v, vec4f_t ignore) @@ -138,12 +134,12 @@ static vec4f_t tqconjf (vec4f_t v, vec4f_t ignore) static vec4f_t tvabsf (vec4f_t v, vec4f_t ignore) { - return vabsf (v); + return vabs4f (v); } static vec4f_t tvsqrtf (vec4f_t v, vec4f_t ignore) { - return vsqrtf (v); + return vsqrt4f (v); } static vec4f_t tmagnitudef (vec4f_t v, vec4f_t ignore) @@ -158,7 +154,6 @@ static vec4f_t tmagnitude3f (vec4f_t v, vec4f_t ignore) #define T(t...) { __LINE__, t } -#ifdef __AVX2__ static vec4d_test_t vec4d_tests[] = { // 3D dot products T(dotd, right, right, one ), @@ -285,7 +280,6 @@ static vec4d_test_t vec4d_tests[] = { T(tqconjd, one, {}, { -1, -1, -1, 1 } ), }; #define num_vec4d_tests (sizeof (vec4d_tests) / (sizeof (vec4d_tests[0]))) -#endif static vec4f_test_t vec4f_tests[] = { // 3D dot products @@ -487,7 +481,6 @@ static mq4f_test_t mq4f_tests[] = { }; #define num_mq4f_tests (sizeof (mq4f_tests) / (sizeof (mq4f_tests[0]))) -#ifdef __AVX2__ static int run_vec4d_tests (void) { @@ -512,7 +505,6 @@ run_vec4d_tests (void) } return ret; } -#endif static int run_vec4f_tests (void) @@ -684,9 +676,7 @@ int main (void) { int ret = 0; -#ifdef __AVX2__ ret |= run_vec4d_tests (); -#endif ret |= run_vec4f_tests (); ret |= run_mat4f_tests (); ret |= run_mv4f_tests (); diff --git a/libs/util/zone.c b/libs/util/zone.c index 88b3e7ecd..ce02fa76c 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -202,8 +202,6 @@ Z_Malloc (memzone_t *zone, size_t size) { void *buf; - if (!developer || developer->int_val & SYS_dev) - Z_CheckHeap (zone); // DEBUG buf = Z_TagMalloc (zone, size, 1); if (!buf) { const char *msg; @@ -224,6 +222,9 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag) int requested_size = size; memblock_t *start, *rover, *new, *base; + if (!developer || developer->int_val & SYS_dev) + Z_CheckHeap (zone); // DEBUG + if (!tag) { if (zone->error) zone->error (zone->data, "Z_TagMalloc: tried to use a 0 tag"); @@ -290,6 +291,9 @@ Z_Realloc (memzone_t *zone, void *ptr, size_t size) if (!ptr) return Z_Malloc (zone, size); + if (!developer || developer->int_val & SYS_dev) + Z_CheckHeap (zone); // DEBUG + block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); if (block->id != ZONEID/* || block->id2 != ZONEID*/) { if (zone->error) diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index c09569c56..87cd3e513 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -324,20 +324,24 @@ bi_draw_clear (progs_t *pr, void *data) Hash_FlushTable (res->pic_hash); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Draw_FreePic", bi_Draw_FreePic, -1}, - {"Draw_MakePic", bi_Draw_MakePic, -1}, - {"Draw_CachePic", bi_Draw_CachePic, -1}, - {"Draw_Pic", bi_Draw_Pic, -1}, - {"Draw_Picf", bi_Draw_Picf, -1}, - {"Draw_SubPic", bi_Draw_SubPic, -1}, - {"Draw_CenterPic", bi_Draw_CenterPic, -1}, - {"Draw_Character", bi_Draw_Character, -1}, - {"Draw_String", bi_Draw_String, -1}, - {"Draw_nString", bi_Draw_nString, -1}, - {"Draw_AltString", bi_Draw_AltString, -1}, - {"Draw_Fill", bi_Draw_Fill, -1}, - {"Draw_Crosshair", bi_Draw_Crosshair, -1}, + bi(Draw_FreePic, 1, p(ptr)), + bi(Draw_MakePic, 3, p(int), p(int), p(string)), + bi(Draw_CachePic, 2, p(string), p(int)), + bi(Draw_Pic, 3, p(int), p(int), p(ptr)), + bi(Draw_Picf, 3, p(float), p(float), p(ptr)), + bi(Draw_SubPic, 7, p(int), p(int), p(ptr), + p(int), p(int), p(int), p(int)), + bi(Draw_CenterPic, 3, p(int), p(int), p(ptr)), + bi(Draw_Character, 3, p(int), p(int), p(int)), + bi(Draw_String, 3, p(int), p(int), p(string)), + bi(Draw_nString, 4, p(int), p(int), p(string), p(int)), + bi(Draw_AltString, 3, p(int), p(int), p(string)), + bi(Draw_Fill, 5, p(int), p(int), p(int), p(int), p(int)), + bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), {0} }; @@ -349,5 +353,5 @@ R_Progs_Init (progs_t *pr) pr->hashlink_freelist); PR_Resources_Register (pr, "Draw", res, bi_draw_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2d7c5bf97..ef35d022a 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -147,6 +147,7 @@ vulkan_R_RenderFrame (SCR_Func *scr_funcs) for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + frame->framebuffer = rp->framebuffers->a[imageIndex]; rp->draw (rpFrame); } @@ -164,7 +165,6 @@ vulkan_R_RenderFrame (SCR_Func *scr_funcs) __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; if (rpFrame->renderpass) { - frame->framebuffer = rp->framebuffers->a[imageIndex]; renderPassInfo.framebuffer = frame->framebuffer, renderPassInfo.renderPass = rp->renderpass; renderPassInfo.clearValueCount = rp->clearValues->size; diff --git a/libs/video/renderer/vulkan/vkgen/stdint.h b/libs/video/renderer/vulkan/vkgen/stdint.h index 04fc06933..e343a15b5 100644 --- a/libs/video/renderer/vulkan/vkgen/stdint.h +++ b/libs/video/renderer/vulkan/vkgen/stdint.h @@ -7,5 +7,4 @@ typedef int int16_t; typedef int int32_t; typedef int int64_t; typedef int size_t; -typedef int long; typedef int char; diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index e0aad2943..bbb7ffb21 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -33,7 +33,7 @@ } else if ([alias class] == [Enum class] || [alias class] == [Struct class]) { [alias addToQueue]; - } else if (alias.type.meta == ty_basic && alias.type.type == ev_pointer) { + } else if (alias.type.meta == ty_basic && alias.type.type == ev_ptr) { Type *type = [Type findType:alias.type.fldptr.aux_type]; if (!type) { // pointer to opaque struct. Probably diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 4bcd74ee4..a3a5e426f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -66,7 +66,7 @@ void print_type (qfot_type_t *type) case ty_basic: //printf (" %d", type.type); switch (type.type) { - case ev_pointer: + case ev_ptr: case ev_field: //printf (" "); print_type (type.fldptr.aux_type); diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index f9776dcd4..70de1fbc7 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -77,7 +77,7 @@ static string get_type_key (void *type, void *unused) -(string) name { if (type.meta == ty_basic) { - if (type.type == ev_integer) { + if (type.type == ev_int) { return "int"; } return pr_type_name[type.type]; @@ -89,7 +89,7 @@ static string get_type_key (void *type, void *unused) -(void) addToQueue { string name = [self name]; - if (type.meta == ty_basic && type.type == ev_pointer) { + if (type.meta == ty_basic && type.type == ev_ptr) { [[Type findType: type.fldptr.aux_type] addToQueue]; } } @@ -123,7 +123,7 @@ static string get_type_key (void *type, void *unused) -(string) parseData { if (type.meta == ty_basic) { - if (type.type == ev_integer) { + if (type.type == ev_int) { return "&cexpr_int"; } return "&cexpr_" + pr_type_name[type.type]; @@ -134,7 +134,7 @@ static string get_type_key (void *type, void *unused) -(int) isPointer { if ((type.meta == ty_basic || type.meta == ty_alias) - && type.type == ev_pointer) { + && type.type == ev_ptr) { return 1; } return 0; @@ -143,10 +143,10 @@ static string get_type_key (void *type, void *unused) -(Type *) dereference { qfot_type_t *t = type; - if (t.meta == ty_alias && t.type == ev_pointer) { + if (t.meta == ty_alias && t.type == ev_ptr) { t = type.alias.full_type; } - if (t.meta == ty_basic && t.type == ev_pointer) { + if (t.meta == ty_basic && t.type == ev_ptr) { t = type.fldptr.aux_type; } return [Type findType:t]; diff --git a/nq/include/server.h b/nq/include/server.h index 7e78394ce..5af088cc8 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -44,8 +44,8 @@ extern progs_t sv_pr_state; typedef struct { - int maxclients; - int maxclientslimit; + unsigned maxclients; + unsigned maxclientslimit; struct client_s *clients; // [maxclients] void (*phys_client) (struct edict_s *ent, int num); int serverflags; // episode completion information @@ -75,7 +75,7 @@ typedef struct struct model_s *models[MAX_MODELS]; const char *sound_precache[MAX_SOUNDS]; // NULL terminated const char *lightstyles[MAX_LIGHTSTYLES]; - int num_edicts; + unsigned num_edicts; int max_edicts; edict_t *edicts; // can NOT be array indexed, because // edict_t is variable sized, but can diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 71a371f48..4a09f1c5a 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -38,14 +38,14 @@ #include "sv_pr_cmds.h" typedef struct { - pr_int_t *self; - pr_int_t *other; - pr_int_t *world; + pr_uint_t *self; + pr_uint_t *other; + pr_uint_t *world; float *time; float *frametime; float *force_retouch; - string_t *mapname; - string_t *startspot; + pr_string_t *mapname; + pr_string_t *startspot; float *deathmatch; float *coop; float *teamplay; @@ -64,30 +64,30 @@ typedef struct { vec3_t *trace_endpos; vec3_t *trace_plane_normal; float *trace_plane_dist; - pr_int_t *trace_ent; + pr_uint_t *trace_ent; float *trace_inopen; float *trace_inwater; - pr_int_t *msg_entity; - string_t *null; + pr_uint_t *msg_entity; + pr_string_t *null; - pr_int_t *newmis; + pr_uint_t *newmis; } sv_globals_t; extern sv_globals_t sv_globals; typedef struct { - func_t main; - func_t StartFrame; - func_t PlayerPreThink; - func_t PlayerPostThink; - func_t ClientKill; - func_t ClientConnect; - func_t PutClientInServer; - func_t ClientDisconnect; - func_t SetNewParms; - func_t SetChangeParms; + pr_func_t main; + pr_func_t StartFrame; + pr_func_t PlayerPreThink; + pr_func_t PlayerPostThink; + pr_func_t ClientKill; + pr_func_t ClientConnect; + pr_func_t PutClientInServer; + pr_func_t ClientDisconnect; + pr_func_t SetNewParms; + pr_func_t SetChangeParms; - func_t EndFrame; + pr_func_t EndFrame; } sv_funcs_t; extern sv_funcs_t sv_funcs; @@ -106,8 +106,8 @@ typedef struct pr_int_t angles; //vec3_t pr_int_t avelocity; //vec3_t pr_int_t punchangle; //vec3_t - pr_int_t classname; //string_t - pr_int_t model; //string_t + pr_int_t classname; //pr_string_t + pr_int_t model; //pr_string_t pr_int_t frame; //float pr_int_t skin; //float pr_int_t effects; //float @@ -115,15 +115,15 @@ typedef struct pr_int_t mins; //vec3_t pr_int_t maxs; //vec3_t pr_int_t size; //vec3_t - pr_int_t touch; //func_t - pr_int_t think; //func_t - pr_int_t blocked; //func_t + pr_int_t touch; //pr_func_t + pr_int_t think; //pr_func_t + pr_int_t blocked; //pr_func_t pr_int_t nextthink; //float pr_int_t groundentity; //int pr_int_t health; //float pr_int_t frags; //float pr_int_t weapon; //float - pr_int_t weaponmodel; //string_t + pr_int_t weaponmodel; //pr_string_t pr_int_t weaponframe; //float pr_int_t currentammo; //float pr_int_t ammo_shells; //float @@ -142,7 +142,7 @@ typedef struct pr_int_t fixangle; //float pr_int_t v_angle; //vec3_t pr_int_t idealpitch; //float - pr_int_t netname; //string_t + pr_int_t netname; //pr_string_t pr_int_t enemy; //int pr_int_t flags; //float pr_int_t colormap; //float @@ -160,7 +160,7 @@ typedef struct pr_int_t dmg_inflictor; //int pr_int_t owner; //int pr_int_t movedir; //vec3_t - pr_int_t message; //string_t + pr_int_t message; //pr_string_t pr_int_t sounds; //float pr_int_t rotated_bbox; //int @@ -187,7 +187,7 @@ extern progs_t sv_pr_state; #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) #define SVvector(e,f) (&SVFIELD (e, f, vector)) -#define SVinteger(e,f) SVFIELD (e, f, integer) +#define SVint(e,f) SVFIELD (e, f, int) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) #else @@ -213,19 +213,29 @@ typedef struct sv_data_s { #define EDICT_FROM_AREA(l) (STRUCT_FROM_LINK(l,sv_data_t,area)->edict) static inline void -sv_pr_touch (edict_t *self, edict_t *other) +sv_pr_exec (edict_t *self, edict_t *other, pr_func_t func) { pr_int_t this; *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); if ((this = sv_pr_state.fields.this) != -1) { + PR_PushFrame (&sv_pr_state); PR_RESET_PARAMS (&sv_pr_state); P_INT (&sv_pr_state, 0) = E_POINTER (self, this); P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); + P_INT (&sv_pr_state, 2) = other ? E_POINTER (other, this) : 0; } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, touch)); + PR_ExecuteProgram (&sv_pr_state, func); + if ((this = sv_pr_state.fields.this) != -1) { + PR_PopFrame (&sv_pr_state); + } +} + +static inline void +sv_pr_touch (edict_t *self, edict_t *other) +{ + sv_pr_exec (self, other, SVfunc (self, touch)); } static inline void @@ -236,33 +246,13 @@ sv_pr_use (edict_t *self, edict_t *other) static inline void sv_pr_think (edict_t *self) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = 0; - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = 0; - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, think)); + sv_pr_exec (self, 0, SVfunc (self, think)); } static inline void sv_pr_blocked (edict_t *self, edict_t *other) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, blocked)); + sv_pr_exec (self, other, SVfunc (self, blocked)); } #endif // __sv_progs_h diff --git a/nq/source/host.c b/nq/source/host.c index be2b2d232..601d5d335 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -323,7 +323,6 @@ void SV_BroadcastPrintf (const char *fmt, ...) { static dstring_t *str; - int i; va_list argptr; if (!str) @@ -333,7 +332,7 @@ SV_BroadcastPrintf (const char *fmt, ...) dvsprintf (str, fmt, argptr); va_end (argptr); - for (i = 0; i < svs.maxclients; i++) + for (unsigned i = 0; i < svs.maxclients; i++) if (svs.clients[i].active && svs.clients[i].spawned) { MSG_WriteByte (&svs.clients[i].message, svc_print); MSG_WriteString (&svs.clients[i].message, str->str); @@ -372,7 +371,8 @@ void SV_DropClient (qboolean crash) { client_t *client; - int saveSelf, i; + unsigned i; + pr_uint_t saveSelf; if (!crash) { // send any final messages (don't check for errors) @@ -386,8 +386,7 @@ SV_DropClient (qboolean crash) // call the prog function for removing a client // this will set the body to a dead frame, among other things saveSelf = *sv_globals.self; - *sv_globals.self = - EDICT_TO_PROG (&sv_pr_state, host_client->edict); + *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, host_client->edict); PR_ExecuteProgram (&sv_pr_state, sv_funcs.ClientDisconnect); *sv_globals.self = saveSelf; } @@ -406,7 +405,8 @@ SV_DropClient (qboolean crash) net_activeconnections--; // send notification to all clients - for (i = 0, client = svs.clients; i < svs.maxclients; i++, client++) { + for (i = 0, client = svs.clients; i < svs.maxclients; + i++, client++) { if (!client->active) continue; MSG_WriteByte (&client->message, svc_updatename); @@ -431,7 +431,7 @@ Host_ShutdownServer (qboolean crash) { byte message[4]; double start; - int count, i; + unsigned count, i; sizebuf_t buf; if (!sv.active) @@ -711,7 +711,7 @@ Host_Frame (float time) { double time1, time2; static double timetotal; - int i, c, m; + int c, m; static int timecount; if (!serverprofile->int_val) { @@ -733,7 +733,7 @@ Host_Frame (float time) timecount = 0; timetotal = 0; c = 0; - for (i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { if (svs.clients[i].active) c++; } diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 9f10ed8e9..3c51cb894 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -78,7 +78,7 @@ Host_Status_f (void) int seconds; int minutes; int hours = 0; - int j; + unsigned j; __attribute__((format(PRINTF, 1, 2))) void (*print) (const char *fmt, ...); if (cmd_source == src_command) { @@ -210,7 +210,7 @@ Host_Fly_f (void) static void Host_Ping_f (void) { - int i, j; + unsigned i, j; float total; client_t *client; @@ -421,7 +421,7 @@ static plitem_t * entities_array (void) { plitem_t *entities = PL_NewArray (); - int i; + pr_uint_t i; for (i = 0; i < sv.num_edicts; i++) { PL_A_AddObject (entities, @@ -517,7 +517,6 @@ Host_Savegame_f (void) const char *save_name; char *save_text; QFile *f; - int i; char *bup1, *bup2 = 0; @@ -549,7 +548,7 @@ Host_Savegame_f (void) return; } - for (i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { if (svs.clients[i].active && (SVfloat (svs.clients[i].edict, health) <= 0)) { Sys_Printf ("Can't savegame with a dead player\n"); @@ -562,7 +561,7 @@ Host_Savegame_f (void) if (strcmp (save_name, "quick") == 0) { bup2 = nva ("%s/%s%d.sav", qfs_gamedir->dir.def, save_name, MAX_QUICK); QFS_Remove (bup2); - for (i = MAX_QUICK - 1; i > 0; i--) { + for (int i = MAX_QUICK - 1; i > 0; i--) { bup1 = nva ("%s/%s%d.sav", qfs_gamedir->dir.def, save_name, i); QFS_Rename (bup1, bup2); free (bup2); @@ -783,7 +782,7 @@ Host_Say (qboolean teamonly) { client_t *client; client_t *save; - int j; + unsigned j; char *p; char text[64]; qboolean fromServer = false; @@ -817,7 +816,7 @@ Host_Say (qboolean teamonly) snprintf (text, sizeof (text), "%c<%s> ", 1, hostname->string); j = sizeof (text) - 2 - strlen (text); // -2 for /n and null terminator - if ((int) strlen (p) > j) + if (strlen (p) > j) p[j] = 0; strcat (text, p); @@ -854,7 +853,7 @@ Host_Tell_f (void) { client_t *client; client_t *save; - int j; + unsigned j; char *p; char text[64]; @@ -879,7 +878,7 @@ Host_Tell_f (void) } // check length & truncate if necessary j = sizeof (text) - 2 - strlen (text); // -2 for /n and null terminator - if ((int) strlen (p) > j) + if (strlen (p) > j) p[j] = 0; strcat (text, p); @@ -969,7 +968,7 @@ Host_PreSpawn_f (void) static void Host_Spawn_f (void) { - int i; + unsigned i; client_t *client; edict_t *ent; float *sendangles; @@ -1099,7 +1098,7 @@ Host_Kick_f (void) const char *who; const char *message = NULL; client_t *save; - int i; + unsigned i; qboolean byNumber = false; if (cmd_source == src_command) { @@ -1115,7 +1114,7 @@ Host_Kick_f (void) if (Cmd_Argc () > 2 && strcmp (Cmd_Argv (1), "#") == 0) { i = atof (Cmd_Argv (2)) - 1; - if (i < 0 || i >= svs.maxclients) + if (i >= svs.maxclients) return; if (!svs.clients[i].active) return; @@ -1291,7 +1290,7 @@ Host_Give_f (void) static edict_t * FindViewthing (void) { - int i; + pr_uint_t i; edict_t *e; for (i = 0; i < sv.num_edicts; i++) { diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 3f5e248e2..d1d795de8 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -351,7 +351,7 @@ SV_ConnectClient (int clientnum) void SV_CheckForNewClients (void) { - int i; + unsigned i; struct qsocket_s *ret; // check for new connections @@ -443,7 +443,7 @@ SV_FatPVS (vec3_t org) static void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) { - int bits, e, i; + pr_uint_t bits, e; set_t *pvs; float miss; vec3_t org; @@ -489,7 +489,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) bits = 0; - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { miss = SVvector (ent, origin)[i] - baseline->origin[i]; if (miss < -0.1 || miss > 0.1) bits |= U_ORIGIN1 << i; @@ -603,7 +603,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) static void SV_CleanupEnts (void) { - int e; + pr_uint_t e; edict_t *ent; ent = NEXT_EDICT (&sv_pr_state, sv.edicts); @@ -826,7 +826,7 @@ SV_SendClientDatagram (client_t *client) static void SV_UpdateToReliableMessages (void) { - int i, j; + unsigned i, j; client_t *client; // check for changes to be sent over the reliable streams @@ -884,7 +884,7 @@ SV_SendNop (client_t *client) void SV_SendClientMessages (void) { - int i; + unsigned i; // update frags, names, etc SV_UpdateToReliableMessages (); @@ -964,7 +964,7 @@ SV_ModelIndex (const char *name) static void SV_CreateBaseline (void) { - int entnum; + pr_uint_t entnum; edict_t *svent; entity_state_t *baseline; int bits; @@ -1077,7 +1077,7 @@ SV_SendReconnect (void) void SV_SaveSpawnparms (void) { - int i, j; + unsigned i, j; svs.serverflags = *sv_globals.serverflags; @@ -1087,8 +1087,7 @@ SV_SaveSpawnparms (void) continue; // call the progs to get default spawn parms for the new client - *sv_globals.self = - EDICT_TO_PROG (&sv_pr_state, host_client->edict); + *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, host_client->edict); PR_ExecuteProgram (&sv_pr_state, sv_funcs.SetChangeParms); for (j = 0; j < NUM_SPAWN_PARMS; j++) host_client->spawn_parms[j] = sv_globals.parms[j]; @@ -1161,7 +1160,7 @@ SV_SpawnServer (const char *server) // leave slots at start for only clients sv.num_edicts = svs.maxclients + 1; - for (int i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { ent = EDICT_NUM (&sv_pr_state, i + 1); svs.clients[i].edict = ent; } @@ -1243,7 +1242,7 @@ SV_SpawnServer (const char *server) sv.signon.cursize); // send serverinfo to all connected clients - for (int i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { host_client = svs.clients + i; if (host_client->active) { SV_SendServerinfo (host_client); diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index ffaf35ae1..ab2b4f966 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -414,7 +414,7 @@ static qboolean SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) { float solid_save; - int num_moved, i, e; + int num_moved, i; edict_t *check, *block; edict_t **moved_edict; vec3_t move, org, org2; @@ -455,7 +455,7 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; + for (unsigned e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; @@ -484,8 +484,8 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // entity? c_absmin = SVvector (check, absmin); c_absmax = SVvector (check, absmax); - if (VectorCompCompare (c_absmin, >=, maxs) - || VectorCompCompare (c_absmax, <=, mins)) + if (VectorCompCompareAll (c_absmin, >=, maxs) + || VectorCompCompareAll (c_absmax, <=, mins)) continue; if (!SV_TestEntityPosition (check)) @@ -854,14 +854,14 @@ void SV_Physics (void) { edict_t *ent; - int i; SV_ProgStartFrame (); // treat each object in turn // even the world gets a chance to think ent = sv.edicts; - for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { + for (unsigned i = 0; i < sv.num_edicts; + i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { if (ent->free) continue; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 466fa92cb..eee7778a1 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -71,9 +71,9 @@ PF_error (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======SERVER ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); @@ -95,9 +95,9 @@ PF_objerror (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); ED_Free (pr, ed); @@ -287,7 +287,7 @@ PF_bprint (progs_t *pr) { const char *s; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); SV_BroadcastPrintf ("%s", s); } @@ -304,10 +304,10 @@ PF_sprint (progs_t *pr) { const char *s; client_t *client; - int entnum; + unsigned entnum; entnum = P_EDICTNUM (pr, 0); - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); if (entnum < 1 || entnum > svs.maxclients) { Sys_Printf ("tried to sprint to a non-client\n"); @@ -333,10 +333,10 @@ PF_centerprint (progs_t *pr) { const char *s; client_t *cl; - int entnum; + unsigned entnum; entnum = P_EDICTNUM (pr, 0); - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); if (entnum < 1 || entnum > svs.maxclients) { Sys_Printf ("tried to sprint to a non-client\n"); @@ -542,11 +542,11 @@ PF_checkpos (progs_t *pr) static set_t *checkpvs; -static int -PF_newcheckclient (progs_t *pr, int check) +static unsigned +PF_newcheckclient (progs_t *pr, unsigned check) { edict_t *ent; - int i; + unsigned i; mleaf_t *leaf; vec3_t org; @@ -656,7 +656,7 @@ PF_stuffcmd (progs_t *pr) { const char *str; client_t *old; - int entnum; + pr_uint_t entnum; entnum = P_EDICTNUM (pr, 0); if (entnum < 1 || entnum > svs.maxclients) @@ -700,7 +700,7 @@ PF_findradius (progs_t *pr) edict_t *ent, *chain; float rsqr; vec_t *emins, *emaxs, *org; - int i, j; + pr_uint_t i; vec3_t eorg; chain = (edict_t *) sv.edicts; @@ -717,7 +717,7 @@ PF_findradius (progs_t *pr) continue; emins = SVvector (ent, absmin); emaxs = SVvector (ent, absmax); - for (j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) eorg[j] = org[j] - 0.5 * (emins[j] + emaxs[j]); if (DotProduct (eorg, eorg) > rsqr) continue; @@ -731,7 +731,7 @@ PF_findradius (progs_t *pr) // entity () spawn static void -PF_Spawn (progs_t *pr) +PF_spawn (progs_t *pr) { edict_t *ed; @@ -741,7 +741,7 @@ PF_Spawn (progs_t *pr) // void (entity e) remove static void -PF_Remove (progs_t *pr) +PF_remove (progs_t *pr) { edict_t *ed; @@ -798,6 +798,7 @@ PF_precache_file (progs_t *pr) // precache_file is used only to copy files with qcc, it does nothing R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_file2 PF_precache_file // void (string s) precache_sound // string (string s) precache_sound2 @@ -808,6 +809,7 @@ PF_precache_sound (progs_t *pr) "precache_sound"); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_sound2 PF_precache_sound // void (string s) precache_model // string (string s) precache_model2 @@ -821,6 +823,7 @@ PF_precache_model (progs_t *pr) sv.models[ind] = Mod_ForName (mod, true); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_model2 PF_precache_model /* PF_walkmove @@ -903,7 +906,8 @@ PF_lightstyle (progs_t *pr) { const char *val; client_t *cl; - int style, j; + int style; + unsigned j; style = P_FLOAT (pr, 0); val = P_GSTRING (pr, 1); @@ -960,7 +964,7 @@ PF_aim (progs_t *pr) edict_t *ent, *check, *bestent; float dist, bestdist, speed; float *mins, *maxs, *org; - int i, j; + pr_uint_t i; trace_t tr; vec3_t start, dir, end, bestdir; @@ -1000,7 +1004,7 @@ PF_aim (progs_t *pr) mins = SVvector (check, mins); maxs = SVvector (check, maxs); org = SVvector (check, origin); - for (j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) end[j] = org[j] + 0.5 * (mins[j] + maxs[j]); VectorSubtract (end, start, dir); VectorNormalize (dir); @@ -1075,7 +1079,7 @@ PF_changeyaw (progs_t *pr) static __attribute__((pure)) sizebuf_t * WriteDest (progs_t *pr) { - int entnum; + pr_uint_t entnum; int dest; edict_t *ent; @@ -1110,10 +1114,24 @@ static void PF_WriteBytes (progs_t *pr) { int i, p; + int argc = pr->pr_argc - 1; + pr_type_t **argv = pr->pr_params + 1; sizebuf_t *msg = WriteDest (pr); - for (i = 1; i < pr->pr_argc; i++) { - p = P_FLOAT (pr, i); + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + argc = va_list->count; + if (argc) { + argv = alloca (argc * sizeof (pr_type_t *)); + for (int i = 0; i < argc; i++) { + argv[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + argv = 0; + } + } + for (i = 0; i < argc; i++) { + p = argv[i]->float_var; MSG_WriteByte (msg, p); } } @@ -1256,7 +1274,7 @@ PF_setspawnparms (progs_t *pr) { client_t *client; edict_t *ent; - int i; + unsigned i; ent = P_EDICT (pr, 0); i = NUM_FOR_EDICT (pr, ent); @@ -1473,78 +1491,83 @@ PF_checkextension (progs_t *pr) #define QF (PR_RANGE_QF << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"makevectors", PF_makevectors, 1}, - {"setorigin", PF_setorigin, 2}, - {"setmodel", PF_setmodel, 3}, - {"setsize", PF_setsize, 4}, + bi(makevectors, 1, 1, p(vector)), + bi(setorigin, 2, 2, p(entity), p(vector)), + bi(setmodel, 3, 2, p(entity), p(string)), + bi(setsize, 4, 3, p(entity), p(vector), p(vector)), - {"sound", PF_sound, 8}, + bi(sound, 8, 3, p(entity), p(float), p(string)), - {"error", PF_error, 10}, - {"objerror", PF_objerror, 11}, - {"spawn", PF_Spawn, 14}, - {"remove", PF_Remove, 15}, - {"traceline", PF_traceline, 16}, - {"checkclient", PF_checkclient, 17}, + bi(error, 10, -1), // (...) + bi(objerror, 11, -1), // (...) + bi(spawn, 14, 0), // (void) + bi(remove, 15, 1, p(entity)), + bi(traceline, 16, 3, p(vector), p(vector), p(float)), + bi(checkclient, 17, 0), // (void) - {"precache_sound", PF_precache_sound, 19}, - {"precache_model", PF_precache_model, 20}, - {"stuffcmd", PF_stuffcmd, 21}, - {"findradius", PF_findradius, 22}, - {"bprint", PF_bprint, 23}, - {"sprint", PF_sprint, 24}, + bi(precache_sound, 19, 1, p(string)), + bi(precache_model, 20, 1, p(string)), + bi(stuffcmd, 21, 2, p(entity), p(string)), + bi(findradius, 22, 2, p(vector), p(float)), + bi(bprint, 23, -1), // (...) + bi(sprint, 24, -2, p(entity)), // (entity, string...) - {"walkmove", PF_walkmove, 32}, + bi(walkmove, 32, 2, p(float), p(float)), - {"droptofloor", PF_droptofloor, 34}, - {"lightstyle", PF_lightstyle, 35}, + bi(droptofloor, 34, 0), // (void) + bi(lightstyle, 35, 2, p(float), p(string)), - {"checkbottom", PF_checkbottom, 40}, - {"pointcontents", PF_pointcontents, 41}, + bi(checkbottom, 40, 1, p(entity)), + bi(pointcontents, 41, 1, p(vector)), - {"aim", PF_aim, 44}, + bi(aim, 44, 2, p(entity), p(float)), - {"localcmd", PF_localcmd, 46}, + bi(localcmd, 46, 1, p(string)), - {"particle", PF_particle, 48}, - {"changeyaw", PF_changeyaw, 49}, + bi(particle, 48, 4, p(vector), p(vector), p(float), p(float)), + bi(changeyaw, 49, 0), // (void) - {"writebyte", PF_WriteByte, 52}, - {"WriteBytes", PF_WriteBytes, -1}, - {"writechar", PF_WriteChar, 53}, - {"writeshort", PF_WriteShort, 54}, - {"writelong", PF_WriteLong, 55}, - {"writecoord", PF_WriteCoord, 56}, - {"writeangle", PF_WriteAngle, 57}, - {"WriteCoordV", PF_WriteCoordV, -1}, - {"WriteAngleV", PF_WriteAngleV, -1}, - {"writestring", PF_WriteString, 58}, - {"writeentity", PF_WriteEntity, 59}, + bi(WriteByte, 52, 2, p(float), p(float)), + bi(WriteBytes, -1, -2, p(float)), // (float, float...) + bi(WriteChar, 53, 2, p(float), p(float)), + bi(WriteShort, 54, 2, p(float), p(float)), + bi(WriteLong, 55, 2, p(float), p(float)), + bi(WriteCoord, 56, 2, p(float), p(float)), + bi(WriteAngle, 57, 2, p(float), p(float)), + bi(WriteCoordV, -1, 2, p(float), p(vector)), + bi(WriteAngleV, -1, 2, p(float), p(vector)), + bi(WriteString, 58, 2, p(float), p(string)), + bi(WriteEntity, 59, 2, p(float), p(entity)), +#define PF_movetogoal SV_MoveToGoal + bi(movetogoal, 67, 0), // (void) +#undef PF_movetogoal + bi(precache_file, 68, 1, p(string)), + bi(makestatic, 69, 1, p(entity)), + bi(changelevel, 70, 1, p(string)), - {"movetogoal", SV_MoveToGoal, 67}, - {"precache_file", PF_precache_file, 68}, - {"makestatic", PF_makestatic, 69}, - {"changelevel", PF_changelevel, 70}, - - {"centerprint", PF_centerprint, 73}, - {"ambientsound", PF_ambientsound, 74}, - {"precache_model2", PF_precache_model, 75}, - {"precache_sound2", PF_precache_sound, 76}, - {"precache_file2", PF_precache_file, 77}, - {"setspawnparms", PF_setspawnparms, 78}, - - {"testentitypos", PF_testentitypos, QF 92}, - {"hullpointcontents", PF_hullpointcontents, QF 93}, - {"getboxbounds", PF_getboxbounds, QF 94}, - {"getboxhull", PF_getboxhull, QF 95}, - {"freeboxhull", PF_freeboxhull, QF 96}, - {"rotate_bbox", PF_rotate_bbox, QF 97}, - {"tracebox", PF_tracebox, QF 98}, - {"checkextension", PF_checkextension, QF 99}, - - {"EntityParseFunction", ED_EntityParseFunction, -1}, + bi(centerprint, 73, -1), // (...) + bi(ambientsound, 74, 4, p(vector), p(string), p(float), p(float)), + bi(precache_model2, 75, 1, p(string)), + bi(precache_sound2, 76, 1, p(string)), + bi(precache_file2, 77, 1, p(string)), + bi(setspawnparms, 78, 1, p(entity)), + bi(testentitypos, QF 92, 1, p(entity)), + bi(hullpointcontents, QF 93, 2, p(entity), p(vector)), + bi(getboxbounds, QF 94, 2, p(int), p(int)), + bi(getboxhull, QF 95, 0), // (void) + bi(freeboxhull, QF 96, 1, p(int)), + bi(rotate_bbox, QF 97, 6, p(int), p(vector), p(vector), p(vector), + p(vector), p(vector)), + bi(tracebox, QF 98, 6, p(vector), p(vector), p(vector), p(vector), + p(float), p(entity)), + bi(checkextension, QF 99, -1, {}), //FIXME correct params? +#define PF_EntityParseFunction ED_EntityParseFunction + bi(EntityParseFunction, -1, 1, p(func)), +#undef PF_EntityParseFunction {0} }; @@ -1555,5 +1578,5 @@ SV_PR_Cmds_Init () PR_Cmds_Init (&sv_pr_state); - PR_RegisterBuiltins (&sv_pr_state, builtins); + PR_RegisterBuiltins (&sv_pr_state, builtins, 0); } diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 58f79bc7e..a0235e108 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -57,6 +57,7 @@ sv_data_t sv_data[MAX_EDICTS]; cvar_t *sv_progs; cvar_t *sv_progs_zone; +cvar_t *sv_progs_stack; cvar_t *sv_progs_ext; cvar_t *pr_checkextensions; @@ -323,7 +324,7 @@ static sv_def_t nq_opt_funcs[] = { }; static sv_def_t nq_opt_fields[] = { - {ev_integer, 0, "rotated_bbox", &sv_fields.rotated_bbox}, + {ev_int, 0, "rotated_bbox", &sv_fields.rotated_bbox}, {ev_float, 0, "alpha", &sv_fields.alpha}, {ev_float, 0, "gravity", &sv_fields.gravity}, {ev_float, 0, "items2", &sv_fields.items2}, @@ -339,12 +340,13 @@ set_address (sv_def_t *def, void *address) switch (def->type) { case ev_void: case ev_short: + case ev_ushort: case ev_invalid: case ev_type_count: break; case ev_float: case ev_vector: - case ev_quat: + case ev_quaternion: *(float **)def->field = (float *) address; break; case ev_double: @@ -354,10 +356,14 @@ set_address (sv_def_t *def, void *address) case ev_entity: case ev_field: case ev_func: - case ev_pointer: - case ev_integer: - case ev_uinteger: - *(int **)def->field = (int *) address; + case ev_ptr: + case ev_int: + case ev_uint: + *(pr_int_t **)def->field = (pr_int_t *) address; + break; + case ev_long: + case ev_ulong: + *(pr_long_t **)def->field = (pr_long_t *) address; break; } } @@ -393,13 +399,13 @@ resolve_functions (progs_t *pr, sv_def_t *def, int mode) if (mode == 2) { for (; def->name; def++) - *(func_t *) def->field = G_FUNCTION (pr, def->offset); + *(pr_func_t *) def->field = G_FUNCTION (pr, def->offset); return 1; } for (; def->name; def++) { dfunc = PR_FindFunction (pr, def->name); if (dfunc) { - *(func_t *) def->field = dfunc - pr->pr_functions; + *(pr_func_t *) def->field = dfunc - pr->pr_functions; } else if (mode) { PR_Undefined (pr, "function", def->name); ret = 0; @@ -456,7 +462,7 @@ resolve (progs_t *pr) resolve_fields (pr, nq_opt_fields, 0); // progs engine needs these globals anyway sv_pr_state.globals.self = sv_globals.self; - sv_pr_state.globals.time = sv_globals.time; + sv_pr_state.globals.ftime = sv_globals.time;//FIXME double time return ret; } @@ -509,6 +515,7 @@ SV_LoadProgs (void) sv_pr_state.max_edicts = sv.max_edicts; sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; + sv_pr_state.stack_size = sv_progs_stack->int_val * 1024; sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name); @@ -556,6 +563,8 @@ SV_Progs_Init_Cvars (void) "Override the default game progs."); sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, "size of the zone for progs in kb"); + sv_progs_stack = Cvar_Get ("sv_progs_stack", "256", CVAR_NONE, NULL, + "size of the stack for progs in kb"); sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL, "extention mapping to use: " "none, id, qf"); diff --git a/nq/source/sv_user.c b/nq/source/sv_user.c index 0475efc0a..87623e7d6 100644 --- a/nq/source/sv_user.c +++ b/nq/source/sv_user.c @@ -584,7 +584,7 @@ SV_ReadClientMessage (void) void SV_RunClients (void) { - int i; + unsigned i; for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++) { diff --git a/nq/source/world.c b/nq/source/world.c index 5f8bce898..b8b423d83 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -215,7 +215,7 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, vec3_t hullmins, hullmaxs, size; if ((sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) + && SVint (ent, rotated_bbox)) || SVfloat (ent, solid) == SOLID_BSP) { VectorSubtract (maxs, mins, size); if (size[0] < 3) @@ -226,8 +226,8 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, hull_index = 2; } if (sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) { - int h = SVinteger (ent, rotated_bbox) - 1; + && SVint (ent, rotated_bbox)) { + int h = SVint (ent, rotated_bbox) - 1; hull_list = pf_hull_list[h]->hulls; } if (SVfloat (ent, solid) == SOLID_BSP) { // explicit hulls in the BSP model @@ -780,11 +780,10 @@ SV_ClipToLinks (areanode_t *node, moveclip_t *clip) edict_t *touch; link_t *l, *next; trace_t trace; - int i; if (clip->type == TL_EVERYTHING) { touch = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (i = 1; i < sv.num_edicts; i++, + for (unsigned i = 1; i < sv.num_edicts; i++, touch = NEXT_EDICT (&sv_pr_state, touch)) { if (clip->trace.allsolid) return; @@ -897,7 +896,6 @@ SV_Move (const vec3_t start, const vec3_t mins, const vec3_t maxs, edict_t * SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) { - int e; edict_t *check; hull_t *hull; vec3_t boxmins, boxmaxs, offset; @@ -912,8 +910,8 @@ SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) VectorAdd (origin, SVvector (ent, maxs), boxmaxs); check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, - check)) { + for (unsigned e = 1; e < sv.num_edicts; + e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; if (check == ent) diff --git a/qw/include/server.h b/qw/include/server.h index ebe9cf2ce..bd7fb8062 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -81,7 +81,7 @@ typedef struct { const char *lightstyles[MAX_LIGHTSTYLES]; struct model_s *models[MAX_MODELS]; - int num_edicts; // increases towards MAX_EDICTS + unsigned num_edicts; // increases towards MAX_EDICTS struct edict_s *edicts; // can NOT be array indexed, because // struct edict_s is variable sized, but can // be used to reference the world ent @@ -304,8 +304,8 @@ typedef struct { int spawncount; // number of servers spawned since start, // used to check late spawns client_t clients[MAX_CLIENTS]; - int maxclients; - int num_clients; + unsigned maxclients; + unsigned num_clients; int serverflags; // episode completion information void (*phys_client) (struct edict_s *ent, int num); diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index 88fe18c24..701475b7e 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -38,14 +38,14 @@ #include "sv_pr_cmds.h" typedef struct { - pr_int_t *self; - pr_int_t *other; - pr_int_t *world; + pr_uint_t *self; + pr_uint_t *other; + pr_uint_t *world; float *time; float *frametime; - pr_int_t *newmis; + pr_uint_t *newmis; float *force_retouch; - string_t *mapname; + pr_string_t *mapname; float *serverflags; float *total_secrets; float *total_monsters; @@ -61,35 +61,35 @@ typedef struct { vec3_t *trace_endpos; vec3_t *trace_plane_normal; float *trace_plane_dist; - pr_int_t *trace_ent; + pr_uint_t *trace_ent; float *trace_inopen; float *trace_inwater; - pr_int_t *msg_entity; + pr_uint_t *msg_entity; float *skill; } sv_globals_t; extern sv_globals_t sv_globals; typedef struct { - func_t main; - func_t StartFrame; - func_t PlayerPreThink; - func_t PlayerPostThink; - func_t ClientKill; - func_t ClientConnect; - func_t PutClientInServer; - func_t ClientDisconnect; - func_t SetNewParms; - func_t SetChangeParms; + pr_func_t main; + pr_func_t StartFrame; + pr_func_t PlayerPreThink; + pr_func_t PlayerPostThink; + pr_func_t ClientKill; + pr_func_t ClientConnect; + pr_func_t PutClientInServer; + pr_func_t ClientDisconnect; + pr_func_t SetNewParms; + pr_func_t SetChangeParms; - func_t EndFrame; - func_t SpectatorConnect; - func_t SpectatorThink; - func_t SpectatorDisconnect; - func_t UserInfoCallback; - func_t UserInfoChanged; - func_t ChatMessage; - func_t LocalinfoChanged; + pr_func_t EndFrame; + pr_func_t SpectatorConnect; + pr_func_t SpectatorThink; + pr_func_t SpectatorDisconnect; + pr_func_t UserInfoCallback; + pr_func_t UserInfoChanged; + pr_func_t ChatMessage; + pr_func_t LocalinfoChanged; } sv_funcs_t; extern sv_funcs_t sv_funcs; @@ -108,23 +108,23 @@ typedef struct pr_int_t velocity; //vec3_t pr_int_t angles; //vec3_t pr_int_t avelocity; //vec3_t - pr_int_t classname; //string_t - pr_int_t model; //string_t + pr_int_t classname; //pr_string_t + pr_int_t model; //pr_string_t pr_int_t frame; //float pr_int_t skin; //float pr_int_t effects; //float pr_int_t mins; //vec3_t pr_int_t maxs; //vec3_t pr_int_t size; //vec3_t - pr_int_t touch; //func_t - pr_int_t think; //func_t - pr_int_t blocked; //func_t + pr_int_t touch; //pr_func_t + pr_int_t think; //pr_func_t + pr_int_t blocked; //pr_func_t pr_int_t nextthink; //float pr_int_t groundentity; //int pr_int_t health; //float pr_int_t frags; //float pr_int_t weapon; //float - pr_int_t weaponmodel; //string_t + pr_int_t weaponmodel; //pr_string_t pr_int_t weaponframe; //float pr_int_t currentammo; //float pr_int_t ammo_shells; //float @@ -141,7 +141,7 @@ typedef struct pr_int_t impulse; //float pr_int_t fixangle; //float pr_int_t v_angle; //vec3_t - pr_int_t netname; //string_t + pr_int_t netname; //pr_string_t pr_int_t enemy; //int pr_int_t flags; //float pr_int_t colormap; //float @@ -158,7 +158,7 @@ typedef struct pr_int_t dmg_save; //float pr_int_t dmg_inflictor; //int pr_int_t owner; //int - pr_int_t message; //string_t + pr_int_t message; //pr_string_t pr_int_t sounds; //float pr_int_t rotated_bbox; //int @@ -194,7 +194,7 @@ extern progs_t sv_pr_state; #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) #define SVvector(e,f) (&SVFIELD (e, f, vector)) -#define SVinteger(e,f) SVFIELD (e, f, integer) +#define SVint(e,f) SVFIELD (e, f, int) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) #else @@ -218,19 +218,29 @@ typedef struct sv_data_s { #define EDICT_FROM_AREA(l) (STRUCT_FROM_LINK(l,sv_data_t,area)->edict) static inline void -sv_pr_touch (edict_t *self, edict_t *other) +sv_pr_exec (edict_t *self, edict_t *other, pr_func_t func) { pr_int_t this; *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); if ((this = sv_pr_state.fields.this) != -1) { + PR_PushFrame (&sv_pr_state); PR_RESET_PARAMS (&sv_pr_state); P_INT (&sv_pr_state, 0) = E_POINTER (self, this); P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); + P_INT (&sv_pr_state, 2) = other ? E_POINTER (other, this) : 0; } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, touch)); + PR_ExecuteProgram (&sv_pr_state, func); + if ((this = sv_pr_state.fields.this) != -1) { + PR_PopFrame (&sv_pr_state); + } +} + +static inline void +sv_pr_touch (edict_t *self, edict_t *other) +{ + sv_pr_exec (self, other, SVfunc (self, touch)); } static inline void @@ -241,33 +251,13 @@ sv_pr_use (edict_t *self, edict_t *other) static inline void sv_pr_think (edict_t *self) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = 0; - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = 0; - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, think)); + sv_pr_exec (self, 0, SVfunc (self, think)); } static inline void sv_pr_blocked (edict_t *self, edict_t *other) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, blocked)); + sv_pr_exec (self, other, SVfunc (self, blocked)); } #endif // __sv_progs_h diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 39d27b249..e82e45d10 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -422,7 +422,7 @@ CL_GetMessage (void) if (net_packetlog->int_val) Log_Incoming_Packet (net_message->message->data, - net_message->message->cursize, 1, 0); + net_message->message->cursize, 1); if (cls.demorecording) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 98ed535a5..bfd520246 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1027,7 +1027,7 @@ CL_ReadPackets (void) if (cls.demoplayback && net_packetlog->int_val) Log_Incoming_Packet (net_message->message->data, - net_message->message->cursize, 0, 0); + net_message->message->cursize, 0); // remote command packet if (*(int *) net_message->message->data == -1) { @@ -1863,7 +1863,7 @@ Host_Init (void) for (i = 0; i < MAX_MODELS; i++) sound_precache[i] = cl.sound_name[i]; - Net_Log_Init (sound_precache); + Net_Log_Init (sound_precache, 0); } CL_HTTP_Init (); diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 72dbe22d0..92cddcb38 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -166,6 +166,7 @@ static QFile *Net_PacketLog; static const char **Net_sound_precache; static sizebuf_t _packet; static qmsg_t packet = {0, 0, &_packet}; +static int is_server = 0; static int Net_LogStart (const char *fname) @@ -224,7 +225,7 @@ ascii_dump_buf (unsigned char *buf, int len) } */ void -Log_Incoming_Packet (const byte *p, int len, int has_sequence, int is_server) +Log_Incoming_Packet (const byte *p, int len, int has_sequence) { if (!net_loglevel->int_val) return; @@ -248,7 +249,7 @@ Log_Incoming_Packet (const byte *p, int len, int has_sequence, int is_server) } void -Log_Outgoing_Packet (const byte *p, int len, int has_sequence, int is_server) +Log_Outgoing_Packet (const byte *p, int len, int has_sequence) { if (!net_loglevel->int_val) return; @@ -520,6 +521,7 @@ Parse_Server_Packet (int has_sequence) break; case svc_temp_entity: i = MSG_ReadByte (&packet); + Net_LogPrintf (" type %d", i); switch (i) { case 0: case 1: @@ -952,7 +954,7 @@ Analyze_Client_Packet (const byte * data, int len, int has_sequence) static void net_packet_log_f (int length, const void *data, netadr_t to) { - Log_Outgoing_Packet (data, length, 1, 1); + Log_Outgoing_Packet (data, length, 1); } static void @@ -981,8 +983,9 @@ Net_PacketLog_Zap_f (void) } int -Net_Log_Init (const char **sound_precache) +Net_Log_Init (const char **sound_precache, int server) { + is_server = server; Net_sound_precache = sound_precache; _stdout = Qdopen (1, "wt"); // create a QFile of stdout diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 30a0a12d2..929cd4853 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -122,11 +122,8 @@ SV_FlushSignon (void) static void SV_CreateBaseline (void) { - int entnum; - edict_t *svent; - - for (entnum = 0; entnum < sv.num_edicts; entnum++) { - svent = EDICT_NUM (&sv_pr_state, entnum); + for (unsigned entnum = 0; entnum < sv.num_edicts; entnum++) { + edict_t *svent = EDICT_NUM (&sv_pr_state, entnum); if (svent->free) continue; // create baselines for all player slots, diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index c97fc8647..1d81ff1af 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -1747,7 +1747,7 @@ void SV_OutOfBand (netadr_t adr, unsigned length, byte *data) { if (net_packetlog->int_val) { - Log_Outgoing_Packet (data, length, 0, 1); + Log_Outgoing_Packet (data, length, 0); } Netchan_OutOfBand (adr, length, data); } @@ -1781,7 +1781,7 @@ SV_ReadPackets (void) while (NET_GetPacket ()) { if (net_packetlog->int_val) Log_Incoming_Packet (net_message->message->data, - net_message->message->cursize, 1, 1); + net_message->message->cursize, 1); if (SV_FilterIP (net_from.ip, &until)) { SV_SendBan (until); // tell them we aren't listening... continue; @@ -2465,7 +2465,7 @@ SV_InitNet (void) Netchan_Init (); net_realtime = &realtime; - Net_Log_Init (sv.sound_precache); + Net_Log_Init (sv.sound_precache, 1); svs.last_heartbeat = -99999; // send immediately sv_net_initialized = 1; diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 41ae45ccd..856a5ef16 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -417,7 +417,7 @@ static qboolean SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) { float solid_save; - int num_moved, i, e; + int num_moved, i; edict_t *check, *block; edict_t **moved_edict; vec3_t move, org, org2; @@ -458,7 +458,7 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; + for (unsigned e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; @@ -487,8 +487,8 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // entity? c_absmin = SVvector (check, absmin); c_absmax = SVvector (check, absmax); - if (VectorCompCompare (c_absmin, >=, maxs) - || VectorCompCompare (c_absmax, <=, mins)) + if (VectorCompCompareAll (c_absmin, >=, maxs) + || VectorCompCompareAll (c_absmax, <=, mins)) continue; if (!SV_TestEntityPosition (check)) @@ -862,14 +862,14 @@ void SV_Physics (void) { edict_t *ent; - int i; SV_ProgStartFrame (); // treat each object in turn // even the world gets a chance to think ent = sv.edicts; - for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { + for (unsigned i = 0; i < sv.num_edicts; + i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { if (ent->free) continue; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 36498b8bd..f2e9b8a37 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -73,9 +73,9 @@ PF_error (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======SERVER ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); @@ -97,9 +97,9 @@ PF_objerror (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); ED_Free (pr, ed); @@ -222,7 +222,7 @@ PF_bprint (progs_t *pr) level = P_FLOAT (pr, 0); - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); SV_BroadcastPrintf (level, "%s", s); } @@ -254,7 +254,7 @@ PF_sprint (progs_t *pr) if (client->state == cs_server) //FIXME record to mvd? return; - s = PF_VarString (pr, 2); + s = PF_VarString (pr, 2, 3); SV_ClientPrintf (1, client, level, "%s", s); } @@ -286,7 +286,7 @@ PF_centerprint (progs_t *pr) if (cl->state == cs_server) //FIXME record to mvd? return; - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); MSG_ReliableWrite_Begin (&cl->backbuf, svc_centerprint, 2 + strlen (s)); MSG_ReliableWrite_String (&cl->backbuf, s); @@ -653,7 +653,6 @@ PF_findradius (progs_t *pr) edict_t *ent, *chain; float rsqr; vec_t *emins, *emaxs, *org; - int i, j; vec3_t eorg; chain = (edict_t *) sv.edicts; @@ -663,7 +662,7 @@ PF_findradius (progs_t *pr) rsqr *= rsqr; // Square early, sqrt never ent = NEXT_EDICT (pr, sv.edicts); - for (i = 1; i < sv.num_edicts; i++, ent = NEXT_EDICT (pr, ent)) { + for (unsigned i = 1; i < sv.num_edicts; i++, ent = NEXT_EDICT (pr, ent)) { if (ent->free) continue; if (SVfloat (ent, solid) == SOLID_NOT @@ -671,7 +670,7 @@ PF_findradius (progs_t *pr) continue; emins = SVvector (ent, absmin); emaxs = SVvector (ent, absmax); - for (j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) eorg[j] = org[j] - 0.5 * (emins[j] + emaxs[j]); if (DotProduct (eorg, eorg) > rsqr) continue; @@ -685,7 +684,7 @@ PF_findradius (progs_t *pr) // entity () spawn static void -PF_Spawn (progs_t *pr) +PF_spawn (progs_t *pr) { edict_t *ed; @@ -697,7 +696,7 @@ cvar_t *pr_double_remove; // void (entity e) remove static void -PF_Remove (progs_t *pr) +PF_remove (progs_t *pr) { edict_t *ed; @@ -768,6 +767,7 @@ PF_precache_file (progs_t *pr) // precache_file is used only to copy files with qcc, it does nothing R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_file2 PF_precache_file // void (string s) precache_sound // string (string s) precache_sound2 @@ -778,6 +778,7 @@ PF_precache_sound (progs_t *pr) "precache_sound"); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_sound2 PF_precache_sound // void (string s) precache_model // string (string s) precache_model2 @@ -788,6 +789,7 @@ PF_precache_model (progs_t *pr) "precache_model"); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_model2 PF_precache_model /* PF_walkmove @@ -936,7 +938,7 @@ PF_aim (progs_t *pr) edict_t *ent, *check, *bestent; float dist, bestdist, speed; float *mins, *maxs, *org; - int i, j; + unsigned i, j; trace_t tr; vec3_t start, dir, end, bestdir; @@ -1115,11 +1117,24 @@ static void PF_WriteBytes (progs_t *pr) { int i, p; - int count = pr->pr_argc - 1; - byte buf[MAX_PARMS]; + byte buf[PR_MAX_PARAMS]; + int argc = pr->pr_argc - 1; + pr_type_t **argv = pr->pr_params + 1; - for (i = 0; i < count; i++) { - p = P_FLOAT (pr, i + 1); + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + argc = va_list->count; + if (argc) { + argv = alloca (argc * sizeof (pr_type_t *)); + for (int i = 0; i < argc; i++) { + argv[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + argv = 0; + } + } + for (i = 0; i < argc; i++) { + p = argv[i]->float_var; buf[i] = p; } @@ -1127,17 +1142,17 @@ PF_WriteBytes (progs_t *pr) client_t *cl = Write_GetClient (pr); if (cl->state != cs_server) { - MSG_ReliableCheckBlock (&cl->backbuf, count); - MSG_ReliableWrite_SZ (&cl->backbuf, buf, count); + MSG_ReliableCheckBlock (&cl->backbuf, argc); + MSG_ReliableWrite_SZ (&cl->backbuf, buf, argc); } if (sv.recorders) { sizebuf_t *dbuf; - dbuf = SVR_WriteBegin (dem_single, cl - svs.clients, count); - SZ_Write (dbuf, buf, count); + dbuf = SVR_WriteBegin (dem_single, cl - svs.clients, argc); + SZ_Write (dbuf, buf, argc); } } else { sizebuf_t *msg = WriteDest (pr); - SZ_Write (msg, buf, count); + SZ_Write (msg, buf, argc); } } @@ -1640,7 +1655,7 @@ PF_testentitypos (progs_t *pr) #define MAX_PF_HULLS 64 // FIXME make dynamic? clip_hull_t *pf_hull_list[MAX_PF_HULLS]; -// integer (entity ent, vector point) hullpointcontents +// int (entity ent, vector point) hullpointcontents static void PF_hullpointcontents (progs_t *pr) { @@ -1656,7 +1671,7 @@ PF_hullpointcontents (progs_t *pr) R_INT (pr) = SV_HullPointContents (hull, 0, offset); } -// vector (integer hull, integer max) getboxbounds +// vector (int hull, int max) getboxbounds static void PF_getboxbounds (progs_t *pr) { @@ -1673,7 +1688,7 @@ PF_getboxbounds (progs_t *pr) } } -// integer () getboxhull +// int () getboxhull static void PF_getboxhull (progs_t *pr) { @@ -1698,7 +1713,7 @@ PF_getboxhull (progs_t *pr) } } -// void (integer hull) freeboxhull +// void (int hull) freeboxhull static void PF_freeboxhull (progs_t *pr) { @@ -1728,7 +1743,7 @@ calc_dist (vec3_t p, vec3_t n, vec3_t *offsets) return DotProduct (v, n); } -// void (integer hull, vector right, vector forward, vector up, vector mins, vector maxs) rotate_bbox +// void (int hull, vector right, vector forward, vector up, vector mins, vector maxs) rotate_bbox static void PF_rotate_bbox (progs_t *pr) { @@ -1829,7 +1844,7 @@ PF_sv_cvar (progs_t *pr) } } -// int () SV_ClientNumber +// int (entity) SV_ClientNumber // returns -1 if the entity is not a client (either not in the client range // or the entity is not in use by a client) static void @@ -1838,7 +1853,8 @@ PF_SV_ClientNumber (progs_t *pr) int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; - if (entnum < 1 || entnum > MAX_CLIENTS || cl->state != cs_server) { + if (entnum < 1 || entnum > MAX_CLIENTS + || cl->state == cs_free || cl->state == cs_zombie) { entnum = 0; // nil entity } R_INT (pr) = entnum - 1; @@ -1899,9 +1915,9 @@ PF_SV_SetUserinfo (progs_t *pr) SV_ExtractFromUserinfo (cl); } -// void (entity cl, integer ping) SV_SetPing +// void (entity cl, int ping) SV_SetPing static void -PR_SV_SetPing (progs_t *pr) +PF_SV_SetPing (progs_t *pr) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1911,9 +1927,9 @@ PR_SV_SetPing (progs_t *pr) cl->ping = P_INT (pr, 1); } -// void (entity cl, float secs, vector angles, vector move, integer buttons, integer impulse) SV_UserCmd +// void (entity cl, float secs, vector angles, vector move, int buttons, int impulse) SV_UserCmd static void -PR_SV_UserCmd (progs_t *pr) +PF_SV_UserCmd (progs_t *pr) { usercmd_t ucmd; int entnum = P_EDICTNUM (pr, 0); @@ -1939,7 +1955,7 @@ PR_SV_UserCmd (progs_t *pr) // void (entity cl) SV_Spawn static void -PR_SV_Spawn (progs_t *pr) +PF_SV_Spawn (progs_t *pr) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1952,96 +1968,106 @@ PR_SV_Spawn (progs_t *pr) #define QF (PR_RANGE_QF << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"makevectors", PF_makevectors, 1}, - {"setorigin", PF_setorigin, 2}, - {"setmodel", PF_setmodel, 3}, - {"setsize", PF_setsize, 4}, + bi(makevectors, 1, 1, p(vector)), + bi(setorigin, 2, 2, p(entity), p(vector)), + bi(setmodel, 3, 2, p(entity), p(string)), + bi(setsize, 4, 3, p(entity), p(vector), p(vector)), - {"sound", PF_sound, 8}, + bi(sound, 8, 3, p(entity), p(float), p(string)), - {"error", PF_error, 10}, - {"objerror", PF_objerror, 11}, - {"spawn", PF_Spawn, 14}, - {"remove", PF_Remove, 15}, - {"traceline", PF_traceline, 16}, - {"checkclient", PF_checkclient, 17}, + bi(error, 10, -1), // (...) + bi(objerror, 11, -1), // (...) + bi(spawn, 14, 0), // (void) + bi(remove, 15, 1, p(entity)), + bi(traceline, 16, 3, p(vector), p(vector), p(float)), + bi(checkclient, 17, 0), // (void) - {"precache_sound", PF_precache_sound, 19}, - {"precache_model", PF_precache_model, 20}, - {"stuffcmd", PF_stuffcmd, 21}, - {"findradius", PF_findradius, 22}, - {"bprint", PF_bprint, 23}, - {"sprint", PF_sprint, 24}, + bi(precache_sound, 19, 1, p(string)), + bi(precache_model, 20, 1, p(string)), + bi(stuffcmd, 21, 2, p(entity), p(string)), + bi(findradius, 22, 2, p(vector), p(float)), + bi(bprint, 23, -1), // (...) + bi(sprint, 24, -2, p(entity)), // (entity, string...) - {"walkmove", PF_walkmove, 32}, + bi(walkmove, 32, 2, p(float), p(float)), - {"droptofloor", PF_droptofloor, 34}, - {"lightstyle", PF_lightstyle, 35}, + bi(droptofloor, 34, 0), // (void) + bi(lightstyle, 35, 2, p(float), p(string)), - {"checkbottom", PF_checkbottom, 40}, - {"pointcontents", PF_pointcontents, 41}, + bi(checkbottom, 40, 1, p(entity)), + bi(pointcontents, 41, 1, p(vector)), - {"aim", PF_aim, 44}, + bi(aim, 44, 2, p(entity), p(float)), - {"localcmd", PF_localcmd, 46}, + bi(localcmd, 46, 1, p(string)), - {"changeyaw", PF_changeyaw, 49}, +// bi(particle, 48, 4, p(vector), p(vector), p(float), p(float)), + bi(changeyaw, 49, 0), // (void) - {"writebyte", PF_WriteByte, 52}, - {"WriteBytes", PF_WriteBytes, -1}, - {"writechar", PF_WriteChar, 53}, - {"writeshort", PF_WriteShort, 54}, - {"writelong", PF_WriteLong, 55}, - {"writecoord", PF_WriteCoord, 56}, - {"writeangle", PF_WriteAngle, 57}, - {"WriteCoordV", PF_WriteCoordV, -1}, - {"WriteAngleV", PF_WriteAngleV, -1}, - {"writestring", PF_WriteString, 58}, - {"writeentity", PF_WriteEntity, 59}, + bi(WriteByte, 52, 2, p(float), p(float)), + bi(WriteBytes, -1, -2, p(float)), // (float, float...) + bi(WriteChar, 53, 2, p(float), p(float)), + bi(WriteShort, 54, 2, p(float), p(float)), + bi(WriteLong, 55, 2, p(float), p(float)), + bi(WriteCoord, 56, 2, p(float), p(float)), + bi(WriteAngle, 57, 2, p(float), p(float)), + bi(WriteCoordV, -1, 2, p(float), p(vector)), + bi(WriteAngleV, -1, 2, p(float), p(vector)), + bi(WriteString, 58, 2, p(float), p(string)), + bi(WriteEntity, 59, 2, p(float), p(entity)), +#define PF_movetogoal SV_MoveToGoal + bi(movetogoal, 67, 0), // (void) +#undef PF_movetogoal + bi(precache_file, 68, 1, p(string)), + bi(makestatic, 69, 1, p(entity)), + bi(changelevel, 70, 1, p(string)), - {"movetogoal", SV_MoveToGoal, 67}, - {"precache_file", PF_precache_file, 68}, - {"makestatic", PF_makestatic, 69}, - {"changelevel", PF_changelevel, 70}, + bi(centerprint, 73, -1), // (...) + bi(ambientsound, 74, 4, p(vector), p(string), p(float), p(float)), + bi(precache_model2, 75, 1, p(string)), + bi(precache_sound2, 76, 1, p(string)), + bi(precache_file2, 77, 1, p(string)), + bi(setspawnparms, 78, 1, p(entity)), - {"centerprint", PF_centerprint, 73}, - {"ambientsound", PF_ambientsound, 74}, - {"precache_model2", PF_precache_model, 75}, - {"precache_sound2", PF_precache_sound, 76}, - {"precache_file2", PF_precache_file, 77}, - {"setspawnparms", PF_setspawnparms, 78}, + bi(logfrag, 79, 2, p(entity), p(entity)), + bi(infokey, 80, 2, p(entity), p(string)), + bi(multicast, 82, 2, p(vector), p(float)), - {"logfrag", PF_logfrag, 79}, - {"infokey", PF_infokey, 80}, - {"multicast", PF_multicast, 82}, + bi(testentitypos, QF 92, 1, p(entity)), + bi(hullpointcontents, QF 93, 2, p(entity), p(vector)), + bi(getboxbounds, QF 94, 2, p(int), p(int)), + bi(getboxhull, QF 95, 0), // (void) + bi(freeboxhull, QF 96, 1, p(int)), + bi(rotate_bbox, QF 97, 6, p(int), p(vector), p(vector), p(vector), + p(vector), p(vector)), + bi(tracebox, QF 98, 6, p(vector), p(vector), p(vector), p(vector), + p(float), p(entity)), + bi(checkextension, QF 99, -1, {}), //FIXME correct params? - {"testentitypos", PF_testentitypos, QF 92}, - {"hullpointcontents", PF_hullpointcontents, QF 93}, - {"getboxbounds", PF_getboxbounds, QF 94}, - {"getboxhull", PF_getboxhull, QF 95}, - {"freeboxhull", PF_freeboxhull, QF 96}, - {"rotate_bbox", PF_rotate_bbox, QF 97}, - {"tracebox", PF_tracebox, QF 98}, - {"checkextension", PF_checkextension, QF 99}, - {"setinfokey", PF_setinfokey, QF 102}, - {"cfopen", PF_cfopen, QF 103}, - {"cfclose", PF_cfclose, QF 104}, - {"cfread", PF_cfread, QF 105}, - {"cfwrite", PF_cfwrite, QF 106}, - {"cfeof", PF_cfeof, QF 107}, - {"cfquota", PF_cfquota, QF 108}, + bi(setinfokey, QF 102, 3, p(entity), p(string), p(string)), + bi(cfopen, QF 103, 2, p(string), p(string)), + bi(cfclose, QF 104, 1, p(float)), + bi(cfread, QF 105, 1, p(float)), + bi(cfwrite, QF 106, 2, p(float), p(string)), + bi(cfeof, QF 107, 1, p(float)), + bi(cfquota, QF 108, 0), // (void) - {"SV_ClientNumber", PF_SV_ClientNumber, -1}, - {"SV_AllocClient", PF_SV_AllocClient, -1}, - {"SV_FreeClient", PF_SV_FreeClient, -1}, - {"SV_SetUserinfo", PF_SV_SetUserinfo, -1}, - {"SV_SetPing", PR_SV_SetPing, -1}, - {"SV_UserCmd", PR_SV_UserCmd, -1}, - {"SV_Spawn", PR_SV_Spawn, -1}, + bi(SV_ClientNumber, -1, 1, p(entity)), + bi(SV_AllocClient, -1, 0), // (void) + bi(SV_FreeClient, -1, 1, p(entity)), + bi(SV_SetUserinfo, -1, 2, p(entity), p(string)), + bi(SV_SetPing, -1, 2, p(entity), p(int)), + bi(SV_UserCmd, -1, 6, p(entity), p(float), p(vector), p(vector), + p(int), p(int)), + bi(SV_Spawn, -1, 1, p(entity)), - {"EntityParseFunction", ED_EntityParseFunction, -1}, +#define PF_EntityParseFunction ED_EntityParseFunction + bi(EntityParseFunction, -1, 1, p(func)), +#undef PF_EntityParseFunction {0} }; @@ -2058,5 +2084,5 @@ SV_PR_Cmds_Init () bi = PR_FindBuiltin (&sv_pr_state, "cvar"); bi->proc = PF_sv_cvar; - PR_RegisterBuiltins (&sv_pr_state, builtins); + PR_RegisterBuiltins (&sv_pr_state, builtins, 0); } diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index e2ac3ffd2..32e82e7b9 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -45,7 +45,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "world.h" static struct { - func_t ClientCommand; + pr_func_t ClientCommand; } cpqw_funcs; /* @@ -446,7 +446,7 @@ PF_putsaytime (progs_t *pr) static void PF_makestr (progs_t *pr) { - string_t res = PR_NewMutableString (pr); + pr_string_t res = PR_NewMutableString (pr); dstring_t *dst = PR_GetMutableString (pr, res); const char *src = P_GSTRING (pr, 0); @@ -729,7 +729,7 @@ PF_touchworld (progs_t *pr) #define TL_EVERYTHING 4 // scan for anything static void -CPQW_traceline (progs_t *pr) +PF_traceline (progs_t *pr) { float *v1, *v2; edict_t *ent; @@ -774,29 +774,33 @@ CPQW_traceline (progs_t *pr) #define CPQW (PR_RANGE_CPQW << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {"CPCW:"#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"CPCW:traceline", CPQW_traceline, CPQW 16}, - {"CPQW:getuid", PF_getuid, CPQW 83}, - {"CPQW:strcat", PF_strcat, CPQW 84}, - {"CPQW:padstr", PF_padstr, CPQW 85}, - {"CPQW:colstr", PF_colstr, CPQW 86}, - {"CPQW:strcasecmp", PF_strcasecmp, CPQW 87}, - {"CPQW:strlen", PF_strlen, CPQW 88}, - {"CPQW:getclient", PF_getclient, CPQW 89}, - {"CPQW:mutedtime", PF_mutedtime, CPQW 90}, - {"CPQW:validatefile", PF_validatefile, CPQW 91}, - {"CPQW:putsaytime", PF_putsaytime, CPQW 92}, - {"CPQW:makestr", PF_makestr, CPQW 93}, - {"CPQW:delstr", PF_delstr, CPQW 94}, - {"CPQW:getwave", PF_getwave, CPQW 95}, - {"CPQW:clientsound", PF_clientsound, CPQW 96}, - {"CPQW:touchworld", PF_touchworld, CPQW 97}, + bi(traceline, CPQW 16, 3, p(vector), p(vector), p(float)), + bi(getuid, CPQW 83, 1, p(entity)), + bi(strcat, CPQW 84, 2, p(string), p(string)), + bi(padstr, CPQW 85, 2, p(string), p(float)), + bi(colstr, CPQW 86, 2, p(string), p(float)), + bi(strcasecmp, CPQW 87, 2, p(string), p(string)), + bi(strlen, CPQW 88, 1, p(string)), + bi(getclient, CPQW 89, 1, p(string)), + bi(mutedtime, CPQW 90, 1, p(entity)), + bi(validatefile, CPQW 91, 1, p(string)), + bi(putsaytime, CPQW 92, 1, p(entity)), + bi(makestr, CPQW 93, 1, p(string)), + bi(delstr, CPQW 94, 1, p(string)), + bi(getwave, CPQW 95, 7, p(float), p(float), p(float), p(float), + p(float), p(float), p(float)), + bi(clientsound, CPQW 96, 1, p(entity)), + bi(touchworld, CPQW 97, 0), {0} }; static struct { const char *name; - func_t *field; + pr_func_t *field; } cpqw_func_list[] = { {"ClientCommand", &cpqw_funcs.ClientCommand}, {"UserInfoChanged", &sv_funcs.UserInfoChanged}, @@ -817,6 +821,7 @@ cpqw_user_cmd (void) *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv_player); PR_PushFrame (pr); + PR_RESET_PARAMS (pr); P_FLOAT (pr, 0) = argc; for (i = 1; i < argc + 1; i++) P_STRING (pr, i) = PR_SetTempString (pr, Cmd_Argv (i - 1)); @@ -841,7 +846,7 @@ cpqw_load (progs_t *pr) *cpqw_func_list[i].field = 0; if (f) - *cpqw_func_list[i].field = (func_t) (f - pr->pr_functions); + *cpqw_func_list[i].field = (pr_func_t) (f - pr->pr_functions); } ucmd_unknown = cpqw_user_cmd; return 1; @@ -850,6 +855,6 @@ cpqw_load (progs_t *pr) void SV_PR_CPQW_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); PR_AddLoadFunc (pr, cpqw_load); } diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index c5e5fb810..eb7322800 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -56,9 +56,9 @@ #include "qw/include/sv_recorder.h" typedef struct { - func_t timeofday; - func_t ConsoleCmd; - func_t UserCmd; + pr_func_t timeofday; + pr_func_t ConsoleCmd; + pr_func_t UserCmd; } qwe_funcs_t; static qwe_funcs_t qwe_funcs; @@ -190,7 +190,7 @@ PF_substr (progs_t *pr) static void PF_strcat (progs_t *pr) { - RETURN_STRING (pr, PF_VarString (pr, 0)); + RETURN_STRING (pr, PF_VarString (pr, 0, pr->pr_argc)); } /* @@ -354,7 +354,7 @@ PF_calltimeofday (progs_t *pr) P_STRING (pr, 6) = PR_SetReturnString (pr, date.str); pr->pr_argc = 7; - PR_ExecuteProgram (pr, (func_t) (f - sv_pr_state.pr_functions)); + PR_ExecuteProgram (pr, (pr_func_t) (f - sv_pr_state.pr_functions)); PR_PopFrame (&sv_pr_state); } } @@ -454,7 +454,7 @@ PF_log (progs_t *pr) name = va (0, "%s/%s.log", qfs_gamedir->dir.def, P_GSTRING (pr, 0)); file = QFS_Open (name, "a"); - text = PF_VarString (pr, 2); + text = PF_VarString (pr, 2, pr->pr_argc); clean_text (text); if (P_FLOAT (pr, 1)) @@ -475,40 +475,43 @@ PF_log (progs_t *pr) static void PF_conprint (progs_t *pr) { - Sys_Printf ("%s", PF_VarString (pr, 0)); + Sys_Printf ("%s", PF_VarString (pr, 0, pr->pr_argc)); } #define QWE (PR_RANGE_QWE << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {"QWE:"#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"QWE:executecmd", PF_executecmd, QWE 83}, - {"QWE:tokanize" /* sic */, PF_tokanize, QWE 84}, - {"QWE:argc", PF_argc, QWE 85}, - {"QWE:argv", PF_argv, QWE 86}, - {"QWE:teamfield", PF_teamfield, QWE 87}, - {"QWE:substr", PF_substr, QWE 88}, - {"QWE:strcat", PF_strcat, QWE 89}, - {"QWE:strlen", PF_strlen, QWE 90}, - {"QWE:str2byte", PF_str2byte, QWE 91}, - {"QWE:str2short", PF_str2short, QWE 92}, - {"QWE:newstr", PF_newstr, QWE 93}, - {"QWE:freestr", PF_freestr, QWE 94}, - {"QWE:conprint", PF_conprint, QWE 95}, - {"QWE:readcmd", PF_readcmd, QWE 96}, - {"QWE:strcpy", PF_strcpy, QWE 97}, - {"QWE:strstr", PF_strstr, QWE 98}, - {"QWE:strncpy", PF_strncpy, QWE 99}, - {"QWE:log", PF_log, QWE 100}, - {"QWE:redirectcmd", PF_redirectcmd, QWE 101}, - {"QWE:calltimeofday", PF_calltimeofday, QWE 102}, - {"QWE:forceddemoframe", PF_forcedemoframe, QWE 103}, + bi(executecmd, QWE 83, 0), + bi(tokanize, QWE 84, 1, p(string)), /* sic */ + bi(argc, QWE 85, 0), + bi(argv, QWE 86, 1, p(float)), + bi(teamfield, QWE 87, 1, p(field)), + bi(substr, QWE 88, 3, p(string), p(float), p(float)), + bi(strcat, QWE 89, -1), + bi(strlen, QWE 90, 1, p(string)), + bi(str2byte, QWE 91, 1, p(string)), + bi(str2short, QWE 92, 1, p(string)), + bi(newstr, QWE 93, 2, p(string), p(float)), + bi(freestr, QWE 94, 1, p(string)), + bi(conprint, QWE 95, -1), + bi(readcmd, QWE 96, 1, p(string)), + bi(strcpy, QWE 97, 2, p(string), p(string)), + bi(strstr, QWE 98, 2, p(string), p(string)), + bi(strncpy, QWE 99, 3, p(string), p(string), p(float)), + bi(log, QWE 100, 3, p(string), p(float), p(string)), + bi(redirectcmd, QWE 101, 2, p(entity), p(string)), + bi(calltimeofday, QWE 102, 0), + bi(forcedemoframe, QWE 103, 1, p(float)), {0} }; #define LAST_QWE_BUILTIN 103 static struct { const char *name; - func_t *field; + pr_func_t *field; } qwe_func_list[] = { {"timeofday", &qwe_funcs.timeofday}, {"ConsoleCmd", &qwe_funcs.ConsoleCmd}, @@ -574,7 +577,7 @@ qwe_load (progs_t *pr) *qwe_func_list[i].field = 0; if (f) - *qwe_func_list[i].field = (func_t) (f - pr->pr_functions); + *qwe_func_list[i].field = (pr_func_t) (f - pr->pr_functions); } sv_cbuf->unknown_command = qwe_console_cmd; @@ -586,6 +589,6 @@ qwe_load (progs_t *pr) void SV_PR_QWE_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); PR_AddLoadFunc (pr, qwe_load); } diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 84873b352..77d7898ff 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -60,12 +60,13 @@ sv_data_t sv_data[MAX_EDICTS]; cvar_t *r_skyname; cvar_t *sv_progs; cvar_t *sv_progs_zone; +cvar_t *sv_progs_stack; cvar_t *sv_progs_ext; cvar_t *pr_checkextensions; cvar_t *sv_old_entity_free; cvar_t *sv_hide_version_info; -static int reserved_edicts = MAX_CLIENTS; +static pr_uint_t reserved_edicts = MAX_CLIENTS; static int sv_range; @@ -352,7 +353,7 @@ static sv_def_t qw_opt_funcs[] = { }; static sv_def_t qw_opt_fields[] = { - {ev_integer, 0, "rotated_bbox", &sv_fields.rotated_bbox}, + {ev_int, 0, "rotated_bbox", &sv_fields.rotated_bbox}, {ev_float, 0, "alpha", &sv_fields.alpha}, {ev_float, 0, "scale", &sv_fields.scale}, {ev_float, 0, "glow_size", &sv_fields.glow_size}, @@ -372,12 +373,13 @@ set_address (sv_def_t *def, void *address) switch (def->type) { case ev_void: case ev_short: + case ev_ushort: case ev_invalid: case ev_type_count: break; case ev_float: case ev_vector: - case ev_quat: + case ev_quaternion: *(float **)def->field = (float *) address; break; case ev_double: @@ -387,10 +389,14 @@ set_address (sv_def_t *def, void *address) case ev_entity: case ev_field: case ev_func: - case ev_pointer: - case ev_integer: - case ev_uinteger: - *(int **)def->field = (int *) address; + case ev_ptr: + case ev_int: + case ev_uint: + *(pr_int_t **)def->field = (pr_int_t *) address; + break; + case ev_long: + case ev_ulong: + *(pr_long_t **)def->field = (pr_long_t *) address; break; } } @@ -426,13 +432,13 @@ resolve_functions (progs_t *pr, sv_def_t *def, int mode) if (mode == 2) { for (; def->name; def++) - *(func_t *) def->field = G_FUNCTION (pr, def->offset); + *(pr_func_t *) def->field = G_FUNCTION (pr, def->offset); return 1; } for (; def->name; def++) { dfunc = PR_FindFunction (pr, def->name); if (dfunc) { - *(func_t *) def->field = dfunc - pr->pr_functions; + *(pr_func_t *) def->field = dfunc - pr->pr_functions; } else if (mode) { PR_Undefined (pr, "function", def->name); ret = 0; @@ -489,7 +495,7 @@ resolve (progs_t *pr) resolve_fields (pr, qw_opt_fields, 0); // progs engine needs these globals anyway sv_pr_state.globals.self = sv_globals.self; - sv_pr_state.globals.time = sv_globals.time; + sv_pr_state.globals.ftime = sv_globals.time;//FIXME double time return ret; } @@ -555,6 +561,7 @@ SV_LoadProgs (void) sv_pr_state.max_edicts = MAX_EDICTS; sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; + sv_pr_state.stack_size = sv_progs_stack->int_val * 1024; sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name); @@ -609,6 +616,8 @@ SV_Progs_Init_Cvars (void) "Override the default game progs."); sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, "size of the zone for progs in kB"); + sv_progs_stack = Cvar_Get ("sv_progs_stack", "64", CVAR_NONE, NULL, + "size of the stack for progs in kB"); sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL, "extention mapping to use: " "none, id, qf, qwe, ktpro, cpqw"); diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index e73835a39..126c84ef8 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -491,16 +491,13 @@ SV_Spawn_f (void *unused) static void SV_SpawnSpectator (void) { - int i; - edict_t *e; - VectorZero (SVvector (sv_player, origin)); VectorZero (SVvector (sv_player, view_ofs)); SVvector (sv_player, view_ofs)[2] = 22; // search for an info_playerstart to spawn the spectator at - for (i = MAX_CLIENTS - 1; i < sv.num_edicts; i++) { - e = EDICT_NUM (&sv_pr_state, i); + for (unsigned i = MAX_CLIENTS - 1; i < sv.num_edicts; i++) { + edict_t *e = EDICT_NUM (&sv_pr_state, i); if (!strcmp (PR_GetString (&sv_pr_state, SVstring (e, classname)), "info_player_start")) { VectorCopy (SVvector (e, origin), SVvector (sv_player, origin)); @@ -1335,7 +1332,7 @@ static void call_qc_hook (void *qc_hook) { *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv_player); - PR_ExecuteProgram (&sv_pr_state, (func_t) (intptr_t) qc_hook); + PR_ExecuteProgram (&sv_pr_state, (pr_func_t) (intptr_t) qc_hook); } static const char * @@ -1425,7 +1422,7 @@ SV_RemoveUserCommand (void *cmd) } static void -PF_AddUserCommand (progs_t *pr) +PF_SV_AddUserCommand (progs_t *pr) { const char *name = P_GSTRING (pr, 0); ucmd_t *cmd; @@ -1516,7 +1513,7 @@ static void AddLinksToPmove (areanode_t *node) { edict_t *check; - int pl, i; + pr_uint_t pl, i; link_t *l, *next; physent_t *pe; @@ -1551,8 +1548,8 @@ AddLinksToPmove (areanode_t *node) pe->info = NUM_FOR_EDICT (&sv_pr_state, check); if (sv_fields.rotated_bbox != -1 - && SVinteger (check, rotated_bbox)) { - int h = SVinteger (check, rotated_bbox) - 1; + && SVint (check, rotated_bbox)) { + int h = SVint (check, rotated_bbox) - 1; pe->hull = pf_hull_list[h]->hulls[1]; } else { @@ -2002,8 +1999,11 @@ SV_ExecuteClientMessage (client_t *cl) } } +#define bi(x,np,params...) {#x, PF_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"SV_AddUserCommand", PF_AddUserCommand, -1}, + bi(SV_AddUserCommand, 3, p(string), p(func), p(int)), {0} }; @@ -2012,7 +2012,7 @@ SV_UserInit (void) { ucmd_table = Hash_NewTable (251, ucmds_getkey, ucmds_free, 0, 0); Hash_SetHashCompare (ucmd_table, ucmd_get_hash, ucmd_compare); - PR_RegisterBuiltins (&sv_pr_state, builtins); + PR_RegisterBuiltins (&sv_pr_state, builtins, 0); cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, "How quickly a player straightens out after " "strafing"); diff --git a/qw/source/world.c b/qw/source/world.c index 393daaf6f..7024bca6c 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -215,7 +215,7 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, vec3_t hullmins, hullmaxs, size; if ((sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) + && SVint (ent, rotated_bbox)) || SVfloat (ent, solid) == SOLID_BSP) { VectorSubtract (maxs, mins, size); if (size[0] < 3) @@ -226,8 +226,8 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, hull_index = 2; } if (sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) { - int h = SVinteger (ent, rotated_bbox) - 1; + && SVint (ent, rotated_bbox)) { + int h = SVint (ent, rotated_bbox) - 1; hull_list = pf_hull_list[h]->hulls; } if (SVfloat (ent, solid) == SOLID_BSP) { // explicit hulls in the BSP model @@ -818,11 +818,10 @@ SV_ClipToLinks (areanode_t *node, moveclip_t *clip) edict_t *touch; link_t *l, *next; trace_t trace; - int i; if (clip->type & MOVE_EVERYTHING) { touch = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (i = 1; i < sv.num_edicts; i++, + for (unsigned i = 1; i < sv.num_edicts; i++, touch = NEXT_EDICT (&sv_pr_state, touch)) { if (clip->trace.allsolid) return; @@ -985,7 +984,6 @@ SV_Move (const vec3_t start, const vec3_t mins, const vec3_t maxs, edict_t * SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) { - int e; edict_t *check; hull_t *hull; vec3_t boxmins, boxmaxs, offset; @@ -1000,8 +998,8 @@ SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) VectorAdd (origin, SVvector (ent, maxs), boxmaxs); check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, - check)) { + for (unsigned e = 1; e < sv.num_edicts; + e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; if (check == ent) diff --git a/ruamoko/cl_menu/menu.r b/ruamoko/cl_menu/menu.r index 748bd35ed..a47650a42 100644 --- a/ruamoko/cl_menu/menu.r +++ b/ruamoko/cl_menu/menu.r @@ -21,3 +21,4 @@ int () Menu_GetIndex = #0; void (void) Menu_Next = #0; void (void) Menu_Prev = #0; void (void) Menu_Enter = #0; +void (void) Menu_Leave = #0; diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index f94e6bdfc..2694e48b5 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -84,7 +84,7 @@ class_from_plist (PLDictionary *pldict) if (str_str (paramstr, ".") >= 0) va_list.list[j].float_val = stof (paramstr); else - va_list.list[j].integer_val = stoi (paramstr); + va_list.list[j].int_val = stoi (paramstr); break; } } diff --git a/ruamoko/include/debug.h b/ruamoko/include/debug.h index 017ca1858..9ea089de0 100644 --- a/ruamoko/include/debug.h +++ b/ruamoko/include/debug.h @@ -62,18 +62,18 @@ /** Print a string to the console if the "developer" Cvar is nonzero. */ -@extern void dprint (string str); +@extern void dprint (.../*string str*/); /** Abort (crash) the server. "str" is the message the server crashes with. */ -@extern void error (string str); +@extern void error (.../*string str*/); /** Prints info on the "self" ENTITY (not object), and error message "e". The entity is freed. */ -@extern void objerror (string e); +@extern void objerror (.../*string e*/); //\} #endif //__ruamoko_debug_h diff --git a/ruamoko/include/message.h b/ruamoko/include/message.h index 7d37e91f5..f0cf5c140 100644 --- a/ruamoko/include/message.h +++ b/ruamoko/include/message.h @@ -35,7 +35,7 @@ #define MULTICAST_PVS_R 5 @extern void bprint (...); -@extern void sprint (entity client, string s); +@extern void sprint (.../*entity client, string s*/); @extern void WriteBytes (float to, ...); @extern void WriteByte (float to, float f); @extern void WriteChar (float to, float f); diff --git a/ruamoko/include/runtime.h b/ruamoko/include/runtime.h index 276d270fb..849b9be1e 100644 --- a/ruamoko/include/runtime.h +++ b/ruamoko/include/runtime.h @@ -45,7 +45,7 @@ typedef enum { //obj_error_handler obj_set_error_handler (objc_error_handler func); @extern IMP obj_msg_lookup (id receiver, SEL op); @extern IMP obj_msg_lookup_super (Super class, SEL op); -@extern @param obj_msg_sendv (id receiver, SEL op, @va_list args); +@extern @attribute(void_return) void obj_msg_sendv (id receiver, SEL op, @va_list args); @extern BOOL obj_decrement_ref_was_zero (id object); @extern BOOL obj_increment_ref_was_zero (id object); @extern void *obj_malloc (int size); diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index 19ec0c736..2ff8a123e 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -1,21 +1,9 @@ #ifndef __types_h #define __types_h +#define EV_TYPE(type) ev_##type, typedef enum { - ev_void, - ev_string, - ev_float, - ev_vector, - ev_entity, - ev_field, - ev_func, - ev_pointer, // end of v6 types - ev_quat, - ev_integer, - ev_uinteger, - ev_short, // value is embedded in the opcode - ev_double, - +#include ev_invalid, // invalid type. used for instruction checking ev_type_count // not a type, gives number of types } etype_t; diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index 6c7e0e6f4..711721d1d 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -12,12 +12,12 @@ void __obj_exec_class (struct obj_module *msg) = #0; BOOL __obj_responds_to(id obj, SEL sel) = #0; void (id object, int code, string fmt, ...) obj_error = #0; void (id object, int code, string fmt, @va_list args) obj_verror = #0; -//obj_error_handler (objc_error_handler func) obj_set_error_handler = #0; +//obj_error_handler obj_set_error_handler (objc_error_handler func) = #0; IMP (id receiver, SEL op) obj_msg_lookup = #0; IMP (Super class, SEL op) obj_msg_lookup_super = #0; id (id receiver, SEL op, ...) obj_msgSend = #0; id obj_msgSend_super (Super *class, SEL op, ...) = #0; -@param (id receiver, SEL op, @va_list args) obj_msg_sendv = #0; +@attribute(void_return) void obj_msg_sendv (id receiver, SEL op, @va_list args) = #0; int obj_decrement_retaincount (id object) = #0; int obj_increment_retaincount (id object) = #0; int obj_get_retaincount (id object) = #0; @@ -27,11 +27,11 @@ void *obj_valloc (int size) = #0; void *obj_realloc (void *mem, int size) = #0; void *obj_calloc (int nelem, int size) = #0; void obj_free (void *mem) = #0; -//(void *) (void) obj_get_uninstalled_dtable = #0; +void *obj_get_uninstalled_dtable (void) = #0; -Class (string name) obj_get_class = #0; -Class (string name) obj_lookup_class = #0; -//Class (void **enum_stage) obj_next_class = #0; +Class obj_get_class (string name) = #0; +Class obj_lookup_class (string name) = #0; +Class obj_next_class (void **enum_stage) = #0; string (SEL selector) sel_get_name = #0; string (SEL selector) sel_get_type = #0; @@ -77,10 +77,12 @@ BOOL (id object) object_is_meta_class = #0; @end +typedef void arIMP(id, SEL, id); + @static BOOL allocDebug; @static Class autoreleaseClass; @static SEL autoreleaseSelector; -@static IMP autoreleaseIMP; +@static arIMP autoreleaseIMP; @implementation Object @@ -89,7 +91,7 @@ BOOL (id object) object_is_meta_class = #0; //allocDebug = localinfo ("AllocDebug"); autoreleaseClass = [AutoreleasePool class]; autoreleaseSelector = @selector(addObject:); - autoreleaseIMP = [autoreleaseClass methodForSelector: autoreleaseSelector]; + autoreleaseIMP = (arIMP)[autoreleaseClass methodForSelector: autoreleaseSelector]; return; } diff --git a/ruamoko/lib/Set.r b/ruamoko/lib/Set.r index 7afc13361..4786b71a7 100644 --- a/ruamoko/lib/Set.r +++ b/ruamoko/lib/Set.r @@ -1,6 +1,7 @@ #include void set_del_iter (set_iter_t *set_iter) = #0; +unsigned set_iter_element (set_iter_t *set_iter) = #0; set_t *set_new (void) = #0; void set_delete (set_t *set) = #0; set_t *set_add (set_t *set, unsigned x) = #0; diff --git a/ruamoko/lib/debug.r b/ruamoko/lib/debug.r index 7cf9c8895..0f2f09375 100644 --- a/ruamoko/lib/debug.r +++ b/ruamoko/lib/debug.r @@ -5,6 +5,6 @@ void coredump (void) = #28; void traceon (void) = #29; void traceoff (void) = #30; void eprint (entity e) = #31; -void dprint (string str) = #25; -void error (string str) = #10; -void objerror (string e) = #11; +void dprint (.../*string str*/) = #25; +void error (.../*string str*/) = #10; +void objerror (.../*string e*/) = #11; diff --git a/ruamoko/lib/key.r b/ruamoko/lib/key.r index 4b8c1a09a..812800128 100644 --- a/ruamoko/lib/key.r +++ b/ruamoko/lib/key.r @@ -5,3 +5,4 @@ string (string imt, int keynum, string binding) Key_SetBinding = #0; int (string imt, int bindnum, string binding) Key_LookupBinding = #0; int (string imt, string binding) Key_CountBinding = #0; string (int keynum) Key_KeynumToString = #0; +int (string keyname) Key_StringToKeynum = #0; diff --git a/ruamoko/lib/message.r b/ruamoko/lib/message.r index 4ddb31571..d01c641e5 100644 --- a/ruamoko/lib/message.r +++ b/ruamoko/lib/message.r @@ -1,7 +1,7 @@ #include void (...) bprint = #23; -void (entity client, string s) sprint = #24; +void (.../*entity client, string s*/) sprint = #24; void (float to, float f) WriteByte = #52; void (float to, float f) WriteChar = #53; void (float to, float f) WriteShort = #54; diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r index 45f51c70e..7c27914ff 100644 --- a/ruamoko/lib/types.r +++ b/ruamoko/lib/types.r @@ -11,36 +11,20 @@ string ty_meta_name[7] = { "alias", }; +//FIXME use pr_type_names.h, but need to fix unsigned, and add missing types +#define field .int +#define func void()(void) +#define ptr void * +#define uint unsigned +#define ulong unsigned long +#define ushort unsigned short +#define EV_TYPE(type) sizeof(type), int pr_type_size[ev_type_count] = { - 1, // ev_void - 1, // ev_string - 1, // ev_float - 3, // ev_vector - 1, // ev_entity - 1, // ev_field - 1, // ev_func - 1, // ev_pointer - 4, // ev_quat - 1, // ev_integer - 1, // ev_uinteger - 0, // ev_short value in opcode - 2, // ev_double - 0, // ev_invalid not a valid/simple type +#include }; +#define EV_TYPE(type) #type, string pr_type_name[ev_type_count] = { - "void", - "string", - "float", - "vector", - "entity", - "field", - "function", - "pointer", - "quaternion", - "integer", - "uinteger", - "short", - "double", +#include "invalid", }; diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 1e7c7d58c..504939543 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -46,6 +46,8 @@ #include "QF/ringbuffer.h" #include "QF/sys.h" +#include "rua_internal.h" + #include "ruamoko/qwaq/qwaq.h" #include "ruamoko/qwaq/ui/curses.h" #include "ruamoko/qwaq/ui/rect.h" @@ -763,9 +765,6 @@ static void bi_syncprintf (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; int string_id = qwaq_pipe_acquire_string (&res->commands); dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_syncprint, 0, string_id }; @@ -773,13 +772,13 @@ bi_syncprintf (progs_t *pr) command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); + RUA_Sprintf (pr, print_buffer, "syncprintf", 0); qwaq_pipe_submit (&res->commands, command, command[1]); } static void -bi_newwin (progs_t *pr) +bi_create_window (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int xpos = P_INT (pr, 0); @@ -800,7 +799,7 @@ bi_newwin (progs_t *pr) } static void -bi_delwin (progs_t *pr) +bi_destroy_window (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int window_id = P_INT (pr, 0); @@ -839,7 +838,7 @@ bi_getwrect (progs_t *pr) } static void -bi_new_panel (progs_t *pr) +bi_create_panel (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int window_id = P_INT (pr, 0); @@ -870,7 +869,7 @@ panel_command (progs_t *pr, qwaq_commands cmd) } static void -bi_del_panel (progs_t *pr) +bi_destroy_panel (progs_t *pr) { panel_command (pr, qwaq_cmd_del_panel); } @@ -1135,8 +1134,7 @@ bi_mvwaddstr (progs_t *pr) } static void -qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, - int count, pr_type_t **args) +qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, int fmt_arg) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); @@ -1151,7 +1149,7 @@ qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); + RUA_Sprintf (pr, print_buffer, "mvwaddstr", fmt_arg); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1162,16 +1160,12 @@ bi_mvwprintf (progs_t *pr) int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); - const char *fmt = P_GSTRING (pr, 3); - int count = pr->pr_argc - 4; - pr_type_t **args = pr->pr_params + 4; - qwaq_mvwprintf (pr, window_id, x, y, fmt, count, args); + qwaq_mvwprintf (pr, window_id, x, y, 3); } static void -qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, - int count, pr_type_t **args) +qwaq_wprintf (progs_t *pr, int window_id, int fmt_arg) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); @@ -1186,7 +1180,7 @@ qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "waddstr", fmt, count, args); + RUA_Sprintf (pr, print_buffer, "wprintf", fmt_arg); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1195,11 +1189,8 @@ static void bi_wprintf (progs_t *pr) { int window_id = P_INT (pr, 0); - const char *fmt = P_GSTRING (pr, 1); - int count = pr->pr_argc - 2; - pr_type_t **args = pr->pr_params + 2; - qwaq_wprintf (pr, window_id, fmt, count, args); + qwaq_wprintf (pr, window_id, 1); } static void @@ -1224,7 +1215,7 @@ qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); + PR_Sprintf (pr, print_buffer, "wvprintf", fmt, args->count, list); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1283,7 +1274,7 @@ qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); + PR_Sprintf (pr, print_buffer, "mvwvprintf", fmt, args->count, list); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1604,26 +1595,26 @@ bi_initialize (progs_t *pr) } static void -bi_c_TextContext__is_initialized (progs_t *pr) +bi__c_TextContext__is_initialized (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); R_INT (pr) = res->initialized; } static void -bi_c_TextContext__max_colors (progs_t *pr) +bi__c_TextContext__max_colors (progs_t *pr) { bi_max_colors (pr); } static void -bi_c_TextContext__max_color_pairs (progs_t *pr) +bi__c_TextContext__max_color_pairs (progs_t *pr) { bi_max_color_pairs (pr); } static void -bi_c_TextContext__init_pair_ (progs_t *pr) +bi__c_TextContext__init_pair_ (progs_t *pr) { int pair = P_INT (pr, 2); int f = P_INT (pr, 3); @@ -1633,7 +1624,7 @@ bi_c_TextContext__init_pair_ (progs_t *pr) } static void -bi_c_TextContext__acs_char_ (progs_t *pr) +bi__c_TextContext__acs_char_ (progs_t *pr) { int acs = P_INT (pr, 2); @@ -1641,7 +1632,7 @@ bi_c_TextContext__acs_char_ (progs_t *pr) } static void -bi_c_TextContext__move_ (progs_t *pr) +bi__c_TextContext__move_ (progs_t *pr) { Point *pos = &P_PACKED (pr, Point, 2); @@ -1649,7 +1640,7 @@ bi_c_TextContext__move_ (progs_t *pr) } static void -bi_c_TextContext__curs_set_ (progs_t *pr) +bi__c_TextContext__curs_set_ (progs_t *pr) { int visibility = P_INT (pr, 2); @@ -1657,36 +1648,30 @@ bi_c_TextContext__curs_set_ (progs_t *pr) } static void -bi_c_TextContext__doupdate (progs_t *pr) +bi__c_TextContext__doupdate (progs_t *pr) { bi_doupdate (pr); } static void -bi_i_TextContext__mvprintf_ (progs_t *pr) +bi__i_TextContext__mvprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); - const char *fmt = P_GSTRING (pr, 3); - int count = pr->pr_argc - 4; - pr_type_t **args = pr->pr_params + 4; - qwaq_mvwprintf (pr, window_id, pos->x, pos->y, fmt, count, args); + qwaq_mvwprintf (pr, window_id, pos->x, pos->y, 3); } static void -bi_i_TextContext__printf_ (progs_t *pr) +bi__i_TextContext__printf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - const char *fmt = P_GSTRING (pr, 2); - int count = pr->pr_argc - 3; - pr_type_t **args = pr->pr_params + 3; - qwaq_wprintf (pr, window_id, fmt, count, args); + qwaq_wprintf (pr, window_id, 2); } static void -bi_i_TextContext__vprintf_ (progs_t *pr) +bi__i_TextContext__vprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *fmt = P_GSTRING (pr, 2); @@ -1696,7 +1681,7 @@ bi_i_TextContext__vprintf_ (progs_t *pr) } static void -bi_i_TextContext__addch_ (progs_t *pr) +bi__i_TextContext__addch_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int ch = P_INT (pr, 2); @@ -1705,7 +1690,7 @@ bi_i_TextContext__addch_ (progs_t *pr) } static void -bi_i_TextContext__addstr_ (progs_t *pr) +bi__i_TextContext__addstr_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *str = P_GSTRING (pr, 2); @@ -1714,7 +1699,7 @@ bi_i_TextContext__addstr_ (progs_t *pr) } static void -bi_i_TextContext__mvvprintf_ (progs_t *pr) +bi__i_TextContext__mvvprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); @@ -1725,7 +1710,7 @@ bi_i_TextContext__mvvprintf_ (progs_t *pr) } static void -bi_i_TextContext__resizeTo_ (progs_t *pr) +bi__i_TextContext__resizeTo_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1738,14 +1723,14 @@ bi_i_TextContext__resizeTo_ (progs_t *pr) } static void -bi_c_TextContext__refresh (progs_t *pr) +bi__c_TextContext__refresh (progs_t *pr) { qwaq_update_panels (pr); qwaq_doupdate (pr); } static void -bi_i_TextContext__refresh (progs_t *pr) +bi__i_TextContext__refresh (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; @@ -1757,7 +1742,7 @@ bi_i_TextContext__refresh (progs_t *pr) } static void -bi_i_TextContext__mvaddch_ (progs_t *pr) +bi__i_TextContext__mvaddch_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); @@ -1767,7 +1752,7 @@ bi_i_TextContext__mvaddch_ (progs_t *pr) } static void -bi_i_TextContext__mvaddstr_ (progs_t *pr) +bi__i_TextContext__mvaddstr_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); @@ -1777,7 +1762,7 @@ bi_i_TextContext__mvaddstr_ (progs_t *pr) } static void -bi_i_TextContext__bkgd_ (progs_t *pr) +bi__i_TextContext__bkgd_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1788,7 +1773,7 @@ bi_i_TextContext__bkgd_ (progs_t *pr) } static void -bi_i_TextContext__clear (progs_t *pr) +bi__i_TextContext__clear (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1798,7 +1783,7 @@ bi_i_TextContext__clear (progs_t *pr) } static void -bi_i_TextContext__scrollok_ (progs_t *pr) +bi__i_TextContext__scrollok_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int flag = P_INT (pr, 2); @@ -1807,7 +1792,7 @@ bi_i_TextContext__scrollok_ (progs_t *pr) } static void -bi_i_TextContext__border_ (progs_t *pr) +bi__i_TextContext__border_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; __auto_type sides = P_PACKED (pr, box_sides_t, 2); @@ -1817,7 +1802,7 @@ bi_i_TextContext__border_ (progs_t *pr) } static void -bi_i_TextContext__mvhline_ (progs_t *pr) +bi__i_TextContext__mvhline_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1829,7 +1814,7 @@ bi_i_TextContext__mvhline_ (progs_t *pr) } static void -bi_i_TextContext__mvvline_ (progs_t *pr) +bi__i_TextContext__mvvline_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1854,74 +1839,95 @@ bi_curses_clear (progs_t *pr, void *data) panel_reset (res); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"initialize", bi_initialize, -1}, - {"syncprintf", bi_syncprintf, -1}, - {"create_window", bi_newwin, -1}, - {"destroy_window", bi_delwin, -1}, - {"getwrect", bi_getwrect, -1}, - {"create_panel", bi_new_panel, -1}, - {"destroy_panel", bi_del_panel, -1}, - {"hide_panel", bi_hide_panel, -1}, - {"show_panel", bi_show_panel, -1}, - {"top_panel", bi_top_panel, -1}, - {"bottom_panel", bi_bottom_panel, -1}, - {"move_panel", bi_move_panel, -1}, - {"panel_window", bi_panel_window, -1}, - {"replace_panel", bi_replace_panel, -1}, - {"update_panels", bi_update_panels, -1}, - {"doupdate", bi_doupdate, -1}, - {"mvwprintf", bi_mvwprintf, -1}, - {"wprintf", bi_wprintf, -1}, - {"wvprintf", bi_wvprintf, -1}, - {"mvwvprintf", bi_mvwvprintf, -1}, - {"mvwaddch", bi_mvwaddch, -1}, - {"waddch", bi_waddch, -1}, - {"mvwaddstr", bi_mvwaddstr, -1}, - {"waddstr", bi_waddstr, -1}, - {"wrefresh", bi_wrefresh, -1}, - {"max_colors", bi_max_colors, -1}, - {"max_color_pairs", bi_max_color_pairs, -1}, - {"init_pair", bi_init_pair, -1}, - {"wbkgd", bi_wbkgd, -1}, - {"werase", bi_werase, -1}, - {"scrollok", bi_scrollok, -1}, - {"wmove", bi_wmove, -1}, - {"acs_char", bi_acs_char, -1}, - {"move", bi_move, -1}, - {"curs_set", bi_curs_set, -1}, - {"wborder", bi_wborder, -1}, - {"mvwblit_line", bi_mvwblit_line, -1}, - {"wresize", bi_wresize, -1}, - {"resizeterm", bi_resizeterm, -1}, - {"mvwhline", bi_mvwhline, -1}, - {"mvwvline", bi_mvwvline, -1}, + bi(initialize, 0), + bi(syncprintf, -2, p(string)), + bi(create_window, 4, p(int), p(int), p(int), p(int)), + bi(destroy_window, 1, p(ptr)), + bi(getwrect, 1, p(ptr)), + bi(create_panel, 1, p(ptr)), + bi(destroy_panel, 1, p(ptr)), + bi(hide_panel, 1, p(ptr)), + bi(show_panel, 1, p(ptr)), + bi(top_panel, 1, p(ptr)), + bi(bottom_panel, 1, p(ptr)), + bi(move_panel, 3, p(ptr), p(int), p(int)), + bi(panel_window, 1, p(ptr)), + bi(replace_panel, 2, p(ptr), p(ptr)), + bi(update_panels, 0), + bi(doupdate, 0), + bi(mvwprintf, -5, p(ptr), p(int), p(int), p(string)), + bi(wprintf, -3, p(ptr), p(string)), + bi(wvprintf, 3, p(ptr), p(string), P(1, 2)), + bi(mvwvprintf, 5, p(ptr), p(int), p(int), p(string), P(1, 2)), + bi(mvwaddch, 4, p(ptr), p(int), p(int), p(int)), + bi(waddch, 2, p(ptr), p(int)), + bi(mvwaddstr, 4, p(ptr), p(int), p(int), p(string)), + bi(waddstr, 2, p(ptr), p(string)), + bi(wrefresh, 1, p(ptr)), + bi(max_colors, 0), + bi(max_color_pairs, 0), + bi(init_pair, 3, p(int), p(int), p(int)), + bi(wbkgd, 2, p(ptr), p(int)), + bi(werase, 1, p(ptr)), + bi(scrollok, 2, p(ptr), p(int)), + bi(wmove, 3, p(ptr), p(int), p(int), p(int)), + bi(acs_char, 1, p(int)), + bi(move, 2, p(int), p(int)), + bi(curs_set, 1, p(int)), + bi(wborder, 3, p(ptr), P(1, 4), P(1, 4)), + bi(mvwblit_line, 5, p(ptr), p(int), p(int), p(ptr), p(int)), + bi(wresize, 3, p(ptr), p(int), p(int)), + bi(resizeterm, 2, p(int), p(int)), + bi(mvwhline, 5, p(ptr), p(int), p(int), p(int), p(int)), + bi(mvwvline, 5, p(ptr), p(int), p(int), p(int), p(int)), - {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, - {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, - {"_c_TextContext__max_color_pairs", bi_c_TextContext__max_color_pairs, -1}, - {"_c_TextContext__init_pair_", bi_c_TextContext__init_pair_, -1}, - {"_c_TextContext__acs_char_", bi_c_TextContext__acs_char_, -1}, - {"_c_TextContext__move_", bi_c_TextContext__move_, -1}, - {"_c_TextContext__curs_set_", bi_c_TextContext__curs_set_, -1}, - {"_c_TextContext__doupdate", bi_c_TextContext__doupdate, -1}, - {"_i_TextContext__mvprintf_", bi_i_TextContext__mvprintf_, -1}, - {"_i_TextContext__printf_", bi_i_TextContext__printf_, -1}, - {"_i_TextContext__vprintf_", bi_i_TextContext__vprintf_, -1}, - {"_i_TextContext__addch_", bi_i_TextContext__addch_, -1}, - {"_i_TextContext__addstr_", bi_i_TextContext__addstr_, -1}, - {"_i_TextContext__mvvprintf_", bi_i_TextContext__mvvprintf_, -1}, - {"_i_TextContext__resizeTo_", bi_i_TextContext__resizeTo_, -1}, - {"_c_TextContext__refresh", bi_c_TextContext__refresh, -1}, - {"_i_TextContext__refresh", bi_i_TextContext__refresh, -1}, - {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, - {"_i_TextContext__mvaddstr_", bi_i_TextContext__mvaddstr_, -1}, - {"_i_TextContext__bkgd_", bi_i_TextContext__bkgd_, -1}, - {"_i_TextContext__clear", bi_i_TextContext__clear, -1}, - {"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1}, - {"_i_TextContext__border_", bi_i_TextContext__border_, -1}, - {"_i_TextContext__mvhline_", bi_i_TextContext__mvhline_, -1}, - {"_i_TextContext__mvvline_", bi_i_TextContext__mvvline_, -1}, + bi(_c_TextContext__is_initialized, 2, p(ptr), p(ptr)), + bi(_c_TextContext__max_colors, 2, p(ptr), p(ptr)), + bi(_c_TextContext__max_color_pairs, 2, p(ptr), p(ptr)), + bi(_c_TextContext__init_pair_, 5, p(ptr), p(ptr), + p(int), p(int), p(int)), + bi(_c_TextContext__acs_char_, 3, p(ptr), p(ptr), + p(int)), + bi(_c_TextContext__move_, 3, p(ptr), p(ptr), + P(1, 2)), + bi(_c_TextContext__curs_set_, 3, p(ptr), p(ptr), + p(int)), + bi(_c_TextContext__doupdate, 2, p(ptr), p(ptr)), + bi(_i_TextContext__mvprintf_, -5, p(ptr), p(ptr), + P(1, 2), p(string)), + bi(_i_TextContext__printf_, -4, p(ptr), p(ptr), + p(string)), + bi(_i_TextContext__vprintf_, 4, p(ptr), p(ptr), + p(string), P(1, 2)), + bi(_i_TextContext__addch_, 3, p(ptr), p(ptr), + p(int)), + bi(_i_TextContext__addstr_, 3, p(ptr), p(ptr), + p(string)), + bi(_i_TextContext__mvvprintf_, 5, p(ptr), p(ptr), + P(1, 2), p(string), P(1, 2)), + bi(_i_TextContext__resizeTo_, 3, p(ptr), p(ptr), + P(1, 2)), + bi(_c_TextContext__refresh, 2, p(ptr), p(ptr)), + bi(_i_TextContext__refresh, 2, p(ptr), p(ptr)), + bi(_i_TextContext__mvaddch_, 4, p(ptr), p(ptr), + P(1, 2), p(int)), + bi(_i_TextContext__mvaddstr_, 4, p(ptr), p(ptr), + P(1, 2), p(string)), + bi(_i_TextContext__bkgd_, 3, p(ptr), p(ptr), + p(int)), + bi(_i_TextContext__clear, 2, p(ptr), p(ptr)), + bi(_i_TextContext__scrollok_, 3, p(ptr), p(ptr), + p(int)), + bi(_i_TextContext__border_, 4, p(ptr), p(ptr), + P(1, 4), P(1, 4)), + bi(_i_TextContext__mvhline_, 5, p(ptr), p(ptr), + P(1, 2), p(int), p(int)), + bi(_i_TextContext__mvvline_, 5, p(ptr), p(ptr), + P(1, 2), p(int), p(int)), {0} }; @@ -1936,6 +1942,6 @@ BI_Curses_Init (progs_t *pr) qwaq_init_pipe (&res->results); PR_Resources_Register (pr, "curses", res, bi_curses_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); Sys_RegisterShutdown (bi_shutdown, pr); } diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 4826c4166..73eb5972f 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -204,7 +204,7 @@ static void qdb_set_trace (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); int state = P_INT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -216,12 +216,12 @@ static void qdb_set_breakpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); unsigned staddr = P_INT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - if (staddr >= tpr->progs->numstatements) { + if (staddr >= tpr->progs->statements.count) { R_INT (pr) = -1; return; } @@ -234,12 +234,12 @@ static void qdb_clear_breakpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); unsigned staddr = P_UINT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - if (staddr >= tpr->progs->numstatements) { + if (staddr >= tpr->progs->statements.count) { R_INT (pr) = -1; return; } @@ -251,8 +251,8 @@ static void qdb_set_watchpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); - pointer_t offset = P_UINT (pr, 1); + pr_ptr_t handle = P_INT (pr, 0); + pr_ptr_t offset = P_UINT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -268,7 +268,7 @@ static void qdb_clear_watchpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -280,7 +280,7 @@ static void qdb_continue (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); pthread_mutex_lock (&target->run_cond.mut); @@ -293,15 +293,15 @@ static void qdb_get_state (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_lineno_t *lineno; pr_auxfunction_t *f; - string_t file = 0; + pr_string_t file = 0; unsigned line = 0; unsigned staddr = tpr->pr_xstatement; - func_t func = 0; + pr_func_t func = 0; if (tpr->pr_xfunction) { func = tpr->pr_xfunction - tpr->function_table; @@ -331,7 +331,7 @@ static void qdb_get_stack_depth (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -342,7 +342,7 @@ static void qdb_get_stack (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; int count = tpr->pr_depth; @@ -350,7 +350,7 @@ qdb_get_stack (progs_t *pr) R_POINTER (pr) = 0; if (count > 0) { size_t size = count * sizeof (qdb_stack_t); - string_t stack_block = PR_AllocTempBlock (pr, size); + pr_string_t stack_block = PR_AllocTempBlock (pr, size); __auto_type stack = (qdb_stack_t *) PR_GetString (pr, stack_block); for (int i = 0; i < count; i++) { @@ -366,7 +366,7 @@ static void qdb_get_event (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); __auto_type event = &P_STRUCT (pr, qdb_event_t, 1); @@ -374,14 +374,14 @@ qdb_get_event (progs_t *pr) event->what = target->event; switch (event->what) { case prd_subenter: - event->function = *(func_t *) target->param; + event->function = *(pr_func_t *) target->param; break; case prd_runerror: case prd_error: - event->message = PR_SetReturnString (pr, *(char **) target->param); + event->message = PR_SetReturnString (pr, (char *) target->param); break; case prd_begin: - event->function = *(func_t *) target->param; + event->function = *(pr_func_t *) target->param; break; case prd_terminate: event->exit_code = *(int *) target->param; @@ -400,12 +400,12 @@ static void qdb_get_data (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - pointer_t srcoff = P_POINTER (pr, 1); + pr_ptr_t srcoff = P_POINTER (pr, 1); unsigned length = P_UINT (pr, 2); - pointer_t dstoff = P_POINTER(pr, 3); + pr_ptr_t dstoff = P_POINTER(pr, 3); pr_type_t *src = PR_GetPointer(tpr, srcoff); pr_type_t *dst = PR_GetPointer(pr, dstoff); @@ -426,10 +426,10 @@ static void qdb_get_string (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - string_t string = P_STRING (pr, 1); + pr_string_t string = P_STRING (pr, 1); R_STRING (pr) = 0; if (PR_StringValid (tpr, string)) { @@ -441,7 +441,7 @@ static void qdb_get_file_path (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *file = P_GSTRING (pr, 1); @@ -466,7 +466,7 @@ static void qdb_find_string (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *str = P_GSTRING (pr, 1); @@ -478,7 +478,7 @@ static void qdb_find_global (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -498,7 +498,7 @@ static void qdb_find_field (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -522,12 +522,12 @@ return_function (progs_t *pr, dfunction_t *func) __auto_type f = (qdb_function_t *) PR_Zone_Malloc (pr, sizeof (qdb_function_t)); f->staddr = func->first_statement; - f->local_data = func->parm_start; + f->local_data = func->params_start; f->local_size = func->locals; f->profile = func->profile; - f->name = func->s_name; - f->file = func->s_file; - f->num_params = func->numparms; + f->name = func->name; + f->file = func->file; + f->num_params = func->numparams; R_POINTER (pr) = PR_SetPointer (pr, f); } } @@ -536,7 +536,7 @@ static void qdb_find_function (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -549,13 +549,13 @@ static void qdb_get_function (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_uint_t fnum = P_INT (pr, 1); dfunction_t *func = tpr->pr_functions + fnum; - if (fnum >= tpr->progs->numfunctions) { + if (fnum >= tpr->progs->functions.count) { func = 0; } return_function (pr, func); @@ -583,7 +583,7 @@ static void qdb_find_auxfunction (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -591,7 +591,7 @@ qdb_find_auxfunction (progs_t *pr) pr_uint_t fnum = func - tpr->pr_functions; pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); - if (fnum >= tpr->progs->numfunctions) { + if (fnum >= tpr->progs->functions.count) { func = 0; } return_auxfunction (pr, auxfunc); @@ -601,7 +601,7 @@ static void qdb_get_auxfunction (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_uint_t fnum = P_UINT (pr, 1); @@ -614,7 +614,7 @@ static void qdb_get_local_defs (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_uint_t fnum = P_UINT (pr, 1); @@ -640,7 +640,7 @@ static void qdb_get_source_line_addr (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *file = P_GSTRING (pr, 1); @@ -649,30 +649,32 @@ qdb_get_source_line_addr (progs_t *pr) R_UINT (pr) = PR_FindSourceLineAddr (tpr, file, line); } +#define bi(x,np,params...) {#x, x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"qdb_set_trace", qdb_set_trace, -1}, - {"qdb_set_breakpoint", qdb_set_breakpoint, -1}, - {"qdb_clear_breakpoint", qdb_clear_breakpoint, -1}, - {"qdb_set_watchpoint", qdb_set_watchpoint, -1}, - {"qdb_clear_watchpoint", qdb_clear_watchpoint, -1}, - {"qdb_continue", qdb_continue, -1}, - {"qdb_get_state", qdb_get_state, -1}, - {"qdb_get_stack_depth", qdb_get_stack_depth, -1}, - {"qdb_get_stack", qdb_get_stack, -1}, - {"qdb_get_event", qdb_get_event, -1}, - {"qdb_get_data", qdb_get_data, -1}, - {"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1}, - {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1}, - {"qdb_get_file_path", qdb_get_file_path, -1}, - {"qdb_find_string", qdb_find_string, -1}, - {"qdb_find_global", qdb_find_global, -1}, - {"qdb_find_field", qdb_find_field, -1}, - {"qdb_find_function", qdb_find_function, -1}, - {"qdb_get_function", qdb_get_function, -1}, - {"qdb_find_auxfunction", qdb_find_auxfunction, -1}, - {"qdb_get_auxfunction", qdb_get_auxfunction, -1}, - {"qdb_get_local_defs", qdb_get_local_defs, -1}, - {"qdb_get_source_line_addr", qdb_get_source_line_addr, -1}, + bi(qdb_set_trace, 2, p(int), p(int)), + bi(qdb_set_breakpoint, 2, p(int), p(uint)), + bi(qdb_clear_breakpoint, 2, p(int), p(uint)), + bi(qdb_set_watchpoint, 2, p(int), p(uint)), + bi(qdb_clear_watchpoint, 1, p(int)), + bi(qdb_continue, 1, p(int)), + bi(qdb_get_state, 1, p(int)), + bi(qdb_get_stack_depth, 1, p(int)), + bi(qdb_get_stack, 1, p(int)), + bi(qdb_get_event, 2, p(int), p(ptr)), + bi(qdb_get_data, 4, p(int), p(uint), p(uint), p(ptr)), + {"qdb_get_string|{tag qdb_target_s=}I", qdb_get_string, -1, 1, {p(uint)}}, + {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1, 1, {p(string)}}, + bi(qdb_get_file_path, 2, p(int), p(string)), + bi(qdb_find_string, 2, p(int), p(string)), + bi(qdb_find_global, 2, p(int), p(string)), + bi(qdb_find_field, 2, p(int), p(string)), + bi(qdb_find_function, 2, p(int), p(string)), + bi(qdb_get_function, 2, p(int), p(uint)), + bi(qdb_find_auxfunction, 2, p(int), p(string)), + bi(qdb_get_auxfunction, 2, p(int), p(uint)), + bi(qdb_get_local_defs, 2, p(int), p(uint)), + bi(qdb_get_source_line_addr, 3, p(int), p(string), p(uint)), {} }; @@ -686,7 +688,7 @@ QWAQ_Debug_Init (progs_t *pr) PR_AddLoadFunc (pr, qwaq_debug_load); PR_Resources_Register (pr, "qwaq-debug", debug, qwaq_debug_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, debug); } void diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index cea68c941..3a8fbdf3a 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -575,7 +575,7 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, //=== static void -bi_i_EditBuffer__init (progs_t *pr) +bi__i_EditBuffer__init (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); @@ -591,7 +591,7 @@ bi_i_EditBuffer__init (progs_t *pr) } static void -bi_i_EditBuffer__initWithFile_ (progs_t *pr) +bi__i_EditBuffer__initWithFile_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); @@ -610,7 +610,7 @@ bi_i_EditBuffer__initWithFile_ (progs_t *pr) } static void -bi_i_EditBuffer__dealloc (progs_t *pr) +bi__i_EditBuffer__dealloc (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); @@ -622,7 +622,7 @@ bi_i_EditBuffer__dealloc (progs_t *pr) } static void -bi_i_EditBuffer__nextChar_ (progs_t *pr) +bi__i_EditBuffer__nextChar_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -633,7 +633,7 @@ bi_i_EditBuffer__nextChar_ (progs_t *pr) } static void -bi_i_EditBuffer__prevChar_ (progs_t *pr) +bi__i_EditBuffer__prevChar_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -644,7 +644,7 @@ bi_i_EditBuffer__prevChar_ (progs_t *pr) } static void -bi_i_EditBuffer__nextNonSpace_ (progs_t *pr) +bi__i_EditBuffer__nextNonSpace_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -655,7 +655,7 @@ bi_i_EditBuffer__nextNonSpace_ (progs_t *pr) } static void -bi_i_EditBuffer__prevNonSpace_ (progs_t *pr) +bi__i_EditBuffer__prevNonSpace_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -666,7 +666,7 @@ bi_i_EditBuffer__prevNonSpace_ (progs_t *pr) } static void -bi_i_EditBuffer__isWord_ (progs_t *pr) +bi__i_EditBuffer__isWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -677,7 +677,7 @@ bi_i_EditBuffer__isWord_ (progs_t *pr) } static void -bi_i_EditBuffer__nextWord_ (progs_t *pr) +bi__i_EditBuffer__nextWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -688,7 +688,7 @@ bi_i_EditBuffer__nextWord_ (progs_t *pr) } static void -bi_i_EditBuffer__prevWord_ (progs_t *pr) +bi__i_EditBuffer__prevWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -699,7 +699,7 @@ bi_i_EditBuffer__prevWord_ (progs_t *pr) } static void -bi_i_EditBuffer__nextLine_ (progs_t *pr) +bi__i_EditBuffer__nextLine_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -710,7 +710,7 @@ bi_i_EditBuffer__nextLine_ (progs_t *pr) } static void -bi_i_EditBuffer__prevLine_ (progs_t *pr) +bi__i_EditBuffer__prevLine_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -721,7 +721,7 @@ bi_i_EditBuffer__prevLine_ (progs_t *pr) } static void -bi_i_EditBuffer__nextLine__ (progs_t *pr) +bi__i_EditBuffer__nextLine__ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -742,7 +742,7 @@ bi_i_EditBuffer__nextLine__ (progs_t *pr) } static void -bi_i_EditBuffer__prevLine__ (progs_t *pr) +bi__i_EditBuffer__prevLine__ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -757,7 +757,7 @@ bi_i_EditBuffer__prevLine__ (progs_t *pr) } static void -bi_i_EditBuffer__charPos_at_ (progs_t *pr) +bi__i_EditBuffer__charPos_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -770,7 +770,7 @@ bi_i_EditBuffer__charPos_at_ (progs_t *pr) } static void -bi_i_EditBuffer__charPtr_at_ (progs_t *pr) +bi__i_EditBuffer__charPtr_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -783,7 +783,7 @@ bi_i_EditBuffer__charPtr_at_ (progs_t *pr) } static void -bi_i_EditBuffer__getWord_ (progs_t *pr) +bi__i_EditBuffer__getWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -797,7 +797,7 @@ bi_i_EditBuffer__getWord_ (progs_t *pr) } static void -bi_i_EditBuffer__getLine_ (progs_t *pr) +bi__i_EditBuffer__getLine_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -811,7 +811,7 @@ bi_i_EditBuffer__getLine_ (progs_t *pr) } static void -bi_i_EditBuffer__getBOL_ (progs_t *pr) +bi__i_EditBuffer__getBOL_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -822,7 +822,7 @@ bi_i_EditBuffer__getBOL_ (progs_t *pr) } static void -bi_i_EditBuffer__getEOL_ (progs_t *pr) +bi__i_EditBuffer__getEOL_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -833,7 +833,7 @@ bi_i_EditBuffer__getEOL_ (progs_t *pr) } static void -bi_i_EditBuffer__getBOT (progs_t *pr) +bi__i_EditBuffer__getBOT (progs_t *pr) { //qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); //int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -843,7 +843,7 @@ bi_i_EditBuffer__getBOT (progs_t *pr) } static void -bi_i_EditBuffer__getEOT (progs_t *pr) +bi__i_EditBuffer__getEOT (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -853,7 +853,7 @@ bi_i_EditBuffer__getEOT (progs_t *pr) } static void -bi_i_EditBuffer__readString_ (progs_t *pr) +bi__i_EditBuffer__readString_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -868,7 +868,7 @@ bi_i_EditBuffer__readString_ (progs_t *pr) } static void -bi_i_EditBuffer__getChar_ (progs_t *pr) +bi__i_EditBuffer__getChar_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -882,7 +882,7 @@ bi_i_EditBuffer__getChar_ (progs_t *pr) } static void -bi_i_EditBuffer__putChar_at_ (progs_t *pr) +bi__i_EditBuffer__putChar_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -897,7 +897,7 @@ bi_i_EditBuffer__putChar_at_ (progs_t *pr) } static void -bi_i_EditBuffer__insertChar_at_ (progs_t *pr) +bi__i_EditBuffer__insertChar_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -912,7 +912,7 @@ bi_i_EditBuffer__insertChar_at_ (progs_t *pr) } static void -bi_i_EditBuffer__countLines_ (progs_t *pr) +bi__i_EditBuffer__countLines_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -924,7 +924,7 @@ bi_i_EditBuffer__countLines_ (progs_t *pr) } static void -bi_i_EditBuffer__search_for_direction_ (progs_t *pr) +bi__i_EditBuffer__search_for_direction_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -938,7 +938,7 @@ bi_i_EditBuffer__search_for_direction_ (progs_t *pr) } static void -bi_i_EditBuffer__isearch_for_direction_ (progs_t *pr) +bi__i_EditBuffer__isearch_for_direction_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -952,7 +952,7 @@ bi_i_EditBuffer__isearch_for_direction_ (progs_t *pr) } static void -bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) +bi__i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -972,7 +972,7 @@ bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) } static void -bi_i_EditBuffer__modified (progs_t *pr) +bi__i_EditBuffer__modified (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -981,7 +981,7 @@ bi_i_EditBuffer__modified (progs_t *pr) } static void -bi_i_EditBuffer__textSize (progs_t *pr) +bi__i_EditBuffer__textSize (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -990,7 +990,7 @@ bi_i_EditBuffer__textSize (progs_t *pr) } static void -bi_i_EditBuffer__saveFile_ (progs_t *pr) +bi__i_EditBuffer__saveFile_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -1015,43 +1015,47 @@ qwaq_ebresources_clear (progs_t *pr, void *data) editbuffer_reset (res); } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"_i_EditBuffer__init", bi_i_EditBuffer__init, -1}, - {"_i_EditBuffer__initWithFile_", bi_i_EditBuffer__initWithFile_, -1}, - {"_i_EditBuffer__dealloc", bi_i_EditBuffer__dealloc, -1}, - {"_i_EditBuffer__nextChar_", bi_i_EditBuffer__nextChar_, -1}, - {"_i_EditBuffer__prevChar_", bi_i_EditBuffer__prevChar_, -1}, - {"_i_EditBuffer__nextNonSpace_", bi_i_EditBuffer__nextNonSpace_, -1}, - {"_i_EditBuffer__prevNonSpace_", bi_i_EditBuffer__prevNonSpace_, -1}, - {"_i_EditBuffer__isWord_", bi_i_EditBuffer__isWord_, -1}, - {"_i_EditBuffer__nextWord_", bi_i_EditBuffer__nextWord_, -1}, - {"_i_EditBuffer__prevWord_", bi_i_EditBuffer__prevWord_, -1}, - {"_i_EditBuffer__nextLine_", bi_i_EditBuffer__nextLine_, -1}, - {"_i_EditBuffer__prevLine_", bi_i_EditBuffer__prevLine_, -1}, - {"_i_EditBuffer__nextLine__", bi_i_EditBuffer__nextLine__, -1}, - {"_i_EditBuffer__prevLine__", bi_i_EditBuffer__prevLine__, -1}, - {"_i_EditBuffer__charPos_at_", bi_i_EditBuffer__charPos_at_, -1}, - {"_i_EditBuffer__charPtr_at_", bi_i_EditBuffer__charPtr_at_, -1}, - {"_i_EditBuffer__getWord_", bi_i_EditBuffer__getWord_, -1}, - {"_i_EditBuffer__getLine_", bi_i_EditBuffer__getLine_, -1}, - {"_i_EditBuffer__getBOL_", bi_i_EditBuffer__getBOL_, -1}, - {"_i_EditBuffer__getEOL_", bi_i_EditBuffer__getEOL_, -1}, - {"_i_EditBuffer__getBOT", bi_i_EditBuffer__getBOT, -1}, - {"_i_EditBuffer__getEOT", bi_i_EditBuffer__getEOT, -1}, - {"_i_EditBuffer__readString_", bi_i_EditBuffer__readString_, -1}, - {"_i_EditBuffer__getChar_", bi_i_EditBuffer__getChar_, -1}, - {"_i_EditBuffer__putChar_at_", bi_i_EditBuffer__putChar_at_, -1}, - {"_i_EditBuffer__insertChar_at_", bi_i_EditBuffer__insertChar_at_,-1}, - {"_i_EditBuffer__countLines_", bi_i_EditBuffer__countLines_, -1}, - {"_i_EditBuffer__search_for_direction_", - bi_i_EditBuffer__search_for_direction_, -1}, - {"_i_EditBuffer__isearch_for_direction_", - bi_i_EditBuffer__isearch_for_direction_,-1}, - {"_i_EditBuffer__formatLine_from_into_width_highlight_colors_", - bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1}, - {"_i_EditBuffer__modified", bi_i_EditBuffer__modified, -1}, - {"_i_EditBuffer__textSize", bi_i_EditBuffer__textSize, -1}, - {"_i_EditBuffer__saveFile_", bi_i_EditBuffer__saveFile_, -1}, + bi(_i_EditBuffer__init, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__initWithFile_, -1, 3, p(ptr), p(ptr), p(string)), + bi(_i_EditBuffer__dealloc, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__nextChar_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevChar_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextNonSpace_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevNonSpace_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__isWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextLine_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevLine_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextLine__, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__prevLine__, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__charPos_at_, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__charPtr_at_, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__getWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getLine_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getBOL_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getEOL_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getBOT, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__getEOT, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__readString_, -1, 3, p(ptr), p(ptr), P(1, 2)), + bi(_i_EditBuffer__getChar_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__putChar_at_, -1, 4, p(ptr), p(ptr), p(int), p(uint)), + bi(_i_EditBuffer__insertChar_at_, -1, 4, p(ptr), p(ptr), p(int), p(uint)), + bi(_i_EditBuffer__countLines_, -1, 3, p(ptr), p(ptr), P(1, 2)), + bi(_i_EditBuffer__search_for_direction_, -1, + 5, p(ptr), p(ptr), P(1, 2), p(string), p(int)), + bi(_i_EditBuffer__isearch_for_direction_,-1, + 5, p(ptr), p(ptr), P(1, 2), p(string), p(int)), + bi(_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1, + 8, p(ptr), p(ptr), + p(uint), p(uint), p(ptr), p(uint), P(1, 2), P(1, 2)), + bi(_i_EditBuffer__modified, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__textSize, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__saveFile_, -1, 3, p(ptr), p(ptr), p(string)), {} }; @@ -1062,5 +1066,5 @@ QWAQ_EditBuffer_Init (progs_t *pr) res->pr = pr; PR_Resources_Register (pr, "qwaq-editbuffer", res, qwaq_ebresources_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 44426ae4a..746332cc4 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -83,7 +83,7 @@ quit_f (void) } static progs_t *bi_rprogs; -static func_t qc2d; +static pr_func_t qc2d; static int event_handler_id; static void @@ -120,15 +120,17 @@ bi_refresh_2d (progs_t *pr) } static void -bi_shutdown_ (progs_t *pr) +bi_shutdown (progs_t *pr) { Sys_Shutdown (); } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"refresh", bi_refresh, -1}, - {"refresh_2d", bi_refresh_2d, -1}, - {"shutdown", bi_shutdown_, -1}, + bi(refresh, -1, 0), + bi(refresh_2d, -1, 1, p(func)), + bi(shutdown, -1, 0), {0} }; @@ -139,7 +141,7 @@ event_handler (const IE_event_t *ie_event, void *_pr) } static void -bi_shutdown (void *data) +BI_shutdown (void *data) { } @@ -149,13 +151,13 @@ BI_Graphics_Init (progs_t *pr) qwaq_thread_t *thread = PR_Resources_Find (pr, "qwaq_thread"); byte *basepal, *colormap; - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); QFS_Init (thread->hunk, "nq"); PI_Init (); PI_RegisterPlugins (client_plugin_list); - Sys_RegisterShutdown (bi_shutdown, pr); + Sys_RegisterShutdown (BI_shutdown, pr); VID_Init_Cvars (); IN_Init_Cvars (); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 3b79f6e5d..9bb4d838f 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -53,6 +53,7 @@ #include "QF/zone.h" #include "compat.h" +#include "rua_internal.h" #include "ruamoko/qwaq/qwaq.h" #include "ruamoko/qwaq/debugger/debug.h" @@ -119,7 +120,7 @@ load_file (progs_t *pr, const char *name, off_t *_size) static void * allocate_progs_mem (progs_t *pr, int size) { - return malloc (size); + return aligned_alloc (64, size); } static void @@ -142,21 +143,14 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - - // Normally, this is done by PR_Init, but PR_Init is not called in the main - // thread. However, PR_Opcode_Init() is idempotent. - PR_Opcode_Init (); } static void bi_printf (progs_t *pr) { - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; dstring_t *dstr = dstring_new (); - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); + RUA_Sprintf (pr, dstr, "printf", 0); if (dstr->str) { Sys_Printf ("%s", dstr->str); } @@ -176,17 +170,19 @@ bi_traceoff (progs_t *pr) pr->pr_trace = false; } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t common_builtins[] = { - {"printf", bi_printf, -1}, - {"traceon", bi_traceon, -1}, - {"traceoff", bi_traceoff, -1}, + bi(printf, -1, -2, p(string)), + bi(traceon, -1, 0), + bi(traceoff, -1, 0), {}, }; static void common_builtins_init (progs_t *pr) { - PR_RegisterBuiltins (pr, common_builtins); + PR_RegisterBuiltins (pr, common_builtins, 0); } static void @@ -230,7 +226,8 @@ load_progs (progs_t *pr, const char *name) } pr->progs_name = name; pr->max_edicts = 1; - pr->zone_size = 1024*1024; + pr->zone_size = 2*1024*1024; + pr->stack_size = 64*1024; PR_LoadProgsFile (pr, file, size); Qclose (file); if (!PR_RunLoadFuncs (pr)) @@ -243,7 +240,7 @@ spawn_progs (qwaq_thread_t *thread) { dfunction_t *dfunc; const char *name = 0; - string_t *pr_argv; + pr_string_t *pr_argv; int pr_argc = 1, i; progs_t *pr; diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index 697cd2e7c..8b34a22e5 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -868,11 +868,13 @@ bi_init_input (progs_t *pr) IE_Send_Event (&event); } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"send_connected_devices", bi_send_connected_devices, -1}, - {"get_device_info", bi_get_device_info, -1}, - {"get_event", bi_get_event, -1}, - {"init_input", bi_init_input, -1}, + bi(send_connected_devices, -1, 0), + bi(get_device_info, -1, 1, p(int)), + bi(get_event, -1, 1, p(ptr)), + bi(init_input, -1, 0), {0} }; @@ -914,6 +916,6 @@ BI_TermInput_Init (progs_t *pr) qwaq_init_cond (&res->events.cond); PR_Resources_Register (pr, "input", res, bi_input_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); Sys_RegisterShutdown (bi_input_shutdown, pr); } diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index 93ef60f3b..bfc0d4f88 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -9,21 +9,21 @@ typedef enum { #ifdef __QFCC__ -#include +#include //FIXME finish unsigned in qfcc #ifndef umax #define umax 0x7fffffff #endif -typedef string string_t; +typedef string pr_string_t; #endif typedef struct qdb_event_s { prdebug_t what; union { - string_t message; + pr_string_t message; unsigned function; int exit_code; }; @@ -32,7 +32,7 @@ typedef struct qdb_event_s { typedef struct qdb_state_s { unsigned staddr; unsigned func; - string_t file; + pr_string_t file; unsigned line; } qdb_state_t; diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index d6246e2ef..fe296a573 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -106,7 +106,7 @@ static void type_free (void *t, void *unused) } switch (type.meta) { case ty_basic: - if (type.type == ev_pointer || type.type == ev_field) { + if (type.type == ev_ptr || type.type == ev_field) { t = [TypeEncodings getType:(unsigned)type.fldptr.aux_type fromTarget:target]; if (!t) { @@ -221,7 +221,7 @@ error: break; case ty_enum: // enums are ints - size = pr_type_size[ev_integer]; + size = pr_type_size[ev_int]; break; case ty_class: //FIXME diff --git a/ruamoko/qwaq/editor/editbuffer.h b/ruamoko/qwaq/editor/editbuffer.h index fe8a15829..08a13d213 100644 --- a/ruamoko/qwaq/editor/editbuffer.h +++ b/ruamoko/qwaq/editor/editbuffer.h @@ -77,11 +77,11 @@ typedef struct eb_color_s { @end #else//__QFCC__ -#include "QF/pr_obj.h" +#include "QF/progs/pr_obj.h" typedef struct qwaq_editbuffer_s { pr_id_t isa; - pointer_t buffer; + pr_ptr_t buffer; } qwaq_editbuffer_t; #endif//!__QFCC__ diff --git a/ruamoko/qwaq/qwaq-input.h b/ruamoko/qwaq/qwaq-input.h index f385917e5..959015a33 100644 --- a/ruamoko/qwaq/qwaq-input.h +++ b/ruamoko/qwaq/qwaq-input.h @@ -9,20 +9,20 @@ typedef struct qwaq_devinfo_s { string name; string id; #else - string_t name; - string_t id; + pr_string_t name; + pr_string_t id; #endif int numaxes; #ifdef __QFCC__ in_axisinfo_t *axes; #else - pointer_t axes; + pr_ptr_t axes; #endif int numbuttons; #ifdef __QFCC__ in_axisinfo_t *buttons; #else - pointer_t buttons; + pr_ptr_t buttons; #endif } qwaq_devinfo_t; diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 4bdc09435..cb16c9af9 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -19,7 +19,7 @@ typedef struct qwaq_thread_s { int rua_security; struct memhunk_s *hunk; struct hashlink_s *hashlink_freelist; - func_t main_func; + pr_func_t main_func; void *data; } qwaq_thread_t; diff --git a/ruamoko/qwaq/ui/event.h b/ruamoko/qwaq/ui/event.h index 8a9f3c608..571e256f6 100644 --- a/ruamoko/qwaq/ui/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -74,8 +74,8 @@ typedef union qwaq_message_s { void *pointer_val; string string_val; #else - pointer_t pointer_val; - string_t string_val; + pr_ptr_t pointer_val; + pr_string_t string_val; #endif } qwaq_message_t; diff --git a/ruamoko/qwaq/ui/listener.r b/ruamoko/qwaq/ui/listener.r index 8fa43b01f..1776e9ffe 100644 --- a/ruamoko/qwaq/ui/listener.r +++ b/ruamoko/qwaq/ui/listener.r @@ -90,7 +90,7 @@ -(void)respond: (void *) caller_data withObject:(void *)anObject { - [listeners makeObjectsPerformSelector: @selector (respond:) + [listeners makeObjectsPerformSelector: @selector (respond:withObject:) withObject: caller_data withObject: anObject]; } diff --git a/ruamoko/qwaq/ui/proxyview.r b/ruamoko/qwaq/ui/proxyview.r index 714b3fd9d..c39358092 100644 --- a/ruamoko/qwaq/ui/proxyview.r +++ b/ruamoko/qwaq/ui/proxyview.r @@ -10,9 +10,9 @@ - (void) forward: (SEL) sel : (@va_list) args { if (!view) { - return; + @return nil; } - obj_msg_sendv (view, sel, args); + @return obj_msg_sendv (view, sel, args); } -initWithView:(View *) view diff --git a/ruamoko/qwaq/ui/textcontext.h b/ruamoko/qwaq/ui/textcontext.h index 21f21b5ae..168a7b9c0 100644 --- a/ruamoko/qwaq/ui/textcontext.h +++ b/ruamoko/qwaq/ui/textcontext.h @@ -61,11 +61,11 @@ #else -#include "QF/pr_obj.h" +#include "QF/progs/pr_obj.h" typedef struct qwaq_textcontext_s { pr_id_t isa; - pointer_t window; + pr_ptr_t window; union { Rect rect; struct { diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index c7fbe58c8..1b7fb4c06 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -264,12 +264,12 @@ updateScreenCursor (View *view) - (void) forward: (SEL) sel : (@va_list) args { if (!textContext) { - return; + @return nil; } if (!__obj_responds_to (textContext, sel)) { [self error: "no implementation for %s", sel_get_name (sel)]; } - obj_msg_sendv (textContext, sel, args); + @return obj_msg_sendv (textContext, sel, args); } - (void) refresh diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index 5d49b816a..0541458dd 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -56,8 +56,10 @@ understand. .TP .B \-\-advanced -Use advanced Ruamoko features. -This is the default when using separate compilation. +Use advanced Ruamoko language features limited to the v6p ISA. This +provides access to structs, arrays, pointers, integers, quaternions, +doubles and object-oriented features mostly compatible with Objective-C +(ie, Objective-QuakeC). For access to SIMD vector types, see --ruamoko. .TP .B \-C, \-\-code OPTION,... @@ -179,6 +181,15 @@ Counteracts the effects of \fB-v\fP. Incremental linking. Generate a larger object file from other object files and libraries. +.TP +.B \-\-raumoko, \-\-ruamoko +In addition to the Ruamoko language features added by --advanced, this +option provides access to SIMD vector types (and instructions), a data +stack for local variables and parameters (allowing pointers to local +variables to be passed to other functions!), and other features still +under development. +This is the default when using separate compilation. + .TP .B \-S, \-\-save\-temps Do not delete temporary files. @@ -190,7 +201,7 @@ Look for \*[progs.src] in \fBDIR\fP instead of the current directory. .TP .B \-\-traditional Use traditional QuakeC syntax, semantics and \*(lqbugs\*(rq. -Also implies the \fBv6only\fP, \fBno-short-circuit\fP, +Also implies the \fBtarget=v6\fP, \fBno-short-circuit\fP, \fBconst-initializers\fP and \fBno-local-merging\fP code generation options (see \fBCODE GENERATION OPTIONS\fP). This is the default when using \fBprogs.src\fP mode. @@ -271,8 +282,8 @@ output file is \*(lqprogs.dat\*(rq, the symbol file will be .B fast\-float Use float values directly in \*(lqif\*(rq statements. Defaults to on. -This option is always enabled when using version 6 progs (\fBv6only\fP is in -effect). +This option is always enabled when targeting v6 progs (\fBtarget=v6\fP is +in effect). .TP .B local-merging @@ -289,8 +300,9 @@ Defaults to off for traditional mode, and on for advanced mode. .TP .B promote\-float Promote float when passed to a function that takes a variable number of -arguements. Defaults to enabled for advanced code, is forced off for -traditional or v6only code (mostly because such code does not have doubles). +arguements. Defaults to enabled for advanced code (v6p or ruamoko), is forced +off for traditional or v6 code (mostly because such code does not have +doubles). .TP .B short\-circuit @@ -329,18 +341,33 @@ Create extra symbols for accessing the components of a vector variable or field. For example, \fBvector vel\fP will also create \fBvel_x\fP, \fBvel_y\fP, and \fBvel_z\fP. Defaults to on for traditional code and off for advanced. +.PP +Any of the above can be prefixed with \fBno\-\fP to negate its meaning. .TP -.B v6only -Restrict the compiler to produce only version 6 progs (original -Quake/QuakeWorld) features. +.B target=v6|v6p|ruamoko +Specify the target for which the compiler is to produce code. +.RS +.TP +.B v6 +Standard Quake VM (qcc compatible). This means that the compiled data file should be able to run on older servers, as long as you have not used any QuakeForge-specific built-in functions. Also disables compiler features (such as integers and string manipulation support) that require extensions. -Defaults to on for traditional mode and off for advanced mode. -.PP -Any of the above can be prefixed with \fBno\-\fP to negate its meaning. +.TP +.B v6p +QuakeForge extended v6 instructions. +This is not compatible with older servers, nor with most (any?) other Quake +engines. It adds a variety of instructions and types, including integers, +quaternions, pointers, doubles, structs, arrays and Objective-C style classes. +.TP +.B ruamoko +QuakeForge SIMD and stack instructions. +.RE +Defaults to v6 for traditional mode, v6p for advanced mode, and ruamoko +for Ruamoko mode (actually, trying to take Ruamoko's power after +granting it may not end well). .SH "WARNING OPTIONS" @@ -703,13 +730,13 @@ gold digits. \fB\-\-qccx\-escapes\fP has no effect on sequences that do not conflict. -.SH TRADITIONAL VS ADVANCED -Compared to \fBqcc\fP, \*[qfcc] has many advanced features and is much stricter -about type checking. +.SH TRADITIONAL VS ADVANCED VS RUAMOKO +Compared to \fBqcc\fP, \*[qfcc] has many advanced features and is much +stricter about type checking. \*[qfcc] also uses the same operator semantics and precedence rules as standard \fBC\fP. -Unfortunately, this means that most older QuakeC code will not compile, or even -worse, will compile incorrectly. +Unfortunately, this means that most older QuakeC code will not compile, +or even worse, will compile incorrectly. .P To address this situation, \*[qfcc] has a \*(lqtraditional\*(rq mode for compiling old progs. @@ -717,20 +744,32 @@ This mode, enabled with \fB--traditional\fP or by default in \fBprogs.src\fP mode, removes the new keywords required by \*[qfcc]'s advanced features, converts new errors to warnings, some warnings to notices and inverts precedence order where required (eg, (!var & flag)). -Traditional mode also affects several code generation options (as always, this -can be overridden): +Traditional mode also affects several code generation options (as +always, this can be overridden): .IP \(bu 4 code output is restricted to version 6 progs instructions .IP \(bu 4 short circuit boolean logic is disabled .IP \(bu 4 -each function has a private area of data for its local variables (this wastes -a lot of data space). +each function has a private area of data for its local variables (this +wastes a lot of data space). .P -Advanced mode is simply \*[qfcc] in its natural state. -Using \fB--advanced\fP, \*[qfcc] can be put in to advanced mode while using the -\fBprogs.src\fP compilation mode. +Advanced mode is \*[qfcc] in what was its natural state until the +introduction of Ruamoko mode. Advanced mode adds several data types and +Objective-C object oriented programming. +Using \fB--advanced\fP, \*[qfcc] can be put in to advanced mode while +using the \fBprogs.src\fP compilation mode. +.P +Ruamoko mode is \*[qfcc] in its natural state. On top of the features +added by Advanced mode, Ruamoko mode adds SIMD types and instructions, +and a data stack for locals and parameters. +.SH RUAMOKO PROGRAMMING LANGUAGE +Ruamoko evolved from the original QuakeC language, gaining standard C +syntax and most features (the char type is not supported, and function +pointers are a little weird (design bug?)), Objective-C object oriented +extensions, and (with the Ruamoko ISA) SIMD vectors and the ability to +pass pointers to local variables to other functions. .SH "FAQ" @@ -741,6 +780,11 @@ Sky-father, and Papatuanuku, the Earth-mother. Ruamoko is the god of volcanoes and earthquakes. For more information, see the Web site at <\fBhttp://maori.com/kmst1.htm\fP>. +.TP +.B Why both Ruamoko and Raumoko? +They are alternative spellings and pronunciations. Use whichever one you +prefer. + .TP .B qfcc hangs This is almost always caused by qfcc incorrectly invoking \*[cpp]. diff --git a/tools/qfcc/include/Makemodule.am b/tools/qfcc/include/Makemodule.am index 689ebad68..f6158b5c4 100644 --- a/tools/qfcc/include/Makemodule.am +++ b/tools/qfcc/include/Makemodule.am @@ -1,4 +1,5 @@ EXTRA_DIST += \ + tools/qfcc/include/attribute.h \ tools/qfcc/include/class.h \ tools/qfcc/include/codespace.h \ tools/qfcc/include/cpp.h \ diff --git a/tools/qfcc/include/attribute.h b/tools/qfcc/include/attribute.h new file mode 100644 index 000000000..2f47642e6 --- /dev/null +++ b/tools/qfcc/include/attribute.h @@ -0,0 +1,43 @@ +/* + attribute.h + + Attribute list handling + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/02/02 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef attribute_h +#define attribute_h + +typedef struct attribute_s { + struct attribute_s *next; + const char *name; + struct ex_value_s *value; +} attribute_t; + +struct expr_s; +attribute_t *new_attribute(const char *name, struct expr_s *value); + +#endif//attribute_h diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index ec160e1d9..217227a73 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -94,6 +94,7 @@ extern struct type_s type_object; extern struct type_s type_class; extern struct type_s type_Class; extern struct type_s type_protocol; +extern struct type_s type_selector; extern struct type_s type_SEL; extern struct type_s type_IMP; extern struct type_s type_supermsg; diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index 6addafcd2..66fbece40 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -35,7 +35,7 @@ */ ///@{ -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #include "statements.h" diff --git a/tools/qfcc/include/debug.h b/tools/qfcc/include/debug.h index af5f322b7..6e7d6f477 100644 --- a/tools/qfcc/include/debug.h +++ b/tools/qfcc/include/debug.h @@ -31,7 +31,7 @@ #ifndef __debug_h #define __debug_h -#include "QF/pr_debug.h" +#include "QF/progs/pr_debug.h" void line_info (char *text); pr_lineno_t *new_lineno (void); diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 691c5d602..6892b5d8a 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -31,8 +31,8 @@ #ifndef __def_h #define __def_h -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" /** \defgroup qfcc_def Def handling \ingroup qfcc @@ -40,6 +40,7 @@ ///@{ struct symbol_s; +struct symtab_s; struct expr_s; /** Represent a memory location that holds a QuakeC/Ruamoko object. @@ -60,6 +61,7 @@ typedef struct def_s { const char *name; ///< the def's name struct defspace_s *space; ///< defspace to which this def belongs int offset; ///< address of this def in its defspace + int reg; ///< base register index to access def /** \name Def aliasing. Aliasing a def provides a different view of the def providing access @@ -98,7 +100,7 @@ typedef struct def_s { unsigned system:1; ///< system def unsigned nosave:1; ///< don't set DEF_SAVEGLOBAL - string_t file; ///< declaring/defining source file + pr_string_t file; ///< declaring/defining source file int line; ///< declaring/defining source line int qfo_def; ///< index to def in qfo defs @@ -219,6 +221,9 @@ void free_temp_def (def_t *temp); */ void def_to_ddef (def_t *def, ddef_t *ddef, int aux); +void init_vector_components (struct symbol_s *vector_sym, int is_field, + struct symtab_s *symtab); + /** Initialize a def referenced by the given symbol. The symbol is checked for redefinition. A symbol is considered to be @@ -241,10 +246,11 @@ void def_to_ddef (def_t *def, ddef_t *ddef, int aux); \param init If not null, the expressions to use to initialize the def. \param space The space from which to allocate space for the def. \param storage The storage class of the def. + \param symtab The symbol table into which the def will be placed. */ void initialize_def (struct symbol_s *sym, struct expr_s *init, struct defspace_s *space, - storage_class_t storage); + storage_class_t storage, struct symtab_s *symtab); /** Determine if two defs overlap. diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index e0414f1c9..eea13bf71 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -31,8 +31,8 @@ #ifndef __defspace_h #define __defspace_h -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" /** \defgroup qfcc_defspace Defspace handling \ingroup qfcc @@ -43,7 +43,8 @@ typedef enum { ds_backed, ///< data space is globally addressable (near/far/type) and ///< has backing store ds_virtual, ///< data space has no backing store (local vars, entity - ///< fields) + ///< fields) defspace_t::max_size reflects the highest + ///< address allocated } ds_type_t; /** Represent a block of memory in the progs data space. @@ -56,7 +57,8 @@ typedef struct defspace_s { struct def_s **def_tail; ///< for appending to \a defs pr_type_t *data; ///< backing memory for this space int size; ///< current high-water mark for alloced data - int max_size; ///< size of backing memory + int max_size; ///< size of backing memory, or highwater mark + ///< for ds_virtual /** Grow the backing memory of the defspace. This function is called when more memory is needed for the space. @@ -168,6 +170,57 @@ void defspace_free_loc (defspace_t *space, int ofs, int size); */ int defspace_add_data (defspace_t *space, pr_type_t *data, int size); +/** Allocate a block of data from the end of the defspace. + + If memory cannot be allocated (there is no free space in the currently + available memory and defspace_t::grow is null), then an internal error + will be generated. + + \param space The space from which to allocate data. + \param size The amount of pr_type_t words to allocated. int and float + need 1 word, vector 3 words, and quaternion 4. + \return The offset of the first word of the freshly allocated + space. May be 0 if the allocated space is at the beginning + of the defspace. +*/ +int defspace_alloc_highwater (defspace_t *space, int size); + +/** Allocate an aligned block of data from the end of the defspace. + + Any unallocated holes in the defspace are ignored, even if the hole is + at the end of the defspace. However, any holes created by the padding + required for aligning the block will be available to defspace_alloc_loc() + and defspace_alloc_aligned_loc(). + + If memory cannot be allocated (there is no free space in the currently + available memory and defspace_t::grow is null), then an internal error + will be generated. + + \param space The space from which to allocate data. + \param size The amount of pr_type_t words to allocated. int and float + need 1 word, vector 3 words, and quaternion 4. + \param alignment The alignment of the allocated space. + \return The offset of the first word of the freshly allocated + space. May be 0 if the allocated space is at the beginning + of the defspace. +*/ +int defspace_alloc_aligned_highwater (defspace_t *space, int size, + int alignment); +/** Reset a defspace, freeing all allocated memory. + + defspace_t::max_size is not affected. This allows the defspace to be used + to find the larged block of memory required for a set of operations (eg, + the largest parameter block required in a function for all its calls + allowing the stack to remain constant instead of using many push/pop + operations. Note that this works best with ds_virtual defspaces. + + If the defspace has backing memory (ds_backed), the memory is not freed, + but it is zeroed so any new allocations will contain zeroed memory. + + \param space The space to be reset. +*/ +void defspace_reset (defspace_t *space); + ///@} #endif//__defspace_h diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 958b44d66..8adec809c 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -31,8 +31,6 @@ #ifndef __diagnostic_h #define __diagnostic_h -#include "QF/pr_comp.h" - /** \defgroup qfcc_diagnostic Diagnostic Messages \ingroup qfcc */ diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 6b8fa8034..2b3887ae1 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -31,7 +31,7 @@ #ifndef __expr_h #define __expr_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" /** \defgroup qfcc_expr Expressions \ingroup qfcc @@ -40,28 +40,12 @@ /** Type of the exression node in an expression tree. */ +#define EX_EXPR(expr) ex_##expr, typedef enum { - ex_error, ///< error expression. used to signal an error - ex_state, ///< state expression (::ex_state_t) - ex_bool, ///< short circuit boolean logic expression (::ex_bool_t) - ex_label, ///< goto/branch label (::ex_label_t) - ex_labelref, ///< label reference (::ex_labelref_t) - ex_block, ///< statement block expression (::ex_block_t) - ex_expr, ///< binary expression (::ex_expr_t) - ex_uexpr, ///< unary expression (::ex_expr_t) - ex_def, ///< non-temporary variable (::def_t) - ex_symbol, ///< non-temporary variable (::symbol_t) - ex_temp, ///< temporary variable (::ex_temp_t) - ex_vector, ///< "vector" expression (::ex_vector_t) - ex_selector, ///< selector expression (::ex_selector_t) - - ex_nil, ///< umm, nil, null. nuff said (0 of any type) - ex_value, ///< constant value (::ex_value_t) - ex_compound, ///< compound initializer - ex_memset, ///< memset needs three params... - +#include "tools/qfcc/include/expr_names.h" ex_count, ///< number of valid expression types } expr_type; +#undef EX_EXPR /** Binary and unary expressions. @@ -209,25 +193,76 @@ typedef struct ex_value_s { union { const char *string_val; ///< string constant double double_val; ///< double constant + int64_t long_val; ///< signed 64-bit constant + uint64_t ulong_val; ///< unsigned 64-bit constant float float_val; ///< float constant float vector_val[3]; ///< vector constant int entity_val; ///< entity constant ex_func_t func_val; ///< function constant ex_pointer_t pointer; ///< pointer constant float quaternion_val[4]; ///< quaternion constant - int integer_val; ///< integer constant - unsigned uinteger_val; ///< unsigned integer constant - short short_val; ///< short constant + int int_val; ///< int constant + unsigned uint_val; ///< unsigned int constant + int16_t short_val; ///< short constant + uint16_t ushort_val; ///< unsigned short constant } v; } ex_value_t; +typedef struct { + struct type_s *type; ///< type to view the expression + struct expr_s *expr; ///< the expression to alias + struct expr_s *offset; ///< offset for alias +} ex_alias_t; + +typedef struct { + struct type_s *type; ///< pointer type + struct expr_s *lvalue; ///< the lvalue being addressed + struct expr_s *offset; ///< offset from the address +} ex_address_t; + +typedef struct { + struct expr_s *dst; ///< destination of assignment + struct expr_s *src; ///< source of assignment +} ex_assign_t; + +typedef struct { + pr_branch_e type; ///< type of branch + struct expr_s *target; ///< destination of branch + struct expr_s *index; ///< index for indirect branches + struct expr_s *test; ///< test expression (null for jump/call) + struct expr_s *args; ///< only for call + struct type_s *ret_type; ///< void for non-call +} ex_branch_t; + +typedef struct { + struct expr_s *ret_val; + int at_return; ///< return void_return call through void +} ex_return_t; + +typedef struct { + short mode; ///< currently must be 0 + short offset; ///< amount by which stack will be adjusted +} ex_adjstk_t; + +typedef struct { + short mode; + short reg; ///< base register to load + struct expr_s *with; ///< value to load +} ex_with_t; + +typedef struct { + int op; ///< operation to perform + struct expr_s *vec; ///< vector expression on which to operate + struct type_s *type; ///< result type +} ex_horizontal_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { struct expr_s *next; ///< the next expression in a block expression expr_type type; ///< the type of the result of this expression int line; ///< source line that generated this expression - string_t file; ///< source file that generated this expression + pr_string_t file; ///< source file that generated this expression int printid; ///< avoid duplicate output when printing unsigned paren:1; ///< the expression is enclosed in () unsigned rvalue:1; ///< the expression is on the right side of = @@ -247,7 +282,15 @@ typedef struct expr_s { ex_value_t *value; ///< constant value element_chain_t compound; ///< compound initializer ex_memset_t memset; ///< memset expr params + ex_alias_t alias; ///< alias expr params + ex_address_t address; ///< alias expr params + ex_assign_t assign; ///< assignment expr params + ex_branch_t branch; ///< branch expr params + ex_return_t retrn; ///< return expr params + ex_adjstk_t adjstk; ///< stack adjust param + ex_with_t with; ///< with expr param struct type_s *nil; ///< type for nil if known + ex_horizontal_t hop; ///< horizontal vector operation } e; } expr_t; @@ -397,7 +440,7 @@ void build_element_chain (element_chain_t *element_chain, expr_t *eles, int base_offset); void free_element_chain (element_chain_t *element_chain); -/** Create a new binary expression node node. +/** Create a new binary expression node. If either \a e1 or \a e2 are error expressions, then that expression will be returned instead of a new binary expression. @@ -411,7 +454,7 @@ void free_element_chain (element_chain_t *element_chain); */ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2); -/** Create a new unary expression node node. +/** Create a new unary expression node. If \a e1 is an error expression, then it will be returned instead of a new unary expression. @@ -423,6 +466,19 @@ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2); */ expr_t *new_unary_expr (int op, expr_t *e1); +/** Create a new horizontal vector operantion node. + + If \a vec is an error expression, then it will be returned instead of a + new unary expression. + + \param op The op-code of the horizontal operation. + \param vec The expression (must be a vector type) on which to operate. + \param type The result type (must be scalar type) + \return The new unary expression node (::ex_expr_t) if \a e1 + is not an error expression, otherwise \a e1. +*/ +expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type); + /** Create a new def reference (non-temporary variable) expression node. \return The new def reference expression node (::def_t). @@ -453,6 +509,14 @@ expr_t *new_temp_def_expr (const struct type_s *type); */ expr_t *new_nil_expr (void); +/** Create a new args expression node + + Marker between real parameters and those passed through ... + + \return The new args expression node. +*/ +expr_t *new_args_expr (void); + /** Create a new value expression node. \param value The value to put in the expression node. @@ -550,23 +614,23 @@ expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def); expr_t *new_quaternion_expr (const float *quaternion_val); const float *expr_quaternion (expr_t *e) __attribute__((pure)); -/** Create a new integer constant expression node. +/** Create a new itn constant expression node. - \param integer_val The integer constant being represented. - \return The new integer constant expression node - (expr_t::e::integer_val). + \param int_val The int constant being represented. + \return The new int constant expression node + (expr_t::e::int_val). */ -expr_t *new_integer_expr (int integer_val); -int expr_integer (expr_t *e) __attribute__((pure)); +expr_t *new_int_expr (int int_val); +int expr_int (expr_t *e) __attribute__((pure)); -/** Create a new integer constant expression node. +/** Create a new int constant expression node. - \param uinteger_val The integer constant being represented. - \return The new integer constant expression node - (expr_t::e::integer_val). + \param uint_val The int constant being represented. + \return The new int constant expression node + (expr_t::e::int_val). */ -expr_t *new_uinteger_expr (unsigned uinteger_val); -unsigned expr_uinteger (expr_t *e) __attribute__((pure)); +expr_t *new_uint_expr (unsigned uint_val); +unsigned expr_uint (expr_t *e) __attribute__((pure)); /** Create a new short constant expression node. @@ -586,6 +650,14 @@ int expr_integral (expr_t *e) __attribute__((pure)); */ int is_constant (expr_t *e) __attribute__((pure)); +/** Check if the expression refers to a variable. + + \param e The expression to check. + \return True if the expression refers to a variable (def + expression, var symbol expression, or temp expression). +*/ +int is_variable (expr_t *e) __attribute__((pure)); + /** Check if the expression refers to a selector \param e The expression to check. @@ -625,14 +697,15 @@ int is_math_op (int op) __attribute__((const)); int is_logic (int op) __attribute__((const)); int has_function_call (expr_t *e) __attribute__((pure)); +int is_function_call (expr_t *e) __attribute__((pure)); int is_nil (expr_t *e) __attribute__((pure)); int is_string_val (expr_t *e) __attribute__((pure)); int is_float_val (expr_t *e) __attribute__((pure)); int is_vector_val (expr_t *e) __attribute__((pure)); int is_quaternion_val (expr_t *e) __attribute__((pure)); -int is_integer_val (expr_t *e) __attribute__((pure)); -int is_uinteger_val (expr_t *e) __attribute__((pure)); +int is_int_val (expr_t *e) __attribute__((pure)); +int is_uint_val (expr_t *e) __attribute__((pure)); int is_short_val (expr_t *e) __attribute__((pure)); int is_integral_val (expr_t *e) __attribute__((pure)); int is_pointer_val (expr_t *e) __attribute__((pure)); @@ -661,6 +734,13 @@ expr_t *new_ret_expr (struct type_s *type); expr_t *new_alias_expr (struct type_s *type, expr_t *expr); expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset); +expr_t *new_address_expr (struct type_s *lvtype, expr_t *lvalue, + expr_t *offset); +expr_t *new_assign_expr (expr_t *dst, expr_t *src); +expr_t *new_return_expr (expr_t *ret_val); +expr_t *new_adjstk_expr (int mode, int offset); +expr_t *new_with_expr (int mode, int reg, expr_t *val); + /** Create an expression of the correct type that references the specified parameter slot. @@ -670,22 +750,6 @@ expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset); */ expr_t *new_param_expr (struct type_s *type, int num); -/** Create an expression representing a block copy. - - This is used for structure assignments. - - \param e1 Destination of move. - \param e2 Source of move. - \param type type giving size of move. - \param indirect Move uses dereferenced pointers. - \return A new expression representing the move. -*/ -expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type, - int indirect); - -expr_t *new_memset_expr (expr_t *dst, expr_t *val, struct type_s *type); - - /** Convert a name to an expression of the appropriate type. Converts the expression in-place. If the exprssion is not a name @@ -698,6 +762,7 @@ void convert_name (expr_t *e); expr_t *convert_vector (expr_t *e); expr_t *append_expr (expr_t *block, expr_t *e); +expr_t *prepend_expr (expr_t *block, expr_t *e); expr_t *reverse_expr_list (expr_t *e); void print_expr (expr_t *e); @@ -724,12 +789,16 @@ expr_t *function_expr (expr_t *e1, expr_t *e2); struct function_s; expr_t *branch_expr (int op, expr_t *test, expr_t *label); expr_t *goto_expr (expr_t *label); +expr_t *jump_table_expr (expr_t *table, expr_t *index); +expr_t *call_expr (expr_t *func, expr_t *args, struct type_s *ret_type); expr_t *return_expr (struct function_s *f, expr_t *e); +expr_t *at_return_expr (struct function_s *f, expr_t *e); expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2); expr_t *incop_expr (int op, expr_t *e, int postop); expr_t *array_expr (expr_t *array, expr_t *index); -expr_t *pointer_expr (expr_t *pointer); -expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); +expr_t *deref_pointer_expr (expr_t *pointer); +expr_t *offset_pointer_expr (expr_t *pointer, expr_t *offset); +expr_t *address_expr (expr_t *e1, struct type_s *t); expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2); expr_t *build_while_statement (int not, expr_t *test, expr_t *statement, diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h new file mode 100644 index 000000000..05d1f197a --- /dev/null +++ b/tools/qfcc/include/expr_names.h @@ -0,0 +1,67 @@ +/* + expr_names.h + + expression construction and manipulations + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/01/7 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +/** \defgroup qfcc_expr Expressions + \ingroup qfcc +*/ +///@{ + +#ifndef EX_EXPR +#define EX_EXPR(expr) +#endif + +EX_EXPR(error) ///< error expression. used to signal an error +EX_EXPR(state) ///< state expression (::ex_state_t) +EX_EXPR(bool) ///< short circuit boolean logic expression (::ex_bool_t) +EX_EXPR(label) ///< goto/branch label (::ex_label_t) +EX_EXPR(labelref) ///< label reference (::ex_labelref_t) +EX_EXPR(block) ///< statement block expression (::ex_block_t) +EX_EXPR(expr) ///< binary expression (::ex_expr_t) +EX_EXPR(uexpr) ///< unary expression (::ex_expr_t) +EX_EXPR(def) ///< non-temporary variable (::def_t) +EX_EXPR(symbol) ///< non-temporary variable (::symbol_t) +EX_EXPR(temp) ///< temporary variable (::ex_temp_t) +EX_EXPR(vector) ///< "vector" expression (::ex_vector_t) +EX_EXPR(selector) ///< selector expression (::ex_selector_t) +EX_EXPR(nil) ///< umm, nil, null. nuff said (0 of any type) +EX_EXPR(value) ///< constant value (::ex_value_t) +EX_EXPR(compound) ///< compound initializer +EX_EXPR(memset) ///< memset needs three params... +EX_EXPR(alias) ///< view expression as different type (::ex_alias_t) +EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t) +EX_EXPR(assign) ///< assignment of src expr to dst expr (::ex_assing_t) +EX_EXPR(branch) ///< branch expression (::ex_branch_t) +EX_EXPR(return) ///< return expression (::ex_return_t) +EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t) +EX_EXPR(with) ///< with expression (::ex_with_t) +EX_EXPR(args) ///< @args marker in parameter list. no data +EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t) + +///@} diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 48a82f9e9..83b455555 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -36,11 +36,13 @@ */ ///@{ -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" #include "def.h" +#define MAX_DEF_SIZE ((int)PR_SIZEOF(lvec4)) + /** Represent an overloading of a function. Every function, whether overloaded or not, has an entry in the overloaded @@ -53,7 +55,7 @@ typedef struct overloaded_function_s { ///< encoding const struct type_s *type; ///< type of this function int overloaded; ///< is this function overloaded - string_t file; ///< source file of the function + pr_string_t file; ///< source file of the function int line; ///< source line of this function } overloaded_function_t; @@ -65,21 +67,41 @@ typedef struct function_s { int code; ///< first statement int function_num; int line_info; - int local_defs; - string_t s_file; ///< source file with definition - string_t s_name; ///< name of function in output + int params_start;///< relative to locals space. 0 for v6p + pr_string_t s_file; ///< source file with definition + pr_string_t s_name; ///< name of function in output const struct type_s *type; ///< function's type without aliases + int temp_reg; ///< base register to use for temp defs int temp_num; ///< number for next temp var - struct def_s *temp_defs[4]; ///< freed temp vars (by size) + struct def_s *temp_defs[MAX_DEF_SIZE];///< freed temp vars (by size) struct def_s *def; ///< output def holding function number struct symbol_s *sym; ///< internal symbol for this function - /** Root scope symbol table of the function. + /** \name Local data space - Sub-scope symbol tables are not directly accessible, but all defs - created in the function's local data space are recorded in the root - scope symbol table's defspace. + The function parameters form the root scope for the function. Its + defspace is separate from the locals defspace so that it can be moved + to the beginning of locals space for v6 progs, and too the end (just + above the stack pointer on entry to the function) for Ruamoko progs. + + The locals scope is a direct child of the parameters scope, and any + sub-scope symbol tables are not directly accessible, but all defs + other than function call arugments created in the function's local + data space are recorded in the root local scope symbol table's + defspace. + + The arguments defspace is not used for v6 progs. It is used as a + highwater allocator for the arguments to all calls made by the + funciton, with the arguments to separate functions overlapping each + other. + + Afther the function has been emitted, locals, arguments and possibly + parameters will be merged into the one defspace. */ - struct symtab_s *symtab; + ///@{ + struct symtab_s *parameters; ///< Root scope symbol table + struct symtab_s *locals; ///< Actual local variables + struct defspace_s *arguments; ///< Space for called function arguments + ///@} struct symtab_s *label_scope; struct reloc_s *refs; ///< relocation targets for this function struct expr_s *var_init; @@ -146,7 +168,6 @@ function_t *build_code_function (struct symbol_s *fsym, function_t *build_builtin_function (struct symbol_s *sym, struct expr_s *bi_val, int far, enum storage_class_e storage); -void finish_function (function_t *f); void emit_function (function_t *f, struct expr_s *e); int function_parms (function_t *f, byte *parm_size); void clear_functions (void); diff --git a/tools/qfcc/include/idstuff.h b/tools/qfcc/include/idstuff.h index 82ef617f8..2eadb691b 100644 --- a/tools/qfcc/include/idstuff.h +++ b/tools/qfcc/include/idstuff.h @@ -31,7 +31,7 @@ #ifndef __idstuff_h #define __idstuff_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" //XXX eww :/ void PrecacheSound (const char *, int ch); diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 630659276..e93c3013a 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -36,8 +36,8 @@ */ ///@{ -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" #include "QF/quakeio.h" /** Identifier string for qfo object files (includes terminating nul) @@ -49,7 +49,7 @@ \hideinitializer */ -#define QFO_VERSION 0x00001006 +#define QFO_VERSION 0x00001007 /** Header block of QFO object files. The sections of the object file come immediately after the header, and are always in the order given by @@ -68,6 +68,8 @@ typedef struct qfo_header_s { pr_uint_t num_lines; ///< number of line records pr_uint_t num_loose_relocs; ///< number of loose relocation records ///< (included in num_relocs) + pr_uint_t progs_version; ///< version of compatible VM + pr_uint_t reserved[3]; } qfo_header_t; typedef enum qfos_type_e { @@ -95,16 +97,16 @@ typedef struct qfo_space_s { /** Representation of a def in the object file. */ typedef struct qfo_def_s { - pointer_t type; ///< offset in type space - string_t name; ///< def name - pointer_t offset; ///< def offset (address) + pr_ptr_t type; ///< offset in type space + pr_string_t name; ///< def name + pr_ptr_t offset; ///< def offset (address) pr_uint_t relocs; ///< index of first reloc record pr_uint_t num_relocs; ///< number of reloc records pr_uint_t flags; ///< \ref qfcc_qfo_QFOD "QFOD flags" - string_t file; ///< source file name + pr_string_t file; ///< source file name pr_uint_t line; ///< source line number } qfo_def_t; ///@} @@ -178,9 +180,9 @@ typedef struct qfo_def_s { /** Representation of a function in the object file. */ typedef struct qfo_func_s { - string_t name; ///< function name - pointer_t type; ///< function type (in type data space) - string_t file; ///< source file name + pr_string_t name; ///< function name + pr_ptr_t type; ///< function type (in type data space) + pr_string_t file; ///< source file name pr_uint_t line; ///< source line number /** \name Function code location. @@ -209,7 +211,9 @@ typedef struct qfo_func_s { pr_uint_t relocs; ///< Index to first ::qfo_reloc_t reloc record. pr_uint_t num_relocs; ///< Number of reloc records. //@} - pr_int_t reserved[2]; + pr_uint_t params_start; ///< locals_space relative start of parameters + ///< always 0 for v6/v6p progs + pr_int_t reserved; } qfo_func_t; /** Evil source of many headaches. The whole reason I've started writing this @@ -218,23 +222,21 @@ typedef struct qfo_func_s { referenced relocs unreferenced relocs - For \c ref_op_* relocation types, \c ofs is the code section address of the - statement that needs to be adjusted. + For \c ref_op_* relocation types, \c offset is the code section address + of the statement that needs to be adjusted. - For \c rel_def_* relocation types, - \c ofs refers to the data section address of the word that needs to be - adjusted. + For \c rel_def_* relocation types, \c offset refers to the data section + address of the word that needs to be adjusted. - For \c ref_*_def(_ofs) relocation types, \c def is the index of the + For \c ref_*_def(_ofs) relocation types, \c target is the index of the referenced def. - For \c ref_*_op relocation types, \c def is the address of - the referenced statement. + For \c ref_*_op relocation types, \c target is the address of the + referenced statement. - For \c ref_*_string relocation types, \c def is - always 0. + For \c ref_*_string relocation types, \c target is always 0. - For \c ref_*_field(_ofs) relocation types, \c def is the index of + For \c ref_*_field(_ofs) relocation types, \c target is the index of the referenced field def. */ typedef struct qfo_reloc_s { @@ -249,31 +251,32 @@ typedef struct qfo_reloc_s { typedef struct qfo_mspace_s { qfos_type_t type; qfo_def_t *defs; - unsigned num_defs; + pr_uint_t num_defs; union { dstatement_t *code; pr_type_t *data; char *strings; }; - unsigned data_size; - unsigned id; + pr_uint_t data_size; + pr_uint_t id; } qfo_mspace_t; /** In-memory representation of a QFO object file. */ typedef struct qfo_s { + pr_uint_t progs_version; ///< version of compatible VM void *data; ///< data buffer holding qfo file when read qfo_mspace_t *spaces; - unsigned num_spaces; + pr_uint_t num_spaces; qfo_reloc_t *relocs; - unsigned num_relocs; // includes num_loose_relocs + pr_uint_t num_relocs; // includes num_loose_relocs qfo_def_t *defs; - unsigned num_defs; + pr_uint_t num_defs; qfo_func_t *funcs; - unsigned num_funcs; + pr_uint_t num_funcs; pr_lineno_t *lines; - unsigned num_lines; - unsigned num_loose_relocs; // included in num_relocs + pr_uint_t num_lines; + pr_uint_t num_loose_relocs; // included in num_relocs } qfo_t; enum { @@ -333,10 +336,10 @@ enum { */ #define QFO_FLOAT(q, s, o) QFO_var (q, s, float, o) -/** Access a integer variable in the object file. Can be assigned to. +/** Access a int variable in the object file. Can be assigned to. \par QC type: - \c integer + \c int \param q pointer to ::qfo_t struct \param s space index \param o offset into object file data space @@ -344,7 +347,7 @@ enum { \hideinitializer */ -#define QFO_INT(q, s, o) QFO_var (q, s, integer, o) +#define QFO_INT(q, s, o) QFO_var (q, s, int, o) /** Access a vector variable in the object file. Can be assigned to. @@ -366,7 +369,7 @@ enum { \param q pointer to ::qfo_t struct \param s space index \param o offset into object file data space - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ @@ -419,7 +422,7 @@ enum { \param q pointer to ::qfo_t struct \param s space index \param o offset into object file data space - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ @@ -437,7 +440,7 @@ enum { \hideinitializer */ -#define QFO_POINTER(q, s, t, o) ((t *)(char *)&QFO_var (q, s, integer, o)) +#define QFO_POINTER(q, s, t, o) ((t *)(char *)&QFO_var (q, s, int, o)) /** Access a structure variable in the object file. Can be assigned to. @@ -499,7 +502,7 @@ qfo_t *qfo_new (void); */ void qfo_delete (qfo_t *qfo); -__attribute__((const)) int qfo_log2 (unsigned x); +__attribute__((const)) int qfo_log2 (pr_uint_t x); ///@} diff --git a/tools/qfcc/include/obj_type.h b/tools/qfcc/include/obj_type.h index a8c546703..c3d9cb6e7 100644 --- a/tools/qfcc/include/obj_type.h +++ b/tools/qfcc/include/obj_type.h @@ -31,7 +31,7 @@ #ifndef __obj_type_h #define __obj_type_h -#include "QF/pr_type.h" +#include "QF/progs/pr_type.h" #include "type.h" diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index 779370340..055066f4b 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -31,25 +31,15 @@ #ifndef __opcodes_h #define __opcodes_h -extern struct opcode_s *op_done; -extern struct opcode_s *op_return; -extern struct opcode_s *op_return_v; -extern struct opcode_s *op_if; -extern struct opcode_s *op_ifnot; -extern struct opcode_s *op_ifbe; -extern struct opcode_s *op_ifb; -extern struct opcode_s *op_ifae; -extern struct opcode_s *op_ifa; -extern struct opcode_s *op_state; -extern struct opcode_s *op_state_f; -extern struct opcode_s *op_goto; -extern struct opcode_s *op_jump; -extern struct opcode_s *op_jumpb; +#include "QF/progs/pr_comp.h" + +typedef struct instruction_s instruction_t; struct operand_s; - -struct opcode_s *opcode_find (const char *name, struct operand_s *op_a, - struct operand_s *op_b, struct operand_s *op_c); +pr_ushort_t opcode_get (instruction_t *inst) __attribute__((pure)); +instruction_t *opcode_find (const char *name, struct operand_s *op_a, + struct operand_s *op_b, struct operand_s *op_c); void opcode_init (void); +void opcode_print_statement (pr_uint_t addr, dstatement_t *st); #endif//__opcodes_h diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 580f97370..42b95c257 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -49,6 +49,10 @@ typedef struct { qboolean promote_float; // promote float through ... } code_options_t; +typedef struct { + int vector_mult; // operation for vector * vector +} math_options_t; + typedef struct { qboolean promote; // Promote warnings to errors qboolean cow; // Warn on copy-on-write detection @@ -93,6 +97,7 @@ typedef struct { typedef struct { code_options_t code; // Code generation options + math_options_t math; // Various math options warn_options_t warnings; // Warning options notice_options_t notices; // Notice options bug_options_t bug; // Bug options @@ -109,7 +114,7 @@ typedef struct { qboolean progdefs_h; // generate progdefs.h qboolean qccx_escapes; // use qccx escapes instead of standard C int traditional; // behave more like qcc - qboolean advanced; // behold the power of Ruamoko + int advanced; // behold the power of Ruamoko qboolean compile; // serparate compilation mode qboolean partial_link; // partial linking qboolean preprocess_only;// run only cpp, don't compile diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 9d552ab3e..b678cc5a4 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -35,7 +35,7 @@ #include #include "QF/darray.h" -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" /** \defgroup qfcc_general General functions \ingroup qfcc @@ -45,7 +45,7 @@ typedef struct srcline_s srcline_t; struct srcline_s { srcline_t *next; - string_t source_file; + pr_string_t source_file; int source_line; }; @@ -79,7 +79,7 @@ typedef struct pr_info_s { struct symtab_s *entity_fields; srcline_t *srcline_stack; - string_t source_file; + pr_string_t source_file; int source_line; int error_count; @@ -100,7 +100,7 @@ extern pr_info_t pr; #define D_var(t, d) ((d)->space->data[(d)->offset].t##_var) #define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset)) #define D_FLOAT(d) D_var (float, d) -#define D_INT(d) D_var (integer, d) +#define D_INT(d) D_var (int, d) #define D_VECTOR(d) (&D_var (vector, d)) #define D_QUAT(d) (&D_var (quat, d)) #define D_STRING(d) D_var (string, d) diff --git a/tools/qfcc/include/reloc.h b/tools/qfcc/include/reloc.h index dc6e802c8..98c828e60 100644 --- a/tools/qfcc/include/reloc.h +++ b/tools/qfcc/include/reloc.h @@ -77,7 +77,7 @@ typedef struct reloc_s { ///< adjustment reloc_type type; ///< type type of relocation to perform int line; ///< current source line when creating reloc - string_t file; ///< current source file when creating reloc + pr_string_t file; ///< current source file when creating reloc const void *return_address; ///< for debugging } reloc_t; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index bc15244c6..a1fc6914e 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -30,7 +30,7 @@ #ifndef statement_h #define statement_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" typedef enum { op_def, @@ -68,6 +68,7 @@ typedef struct operand_s { op_type_e op_type; struct type_s *type; ///< possibly override def's/nil's type int size; ///< for structures + int width; ///< for SIMD selection struct expr_s *expr; ///< expression generating this operand void *return_addr; ///< who created this operand union { @@ -101,6 +102,7 @@ typedef enum { st_state, ///< state (a, b); or state (a, b, c) st_func, ///< call, rcall or return/done st_flow, ///< if/ifa/ifae/ifb/ifbe/ifnot or goto or jump/jumpb + st_address, ///< lea } st_type_t; typedef struct statement_s { @@ -112,9 +114,9 @@ typedef struct statement_s { operand_t *opc; struct expr_s *expr; ///< source expression for this statement int number; ///< number of this statement in function - operand_t *use; ///< list of pseudo operands used - operand_t *def; ///< list of pseudo operands defined - operand_t *kill; ///< list of pseudo operands killed + operand_t *use; ///< list of auxiliary operands used + operand_t *def; ///< list of auxiliary operands defined + operand_t *kill; ///< list of auxiliary operands killed } statement_t; typedef struct sblock_s { diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index ca079eb01..63fb194e3 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -31,7 +31,7 @@ #ifndef __type_h #define __type_h -#include "QF/pr_type.h" +#include "QF/progs/pr_type.h" #include "def.h" @@ -39,6 +39,13 @@ typedef struct ty_func_s { struct type_s *type; int num_params; struct type_s **param_types; + union { + struct { + unsigned no_va_list:1;///< don't inject va_list for ... function + unsigned void_return:1;///< special handling for return value + }; + unsigned attribute_bits; + }; } ty_func_t; typedef struct ty_fldptr_s { @@ -60,6 +67,9 @@ typedef struct type_s { etype_t type; ///< ev_invalid means structure/array etc const char *name; int alignment; ///< required alignment for instances + int width; ///< components in vector types, otherwise 1 + ///< vector and quaternion are 1 (separate from + ///< vec3 and vec4) /// function/pointer/array/struct types are more complex ty_meta_e meta; union { @@ -85,35 +95,37 @@ typedef struct { struct param_s *params; struct symbol_s *sym; ///< for dealing with "int id" etc storage_class_t storage; - unsigned multi_type:1; - unsigned multi_store:1; - unsigned is_signed:1; - unsigned is_unsigned:1; - unsigned is_short:1; - unsigned is_long:1; - unsigned is_typedef:1; - unsigned is_overload:1; - unsigned nosave:1; + union { + struct { + unsigned multi_type:1; + unsigned multi_store:1; + unsigned is_signed:1; + unsigned is_unsigned:1; + unsigned is_short:1; + unsigned is_long:1; + unsigned is_typedef:1; + unsigned is_overload:1; + unsigned nosave:1; + unsigned no_va_list:1; + unsigned void_return:1; + }; + unsigned spec_bits; + }; } specifier_t; +#define EV_TYPE(type) extern type_t type_##type; +#include "QF/progs/pr_type_names.h" + +#define VEC_TYPE(type_name, base_type) extern type_t type_##type_name; +#include "tools/qfcc/include/vec_types.h" + extern type_t type_invalid; -extern type_t type_void; -extern type_t type_string; -extern type_t type_double; -extern type_t type_float; -extern type_t type_vector; -extern type_t type_entity; -extern type_t type_field; -extern type_t type_function; -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 ... extern type_t *type_default; // default type (float or int) +extern type_t *type_long_int; // supported type for long +extern type_t *type_ulong_uint;// supported type for ulong extern type_t type_va_list; extern type_t type_param; @@ -159,30 +171,24 @@ void dump_dot_type (void *t, const char *filename); const char *encode_params (const type_t *type); void encode_type (struct dstring_s *encoding, const type_t *type); const char *type_get_encoding (const type_t *type); -int is_void (const type_t *type) __attribute__((pure)); + +#define EV_TYPE(t) int is_##t (const type_t *type) __attribute__((pure)); +#include "QF/progs/pr_type_names.h" + int is_enum (const type_t *type) __attribute__((pure)); -int is_integer (const type_t *type) __attribute__((pure)); -int is_uinteger (const type_t *type) __attribute__((pure)); -int is_short (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); -int is_double (const type_t *type) __attribute__((pure)); -int is_float (const type_t *type) __attribute__((pure)); +int is_real (const type_t *type) __attribute__((pure)); int is_scalar (const type_t *type) __attribute__((pure)); -int is_vector (const type_t *type) __attribute__((pure)); -int is_quaternion (const type_t *type) __attribute__((pure)); +int is_nonscalar (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); -int is_pointer (const type_t *type) __attribute__((pure)); -int is_field (const type_t *type) __attribute__((pure)); -int is_entity (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); int is_structural (const type_t *type) __attribute__((pure)); -int is_func (const type_t *type) __attribute__((pure)); -int is_string (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); int type_same (const type_t *dst, const type_t *src) __attribute__((pure)); int type_size (const type_t *type) __attribute__((pure)); +int type_width (const type_t *type) __attribute__((pure)); void init_types (void); void chain_initial_types (void); diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index a2f13dd67..21e10f43d 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -53,8 +53,8 @@ struct ex_value_s *new_pointer_val (int val, struct type_s *type, struct def_s *def, struct operand_s *tempop); struct ex_value_s *new_quaternion_val (const float *quaternion_val); -struct ex_value_s *new_integer_val (int integer_val); -struct ex_value_s *new_uinteger_val (int uinteger_val); +struct ex_value_s *new_int_val (int int_val); +struct ex_value_s *new_uint_val (int uint_val); struct ex_value_s *new_short_val (short short_val); struct ex_value_s *new_nil_val (struct type_s *type); diff --git a/tools/qfcc/include/vec_types.h b/tools/qfcc/include/vec_types.h new file mode 100644 index 000000000..4931c8d09 --- /dev/null +++ b/tools/qfcc/include/vec_types.h @@ -0,0 +1,24 @@ +#ifndef VEC_TYPE +#define VEC_TYPE(type_name, base_type) +#endif + +VEC_TYPE(ivec2, int) +VEC_TYPE(ivec3, int) +VEC_TYPE(ivec4, int) +VEC_TYPE(vec2, float) +VEC_TYPE(vec3, float) +VEC_TYPE(vec4, float) +VEC_TYPE(lvec2, long) +VEC_TYPE(lvec3, long) +VEC_TYPE(lvec4, long) +VEC_TYPE(dvec2, double) +VEC_TYPE(dvec3, double) +VEC_TYPE(dvec4, double) +VEC_TYPE(uivec2, uint) +VEC_TYPE(uivec3, uint) +VEC_TYPE(uivec4, uint) +VEC_TYPE(ulvec2, ulong) +VEC_TYPE(ulvec3, ulong) +VEC_TYPE(ulvec4, ulong) + +#undef VEC_TYPE diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index 76e3f73d8..d7d85e597 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -7,6 +7,7 @@ bin_PROGRAMS += @QFCC_TARGETS@ bin_SCRIPTS += tools/qfcc/source/qfpreqcc qfcc_SOURCES = \ + tools/qfcc/source/attribute.c \ tools/qfcc/source/class.c \ tools/qfcc/source/codespace.c \ tools/qfcc/source/constfold.c \ diff --git a/tools/qfcc/source/attribute.c b/tools/qfcc/source/attribute.c new file mode 100644 index 000000000..b821124c1 --- /dev/null +++ b/tools/qfcc/source/attribute.c @@ -0,0 +1,55 @@ +/* + attribute.c + + Attribute list handling + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/02/02 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/alloc.h" + +#include "tools/qfcc/include/attribute.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/strpool.h" + +static attribute_t *attributes_freelist; + +attribute_t *new_attribute(const char *name, expr_t *value) +{ + if (value && value->type != ex_value) { + error (value, "not a literal constant"); + return 0; + } + + attribute_t *attr; + ALLOC (16384, attribute_t, attributes, attr); + attr->name = save_string (name); + attr->value = value ? value->e.value : 0; + return attr; +} diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index dfaf638c8..c19f2dd01 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -41,9 +41,10 @@ #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/pr_obj.h" #include "QF/va.h" +#include "QF/progs/pr_obj.h" + #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/codespace.h" @@ -70,33 +71,114 @@ static hashtab_t *static_instances; static hashtab_t *static_instance_classes; // these will be built up further -type_t type_selector = { ev_invalid, 0, 0, ty_struct}; -type_t type_SEL = { ev_pointer, "SEL", 1, ty_basic, {{&type_selector}}}; -type_t *IMP_params[] = {&type_id, &type_SEL}; -type_t type_IMP = { ev_func, "IMP", 1, ty_basic, - {{&type_id, -3, IMP_params}}}; -type_t type_super = { ev_invalid, 0, 0 }; -type_t type_SuperPtr = { ev_pointer, 0, 1, ty_basic, {{&type_super}}}; -type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; -type_t type_supermsg = { ev_func, ".supermsg", 1, ty_basic, - {{&type_id, -3, supermsg_params}}}; -type_t type_method = { ev_invalid, 0, 0, ty_struct }; -type_t type_method_description = { ev_invalid, 0, 0, ty_struct }; -type_t type_category = { ev_invalid, 0, 0, ty_struct}; -type_t type_ivar = { ev_invalid, 0, 0, ty_struct}; -type_t type_module = { ev_invalid, 0, 0, ty_struct}; -type_t type_moduleptr = { ev_pointer, 0, 1, ty_basic, {{&type_module}}}; -type_t *obj_exec_class_params[] = { &type_moduleptr }; -type_t type_exec_class = { ev_func, 0, 1, ty_basic, - {{&type_void, 1, obj_exec_class_params}}}; +type_t type_selector = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_SEL = { + .type = ev_ptr, + .name = "SEL", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_selector}}, +}; +type_t *IMP_params[] = { &type_id, &type_SEL }; +type_t type_IMP = { + .type = ev_func, + .name = "IMP", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_id, -3, IMP_params, .no_va_list = 1}}, +}; +type_t type_super = { + .type = ev_invalid, +}; +type_t type_SuperPtr = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_super}}, +}; +type_t *supermsg_params[] = { &type_SuperPtr, &type_SEL }; +type_t type_supermsg = { + .type = ev_func, + .name = ".supermsg", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_id, -3, supermsg_params}}, +}; +type_t type_method = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_method_description = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_category = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_ivar = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_module = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_moduleptr = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_module}}, +}; +type_t *obj_exec_class_params[] = { + &type_moduleptr, +}; +type_t type_exec_class = { + .type = ev_func, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_void, 1, obj_exec_class_params}}, +}; // the cast of 1 in the init is to ensure pointers to incomplete types // are never misidentified as id. It will be set to the correct value // when the obj system is initialized. -type_t type_object = {ev_invalid, 0, 0, ty_struct, {{(type_t *)1}}}; -type_t type_id = { ev_pointer, "id", 1, ty_basic, {{&type_object}}}; -type_t type_class = { ev_invalid, 0, 0, ty_struct}; -type_t type_Class = { ev_pointer, 0, 1, ty_basic, {{&type_class}}}; -type_t type_protocol = { ev_invalid, 0, 0, ty_struct}; +type_t type_object = { + .type = ev_invalid, + .meta = ty_struct, + {{(type_t *)1}}, +}; +type_t type_id = { + .type = ev_ptr, + .name = "id", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_object}}, +}; +type_t type_class = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_Class = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_class}}, +}; +type_t type_protocol = { + .type = ev_invalid, + .meta = ty_struct, +}; int obj_initialized = 0; @@ -122,16 +204,16 @@ static struct_def_t method_desc_struct[] = { static struct_def_t category_struct[] = { {"category_name", &type_string}, {"class_name", &type_string}, - {"instance_methods", &type_pointer}, - {"class_methods", &type_pointer}, - {"protocols", &type_pointer}, + {"instance_methods", &type_ptr}, + {"class_methods", &type_ptr}, + {"protocols", &type_ptr}, {0, 0} }; static struct_def_t ivar_struct[] = { {"ivar_name", &type_string}, {"ivar_type", &type_string}, - {"ivar_offset", &type_integer}, + {"ivar_offset", &type_int}, {0, 0} }; @@ -142,10 +224,10 @@ static struct_def_t super_struct[] = { }; static struct_def_t module_struct[] = { - {"version", &type_integer}, - {"size", &type_integer}, + {"version", &type_int}, + {"size", &type_int}, {"name", &type_string}, - {"symtab", &type_pointer}, + {"symtab", &type_ptr}, {0, 0} }; @@ -153,25 +235,25 @@ static struct_def_t class_struct[] = { {"class_pointer", &type_Class}, {"super_class", &type_Class}, {"name", &type_string}, - {"version", &type_integer}, - {"info", &type_integer}, - {"instance_size", &type_integer}, - {"ivars", &type_pointer}, - {"methods", &type_pointer}, - {"dtable", &type_pointer}, - {"subclass_list", &type_pointer}, - {"sibling_class", &type_pointer}, - {"protocols", &type_pointer}, - {"gc_object_type", &type_pointer}, + {"version", &type_int}, + {"info", &type_int}, + {"instance_size", &type_int}, + {"ivars", &type_ptr}, + {"methods", &type_ptr}, + {"dtable", &type_ptr}, + {"subclass_list", &type_ptr}, + {"sibling_class", &type_ptr}, + {"protocols", &type_ptr}, + {"gc_object_type", &type_ptr}, {0, 0} }; static struct_def_t protocol_struct[] = { {"class_pointer", &type_Class}, {"protocol_name", &type_string}, - {"protocol_list", &type_pointer}, - {"instance_methods", &type_pointer}, - {"class_methods", &type_pointer}, + {"protocol_list", &type_ptr}, + {"instance_methods", &type_ptr}, + {"class_methods", &type_ptr}, {0, 0} }; @@ -228,7 +310,7 @@ emit_instance_defs (def_t *def, void *data, int index) { obj_static_instances_data_t *da = (obj_static_instances_data_t *)data; - if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer) + if (!is_array (def->type) || def->type->t.array.type->type != ev_ptr) internal_error (0, "%s: expected array of pointers def", __FUNCTION__); if (index < 0 || index >= da->num_instances + 1) internal_error (0, "%s: out of bounds index: %d %d", @@ -256,8 +338,7 @@ emit_static_instances (const char *classname) for (static_instance_t **inst = data.instances; *inst; inst++) { data.num_instances++; } - instances_struct[1].type = array_type (&type_pointer, - data.num_instances + 1); + instances_struct[1].type = array_type (&type_ptr, data.num_instances + 1); instances_def = emit_structure (va (0, "_OBJ_STATIC_INSTANCES_%s", classname), 's', instances_struct, 0, &data, @@ -275,7 +356,7 @@ emit_static_instances_list (void) type_t *instance_lists_type; symbol_t *instance_lists_sym; def_t *instance_lists_def; - pointer_t *list; + pr_ptr_t *list; defspace_t *space; if (!static_instance_classes || !static_instances) { @@ -297,7 +378,7 @@ emit_static_instances_list (void) free (classes); // +1 for terminating null - instance_lists_type = array_type (&type_pointer, num_classes + 1); + instance_lists_type = array_type (&type_ptr, num_classes + 1); instance_lists_sym = make_symbol ("_OBJ_STATIC_INSTANCES", instance_lists_type, pr.far_data, sc_static); @@ -308,7 +389,7 @@ emit_static_instances_list (void) instance_lists_def->initialized = instance_lists_def->constant = 1; instance_lists_def->nosave = 1; - list = D_POINTER (pointer_t, instance_lists_def); + list = D_POINTER (pr_ptr_t, instance_lists_def); space = instance_lists_def->space; for (int i = 0; i < num_classes; i++, list++) { EMIT_DEF (space, *list, instance_lists[i]); @@ -324,7 +405,7 @@ is_id (const type_t *type) return 1; // type may be a qualified id, in which case it will be a pointer to // a qualified obj_object struct - if (type->type != ev_pointer) + if (type->type != ev_ptr) return 0; if (!is_struct (type->t.fldptr.type)) return 0; @@ -356,7 +437,7 @@ is_classptr (const type_t *type) // easy cases first :) if (is_id (type) || is_Class (type)) return 1; - if (type->type != ev_pointer) + if (type->type != ev_ptr) return 0; type = type->t.fldptr.type; if (is_class (type)) @@ -391,7 +472,7 @@ is_method_description (const type_t *type) static protocollist_t * obj_get_class_protos (const type_t *type) { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; if (is_class (type)) return type->t.class->protocols; @@ -401,7 +482,7 @@ obj_get_class_protos (const type_t *type) static protocollist_t * obj_get_protos (const type_t *type) { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; return type->protos; } @@ -409,7 +490,7 @@ obj_get_protos (const type_t *type) static category_t * obj_get_categories (const type_t *type) { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; if (is_class (type)) return type->t.class->categories; @@ -430,7 +511,7 @@ obj_classname (const type_t *type) } else if (is_Class (type)) { dstring_copystr (str, "Class"); } else { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; if (is_class (type)) dstring_copystr (str, type->t.class->name); @@ -728,8 +809,8 @@ emit_ivar_count (def_t *def, void *data, int index) { ivar_data_t *ivar_data = (ivar_data_t *) data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = ivar_data->count; } @@ -773,8 +854,8 @@ static def_t * emit_ivars (symtab_t *ivars, const char *name) { static struct_def_t ivar_list_struct[] = { - {"ivar_count", &type_integer, emit_ivar_count}, - {"ivar_list", 0, emit_ivar_list_item}, + {"ivar_count", &type_int, emit_ivar_count}, + {"ivar_list", 0, emit_ivar_list_item}, {0, 0} }; ivar_data_t ivar_data = {0, 0, 0}; @@ -877,7 +958,7 @@ emit_class_ref (const char *class_name) def_t *name_def; ref_sym = make_symbol (va (0, ".obj_class_ref_%s", class_name), - &type_pointer, pr.far_data, sc_static); + &type_ptr, pr.far_data, sc_static); if (!ref_sym->table) symtab_addsymbol (pr.symtab, ref_sym); ref_def = ref_sym->s.def; @@ -885,7 +966,7 @@ emit_class_ref (const char *class_name) return; ref_def->initialized = ref_def->constant = ref_def->nosave = 1; name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name), - &type_pointer, pr.far_data, sc_extern); + &type_ptr, pr.far_data, sc_extern); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -901,7 +982,7 @@ emit_class_name (const char *class_name) def_t *name_def; name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name), - &type_pointer, pr.far_data, sc_global); + &type_ptr, pr.far_data, sc_global); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -922,7 +1003,7 @@ emit_category_ref (const char *class_name, const char *category_name) ref_sym = make_symbol (va (0, ".obj_category_ref_%s_%s", class_name, category_name), - &type_pointer, pr.far_data, sc_static); + &type_ptr, pr.far_data, sc_static); if (!ref_sym->table) symtab_addsymbol (pr.symtab, ref_sym); ref_def = ref_sym->s.def; @@ -932,7 +1013,7 @@ emit_category_ref (const char *class_name, const char *category_name) ref_def->nosave = 1; name_sym = make_symbol (va (0, ".obj_category_name_%s_%s", class_name, category_name), - &type_pointer, pr.far_data, sc_extern); + &type_ptr, pr.far_data, sc_extern); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -949,7 +1030,7 @@ emit_category_name (const char *class_name, const char *category_name) name_sym = make_symbol (va (0, ".obj_category_name_%s_%s", class_name, category_name), - &type_pointer, pr.far_data, sc_global); + &type_ptr, pr.far_data, sc_global); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -1410,8 +1491,8 @@ emit_symtab_ref_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = 0; if (da->refs) D_INT (def) = da->refs->type->t.array.size; @@ -1434,8 +1515,8 @@ emit_symtab_cls_def_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = da->cls_def_cnt; } @@ -1444,8 +1525,8 @@ emit_symtab_cat_def_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = da->cat_def_cnt; } @@ -1454,7 +1535,7 @@ emit_symtab_defs (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer) + if (!is_array (def->type) || def->type->t.array.type->type != ev_ptr) internal_error (0, "%s: expected array of pointers def", __FUNCTION__); if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt + 1) internal_error (0, "%s: out of bounds index: %d %d", @@ -1488,11 +1569,11 @@ void class_finish_module (void) { static struct_def_t symtab_struct[] = { - {"sel_ref_cnt", &type_integer, emit_symtab_ref_cnt}, - {"refs", &type_SEL, emit_symtab_refs}, - {"cls_def_cnt", &type_integer, emit_symtab_cls_def_cnt}, - {"cat_def_cnt", &type_integer, emit_symtab_cat_def_cnt}, - {"defs", 0, emit_symtab_defs}, + {"sel_ref_cnt", &type_int, emit_symtab_ref_cnt}, + {"refs", &type_SEL, emit_symtab_refs}, + {"cls_def_cnt", &type_int, emit_symtab_cls_def_cnt}, + {"cat_def_cnt", &type_int, emit_symtab_cat_def_cnt}, + {"defs", 0, emit_symtab_defs}, {0, 0} }; @@ -1525,7 +1606,7 @@ class_finish_module (void) if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt && !data.instances_list) return; - symtab_struct[4].type = array_type (&type_pointer, + symtab_struct[4].type = array_type (&type_ptr, data.cls_def_cnt + data.cat_def_cnt + 1); @@ -1552,10 +1633,10 @@ class_finish_module (void) sc_extern); } - init_sym = new_symbol_type (".ctor", &type_function); + init_sym = new_symbol_type (".ctor", &type_func); init_sym = function_symbol (init_sym, 0, 1); - module_expr = address_expr (new_symbol_expr (module_sym), 0, 0); + module_expr = address_expr (new_symbol_expr (module_sym), 0); init_expr = new_block_expr (); append_expr (init_expr, @@ -1738,7 +1819,7 @@ emit_protocol (protocol_t *protocol) static void emit_protocol_next (def_t *def, void *data, int index) { - if (!is_pointer(def->type)) { + if (!is_ptr(def->type)) { internal_error (0, "%s: expected pointer def", __FUNCTION__); } D_INT (def) = 0; @@ -1749,8 +1830,8 @@ emit_protocol_count (def_t *def, void *data, int index) { protocollist_t *protocols = (protocollist_t *) data; - if (!is_integer(def->type)) { - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) { + internal_error (0, "%s: expected int def", __FUNCTION__); } D_INT (def) = protocols->count; } @@ -1761,7 +1842,7 @@ emit_protocol_list_item (def_t *def, void *data, int index) protocollist_t *protocols = (protocollist_t *) data; protocol_t *protocol = protocols->list[index]; - if (!is_array (def->type) || !is_pointer(def->type->t.array.type)) { + if (!is_array (def->type) || !is_ptr(def->type->t.array.type)) { internal_error (0, "%s: expected array of pointer def", __FUNCTION__); } if (index < 0 || index >= protocols->count) { @@ -1775,15 +1856,15 @@ def_t * emit_protocol_list (protocollist_t *protocols, const char *name) { static struct_def_t proto_list_struct[] = { - {"next", &type_pointer, emit_protocol_next}, - {"count", &type_integer, emit_protocol_count}, - {"list", 0, emit_protocol_list_item}, + {"next", &type_ptr, emit_protocol_next}, + {"count", &type_int, emit_protocol_count}, + {"list", 0, emit_protocol_list_item}, {0, 0}, }; if (!protocols) return 0; - proto_list_struct[2].type = array_type (&type_pointer, protocols->count); + proto_list_struct[2].type = array_type (&type_ptr, protocols->count); return emit_structure (va (0, "_OBJ_PROTOCOLS_%s", name), 's', proto_list_struct, 0, protocols, 0, sc_static); } diff --git a/tools/qfcc/source/codespace.c b/tools/qfcc/source/codespace.c index b7cd56bcc..5d6aee439 100644 --- a/tools/qfcc/source/codespace.c +++ b/tools/qfcc/source/codespace.c @@ -39,7 +39,7 @@ #endif #include -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #include "tools/qfcc/include/codespace.h" diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 2d2c1400d..6b01bc7f4 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -76,30 +76,42 @@ cmp_result_expr (int result) if (is_float (type_default)) { return new_float_expr (result); } else { - return new_integer_expr(result); + return new_int_expr(result); } } +static int +is_addsub (int op) +{ + return op == '+' || op == '-'; +} + +static int +inv_addsub (int op) +{ + return op == '+' ? '-' : '+'; +} + static expr_t * do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) { const char *s1, *s2; static dstring_t *temp_str; - static int valid[] = {'=', '+', LT, GT, LE, GE, EQ, NE, 0}; + static int valid[] = {'+', LT, GT, LE, GE, EQ, NE, 0}; if (!valid_op (op, valid)) return error (e1, "invalid operand for string"); if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else { e->e.expr.type = &type_string; } - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; s1 = expr_string (e1); @@ -153,7 +165,7 @@ convert_to_float (expr_t *e) switch (e->type) { case ex_value: switch (e->e.value->lltype) { - case ev_integer: + case ev_int: convert_int (e); return e; case ev_short: @@ -188,8 +200,8 @@ convert_to_double (expr_t *e) switch (e->type) { case ex_value: switch (e->e.value->lltype) { - case ev_integer: - e->e.value = new_double_val (expr_integer (e)); + case ev_int: + e->e.value = new_double_val (expr_int (e)); return e; case ev_short: e->e.value = new_double_val (expr_short (e)); @@ -220,31 +232,22 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) expr_t *conv; type_t *type = &type_float; static int valid[] = { - '=', '+', '-', '*', '/', '&', '|', '^', '%', + '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 }; if (!valid_op (op, valid)) return error (e1, "invalid operator for float"); - if (op == '=') { - if (!is_float(type = get_type (e1))) { - //FIXME optimize casting a constant - e->e.expr.e2 = e2 = cf_cast_expr (type, e2); - } else if ((conv = convert_to_float (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } - } else { - if ((conv = convert_to_float (e1)) != e1) { - e->e.expr.e1 = e1 = conv; - } - if ((conv = convert_to_float (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } + if ((conv = convert_to_float (e1)) != e1) { + e->e.expr.e1 = e1 = conv; + } + if ((conv = convert_to_float (e2)) != e2) { + e->e.expr.e2 = e2 = conv; } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - type = &type_integer; + type = &type_int; else type = &type_float; } @@ -271,7 +274,7 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && expr_float (e2) == 0) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; f1 = expr_float (e1); @@ -349,30 +352,21 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) expr_t *conv; type_t *type = &type_double; static int valid[] = { - '=', '+', '-', '*', '/', '%', + '+', '-', '*', '/', '%', LT, GT, LE, GE, EQ, NE, 0 }; if (!valid_op (op, valid)) return error (e1, "invalid operator for double"); - if (op == '=') { - if (!is_double(type = get_type (e1))) { - //FIXME optimize casting a constant - e->e.expr.e2 = e2 = cf_cast_expr (type, e2); - } else if ((conv = convert_to_double (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } - } else { - if ((conv = convert_to_double (e1)) != e1) { - e->e.expr.e1 = e1 = conv; - } - if ((conv = convert_to_double (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } + if ((conv = convert_to_double (e1)) != e1) { + e->e.expr.e1 = e1 = conv; + } + if ((conv = convert_to_double (e2)) != e2) { + e->e.expr.e2 = e2 = conv; } if (is_compare (op) || is_logic (op)) { - type = &type_integer; + type = &type_int; } e->e.expr.type = type; @@ -397,7 +391,7 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && expr_double (e2) == 0) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; d1 = expr_double (e1); @@ -452,7 +446,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *v1, *v2; vec3_t v, float_vec; - static int valid[] = {'=', '+', '-', '*', EQ, NE, 0}; + static int valid[] = {'+', '-', '*', SCALE, EQ, NE, 0}; expr_t *t; if (!is_vector(get_type (e1))) { @@ -466,7 +460,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (!is_vector(get_type (e2))) { e->e.expr.e2 = e2 = convert_to_float (e2); - if (op != '*' && op != '/') + if (op != SCALE && op != '/') return error (e1, "invalid operator for vector"); } else { if (!valid_op (op, valid)) @@ -474,7 +468,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else if (op == '*' && is_vector(get_type (e2))) { @@ -510,7 +504,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && VectorIsZero (expr_vector (e2))) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; if (is_float_val (e1)) { @@ -568,17 +562,17 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type = get_type (e2); - if ((op == '.' || op == '&') && type->type == ev_field) { + if (op == '.' && type->type == ev_field) { return e; } if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; return e; } - if (op != '=' || !is_entity(type)) + if (!is_entity(type)) return error (e1, "invalid operator for entity"); e->e.expr.type = &type_entity; return e; @@ -587,37 +581,27 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * do_op_field (int op, expr_t *e, expr_t *e1, expr_t *e2) { - if (op != '=') - return error (e1, "invalid operator for field"); - e->e.expr.type = &type_field; - return e; + return error (e1, "invalid operator for field"); } static expr_t * do_op_func (int op, expr_t *e, expr_t *e1, expr_t *e2) { - if (op == 'c') { - e->e.expr.type = get_type (e1)->t.func.type; - return e; - } if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; return e; } - if (op != '=') - return error (e1, "invalid operator for func"); - e->e.expr.type = &type_function; - return e; + return error (e1, "invalid operator for func"); } static expr_t * do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type; - static int valid[] = {'=', '-', '&', 'M', '.', EQ, NE, 0}; + static int valid[] = {'-', '.', EQ, NE, 0}; if (is_integral (type = get_type (e2)) && (op == '-' || op == '+')) { // pointer arithmetic @@ -634,24 +618,23 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) type = get_type (e1); if (type != get_type (e2)) return error (e2, "invalid operands to binary -"); - e1 = new_alias_expr (&type_integer, e1); - e2 = new_alias_expr (&type_integer, e2); + e1 = new_alias_expr (&type_int, e1); + e2 = new_alias_expr (&type_int, e2); e = binary_expr ('-', e1, e2); if (type_size (type) != 1) - e = binary_expr ('/', e, new_integer_expr (type_size (type))); + e = binary_expr ('/', e, new_int_expr (type_size (type))); return e; } if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } - if (op != '.' && op != '&' && op != 'M' - && extract_type (e1) != extract_type (e2)) + if (op != '.' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); - if ((op == '.' || op == '&') && is_uinteger(get_type (e2))) - e->e.expr.e2 = cf_cast_expr (&type_integer, e2); + if (op == '.' && is_uint(get_type (e2))) + e->e.expr.e2 = cf_cast_expr (&type_int, e2); return e; } @@ -682,7 +665,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *q1, *q2; quat_t q, float_quat; - static int valid[] = {'=', '+', '-', '*', EQ, NE, 0}; + static int valid[] = {'+', '-', '*', EQ, NE, 0}; expr_t *t; if (!is_quaternion(get_type (e1))) { @@ -706,7 +689,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else if (op == '/' && !is_constant (e1)) { @@ -731,7 +714,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && QuatIsZero (expr_quaternion (e2))) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; if (is_float_val (e1)) { @@ -788,43 +771,43 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) } static expr_t * -do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) +do_op_int (int op, expr_t *e, expr_t *e1, expr_t *e2) { int isval1 = 0, isval2 = 0; int val1 = 0, val2 = 0; static int valid[] = { - '=', '+', '-', '*', '/', '&', '|', '^', '%', + '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 }; if (!valid_op (op, valid)) - return error (e1, "invalid operator for integer"); + return error (e1, "invalid operator for int"); if (is_short_val (e1)) { isval1 = 1; val1 = expr_short (e1); } - if (is_integer_val (e1)) { + if (is_int_val (e1)) { isval1 = 1; - val1 = expr_integer (e1); + val1 = expr_int (e1); } if (is_short_val (e2)) { isval2 = 1; val2 = expr_short (e2); } - if (is_integer_val (e2)) { + if (is_int_val (e2)) { isval2 = 1; - val2 = expr_integer (e2); + val2 = expr_int (e2); } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else { - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; } if (op == '*' && isval1 && val1 == 1) @@ -848,41 +831,95 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && isval2 && val2 == 0) return e1; - if (op == '=' || !isval1 || !isval2) + if (!isval1) { + if (e1->type == ex_expr) { + // at most one of the two sub-expressions is constant otherwise + // e1 would be a constant + if (is_constant (e1->e.expr.e1)) { + if ((op == '*' && e1->e.expr.op == '*') + || (is_addsub (op) && is_addsub (e1->e.expr.op))) { + expr_t *c = binary_expr (op, e1->e.expr.e1, e2); + e = binary_expr (e1->e.expr.op, c, e1->e.expr.e2); + } + } else if (is_constant (e1->e.expr.e2)) { + if ((op == '*' && e1->e.expr.op == '*') + || (is_addsub (op) && e1->e.expr.op == '+')) { + expr_t *c = binary_expr (op, e1->e.expr.e2, e2); + e = binary_expr (e1->e.expr.op, e1->e.expr.e1, c); + } else if (is_addsub (op) && e1->e.expr.op == '-') { + // must ivert op + expr_t *c = binary_expr (inv_addsub (op), + e1->e.expr.e2, e2); + e = binary_expr (e1->e.expr.op, e1->e.expr.e1, c); + } + } + } + return e; + } else if (!isval2) { + if (e2->type == ex_expr) { + // at most one of the two sub-expressions is constant otherwise + // e2 would be a constant + if (is_constant (e2->e.expr.e1)) { + if ((op == '*' && e2->e.expr.op == '*') + || (op == '+' && is_addsub (e2->e.expr.op))) { + expr_t *c = binary_expr (op, e1, e2->e.expr.e1); + e = binary_expr (e2->e.expr.op, c, e2->e.expr.e2); + } else if (op == '-' && is_addsub (e2->e.expr.op)) { + expr_t *c = binary_expr (op, e1, e2->e.expr.e1); + c = fold_constants (c); + e = binary_expr (inv_addsub (e2->e.expr.op), + c, e2->e.expr.e2); + } + } else if (is_constant (e2->e.expr.e2)) { + if ((op == '*' && e2->e.expr.op == '*') + || (op == '+' && is_addsub (e2->e.expr.op))) { + expr_t *c = binary_expr (e2->e.expr.op, + e1, e2->e.expr.e2); + e = binary_expr (op, c, e2->e.expr.e1); + } else if (op == '-' && is_addsub (e2->e.expr.op)) { + expr_t *c = binary_expr (inv_addsub (e2->e.expr.op), + e1, e2->e.expr.e2); + e = binary_expr (op, c, e2->e.expr.e1); + } + } + } + return e; + } + if (!isval1 || !isval2) return e; switch (op) { case '+': - e = new_integer_expr (val1 + val2); + e = new_int_expr (val1 + val2); break; case '-': - e = new_integer_expr (val1 - val2); + e = new_int_expr (val1 - val2); break; case '*': - e = new_integer_expr (val1 * val2); + e = new_int_expr (val1 * val2); break; case '/': if (options.warnings.integer_divide) warning (e2, "%d / %d == %d", val1, val2, val1 / val2); - e = new_integer_expr (val1 / val2); + e = new_int_expr (val1 / val2); break; case '&': - e = new_integer_expr (val1 & val2); + e = new_int_expr (val1 & val2); break; case '|': - e = new_integer_expr (val1 | val2); + e = new_int_expr (val1 | val2); break; case '^': - e = new_integer_expr (val1 ^ val2); + e = new_int_expr (val1 ^ val2); break; case '%': - e = new_integer_expr (val1 % val2); + e = new_int_expr (val1 % val2); break; case SHL: - e = new_integer_expr (val1 << val2); + e = new_int_expr (val1 << val2); break; case SHR: - e = new_integer_expr (val1 >> val2); + e = new_int_expr (val1 >> val2); break; case AND: e = cmp_result_expr (val1 && val2); @@ -917,7 +954,7 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) } static expr_t * -do_op_uinteger (int op, expr_t *e, expr_t *e1, expr_t *e2) +do_op_uint (int op, expr_t *e, expr_t *e1, expr_t *e2) { return e; } @@ -927,7 +964,7 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) { short i1, i2; static int valid[] = { - '=', '+', '-', '*', '/', '&', '|', '^', '%', + '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 }; @@ -936,14 +973,14 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else { e->e.expr.type = &type_short; } - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; i1 = expr_short (e1); @@ -1017,14 +1054,7 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * do_op_struct (int op, expr_t *e, expr_t *e1, expr_t *e2) { - type_t *type; - - if (op != '=' && op != 'm') - return error (e1, "invalid operator for struct"); - if ((type = get_type (e1)) != get_type (e2)) - return type_mismatch (e1, e2, op); - e->e.expr.type = type; - return e; + return error (e1, "invalid operator for struct"); } static expr_t * @@ -1040,14 +1070,14 @@ do_op_compound (int op, expr_t *e, expr_t *e1, expr_t *e2) return do_op_float (op, e, e1, e2); if (t2->type == ev_double) return do_op_float (op, e, e1, e2); - return do_op_integer (op, e, e1, e2); + return do_op_int (op, e, e1, e2); } if (is_enum (t2)) { if (t1->type == ev_double) return do_op_double (op, e, e1, e2); if (t1->type == ev_float) return do_op_float (op, e, e1, e2); - return do_op_integer (op, e, e1, e2); + return do_op_int (op, e, e1, e2); } } return error (e1, "invalid operator for compound"); @@ -1060,8 +1090,6 @@ do_op_invalid (int op, expr_t *e, expr_t *e1, expr_t *e2) type_t *t1 = get_type (e1); type_t *t2 = get_type (e2); - if (e->e.expr.op == 'm') - return e; // assume the rest of the compiler got it right if (is_scalar (t1) && is_scalar (t2)) { // one or both expressions are an enum, and the other is one of // int, float or short. Treat the enum as the other type, or as @@ -1091,258 +1119,288 @@ do_op_invalid (int op, expr_t *e, expr_t *e1, expr_t *e2) } static operation_t op_void[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - 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_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_string[ev_type_count] = { - do_op_invalid, // ev_void - do_op_string, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - 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_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_string, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_float[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_float, // ev_integer - do_op_float, // ev_uinteger - do_op_float, // ev_short - do_op_double, // ev_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_float, + [ev_uint] = do_op_float, + [ev_short] = do_op_float, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_vector[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_vector, // 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_invalid, // ev_quaternion - do_op_vector, // ev_integer - do_op_vector, // ev_uinteger - do_op_vector, // ev_short - do_op_vector, // ev_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_vector, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_vector, + [ev_uint] = do_op_vector, + [ev_short] = do_op_vector, + [ev_double] = do_op_vector, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_entity[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_entity, // ev_entity - do_op_entity, // ev_field - do_op_invalid, // ev_func - 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_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_entity, + [ev_field] = do_op_entity, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_field[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_field, // ev_field - do_op_invalid, // ev_func - 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_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_field, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_func[ev_type_count] = { - do_op_func, // ev_void - do_op_func, // ev_string - do_op_func, // ev_float - do_op_func, // ev_vector - do_op_func, // ev_entity - do_op_func, // ev_field - do_op_func, // ev_func - 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_double - do_op_func, // ev_invalid + [ev_void] = do_op_func, + [ev_string] = do_op_func, + [ev_float] = do_op_func, + [ev_vector] = do_op_func, + [ev_entity] = do_op_func, + [ev_field] = do_op_func, + [ev_func] = do_op_func, + [ev_ptr] = do_op_func, + [ev_quaternion] = do_op_func, + [ev_int] = do_op_func, + [ev_uint] = do_op_func, + [ev_short] = do_op_func, + [ev_double] = do_op_func, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_func, }; static operation_t op_pointer[ev_type_count] = { - do_op_pointer, // ev_void - do_op_pointer, // ev_string - do_op_pointer, // ev_float - do_op_pointer, // ev_vector - do_op_pointer, // ev_entity - do_op_pointer, // ev_field - do_op_pointer, // ev_func - 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_double - do_op_pointer, // ev_invalid + [ev_void] = do_op_pointer, + [ev_string] = do_op_pointer, + [ev_float] = do_op_pointer, + [ev_vector] = do_op_pointer, + [ev_entity] = do_op_pointer, + [ev_field] = do_op_pointer, + [ev_func] = do_op_pointer, + [ev_ptr] = do_op_pointer, + [ev_quaternion] = do_op_pointer, + [ev_int] = do_op_pointer, + [ev_uint] = do_op_pointer, + [ev_short] = do_op_pointer, + [ev_double] = do_op_pointer, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_pointer, }; static operation_t op_quaternion[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_quaternion, // ev_float - do_op_quatvect, // 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_quaternion, // ev_integer - do_op_quaternion, // ev_uinteger - do_op_quaternion, // ev_short - do_op_quaternion, // ev_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_quaternion, + [ev_vector] = do_op_quatvect, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_quaternion, + [ev_uint] = do_op_quaternion, + [ev_short] = do_op_quaternion, + [ev_double] = do_op_quaternion, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; -static operation_t op_integer[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_integer, // ev_integer - do_op_uinteger, // ev_uinteger - do_op_integer, // ev_short - do_op_double, // ev_double - do_op_invalid, // ev_invalid +static operation_t op_int[ev_type_count] = { + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_int, + [ev_uint] = do_op_uint, + [ev_short] = do_op_int, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_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_double, // ev_double - do_op_invalid, // ev_invalid +static operation_t op_uint[ev_type_count] = { + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_uint, + [ev_uint] = do_op_uint, + [ev_short] = do_op_uint, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_short[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_integer, // ev_integer - do_op_uinteger, // ev_uinteger - do_op_short, // ev_short - do_op_double, // ev_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_int, + [ev_uint] = do_op_uint, + [ev_short] = do_op_short, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_double[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_integer, // ev_integer - do_op_uinteger, // ev_uinteger - do_op_short, // ev_short - do_op_double, // ev_double - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_int, + [ev_uint] = do_op_uint, + [ev_short] = do_op_short, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_compound[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_compound, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - 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_double - do_op_compound, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_compound, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_compound, + [ev_uint] = do_op_compound, + [ev_short] = do_op_compound, + [ev_double] = do_op_compound, + [ev_long] = do_op_compound, + [ev_ulong] = do_op_compound, + [ev_invalid] = do_op_compound, }; static operation_t *do_op[ev_type_count] = { - op_void, // ev_void - op_string, // ev_string - op_float, // ev_float - op_vector, // ev_vector - op_entity, // ev_entity - op_field, // ev_field - op_func, // ev_func - op_pointer, // ev_pointer - op_quaternion, // ev_quaternion - op_integer, // ev_integer - op_uinteger, // ev_uinteger - op_short, // ev_short - op_double, // ev_double - op_compound, // ev_invalid + [ev_void] = op_void, + [ev_string] = op_string, + [ev_float] = op_float, + [ev_vector] = op_vector, + [ev_entity] = op_entity, + [ev_field] = op_field, + [ev_func] = op_func, + [ev_ptr] = op_pointer, + [ev_quaternion] = op_quaternion, + [ev_int] = op_int, + [ev_uint] = op_uint, + [ev_short] = op_short, + [ev_double] = op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = op_compound, }; static unaryop_t do_unary_op[ev_type_count]; @@ -1398,7 +1456,7 @@ uop_float (int op, expr_t *e, expr_t *e1) if (op == '+') return e1; type = get_type (e); - if (op == 'C' && !is_integer(type) && !is_double(type)) + if (op == 'C' && !is_int(type) && !is_double(type)) return error (e1, "invalid cast of float"); if (!is_constant (e1)) return e; @@ -1411,8 +1469,8 @@ uop_float (int op, expr_t *e, expr_t *e1) case '~': return new_float_expr (~(int) expr_float (e1)); case 'C': - if (is_integer(type)) { - return new_integer_expr (expr_float (e1)); + if (is_int(type)) { + return new_int_expr (expr_float (e1)); } else { return new_double_expr (expr_float (e1)); } @@ -1541,7 +1599,7 @@ uop_quaternion (int op, expr_t *e, expr_t *e1) } static expr_t * -uop_integer (int op, expr_t *e, expr_t *e1) +uop_int (int op, expr_t *e, expr_t *e1) { static int valid[] = { '+', '-', '!', '~', 'C', 0 }; @@ -1556,19 +1614,19 @@ uop_integer (int op, expr_t *e, expr_t *e1) return e; switch (op) { case '-': - return new_integer_expr (-expr_integer (e1)); + return new_int_expr (-expr_int (e1)); case '!': - return cmp_result_expr (!expr_integer (e1)); + return cmp_result_expr (!expr_int (e1)); case '~': - return new_integer_expr (~expr_integer (e1)); + return new_int_expr (~expr_int (e1)); case 'C': - return new_float_expr (expr_integer (e1)); + return new_float_expr (expr_int (e1)); } - internal_error (e, "integer unary op blew up"); + internal_error (e, "int unary op blew up"); } static expr_t * -uop_uinteger (int op, expr_t *e, expr_t *e1) +uop_uint (int op, expr_t *e, expr_t *e1) { static int valid[] = { '+', '-', '!', '~', 0 }; @@ -1581,13 +1639,13 @@ uop_uinteger (int op, expr_t *e, expr_t *e1) return e; switch (op) { case '-': - return new_uinteger_expr (-expr_uinteger (e1)); + return new_uint_expr (-expr_uint (e1)); case '!': - return cmp_result_expr (!expr_uinteger (e1)); + return cmp_result_expr (!expr_uint (e1)); case '~': - return new_uinteger_expr (~expr_uinteger (e1)); + return new_uint_expr (~expr_uint (e1)); } - internal_error (e, "uinteger unary op blew up"); + internal_error (e, "uint unary op blew up"); } static expr_t * @@ -1625,7 +1683,7 @@ uop_double (int op, expr_t *e, expr_t *e1) if (op == '+') return e1; type = get_type (e); - if (op == 'C' && !is_integer(type) && !is_float(type)) + if (op == 'C' && !is_int(type) && !is_float(type)) return error (e1, "invalid cast of double"); if (!is_constant (e1)) return e; @@ -1636,8 +1694,8 @@ uop_double (int op, expr_t *e, expr_t *e1) print_type (get_type (e)); return cmp_result_expr (!expr_double (e1)); case 'C': - if (is_integer(type)) { - return new_integer_expr (expr_double (e1)); + if (is_int(type)) { + return new_int_expr (expr_double (e1)); } else { return new_float_expr (expr_double (e1)); } @@ -1652,7 +1710,7 @@ uop_compound (int op, expr_t *e, expr_t *e1) if (is_scalar (t1)) { if (is_enum (t1)) { - return uop_integer (op, e, e1); + return uop_int (op, e, e1); } } return error (e1, "invalid operand for unary %s", get_op_string (op)); @@ -1666,10 +1724,10 @@ static unaryop_t do_unary_op[ev_type_count] = { uop_entity, // ev_entity uop_field, // ev_field uop_func, // ev_func - uop_pointer, // ev_pointer + uop_pointer, // ev_ptr uop_quaternion, // ev_quaternion - uop_integer, // ev_integer - uop_uinteger, // ev_uinteger + uop_int, // ev_int + uop_uint, // ev_uint uop_short, // ev_short uop_double, // ev_double uop_compound, // ev_invalid @@ -1688,8 +1746,6 @@ fold_constants (expr_t *e) return e; } op = e->e.expr.op; - if (op == 'A' || op == 'g' || op == 'r') - return e; t1 = extract_type (e1); if (t1 >= ev_type_count || !do_unary_op[t1]) { print_expr (e); @@ -1704,9 +1760,6 @@ fold_constants (expr_t *e) } op = e->e.expr.op; - if (op == 'A' || op == 'i' || op == 'n' || op == 'c' || op == 's') { - return e; - } t1 = extract_type (e1); t2 = extract_type (e2); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 57ed83545..6c787fdc6 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -66,6 +66,8 @@ static dag_t *dags_freelist; static daglabel_t *daglabel_chain; +static void dag_live_aliases(operand_t *op); + static void flush_daglabels (void) { @@ -229,8 +231,6 @@ dag_node (operand_t *op) if (def->daglabel) node = def->daglabel->dagnode; } else if (op->op_type == op_temp) { - while (op->tempop.alias) - op = op->tempop.alias; if (op->tempop.daglabel) node = op->tempop.daglabel->dagnode; } else if (op->op_type == op_value) { @@ -282,8 +282,11 @@ dag_make_children (dag_t *dag, statement_t *s, dagnode_t *node = dag_node (operands[i + 1]); dagnode_t *killer = 0; - if (node && node->killed) { + if (node && (node->killed || s->type == st_address)) { // If the node has been killed, then a new node is needed + // taking the address of a variable effectively kills the node it's + // attached to. FIXME should this be for only when the variable is + // in the attached identifiers list and is not the node's label? killer = node->killed; node = 0; } @@ -327,8 +330,8 @@ dagnode_match (const dagnode_t *n, const daglabel_t *op, if (n->killed) return 0; - if (!strcmp (op->opcode, ".") - && n->label->opcode && !strcmp (n->label->opcode, ".=")) + if (!strcmp (op->opcode, "load") + && n->label->opcode && !strcmp (n->label->opcode, "store")) return dagnode_deref_match (n, op, children); if (n->label->opcode != op->opcode) return 0; @@ -406,7 +409,7 @@ dag_find_node (def_t *def, void *_daglabel) } static void -dagnode_set_edges (dag_t *dag, dagnode_t *n) +dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s) { int i; @@ -427,7 +430,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) set_add (node->edges, n->number); } if (op->op_type == op_value - && op->value->lltype == ev_pointer + && op->value->lltype == ev_ptr && op->value->v.pointer.def) { def_visit_all (op->value->v.pointer.def, 1, dagnode_def_set_edges_visit, n); @@ -447,18 +450,29 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) set_add (n->edges, child->number); } } + for (operand_t *use = s->use; use; use = use->next) { + if (use->op_type == op_pseudo) { + continue; + } + daglabel_t *label = operand_label (dag, use); + label->live = 1; + dag_live_aliases (use); + set_add (n->edges, label->dagnode->number); + } if (n->type == st_func) { const char *num_params = 0; int first_param = 0; function_t *func = dag->flownode->graph->func; flowvar_t **flowvars = func->vars; - if (!strncmp (n->label->opcode, "label->opcode, "call")) { + // nothing to do + } else if (!strncmp (n->label->opcode, "rcall", 5)) { num_params = n->label->opcode + 6; first_param = 2; - } else if (!strncmp (n->label->opcode, "label->opcode, "call", 4)) { num_params = n->label->opcode + 5; - } else if (!strcmp (n->label->opcode, "")) { + } else if (!strcmp (n->label->opcode, "return") && n->children[0]) { daglabel_t *label = n->children[0]->label; if (!label->op) { set_iter_t *lab_i; @@ -817,6 +831,7 @@ dag_create (flownode_t *flownode) dagnode_t **nodes; daglabel_t **labels; int num_statements = 0; + int num_use = 0; int num_nodes; int num_lables; set_t *live_vars = set_new (); @@ -825,18 +840,25 @@ dag_create (flownode_t *flownode) // count the number of statements so the number of nodes and labels can be // guessed - for (s = block->statements; s; s = s->next) + for (s = block->statements; s; s = s->next) { num_statements++; + for (operand_t *use = s->use; use; use = use->next) { + if (use->op_type == op_pseudo) { + continue; + } + num_use++; + } + } set_assign (live_vars, flownode->live_vars.out); dag = new_dag (); dag->flownode = flownode; - // at most FLOW_OPERANDS per statement - num_nodes = num_statements * FLOW_OPERANDS; + // at most FLOW_OPERANDS per statement + use + num_nodes = num_statements * FLOW_OPERANDS + num_use; dag->nodes = alloca (num_nodes * sizeof (dagnode_t)); - // at most FLOW_OPERANDS per statement, + return + params - num_lables = num_statements * (FLOW_OPERANDS + 1 + 8); + // at most FLOW_OPERANDS per statement, + return + params + use + num_lables = num_statements * (FLOW_OPERANDS + 1 + 8) + num_use; dag->labels = alloca (num_lables * sizeof (daglabel_t)); dag->roots = set_new (); @@ -845,6 +867,15 @@ dag_create (flownode_t *flownode) for (s = block->statements; s; s = s->next) { operand_t *operands[FLOW_OPERANDS]; dag_make_leafs (dag, s, operands); + // make sure any auxiliary operands are given nodes, too + for (operand_t *use = s->use; use; use = use->next) { + if (use->op_type == op_pseudo) { + continue; + } + if (!dag_node (use)) { + leaf_node (dag, use, s->expr); + } + } } // actual dag creation for (s = block->statements; s; s = s->next) { @@ -874,7 +905,7 @@ dag_create (flownode_t *flownode) n->type = s->type; n->label = op; dagnode_add_children (dag, n, operands, children); - dagnode_set_edges (dag, n); + dagnode_set_edges (dag, n, s); dagnode_set_reachable (dag, n); } } @@ -1009,7 +1040,7 @@ generate_moves (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var = dag->labels[var_iter->element]; operands[2] = var->op; dst = operands[2]; - st = build_statement ("", operands, var->expr); + st = build_statement ("move", operands, var->expr); sblock_add_statement (block, st); } return dst; @@ -1031,7 +1062,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[1] = make_operand (dag, block, dagnode, 1); if (dagnode->children[2]) { operands[2] = make_operand (dag, block, dagnode, 2); - st = build_statement ("", operands, dagnode->label->expr); + st = build_statement ("movep", operands, dagnode->label->expr); sblock_add_statement (block, st); if ((var_iter = set_first (dagnode->identifiers))) { var = dag->labels[var_iter->element]; @@ -1051,7 +1082,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) } operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), operands[1]->expr); - st = build_statement ("", operands, var->expr); + st = build_statement ("movep", operands, var->expr); sblock_add_statement (block, st); } } @@ -1075,7 +1106,7 @@ generate_memsets (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var = dag->labels[var_iter->element]; operands[2] = var->op; dst = operands[2]; - st = build_statement ("", operands, var->expr); + st = build_statement ("memset", operands, var->expr); sblock_add_statement (block, st); } return dst; @@ -1097,7 +1128,7 @@ generate_memsetps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[1] = make_operand (dag, block, dagnode, 1); if (dagnode->children[2]) { operands[2] = make_operand (dag, block, dagnode, 2); - st = build_statement ("", operands, dagnode->label->expr); + st = build_statement ("memsetp", operands, dagnode->label->expr); sblock_add_statement (block, st); } else { for (var_iter = set_first (dagnode->identifiers); var_iter; @@ -1112,13 +1143,50 @@ generate_memsetps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) } operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), operands[1]->expr); - st = build_statement ("", operands, var->expr); + st = build_statement ("memsetp", operands, var->expr); sblock_add_statement (block, st); } } return dst; } +static operand_t * +generate_call (dag_t *dag, sblock_t *block, dagnode_t *dagnode) +{ + set_iter_t *var_iter; + daglabel_t *var = 0; + operand_t *operands[3] = {0, 0, 0}; + statement_t *st; + operand_t *dst; + + operands[0] = make_operand (dag, block, dagnode, 0); + if (dagnode->children[1]) { + operands[1] = make_operand (dag, block, dagnode, 1); + } + dst = operands[0]; + for (var_iter = set_first (dagnode->identifiers); var_iter; + var_iter = set_next (var_iter)) { + if (var) { + internal_error (var->expr, "more than one return value for call"); + } + var = dag->labels[var_iter->element]; + operands[2] = var->op; + dst = operands[2]; + st = build_statement ("call", operands, var->expr); + sblock_add_statement (block, st); + } + if (var_iter) { + set_del_iter (var_iter); + } + if (!var) { + // void call or return value ignored, still have to call + operands[2] = make_operand (dag, block, dagnode, 2); + st = build_statement ("call", operands, dagnode->label->expr); + sblock_add_statement (block, st); + } + return dst; +} + static operand_t * generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, set_iter_t *var_iter, type_t *type) @@ -1128,14 +1196,14 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, operand_t *operands[3] = {0, 0, 0}; daglabel_t *var; - operands[0] = fix_op_type (src, type); + operands[2] = fix_op_type (src, type); for ( ; var_iter; var_iter = set_next (var_iter)) { var = dag->labels[var_iter->element]; - operands[1] = fix_op_type (var->op, type); + operands[0] = fix_op_type (var->op, type); if (!dst) - dst = operands[1]; + dst = operands[0]; - st = build_statement ("=", operands, var->expr); + st = build_statement ("assign", operands, var->expr); sblock_add_statement (block, st); } return dst; @@ -1161,6 +1229,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) dst = generate_assignments (dag, block, dst, var_iter, type); } break; + case st_address: case st_expr: operands[0] = make_operand (dag, block, dagnode, 0); if (dagnode->children[1]) @@ -1184,15 +1253,15 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) case st_assign: internal_error (0, "unexpected assignment node"); case st_ptrassign: - operands[0] = make_operand (dag, block, dagnode, 0); - operands[1] = make_operand (dag, block, dagnode, 1); - if (dagnode->children[2]) - operands[2] = make_operand (dag, block, dagnode, 2); + operands[2] = make_operand (dag, block, dagnode, 0); + operands[0] = make_operand (dag, block, dagnode, 2); + if (dagnode->children[1]) + operands[1] = make_operand (dag, block, dagnode, 1); st = build_statement (dagnode->label->opcode, operands, dagnode->label->expr); sblock_add_statement (block, st); // the source location is suitable for use in other nodes - dst = operands[0]; + dst = operands[2]; break; case st_move: dst = generate_moves (dag, block, dagnode); @@ -1206,8 +1275,13 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) case st_ptrmemset: dst = generate_memsetps (dag, block, dagnode); break; - case st_state: case st_func: + if (!strcmp (dagnode->label->opcode, "call")) { + dst = generate_call (dag, block, dagnode); + break; + } + // fallthrough + case st_state: for (i = 0; i < 3; i++) if (dagnode->children[i]) operands[i] = make_operand (dag, block, dagnode, i); @@ -1219,6 +1293,8 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[0] = make_operand (dag, block, dagnode, 0); if (dagnode->children[1]) operands[1] = make_operand (dag, block, dagnode, 1); + if (dagnode->children[2]) + operands[2] = make_operand (dag, block, dagnode, 2); st = build_statement (dagnode->label->opcode, operands, dagnode->label->expr); sblock_add_statement (block, st); diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index ec0367fa0..4afff69ee 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -41,7 +41,7 @@ #include #include "QF/alloc.h" -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/def.h" @@ -164,7 +164,7 @@ emit_basedir (def_t *def, void *data, int index) static void emit_num_files (def_t *def, void *data, int index) { - if (!is_integer (def->type)) { + if (!is_int (def->type)) { internal_error (0, "%s: expected int def", __FUNCTION__); } D_INT (def) = pr.comp_files.size; @@ -189,7 +189,7 @@ emit_compunit (const char *modname) static struct_def_t compunit_struct[] = { {"unit_name", &type_string, emit_unit_name}, {"basedir", &type_string, emit_basedir}, - {"num_files", &type_integer, emit_num_files}, + {"num_files", &type_int, emit_num_files}, {"files", 0, emit_files_item}, {0, 0} }; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index df1d36b94..29214b5c3 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -196,6 +196,7 @@ alias_def (def_t *def, type_t *type, int offset) alias->line = pr.source_line; alias->file = pr.source_file; alias->next = def->alias_defs; + alias->reg = def->reg; def->alias_defs = alias; return alias; } @@ -204,11 +205,11 @@ def_t * temp_def (type_t *type) { def_t *temp; - defspace_t *space = current_func->symtab->space; + defspace_t *space = current_func->locals->space; int size = type_size (type); int alignment = type->alignment; - if (size < 1 || size > 4) { + if (size < 1 || size > MAX_DEF_SIZE) { internal_error (0, "%d invalid size for temp def", size); } if (alignment < 1) { @@ -230,6 +231,7 @@ temp_def (type_t *type) temp->line = pr.source_line; set_storage_bits (temp, sc_local); temp->space = space; + temp->reg = current_func->temp_reg; return temp; } @@ -284,7 +286,7 @@ def_to_ddef (def_t *def, ddef_t *ddef, int aux) type = type->t.fldptr.type; // aux is true only for fields ddef->type = type->type; ddef->ofs = def->offset; - ddef->s_name = ReuseString (def->name); + ddef->name = ReuseString (def->name); } static int @@ -378,8 +380,7 @@ init_elements (struct def_s *def, expr_t *eles) reloc_def_op (c->e.labelref.label, &dummy); continue; } else if (c->type == ex_value) { - if (c->e.value->lltype == ev_integer - && is_float (element->type)) { + if (c->e.value->lltype == ev_int && is_float (element->type)) { convert_int (c); } if (is_double (get_type (c)) && is_float (element->type) @@ -411,8 +412,8 @@ init_elements (struct def_s *def, expr_t *eles) free_element_chain (&element_chain); } -static void -init_vector_components (symbol_t *vector_sym, int is_field) +void +init_vector_components (symbol_t *vector_sym, int is_field, symtab_t *symtab) { expr_t *vector_expr; int i; @@ -425,9 +426,9 @@ init_vector_components (symbol_t *vector_sym, int is_field) const char *name; name = va (0, "%s_%s", vector_sym->name, fields[i]); - sym = symtab_lookup (current_symtab, name); + sym = symtab_lookup (symtab, name); if (sym) { - if (sym->table == current_symtab) { + if (sym->table == symtab) { if (sym->sy_type != sy_expr) { error (0, "%s redefined", name); sym = 0; @@ -461,12 +462,13 @@ init_vector_components (symbol_t *vector_sym, int is_field) sym->sy_type = sy_expr; sym->s.expr = expr; if (!sym->table) - symtab_addsymbol (current_symtab, sym); + symtab_addsymbol (symtab, sym); } } static void -init_field_def (def_t *def, expr_t *init, storage_class_t storage) +init_field_def (def_t *def, expr_t *init, storage_class_t storage, + symtab_t *symtab) { type_t *type = (type_t *) dereference_type (def->type);//FIXME cast def_t *field_def; @@ -499,7 +501,7 @@ init_field_def (def_t *def, expr_t *init, storage_class_t storage) } // no support for initialized field vector componets (yet?) if (is_vector(type) && options.code.vector_components) - init_vector_components (field_sym, 1); + init_vector_components (field_sym, 1, symtab); } else if (init->type == ex_symbol) { symbol_t *sym = init->e.symbol; symbol_t *field = symtab_lookup (pr.entity_fields, sym->name); @@ -523,12 +525,12 @@ num_elements (expr_t *e) void initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, - storage_class_t storage) + storage_class_t storage, symtab_t *symtab) { - symbol_t *check = symtab_lookup (current_symtab, sym->name); + symbol_t *check = symtab_lookup (symtab, sym->name); reloc_t *relocs = 0; - if (check && check->table == current_symtab) { + if (check && check->table == symtab) { if (check->sy_type != sy_var || !type_same (check->type, sym->type)) { error (0, "%s redefined", sym->name); } else { @@ -549,7 +551,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } sym->sy_type = sy_var; if (!sym->table) - symtab_addsymbol (current_symtab, sym); + symtab_addsymbol (symtab, sym); if (sym->s.def && sym->s.def->external) { //FIXME this really is not the right way @@ -567,10 +569,10 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, reloc_attach_relocs (relocs, &sym->s.def->relocs); } if (is_vector(sym->type) && options.code.vector_components) - init_vector_components (sym, 0); + init_vector_components (sym, 0, symtab); if (sym->type->type == ev_field && storage != sc_local && storage != sc_param) - init_field_def (sym->s.def, init, storage); + init_field_def (sym->s.def, init, storage, symtab); if (storage == sc_extern) { if (init) error (0, "initializing external variable"); @@ -582,7 +584,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, if (init->type == ex_error) return; if ((is_array (sym->type) || is_struct (sym->type) - || is_vector(sym->type) || is_quaternion(sym->type)) + || is_nonscalar (sym->type)) && ((init->type == ex_compound) || init->type == ex_nil)) { init_elements (sym->s.def, init); @@ -608,18 +610,17 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, error (init, "non-constant initializier"); return; } - while ((init->type == ex_uexpr || init->type == ex_expr) - && init->e.expr.op == 'A') { - if (init->type == ex_expr) { - offset += expr_integer (init->e.expr.e2); + while (init->type == ex_alias) { + if (init->e.alias.offset) { + offset += expr_int (init->e.alias.offset); } - init = init->e.expr.e1; + init = init->e.alias.expr; } if (init->type != ex_value) { //FIXME enum etc internal_error (0, "initializier not a value"); return; } - if (init->e.value->lltype == ev_pointer + if (init->e.value->lltype == ev_ptr || init->e.value->lltype == ev_field) { // FIXME offset pointers D_INT (sym->s.def) = init->e.value->v.pointer.val; diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index 1cfe572c3..a704b45a3 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -105,14 +105,9 @@ grow_space_global (defspace_t *space) static int grow_space_virtual (defspace_t *space) { - int size; - - if (space->size <= space->max_size) - return 1; - - size = space->size + GROW; - size -= size % GROW; - space->max_size = size; + if (space->size > space->max_size) { + space->max_size = space->size; + } return 1; } @@ -208,6 +203,7 @@ defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment) internal_error (0, "unable to allocate %d words", size); } if (pad) { + // mark the padding as free *l = new_locref (ofs, pad, 0); } return ofs + pad; @@ -271,3 +267,46 @@ defspace_add_data (defspace_t *space, pr_type_t *data, int size) memcpy (space->data + loc, data, size * sizeof (pr_type_t)); return loc; } + +int +defspace_alloc_highwater (defspace_t *space, int size) +{ + return defspace_alloc_aligned_highwater (space, size, 1); +} + +int +defspace_alloc_aligned_highwater (defspace_t *space, int size, int alignment) +{ + if (size < 0) + internal_error (0, "invalid number of words requested: %d", size); + if (alignment <= 0) + internal_error (0, "invalid alignment requested: %d", alignment); + + int ofs = space->size; + int pad = alignment * ((ofs + alignment - 1) / alignment) - ofs; + space->size += size + pad; + if (space->size > space->max_size) { + if (!space->grow || !space->grow (space)) + internal_error (0, "unable to allocate %d words", size); + } + locref_t **l = &space->free_locs; + if (pad) { + // mark the padding as free + *l = new_locref (ofs, pad, 0); + } + return ofs + pad; +} + +void +defspace_reset (defspace_t *space) +{ + space->size = 0; + while (space->free_locs) { + locref_t *l = space->free_locs; + space->free_locs = l->next; + del_locref (l); + } + if (space->data) { + memset (space->data, 0, space->max_size * sizeof (pr_type_t)); + } +} diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 9169b42f9..6410fae1e 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -50,8 +50,8 @@ static void report_function (const expr_t *e) { static function_t *last_func = (function_t *)-1L; - static string_t last_file; - string_t file = pr.source_file; + static pr_string_t last_file; + pr_string_t file = pr.source_file; srcline_t *srcline; if (e) @@ -81,7 +81,7 @@ static __attribute__((format(PRINTF, 4, 0))) void format_message (dstring_t *message, const char *msg_type, const expr_t *e, const char *fmt, va_list args) { - string_t file = pr.source_file; + pr_string_t file = pr.source_file; int line = pr.source_line; const char *colon = fmt ? ": " : ""; diff --git a/tools/qfcc/source/disassemble.c b/tools/qfcc/source/disassemble.c index 7002510bc..5b8ec9735 100644 --- a/tools/qfcc/source/disassemble.c +++ b/tools/qfcc/source/disassemble.c @@ -63,20 +63,21 @@ disassemble_progs (progs_t *pr) { unsigned int i; - for (i = 0; i < pr->progs->numstatements; i++) { + for (i = 0; i < pr->progs->statements.count; i++) { dfunction_t *desc = func_find (i); if (desc) { bfunction_t func; func.first_statement = desc->first_statement; - func.parm_start = desc->parm_start; + func.params_start = desc->params_start; func.locals = desc->locals; - func.numparms = desc->numparms; - memcpy (func.parm_size, desc->parm_size, sizeof (func.parm_size)); + func.numparams = desc->numparams; + memcpy (func.param_size, desc->param_size, + sizeof (func.param_size)); func.descriptor = desc; - Sys_Printf ("%s:\n", PR_GetString (pr, desc->s_name)); + Sys_Printf ("%s:\n", PR_GetString (pr, desc->name)); pr->pr_xfunction = &func; } PR_PrintStatement (pr, &pr->pr_statements[i], 2 | (verbosity > 1)); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index cde32c8fd..52db56ca9 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -38,6 +38,7 @@ # include #endif #include +#include #include #include @@ -54,25 +55,13 @@ #include "tools/qfcc/source/qc-parse.h" +#define EX_EXPR(expr) #expr, const char *expr_names[] = { - "error", - "state", - "bool", - "label", - "labelref", - "block", - "expr", - "uexpr", - "def", - "symbol", - "temp", - "vector", - "nil", - "value", - "compound", - "memset", +#include "tools/qfcc/include/expr_names.h" + 0 }; +#undef EX_EXPR const char * get_op_string (int op) @@ -101,20 +90,10 @@ get_op_string (int op) case SHL: return "<<"; case SHR: return ">>"; case '.': return "."; - case 'i': return ""; - case 'n': return ""; - case IFBE: return ""; - case IFB: return ""; - case IFAE: return ""; - case IFA: return ""; - case 'g': return ""; - case 'r': return ""; - case 's': return ""; - case 'c': return ""; - case 'A': return ""; case 'C': return ""; - case 'M': return ""; - case 'm': return ""; + case CROSS: return "@cross"; + case DOT: return "@dot"; + case SCALE: return "@scale"; default: return "unknown"; } @@ -269,6 +248,113 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) } } +static void +print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.expr.e1, level, id, next); + _print_expr (dstr, e->e.expr.e2, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"l\"];\n", indent, "", e, + e->e.expr.e1); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e, + e->e.expr.e2); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + get_op_string (e->e.expr.op), e->line); +} + +static void +print_alias (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.alias.expr, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"a\"];\n", indent, "", e, + e->e.alias.expr); + if (e->e.alias.offset) { + _print_expr (dstr, e->e.alias.offset, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"o\"];\n", indent, "", e, + e->e.alias.offset); + } + + dstring_t *typestr = dstring_newstr(); + print_type_str (typestr, e->e.alias.type); + dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, + "", typestr->str, e->line); + dstring_delete (typestr); +} + +static void +print_address (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.address.lvalue, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"&\"];\n", indent, "", e, + e->e.address.lvalue); + if (e->e.address.offset) { + _print_expr (dstr, e->e.address.offset, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"+\"];\n", indent, "", e, + e->e.address.offset); + } + + dstring_t *typestr = dstring_newstr(); + print_type_str (typestr, e->e.address.type); + dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, + "&", typestr->str, e->line); + dstring_delete (typestr); +} + +static void +print_assign (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.assign.dst, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"lval\"];\n", indent, "", e, + e->e.assign.dst); + _print_expr (dstr, e->e.assign.src, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"rval\"];\n", indent, "", e, + e->e.assign.src); + + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "=", e->line); +} + +static void +print_conditional (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + static const char *condition[] = { + "ifz", "ifb", "ifa", 0, "ifnz", "ifnb", "ifna", 0 + }; + + _print_expr (dstr, e->e.branch.test, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"t\"];\n", indent, "", e, + e->e.branch.test); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"g\"];\n", indent, "", e, + e->e.branch.target); + if (e->next) { + next = e->next; + } + if (next) { + dasprintf (dstr, "%*se_%p -> e_%p [constraint=true," + "style=dashed];\n", indent, "", e, next); + } + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + condition [e->e.branch.type], e->line); +} + +static void +print_jump (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.branch.target, level, id, next); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "jump", e->line); +} + static void print_call (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -277,13 +363,13 @@ print_call (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) int i, count; expr_t **args; - for (count = 0, p = e->e.expr.e2; p; p = p->next) + for (count = 0, p = e->e.branch.args; p; p = p->next) count++; args = alloca (count * sizeof (expr_t *)); - for (i = 0, p = e->e.expr.e2; p; p = p->next, i++) + for (i = 0, p = e->e.branch.args; p; p = p->next, i++) args[count - 1 - i] = p; - _print_expr (dstr, e->e.expr.e1, level, id, next); + _print_expr (dstr, e->e.branch.target, level, id, next); dasprintf (dstr, "%*se_%p [label=\"call", indent, "", e); for (i = 0; i < count; i++) dasprintf (dstr, "|p%d", i, i); @@ -293,68 +379,54 @@ print_call (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dasprintf (dstr, "%*se_%p:p%d -> e_%p;\n", indent + 2, "", e, i, args[i]); } - dasprintf (dstr, "%*se_%p:c -> e_%p;\n", indent, "", e, e->e.expr.e1); + dasprintf (dstr, "%*se_%p:c -> e_%p;\n", indent, "", e, + e->e.branch.target); } static void -print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +print_branch (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + switch (e->e.branch.type) { + case pr_branch_eq: + case pr_branch_lt: + case pr_branch_gt: + case pr_branch_ne: + case pr_branch_ge: + case pr_branch_le: + print_conditional (dstr, e, level, id, next); + break; + case pr_branch_jump: + print_jump (dstr, e, level, id, next); + break; + case pr_branch_call: + print_call (dstr, e, level, id, next); + break; + } +} + +static void +print_return (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - if (e->e.expr.op == 'c') { - print_call (dstr, e, level, id, next); - return; - } else if (e->e.expr.op == 'i' || e->e.expr.op == 'n' - || e->e.expr.op == IFB || e->e.expr.op ==IFBE - || e->e.expr.op == IFA || e->e.expr.op ==IFAE) { - _print_expr (dstr, e->e.expr.e1, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"t\"];\n", indent, "", e, - e->e.expr.e1); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"g\"];\n", indent, "", e, - e->e.expr.e2); - if (e->next) - next = e->next; - if (next) - dasprintf (dstr, "%*se_%p -> e_%p [constraint=true," - "style=dashed];\n", indent, "", e, next); - } else { - _print_expr (dstr, e->e.expr.e1, level, id, next); - _print_expr (dstr, e->e.expr.e2, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"l\"];\n", indent, "", e, - e->e.expr.e1); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e, - e->e.expr.e2); - } - if (e->e.expr.op == 'A') { - dstring_t *typestr = dstring_newstr(); - print_type_str (typestr, e->e.expr.type); - dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, - get_op_string (e->e.expr.op), typestr->str, e->line); - dstring_delete (typestr); - } else { - dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, - get_op_string (e->e.expr.op), e->line); + if (e->e.retrn.ret_val) { + _print_expr (dstr, e->e.retrn.ret_val, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, + e->e.retrn.ret_val); } + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "return", e->line); } static void print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - dstring_t *typestr = dstring_newstr(); - if (e->e.expr.op != 'g' && e->e.expr.e1) - _print_expr (dstr, e->e.expr.e1, level, id, next); - if (e->e.expr.op == 'A') { - dstring_copystr (typestr, "\\n"); - print_type_str (typestr, e->e.expr.type); - } - if (e->e.expr.op != 'r' || e->e.expr.e1) - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, - e->e.expr.e1); - dasprintf (dstr, "%*se_%p [label=\"%s%s\\n%d\"];\n", indent, "", e, - get_op_string (e->e.expr.op), typestr->str, e->line); - dstring_delete (typestr); + _print_expr (dstr, e->e.expr.e1, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.expr.e1); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + get_op_string (e->e.expr.op), e->line); } static void @@ -474,14 +546,14 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->e.value->v.vector_val[1], e->e.value->v.vector_val[2]); break; - case ev_quat: + case ev_quaternion: label = va (0, "'%g %g %g %g'", e->e.value->v.quaternion_val[0], e->e.value->v.quaternion_val[1], e->e.value->v.quaternion_val[2], e->e.value->v.quaternion_val[3]); break; - case ev_pointer: + case ev_ptr: type = e->e.value->v.pointer.type; dstring_clearstr(type_str); if (type) { @@ -507,20 +579,29 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) } break; case ev_entity: - label = va (0, "ent %d", e->e.value->v.integer_val); + label = va (0, "ent %d", e->e.value->v.int_val); break; case ev_func: - label = va (0, "func %d", e->e.value->v.integer_val); + label = va (0, "func %d", e->e.value->v.int_val); break; - case ev_integer: - label = va (0, "i %d", e->e.value->v.integer_val); + case ev_int: + label = va (0, "i %d", e->e.value->v.int_val); break; - case ev_uinteger: - label = va (0, "u %u", e->e.value->v.uinteger_val); + case ev_uint: + label = va (0, "u %u", e->e.value->v.uint_val); + break; + case ev_long: + label = va (0, "i %"PRIi64, e->e.value->v.long_val); + break; + case ev_ulong: + label = va (0, "u %"PRIu64, e->e.value->v.ulong_val); break; case ev_short: label = va (0, "s %d", e->e.value->v.short_val); break; + case ev_ushort: + label = va (0, "us %d", e->e.value->v.ushort_val); + break; case ev_void: label = ""; break; @@ -558,6 +639,36 @@ print_memset (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dasprintf (dstr, "%*se_%p [label=\"memset\"];\n", indent, "", e); } +static void +print_adjstk (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"adjstk %d:%d\\n%d\"];\n", indent, "", e, + e->e.adjstk.mode, e->e.adjstk.offset, e->line); +} + +static void +print_with (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + expr_t *with = e->e.with.with; + + _print_expr (dstr, with, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, with); + dasprintf (dstr, "%*se_%p [label=\"with %d:%d\\n%d\"];\n", indent, "", e, + e->e.with.mode, e->e.with.reg, e->line); +} + +static void +print_args (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"...\\n%d\"];\n", indent, "", e, + e->line); +} + static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -579,6 +690,14 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_value] = print_value, [ex_compound] = print_compound, [ex_memset] = print_memset, + [ex_alias] = print_alias, + [ex_address] = print_address, + [ex_assign] = print_assign, + [ex_branch] = print_branch, + [ex_return] = print_return, + [ex_adjstk] = print_adjstk, + [ex_with] = print_with, + [ex_args] = print_args, }; int indent = level * 2 + 2; @@ -590,9 +709,13 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) return; e->printid = id; - if ((int) e->type < 0 || e->type > ex_memset || !print_funcs[e->type]) { - dasprintf (dstr, "%*se_%p [label=\"(bad expr type)\\n%d\"];\n", - indent, "", e, e->line); + if ((int) e->type < 0 || e->type >= ex_count || !print_funcs[e->type]) { + const char *type = va (0, "%d", e->type); + if (e->type >= 0 && e->type < ex_count) { + type = expr_names[e->type]; + } + dasprintf (dstr, "%*se_%p [label=\"(bad expr type: %s)\\n%d\"];\n", + indent, "", e, type, e->line); return; } print_funcs[e->type] (dstr, e, level, id, next); diff --git a/tools/qfcc/source/dot_type.c b/tools/qfcc/source/dot_type.c index 522fa91fb..5f743dae7 100644 --- a/tools/qfcc/source/dot_type.c +++ b/tools/qfcc/source/dot_type.c @@ -61,7 +61,7 @@ print_pointer (dstring_t *dstr, type_t *t, int level, int id) dot_print_type (dstr, aux, level, id); dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, aux); dasprintf (dstr, "%*st_%p [label=\"%c\"];\n", indent, "", t, - t->type == ev_pointer ? '*' : '.'); + t->type == ev_ptr ? '*' : '.'); } static void @@ -118,7 +118,7 @@ print_function (dstring_t *dstr, type_t *t, int level, int id) static void print_basic (dstring_t *dstr, type_t *t, int level, int id) { - if (t->type == ev_pointer || t->type == ev_field) { + if (t->type == ev_ptr || t->type == ev_field) { print_pointer (dstr, t, level, id); } else if (t->type == ev_func) { print_function (dstr, t, level, id); @@ -169,7 +169,7 @@ print_struct (dstring_t *dstr, type_t *t, int level, int id) int val; const char *port = ""; if (sym->sy_type == sy_const) { - val = sym->s.value->v.integer_val; + val = sym->s.value->v.int_val; } else { if (sym->sy_type != sy_var) { continue; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index e01005a47..c0ade919b 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -65,7 +65,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) const char *type; pr_uint_t offset; const char *comment; - string_t string; + pr_string_t string; const char *str; int saveglobal; @@ -79,19 +79,19 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) comment = " invalid offset"; - if (offset < pr->progs->numglobals) { + if (offset < pr->progs->globals.count) { comment = ""; switch (def->type & ~DEF_SAVEGLOBAL) { case ev_void: break; case ev_string: string = G_INT (pr, offset); - // at runtime, strings can be negative (thus string_t is + // at runtime, strings can be negative (thus pr_string_t is // signed), but negative strings means they have been // dynamically allocated, thus a negative string index should // never appear in compiled code if (string < 0 - || (pr_uint_t) string >= pr->progs->numstrings) { + || (pr_uint_t) string >= pr->progs->strings.count) { str = "invalid string offset"; comment = va (0, " %d %s", string, str); } else { @@ -118,9 +118,9 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) break; case ev_func: { - func_t func = G_FUNCTION (pr, offset); + pr_func_t func = G_FUNCTION (pr, offset); int start; - if (func < pr->progs->numfunctions) { + if (func < pr->progs->functions.count) { start = pr->pr_functions[func].first_statement; if (start > 0) comment = va (0, " %d @ %x", func, start); @@ -131,17 +131,17 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) } } break; - case ev_pointer: + case ev_ptr: comment = va (0, " %x", G_INT (pr, offset)); break; - case ev_quat: + case ev_quaternion: comment = va (0, " '%g %g %g %g'", G_QUAT (pr, offset)[0], G_QUAT (pr, offset)[1], G_QUAT (pr, offset)[2], G_QUAT (pr, offset)[3]); break; - case ev_integer: + case ev_int: comment = va (0, " %d", G_INT (pr, offset)); break; case ev_short: @@ -165,12 +165,12 @@ dump_globals (progs_t *pr) pr_def_t *global_defs = pr->pr_globaldefs; if (sorted) { - global_defs = malloc (pr->progs->numglobaldefs * sizeof (ddef_t)); + global_defs = malloc (pr->progs->globaldefs.count * sizeof (ddef_t)); memcpy (global_defs, pr->pr_globaldefs, - pr->progs->numglobaldefs * sizeof (ddef_t)); - qsort (global_defs, pr->progs->numglobaldefs, sizeof (ddef_t), cmp); + pr->progs->globaldefs.count * sizeof (ddef_t)); + qsort (global_defs, pr->progs->globaldefs.count, sizeof (ddef_t), cmp); } - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { pr_def_t *def = &global_defs[i]; dump_def (pr, def, 0); } @@ -185,7 +185,7 @@ dump_fields (progs_t *pr) int offset; const char *comment; - for (i = 0; i < pr->progs->numfielddefs; i++) { + for (i = 0; i < pr->progs->fielddefs.count; i++) { pr_def_t *def = &pr->pr_fielddefs[i]; name = PR_GetString (pr, def->name); @@ -241,17 +241,17 @@ dump_functions (progs_t *pr) int start; const char *comment; pr_def_t *encodings_def; - pointer_t type_encodings = 0; + pr_ptr_t type_encodings = 0; encodings_def = PR_FindGlobal (pr, ".type_encodings"); if (encodings_def) { type_encodings = encodings_def->ofs; } - for (i = 0; i < pr->progs->numfunctions; i++) { + for (i = 0; i < pr->progs->functions.count; i++) { dfunction_t *func = &pr->pr_functions[i]; - name = PR_GetString (pr, func->s_name); + name = PR_GetString (pr, func->name); start = func->first_statement; if (start > 0) @@ -259,15 +259,15 @@ dump_functions (progs_t *pr) else comment = va (0, " = #%d", -start); - printf ("%-5d %s%s: %d (", i, name, comment, func->numparms); - if (func->numparms < 0) - count = -func->numparms - 1; + printf ("%-5d %s%s: %d (", i, name, comment, func->numparams); + if (func->numparams < 0) + count = -func->numparams - 1; else - count = func->numparms; + count = func->numparams; for (j = 0; j < count; j++) - printf (" %d:%d", func->parm_size[j].alignment, - func->parm_size[j].size); - printf (") %d @ %x", func->locals, func->parm_start); + printf (" %d:%d", func->param_size[j].alignment, + func->param_size[j].size); + printf (") %d @ %x", func->locals, func->params_start); puts (""); if (type_encodings) { pr_auxfunction_t *aux = PR_Debug_MappedAuxFunction (pr, i); @@ -275,7 +275,7 @@ dump_functions (progs_t *pr) continue; } printf (" %d %s:%d %d %d %d %x\n", aux->function, - PR_GetString (pr, func->s_file), aux->source_line, + PR_GetString (pr, func->file), aux->source_line, aux->line_info, aux->local_defs, aux->num_locals, aux->return_type); @@ -327,7 +327,7 @@ qfo_globals (qfo_t *qfo) QFO_TYPESTR (qfo, def->type)); if (!(def->flags & QFOD_EXTERNAL) && qfo->spaces[space].data) printf (" %d", - qfo->spaces[space].data[def->offset].integer_var); + qfo->spaces[space].data[def->offset].int_var); puts (""); } } @@ -476,7 +476,8 @@ qfo_functions (qfo_t *qfo) printf (" @ %x", func->code); else printf (" = #%d", -func->code); - printf (" loc: %d\n", func->locals_space); + printf (" loc: %d params: %d\n", + func->locals_space, func->params_start); if (func->locals_space) { locals = &qfo->spaces[func->locals_space]; printf ("%*s%d %p %d %p %d %d\n", 16, "", locals->type, @@ -512,11 +513,17 @@ static const char *ty_meta_names[] = { "ty_alias", }; #define NUM_META ((int)(sizeof (ty_meta_names) / sizeof (ty_meta_names[0]))) +const int vector_types = (1 << ev_float) + | (1 << ev_int) + | (1 << ev_uint) + | (1 << ev_double) + | (1 << ev_long) + | (1 << ev_ulong); static void dump_qfo_types (qfo_t *qfo, int base_address) { - pointer_t type_ptr; + pr_ptr_t type_ptr; qfot_type_t *type; const char *meta; int i, count; @@ -559,9 +566,12 @@ dump_qfo_types (qfo_t *qfo, int base_address) count = ~count; //ones complement for (i = 0; i < count; i++) printf (" %x", type->func.param_types[i]); - } else if (type->type == ev_pointer + } else if (type->type == ev_ptr || type->type == ev_field) { printf (" %4x", type->fldptr.aux_type); + } else if ((1 << type->type) & vector_types + && type->basic.width > 1) { + printf ("[%d]", type->basic.width); } printf ("\n"); break; diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index 044c7fdc7..4b95b3ad3 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -41,7 +41,8 @@ #include #include "QF/progs.h" -#include "QF/pr_type.h" + +#include "QF/progs/pr_type.h" #include "tools/qfcc/include/obj_file.h" #include "tools/qfcc/include/qfprogs.h" @@ -51,7 +52,7 @@ typedef struct { const char *source_file; pr_uint_t source_line; pr_int_t first_statement; - pointer_t return_type; + pr_ptr_t return_type; pr_uint_t local_defs; pr_uint_t num_locals; pr_uint_t line_info; @@ -77,10 +78,10 @@ progs_get_func_data (unsigned func_index, void *data) func_data.local_defs = aux_func->local_defs; func_data.line_info = aux_func->line_info; func_data.function = aux_func->function; - if (aux_func->function < (unsigned int) pr->progs->numfunctions) { + if (aux_func->function < (unsigned int) pr->progs->functions.count) { func = pr->pr_functions + aux_func->function; - func_data.source_file = pr->pr_strings + func->s_file; - func_data.source_name = pr->pr_strings + func->s_name; + func_data.source_file = pr->pr_strings + func->file; + func_data.source_name = pr->pr_strings + func->name; func_data.first_statement = func->first_statement; } return &func_data; diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index 0fcda6e50..70dfe35c0 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -40,10 +40,11 @@ #include -#include "QF/pr_obj.h" #include "QF/progs.h" #include "QF/va.h" +#include "QF/progs/pr_obj.h" + #include "tools/qfcc/include/qfprogs.h" static void @@ -129,7 +130,7 @@ dump_protocol (progs_t *pr, pr_protocol_t *proto) { const char *protocol_name = ""; printf (" %x %x ", - (pointer_t) ((pr_int_t *) proto - (pr_int_t *) pr->pr_globals), + (pr_ptr_t) ((pr_int_t *) proto - (pr_int_t *) pr->pr_globals), proto->class_pointer); if (PR_StringValid (pr, proto->protocol_name)) protocol_name = PR_GetString (pr, proto->protocol_name); @@ -215,9 +216,9 @@ dump_category (progs_t *pr, pr_category_t *category) } static void -dump_static_instance_lists (progs_t *pr, pointer_t instance_lists) +dump_static_instance_lists (progs_t *pr, pr_ptr_t instance_lists) { - pointer_t *ptr = &G_STRUCT (pr, pointer_t, instance_lists); + pr_ptr_t *ptr = &G_STRUCT (pr, pr_ptr_t, instance_lists); printf (" static instance lists @ %x\n", instance_lists); while (*ptr) { @@ -244,7 +245,7 @@ static void dump_module (progs_t *pr, pr_module_t *module) { pr_symtab_t *symtab = &G_STRUCT (pr, pr_symtab_t, module->symtab); - pointer_t *ptr = symtab->defs; + pr_ptr_t *ptr = symtab->defs; pr_sel_t *sel = &G_STRUCT (pr, pr_sel_t, symtab->refs); int i; const char *module_name = ""; @@ -276,7 +277,7 @@ dump_modules (progs_t *pr) { unsigned int i; - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { pr_def_t *def = &pr->pr_globaldefs[i]; const char *name = ""; diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index c8507011e..df4ca1b04 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -78,7 +78,7 @@ dump_string_block (const char *strblock, size_t size) void dump_strings (progs_t *pr) { - dump_string_block (pr->pr_strings, pr->progs->numstrings); + dump_string_block (pr->pr_strings, pr->progs->strings.count); } void diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 5a7dd129a..30b2d1b4b 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -90,8 +90,7 @@ get_value_def (expr_t *expr, ex_value_t *value, type_t *type) def->offset = value->v.short_val; return def; } - if (is_pointer (type) && value->v.pointer.tempop - && !value->v.pointer.def) { + if (is_ptr (type) && value->v.pointer.tempop && !value->v.pointer.def) { value->v.pointer.def = get_tempop_def (expr, value->v.pointer.tempop, type->t.fldptr.type); } @@ -184,20 +183,36 @@ static void emit_statement (statement_t *statement) { const char *opcode = statement->opcode; + operand_t *op_a, *op_b, *op_c; def_t *def_a, *def_b, *def_c; - opcode_t *op; + instruction_t *inst; dstatement_t *s; - def_a = get_operand_def (statement->expr, statement->opa); - use_tempop (statement->opa, statement->expr); - def_b = get_operand_def (statement->expr, statement->opb); - use_tempop (statement->opb, statement->expr); - def_c = get_operand_def (statement->expr, statement->opc); - use_tempop (statement->opc, statement->expr); - op = opcode_find (opcode, statement->opa, statement->opb, statement->opc); + if (options.code.progsversion < PROG_VERSION + && (strcmp (statement->opcode, "store") == 0 + || strcmp (statement->opcode, "assign") == 0 + || statement_is_cond (statement))) { + // the operands for assign, store and branch instructions are rotated + // when comparing v6/v6p and ruamoko + op_a = statement->opc; + op_b = statement->opa; + op_c = statement->opb; + } else { + op_a = statement->opa; + op_b = statement->opb; + op_c = statement->opc; + } + def_a = get_operand_def (statement->expr, op_a); + use_tempop (op_a, statement->expr); + def_b = get_operand_def (statement->expr, op_b); + use_tempop (op_b, statement->expr); + def_c = get_operand_def (statement->expr, op_c); + use_tempop (op_c, statement->expr); + inst = opcode_find (opcode, op_a, op_b, op_c); - if (!op) { + if (!inst) { print_expr (statement->expr); + printf ("%d ", pr.code->size); print_statement (statement); internal_error (statement->expr, "ice ice baby"); } @@ -213,18 +228,32 @@ emit_statement (statement_t *statement) } } s = codespace_newstatement (pr.code); - s->op = op->opcode; - s->a = def_a ? def_a->offset : 0; - s->b = def_b ? def_b->offset : 0; - s->c = def_c ? def_c->offset : 0; + memset (s, 0, sizeof (*s)); + s->op = opcode_get (inst); + if (def_a) { + s->a = def_a->offset; + s->op |= ((def_a->reg) << OP_A_SHIFT) & OP_A_BASE; + } + if (def_b) { + s->b = def_b->offset; + s->op |= ((def_b->reg) << OP_B_SHIFT) & OP_B_BASE; + } + if (def_c) { + s->c = def_c->offset; + s->op |= ((def_c->reg) << OP_C_SHIFT) & OP_C_BASE; + } + + if (options.verbosity >= 2) { + opcode_print_statement (pr.code->size - 1, s); + } add_statement_def_ref (def_a, s, 0); add_statement_def_ref (def_b, s, 1); add_statement_def_ref (def_c, s, 2); - add_statement_op_ref (statement->opa, s, 0); - add_statement_op_ref (statement->opb, s, 1); - add_statement_op_ref (statement->opc, s, 2); + add_statement_op_ref (op_a, s, 0); + add_statement_op_ref (op_b, s, 1); + add_statement_op_ref (op_c, s, 2); } void diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 26d892c60..65eeb2468 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -91,7 +91,7 @@ convert_name (expr_t *e) } if (!strcmp (sym->name, "__LINE__") && current_func) { - new = new_integer_expr (e->line); + new = new_int_expr (e->line); goto convert; } if (!strcmp (sym->name, "__INFINITY__") @@ -215,18 +215,26 @@ get_type (expr_t *e) const type_t *type = 0; convert_name (e); switch (e->type) { + case ex_branch: + type = e->e.branch.ret_type; + break; case ex_labelref: + case ex_adjstk: + case ex_with: return &type_void; case ex_memset: return e->e.memset.type; - case ex_label: case ex_error: + return 0; + case ex_return: + internal_error (e, "unexpected expression type"); + case ex_label: case ex_compound: - return 0; // something went very wrong + return 0; case ex_bool: if (options.code.progsversion == PROG_ID_VERSION) return &type_float; - return &type_integer; + return &type_int; case ex_nil: if (e->e.nil) { return e->e.nil; @@ -258,6 +266,18 @@ get_type (expr_t *e) return e->e.vector.type; case ex_selector: return &type_SEL; + case ex_alias: + type = e->e.alias.type; + break; + case ex_address: + type = e->e.address.type; + break; + case ex_assign: + return get_type (e->e.assign.dst); + case ex_args: + return &type_va_list; + case ex_horizontal: + return e->e.hop.type; case ex_count: internal_error (e, "invalid expression"); } @@ -315,7 +335,7 @@ cast_error (expr_t *e, type_t *t1, type_t *t2) print_type_str (s1, t1); print_type_str (s2, t2); - e = error (e, "cannot cast from %s to %s", s1->str, s2->str); + e = error (e, "cannot cast from %s to %s", s1->str, s2->str); dstring_delete (s1); dstring_delete (s2); return e; @@ -469,6 +489,55 @@ copy_expr (expr_t *e) n->e.memset.val = copy_expr (e->e.memset.val); n->e.memset.count = copy_expr (e->e.memset.count); return n; + case ex_alias: + n = new_expr (); + *n = *e; + n->e.alias.expr = copy_expr (e->e.alias.expr); + n->e.alias.offset = copy_expr (e->e.alias.offset); + return n; + case ex_address: + n = new_expr (); + *n = *e; + n->e.address.lvalue = copy_expr (e->e.address.lvalue); + n->e.address.offset = copy_expr (e->e.address.offset); + return n; + case ex_assign: + n = new_expr (); + *n = *e; + n->e.assign.dst = copy_expr (e->e.assign.dst); + n->e.assign.src = copy_expr (e->e.assign.src); + return n; + case ex_branch: + n = new_expr (); + *n = *e; + n->e.branch.target = copy_expr (e->e.branch.target); + n->e.branch.index = copy_expr (e->e.branch.index); + n->e.branch.test = copy_expr (e->e.branch.test); + n->e.branch.args = copy_expr (e->e.branch.args); + return n; + case ex_return: + n = new_expr (); + *n = *e; + n->e.retrn.ret_val = copy_expr (e->e.retrn.ret_val); + return n; + case ex_adjstk: + n = new_expr (); + *n = *e; + return n; + case ex_with: + n = new_expr (); + *n = *e; + n->e.with.with = copy_expr (e->e.with.with); + return n; + case ex_args: + n = new_expr (); + *n = *e; + return n; + case ex_horizontal: + n = new_expr (); + *n = *e; + e->e.hop.vec = copy_expr (e->e.hop.vec); + return n; case ex_count: break; } @@ -633,6 +702,28 @@ new_unary_expr (int op, expr_t *e1) return e; } +expr_t * +new_horizontal_expr (int op, expr_t *vec, type_t *type) +{ + type_t *vec_type = get_type (vec); + if (!vec_type) { + return vec; + } + if (!is_math (vec_type) || is_scalar (vec_type)) { + internal_error (vec, "horizontal operand not a vector type"); + } + if (!is_scalar (type)) { + internal_error (vec, "horizontal result not a scalar type"); + } + + expr_t *e = new_expr (); + e->type = ex_horizontal; + e->e.hop.op = op; + e->e.hop.vec = vec; + e->e.hop.type = type; + return e; +} + expr_t * new_def_expr (def_t *def) { @@ -669,6 +760,14 @@ new_nil_expr (void) return e; } +expr_t * +new_args_expr (void) +{ + expr_t *e = new_expr (); + e->type = ex_args; + return e; +} + expr_t * new_value_expr (ex_value_t *value) { @@ -846,20 +945,20 @@ new_quaternion_expr (const float *quaternion_val) } expr_t * -new_integer_expr (int integer_val) +new_int_expr (int int_val) { expr_t *e = new_expr (); e->type = ex_value; - e->e.value = new_integer_val (integer_val); + e->e.value = new_int_val (int_val); return e; } expr_t * -new_uinteger_expr (unsigned uinteger_val) +new_uint_expr (unsigned uint_val) { expr_t *e = new_expr (); e->type = ex_value; - e->e.value = new_uinteger_val (uinteger_val); + e->e.value = new_uint_val (uint_val); return e; } @@ -875,9 +974,8 @@ new_short_expr (short short_val) int is_constant (expr_t *e) { - while ((e->type == ex_uexpr || e->type == ex_expr) - && e->e.expr.op == 'A') { - e = e->e.expr.e1; + while (e->type == ex_alias) { + e = e->e.alias.expr; } if (e->type == ex_nil || e->type == ex_value || e->type == ex_labelref || (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) @@ -887,6 +985,20 @@ is_constant (expr_t *e) return 0; } +int +is_variable (expr_t *e) +{ + while (e->type == ex_alias) { + e = e->e.alias.expr; + } + if (e->type == ex_def + || (e->type == ex_symbol && e->e.symbol->sy_type == sy_var) + || e->type == ex_temp) { + return 1; + } + return 0; +} + int is_selector (expr_t *e) { @@ -1037,10 +1149,10 @@ is_quaternion_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->lltype == ev_quat) + if (e->type == ex_value && e->e.value->lltype == ev_quaternion) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_quat) + && e->e.symbol->type->type == ev_quaternion) return 1; return 0; } @@ -1050,25 +1162,25 @@ expr_quaternion (expr_t *e) { if (e->type == ex_nil) return quat_origin; - if (e->type == ex_value && e->e.value->lltype == ev_quat) + if (e->type == ex_value && e->e.value->lltype == ev_quaternion) return e->e.value->v.quaternion_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_quat) + && e->e.symbol->type->type == ev_quaternion) return e->e.symbol->s.value->v.quaternion_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant - && e->e.symbol->s.def->type->type == ev_quat) + && e->e.symbol->s.def->type->type == ev_quaternion) return D_QUAT (e->e.symbol->s.def); internal_error (e, "not a quaternion constant"); } int -is_integer_val (expr_t *e) +is_int_val (expr_t *e) { if (e->type == ex_nil) { return 1; } - if (e->type == ex_value && e->e.value->lltype == ev_integer) { + if (e->type == ex_value && e->e.value->lltype == ev_int) { return 1; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const @@ -1083,18 +1195,21 @@ is_integer_val (expr_t *e) } int -expr_integer (expr_t *e) +expr_int (expr_t *e) { if (e->type == ex_nil) { return 0; } - if (e->type == ex_value && e->e.value->lltype == ev_integer) { - return e->e.value->v.integer_val; + if (e->type == ex_value && e->e.value->lltype == ev_int) { + return e->e.value->v.int_val; + } + if (e->type == ex_value && e->e.value->lltype == ev_short) { + return e->e.value->v.short_val; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && (e->e.symbol->type->type == ev_integer + && (e->e.symbol->type->type == ev_int || is_enum (e->e.symbol->type))) { - return e->e.symbol->s.value->v.integer_val; + return e->e.symbol->s.value->v.int_val; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant @@ -1105,16 +1220,16 @@ expr_integer (expr_t *e) && is_integral (e->e.def->type)) { return D_INT (e->e.def); } - internal_error (e, "not an integer constant"); + internal_error (e, "not an int constant"); } int -is_uinteger_val (expr_t *e) +is_uint_val (expr_t *e) { if (e->type == ex_nil) { return 1; } - if (e->type == ex_value && e->e.value->lltype == ev_uinteger) { + if (e->type == ex_value && e->e.value->lltype == ev_uint) { return 1; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const @@ -1129,17 +1244,17 @@ is_uinteger_val (expr_t *e) } unsigned -expr_uinteger (expr_t *e) +expr_uint (expr_t *e) { if (e->type == ex_nil) { return 0; } - if (e->type == ex_value && e->e.value->lltype == ev_uinteger) { - return e->e.value->v.uinteger_val; + if (e->type == ex_value && e->e.value->lltype == ev_uint) { + return e->e.value->v.uint_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; + && e->e.symbol->type->type == ev_uint) { + return e->e.symbol->s.value->v.uint_val; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant @@ -1189,10 +1304,10 @@ int is_integral_val (expr_t *e) { if (is_constant (e)) { - if (is_integer_val (e)) { + if (is_int_val (e)) { return 1; } - if (is_uinteger_val (e)) { + if (is_uint_val (e)) { return 1; } if (is_short_val (e)) { @@ -1206,11 +1321,11 @@ int expr_integral (expr_t *e) { if (is_constant (e)) { - if (is_integer_val (e)) { - return expr_integer (e); + if (is_int_val (e)) { + return expr_int (e); } - if (is_uinteger_val (e)) { - return expr_uinteger (e); + if (is_uint_val (e)) { + return expr_uint (e); } if (is_short_val (e)) { return expr_short (e); @@ -1222,7 +1337,7 @@ expr_integral (expr_t *e) int is_pointer_val (expr_t *e) { - if (e->type == ex_value && e->e.value->lltype == ev_pointer) { + if (e->type == ex_value && e->e.value->lltype == ev_ptr) { return 1; } return 0; @@ -1231,15 +1346,29 @@ is_pointer_val (expr_t *e) expr_t * new_alias_expr (type_t *type, expr_t *expr) { - expr_t *alias; - - alias = new_unary_expr ('A', expr); - alias->e.expr.type = type; - //if (expr->type == ex_uexpr && expr->e.expr.op == 'A') - // bug (alias, "aliasing an alias expression"); - if (expr->type == ex_expr && expr->e.expr.op == 'A') { - return new_offset_alias_expr (type, expr, 0); + if (is_ptr (type) && expr->type == ex_address) { + // avoid aliasing a pointer to a pointer (redundant) + expr = copy_expr (expr); + expr->e.address.type = type; + return expr; } + if (expr->type == ex_alias) { + if (expr->e.alias.offset) { + return new_offset_alias_expr (type, expr, 0); + } + expr = expr->e.alias.expr; + } + // this can happen when constant folding an offset pointer results in + // a noop due to the offset being 0 and thus casting back to the original + // type + if (type == get_type (expr)) { + return expr; + } + + expr_t *alias = new_expr (); + alias->type = ex_alias; + alias->e.alias.type = type; + alias->e.alias.expr = expr; alias->file = expr->file; alias->line = expr->line; return alias; @@ -1248,23 +1377,80 @@ new_alias_expr (type_t *type, expr_t *expr) expr_t * new_offset_alias_expr (type_t *type, expr_t *expr, int offset) { - expr_t *alias; - - if (expr->type == ex_expr && expr->e.expr.op == 'A') { - expr_t *ofs_expr = expr->e.expr.e2; - expr = expr->e.expr.e1; + if (expr->type == ex_alias && expr->e.alias.offset) { + expr_t *ofs_expr = expr->e.alias.offset; if (!is_constant (ofs_expr)) { internal_error (ofs_expr, "non-constant offset for alias expr"); } - offset += expr_integer (ofs_expr); + offset += expr_int (ofs_expr); + + if (expr->e.alias.expr->type == ex_alias) { + internal_error (expr, "alias expr of alias expr"); + } + expr = expr->e.alias.expr; } - alias = new_binary_expr ('A', expr, new_integer_expr (offset)); - alias->e.expr.type = type; + + expr_t *alias = new_expr (); + alias->type = ex_alias; + alias->e.alias.type = type; + alias->e.alias.expr = expr; + alias->e.alias.offset = new_int_expr (offset); alias->file = expr->file; alias->line = expr->line; return alias; } +expr_t * +new_address_expr (type_t *lvtype, expr_t *lvalue, expr_t *offset) +{ + expr_t *addr = new_expr (); + addr->type = ex_address; + addr->e.address.type = pointer_type (lvtype); + addr->e.address.lvalue = lvalue; + addr->e.address.offset = offset; + return addr; +} + +expr_t * +new_assign_expr (expr_t *dst, expr_t *src) +{ + expr_t *addr = new_expr (); + addr->type = ex_assign; + addr->e.assign.dst = dst; + addr->e.assign.src = src; + return addr; +} + +expr_t * +new_return_expr (expr_t *ret_val) +{ + expr_t *retrn = new_expr (); + retrn->type = ex_return; + retrn->e.retrn.ret_val = ret_val; + return retrn; +} + +expr_t * +new_adjstk_expr (int mode, int offset) +{ + expr_t *adj = new_expr (); + adj->type = ex_adjstk; + adj->e.adjstk.mode = mode; + adj->e.adjstk.offset = offset; + return adj; +} + +expr_t * +new_with_expr (int mode, int reg, expr_t *val) +{ + expr_t *with = new_expr (); + with->type = ex_with; + with->e.with.mode = mode; + with->e.with.reg = reg; + with->e.with.with = val; + return with; +} + static expr_t * param_expr (const char *name, type_t *type) { @@ -1290,33 +1476,6 @@ new_param_expr (type_t *type, int num) return param_expr (va (0, ".param_%d", num), type); } -expr_t * -new_move_expr (expr_t *e1, expr_t *e2, type_t *type, int indirect) -{ - expr_t *e = new_binary_expr (indirect ? 'M' : 'm', e1, e2); - e->e.expr.type = type; - return e; -} - -expr_t * -new_memset_expr (expr_t *dst, expr_t *val, type_t *type) -{ - expr_t *e; - if (!is_pointer (get_type (dst))) { - return error (dst, "incorrect destination type for memset"); - } - if (!is_scalar (get_type (val))) { - return error (val, "memset value must be a scalar"); - } - e = new_expr (); - e->type = ex_memset; - e->e.memset.dst = dst; - e->e.memset.val = val; - e->e.memset.count = new_integer_expr (type_size (type)); - e->e.memset.type = type; - return e; -} - expr_t * append_expr (expr_t *block, expr_t *e) { @@ -1335,6 +1494,28 @@ append_expr (expr_t *block, expr_t *e) return block; } +expr_t * +prepend_expr (expr_t *block, expr_t *e) +{ + if (block->type != ex_block) + internal_error (block, "not a block expression"); + + if (!e || e->type == ex_error) + return block; + + if (e->next) + internal_error (e, "append_expr: expr loop detected"); + + e->next = block->e.block.head; + block->e.block.head = e; + + if (block->e.block.tail == &block->e.block.head) { + block->e.block.tail = &e->next; + } + + return block; +} + static symbol_t * get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) { @@ -1363,7 +1544,7 @@ field_expr (expr_t *e1, expr_t *e2) t1 = get_type (e1); if (e1->type == ex_error) return e1; - if (t1->type == ev_entity) { + if (is_entity (t1)) { symbol_t *field = 0; if (e2->type == ex_symbol) @@ -1383,7 +1564,7 @@ field_expr (expr_t *e1, expr_t *e2) return e; } } - } else if (t1->type == ev_pointer) { + } else if (is_ptr (t1)) { if (is_struct (t1->t.fldptr.type)) { symbol_t *field; @@ -1391,11 +1572,10 @@ field_expr (expr_t *e1, expr_t *e2) if (!field) return e1; - e2->type = ex_value; - e2->e.value = new_short_val (field->s.offset); - e = new_binary_expr ('&', e1, e2); - e->e.expr.type = pointer_type (field->type); - return unary_expr ('.', e); + expr_t *offset = new_short_expr (field->s.offset); + e1 = offset_pointer_expr (e1, offset); + e1 = cast_expr (pointer_type (field->type), e1); + return unary_expr ('.', e1); } else if (is_class (t1->t.fldptr.type)) { class_t *class = t1->t.fldptr.type->t.class; symbol_t *sym = e2->e.symbol;//FIXME need to check @@ -1405,14 +1585,12 @@ field_expr (expr_t *e1, expr_t *e2) ivar = class_find_ivar (class, protected, sym->name); if (!ivar) return new_error_expr (); - e2->type = ex_value; - e2->e.value = new_short_val (ivar->s.offset); - e = new_binary_expr ('&', e1, e2); - e->e.expr.type = pointer_type (ivar->type); - return unary_expr ('.', e); + expr_t *offset = new_short_expr (ivar->s.offset); + e1 = offset_pointer_expr (e1, offset); + e1 = cast_expr (pointer_type (ivar->type), e1); + return unary_expr ('.', e1); } - } else if (t1->type == ev_vector || t1->type == ev_quat - || is_struct (t1)) { + } else if (is_vector (t1) || is_quaternion (t1) || is_struct (t1)) { symbol_t *field; field = get_struct_field (t1, e1, e2); @@ -1444,10 +1622,10 @@ field_expr (expr_t *e1, expr_t *e2) return field_expr (e1, e2); } else { if (e1->type == ex_uexpr && e1->e.expr.op == '.') { - e2->type = ex_value; - e2->e.value = new_short_val (field->s.offset); - e = address_expr (e1, e2, field->type); - return unary_expr ('.', e); + expr_t *offset = new_short_expr (field->s.offset); + e1 = offset_pointer_expr (e1->e.expr.e1, offset); + e1 = cast_expr (pointer_type (field->type), e1); + return unary_expr ('.', e1); } else { return new_offset_alias_expr (field->type, e1, field->s.offset); } @@ -1470,14 +1648,14 @@ convert_from_bool (expr_t *e, type_t *type) if (is_float (type)) { one = new_float_expr (1); zero = new_float_expr (0); - } else if (is_integer (type)) { - one = new_integer_expr (1); - zero = new_integer_expr (0); + } else if (is_int (type)) { + one = new_int_expr (1); + zero = new_int_expr (0); } else if (is_enum (type) && enum_as_bool (type, &zero, &one)) { // don't need to do anything - } else if (is_uinteger (type)) { - one = new_uinteger_expr (1); - zero = new_uinteger_expr (0); + } else if (is_uint (type)) { + one = new_uint_expr (1); + zero = new_uint_expr (0); } else { return error (e, "can't convert from bool value"); } @@ -1494,7 +1672,7 @@ convert_from_bool (expr_t *e, type_t *type) void convert_int (expr_t *e) { - float float_val = expr_integer (e); + float float_val = expr_int (e); e->type = ex_value; e->e.value = new_float_val (float_val); } @@ -1510,9 +1688,9 @@ convert_short (expr_t *e) void convert_short_int (expr_t *e) { - float integer_val = expr_short (e); + float int_val = expr_short (e); e->type = ex_value; - e->e.value = new_integer_val (integer_val); + e->e.value = new_int_val (int_val); } void @@ -1569,16 +1747,60 @@ has_function_call (expr_t *e) return 1; return 0; case ex_expr: - if (e->e.expr.op == 'c') - return 1; return (has_function_call (e->e.expr.e1) || has_function_call (e->e.expr.e2)); case ex_uexpr: - if (e->e.expr.op != 'g') - return has_function_call (e->e.expr.e1); - default: + return has_function_call (e->e.expr.e1); + case ex_alias: + return has_function_call (e->e.alias.expr); + case ex_address: + return has_function_call (e->e.address.lvalue); + case ex_assign: + return (has_function_call (e->e.assign.dst) + || has_function_call (e->e.assign.src)); + case ex_branch: + if (e->e.branch.type == pr_branch_call) { + return 1; + } + if (e->e.branch.type == pr_branch_jump) { + return 0; + } + return has_function_call (e->e.branch.test); + case ex_return: + return has_function_call (e->e.retrn.ret_val); + case ex_horizontal: + return has_function_call (e->e.hop.vec); + case ex_error: + case ex_state: + case ex_label: + case ex_labelref: + case ex_def: + case ex_symbol: + case ex_temp: + case ex_vector: + case ex_selector: + case ex_nil: + case ex_value: + case ex_compound: + case ex_memset: + case ex_adjstk: + case ex_with: + case ex_args: return 0; + case ex_count: + break; } + internal_error (e, "invalid expression type"); +} + +int +is_function_call (expr_t *e) +{ + if (e->type != ex_block || !e->e.block.is_call) { + return 0; + } + e = e->e.block.result; + return e->type == ex_branch && e->e.branch.type == pr_branch_call; } expr_t * @@ -1619,7 +1841,7 @@ unary_expr (int op, expr_t *e) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: internal_error (e, "type check failed!"); case ev_double: new = new_double_expr (-expr_double (e)); @@ -1630,13 +1852,17 @@ unary_expr (int op, expr_t *e) case ev_vector: VectorNegate (expr_vector (e), v); return new_vector_expr (v); - case ev_quat: + case ev_quaternion: QuatNegate (expr_vector (e), q); 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_long: + case ev_ulong: + case ev_ushort: + internal_error (e, "long not implemented"); + case ev_int: + return new_int_expr (-expr_int (e)); + case ev_uint: + return new_uint_expr (-expr_uint (e)); case ev_short: return new_short_expr (-expr_short (e)); case ev_invalid: @@ -1655,7 +1881,11 @@ unary_expr (int op, expr_t *e) case ex_compound: case ex_memset: case ex_selector: - internal_error (e, 0); + case ex_return: + case ex_adjstk: + case ex_with: + case ex_args: + internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '-') { return e->e.expr.e1; @@ -1676,10 +1906,15 @@ unary_expr (int op, expr_t *e) n->e.expr.type = get_type (e); return n; } + case ex_branch: + return error (e, "invalid type for unary -"); case ex_expr: case ex_bool: case ex_temp: case ex_vector: + case ex_alias: + case ex_assign: + case ex_horizontal: { expr_t *n = new_unary_expr (op, e); @@ -1701,6 +1936,7 @@ unary_expr (int op, expr_t *e) return n; } case ex_nil: + case ex_address: return error (e, "invalid type for unary -"); case ex_count: internal_error (e, "invalid expression"); @@ -1712,23 +1948,27 @@ unary_expr (int op, expr_t *e) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: internal_error (e, 0); case ev_string: s = expr_string (e); - return new_integer_expr (!s || !s[0]); + return new_int_expr (!s || !s[0]); case ev_double: - return new_integer_expr (!expr_double (e)); + return new_int_expr (!expr_double (e)); case ev_float: - return new_integer_expr (!expr_float (e)); + return new_int_expr (!expr_float (e)); case ev_vector: - return new_integer_expr (!VectorIsZero (expr_vector (e))); - case ev_quat: - 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)); + return new_int_expr (!VectorIsZero (expr_vector (e))); + case ev_quaternion: + return new_int_expr (!QuatIsZero (expr_quaternion (e))); + case ev_long: + case ev_ulong: + case ev_ushort: + internal_error (e, "long not implemented"); + case ev_int: + return new_int_expr (!expr_int (e)); + case ev_uint: + return new_uint_expr (!expr_uint (e)); case ev_short: return new_short_expr (!expr_short (e)); case ev_invalid: @@ -1747,7 +1987,11 @@ unary_expr (int op, expr_t *e) case ex_compound: case ex_memset: case ex_selector: - internal_error (e, 0); + case ex_return: + case ex_adjstk: + case ex_with: + case ex_args: + internal_error (e, "unexpected expression type"); case ex_bool: return new_bool_expr (e->e.bool.false_list, e->e.bool.true_list, e); @@ -1760,15 +2004,22 @@ unary_expr (int op, expr_t *e) case ex_symbol: case ex_temp: case ex_vector: - { + case ex_alias: + case ex_address: + case ex_assign: + case ex_horizontal: + if (options.code.progsversion == PROG_VERSION) { + return binary_expr (EQ, e, new_nil_expr ()); + } else { expr_t *n = new_unary_expr (op, e); if (options.code.progsversion > PROG_ID_VERSION) - n->e.expr.type = &type_integer; + n->e.expr.type = &type_int; else n->e.expr.type = &type_float; return n; } + case ex_branch: case ex_nil: return error (e, "invalid type for unary !"); case ex_count: @@ -1782,25 +2033,29 @@ unary_expr (int op, expr_t *e) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: case ev_vector: case ev_double: return error (e, "invalid type for unary ~"); case ev_float: return new_float_expr (~(int) expr_float (e)); - case ev_quat: + case ev_quaternion: QuatConj (expr_vector (e), q); 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_long: + case ev_ulong: + case ev_ushort: + internal_error (e, "long not implemented"); + case ev_int: + return new_int_expr (~expr_int (e)); + case ev_uint: + return new_uint_expr (~expr_uint (e)); case ev_short: return new_short_expr (~expr_short (e)); case ev_invalid: t = get_type (e); if (t->meta == ty_enum) { - return new_integer_expr (~expr_integer (e)); + return new_int_expr (~expr_int (e)); } break; case ev_type_count: @@ -1818,7 +2073,11 @@ unary_expr (int op, expr_t *e) case ex_compound: case ex_memset: case ex_selector: - internal_error (e, 0); + case ex_return: + case ex_adjstk: + case ex_with: + case ex_args: + internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '~') return e->e.expr.e1; @@ -1827,34 +2086,40 @@ unary_expr (int op, expr_t *e) if (!e->e.block.result) return error (e, "invalid type for unary ~"); goto bitnot_expr; + case ex_branch: + return error (e, "invalid type for unary ~"); case ex_expr: case ex_bool: case ex_def: case ex_symbol: case ex_temp: case ex_vector: + case ex_alias: + case ex_assign: + case ex_horizontal: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { - expr_t *n1 = new_integer_expr (-1); + expr_t *n1 = new_int_expr (-1); return binary_expr ('-', n1, e); } else { expr_t *n = new_unary_expr (op, e); type_t *t = get_type (e); - if (!is_integer(t) && !is_float(t) + if (!is_int(t) && !is_float(t) && !is_quaternion(t)) return error (e, "invalid type for unary ~"); n->e.expr.type = t; return n; } case ex_nil: + case ex_address: return error (e, "invalid type for unary ~"); case ex_count: internal_error (e, "invalid expression"); } break; case '.': - if (extract_type (e) != ev_pointer) + if (extract_type (e) != ev_ptr) return error (e, "invalid type for unary ."); e = new_unary_expr ('.', e); e->e.expr.type = get_type (e->e.expr.e1)->t.fldptr.type; @@ -1872,12 +2137,13 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) { expr_t *e; expr_t *p; - int arg_count = 0, parm_count = 0; + int arg_count = 0, param_count = 0; int i; expr_t *args = 0, **a = &args; - type_t *arg_types[MAX_PARMS]; - expr_t *arg_exprs[MAX_PARMS][2]; + type_t *arg_types[PR_MAX_PARAMS]; + expr_t *arg_exprs[PR_MAX_PARAMS][2]; int arg_expr_count = 0; + int emit_args = 0; expr_t *assign; expr_t *call; expr_t *err = 0; @@ -1888,8 +2154,8 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) arg_count++; } - if (arg_count > MAX_PARMS) { - return error (fexpr, "more than %d parameters", MAX_PARMS); + if (arg_count > PR_MAX_PARAMS) { + return error (fexpr, "more than %d parameters", PR_MAX_PARAMS); } if (ftype->t.func.num_params < -1) { if (-arg_count > ftype->t.func.num_params + 1) { @@ -1898,7 +2164,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (options.warnings.traditional) warning (fexpr, "too few arguments"); } - parm_count = -ftype->t.func.num_params - 1; + param_count = -ftype->t.func.num_params - 1; } else if (ftype->t.func.num_params >= 0) { if (arg_count > ftype->t.func.num_params) { return error (fexpr, "too many arguments"); @@ -1908,13 +2174,17 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (options.warnings.traditional) warning (fexpr, "too few arguments"); } - parm_count = ftype->t.func.num_params; + param_count = ftype->t.func.num_params; } + if (ftype->t.func.num_params < 0) { + emit_args = !ftype->t.func.no_va_list; + } + // params is reversed (a, b, c) -> c, b, a for (i = arg_count - 1, e = params; i >= 0; i--, e = e->next) { type_t *t; if (e->type == ex_compound) { - if (i < parm_count) { + if (i < param_count) { t = ftype->t.func.param_types[i]; } else { return error (e, "cannot pass compound initializer " @@ -1933,7 +2203,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (type_size (t) > type_size (&type_param)) err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); - if (i < parm_count) { + if (i < param_count) { if (e->type == ex_nil) convert_nil (e, t = ftype->t.func.param_types[i]); if (e->type == ex_bool) @@ -1950,7 +2220,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) convert_nil (e, t = type_nil); if (e->type == ex_bool) convert_from_bool (e, get_type (e)); - if (is_integer_val (e) + if (is_int_val (e) && options.code.progsversion == PROG_ID_VERSION) convert_int (e); if (options.code.promote_float) { @@ -1968,8 +2238,8 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) } } } - if (is_integer_val (e) && options.warnings.vararg_integer) - warning (e, "passing integer constant into ... function"); + if (is_int_val (e) && options.warnings.vararg_integer) + warning (e, "passing int constant into ... function"); } arg_types[arg_count - 1 - i] = t; } @@ -1978,7 +2248,13 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) call = expr_file_line (new_block_expr (), fexpr); call->e.block.is_call = 1; + // args is built in reverse order so it matches params for (p = params, i = 0; p; p = p->next, i++) { + if (emit_args && arg_count - i == param_count) { + emit_args = 0; + *a = new_args_expr (); + a = &(*a)->next; + } expr_t *e = p; if (e->type == ex_compound) { e = expr_file_line (initialized_temp_expr (arg_types[i], e), e); @@ -1999,6 +2275,11 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) } a = &(*a)->next; } + if (emit_args) { + emit_args = 0; + *a = new_args_expr (); + a = &(*a)->next; + } for (i = 0; i < arg_expr_count - 1; i++) { assign = assign_expr (arg_exprs[i][1], arg_exprs[i][0]); append_expr (call, expr_file_line (assign, arg_exprs[i][0])); @@ -2009,14 +2290,8 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) e = expr_file_line (e, arg_exprs[arg_expr_count - 1][0]); append_expr (call, e); } - e = expr_file_line (new_binary_expr ('c', fexpr, args), fexpr); - e->e.expr.type = ftype->t.func.type; - append_expr (call, e); - if (!is_void(ftype->t.func.type)) { - call->e.block.result = new_ret_expr (ftype->t.func.type); - } else if (options.traditional) { - call->e.block.result = new_ret_expr (&type_float); - } + e = expr_file_line (call_expr (fexpr, args, ftype->t.func.type), fexpr); + call->e.block.result = e; return call; } @@ -2055,21 +2330,70 @@ function_expr (expr_t *fexpr, expr_t *params) expr_t * branch_expr (int op, expr_t *test, expr_t *label) { - if (label && label->type != ex_label) + // need to translated op due to precedence rules dictating the layout + // of the token ids + static pr_branch_e branch_type [] = { + pr_branch_eq, + pr_branch_ne, + pr_branch_lt, + pr_branch_gt, + pr_branch_le, + pr_branch_ge, + }; + if (op < EQ || op > LE) { + internal_error (label, "invalid op: %d", op); + } + if (label && label->type != ex_label) { internal_error (label, "not a label"); - if (label) + } + if (label) { label->e.label.used++; - return new_binary_expr (op, test, label); + } + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = branch_type[op - EQ]; + branch->e.branch.target = label; + branch->e.branch.test = test; + return branch; } expr_t * goto_expr (expr_t *label) { - if (label && label->type != ex_label) + if (label && label->type != ex_label) { internal_error (label, "not a label"); - if (label) + } + if (label) { label->e.label.used++; - return new_unary_expr ('g', label); + } + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = pr_branch_jump; + branch->e.branch.target = label; + return branch; +} + +expr_t * +jump_table_expr (expr_t *table, expr_t *index) +{ + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = pr_branch_jump; + branch->e.branch.target = table;//FIXME separate? all branch types can + branch->e.branch.index = index; + return branch; +} + +expr_t * +call_expr (expr_t *func, expr_t *args, type_t *ret_type) +{ + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = pr_branch_call; + branch->e.branch.target = func; + branch->e.branch.args = args; + branch->e.branch.ret_type = ret_type; + return branch; } expr_t * @@ -2093,7 +2417,7 @@ return_expr (function_t *f, expr_t *e) } // the traditional check above may have set e if (!e) { - return new_unary_expr ('r', 0); + return new_return_expr (0); } } @@ -2115,7 +2439,7 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_bool) { e = convert_from_bool (e, (type_t *) ret_type); //FIXME cast } - if (is_float(ret_type) && is_integer_val (e)) { + if (is_float(ret_type) && is_int_val (e)) { convert_int (e); t = &type_float; } @@ -2150,7 +2474,31 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_block) { e->e.block.result->rvalue = 1; } - return new_unary_expr ('r', e); + return new_return_expr (e); +} + +expr_t * +at_return_expr (function_t *f, expr_t *e) +{ + const type_t *ret_type = unalias_type (f->type->t.func.type); + + if (!is_void(ret_type)) { + return error (e, "use of @return in non-void function"); + } + if (is_nil (e)) { + // int or pointer 0 seems reasonable + return new_return_expr (new_int_expr (0)); + } else if (!is_function_call (e)) { + return error (e, "@return value not a function"); + } + expr_t *call_expr = e->e.block.result->e.branch.target; + const type_t *call_type = get_type (call_expr); + if (!is_func (call_type) && !call_type->t.func.void_return) { + return error (e, "@return function not void_return"); + } + expr_t *ret_expr = new_return_expr (e); + ret_expr->e.retrn.at_return = 1; + return ret_expr; } expr_t * @@ -2202,7 +2550,7 @@ incop_expr (int op, expr_t *e, int postop) if (e->type == ex_error) return e; - one = new_integer_expr (1); // integer constants get auto-cast to float + one = new_int_expr (1); // int constants get auto-cast to float if (postop) { expr_t *t1, *t2; type_t *type = get_type (e); @@ -2217,7 +2565,7 @@ incop_expr (int op, expr_t *e, int postop) append_expr (block, assign_expr (t2, binary_expr (op, t1, one))); res = copy_expr (e); if (res->type == ex_uexpr && res->e.expr.op == '.') - res = pointer_expr (address_expr (res, 0, 0)); + res = deref_pointer_expr (address_expr (res, 0)); append_expr (block, assign_expr (res, t2)); block->e.block.result = t1; return block; @@ -2231,9 +2579,11 @@ array_expr (expr_t *array, expr_t *index) { type_t *array_type = get_type (array); type_t *index_type = get_type (index); + type_t *ele_type; expr_t *scale; expr_t *offset; expr_t *base; + expr_t *ptr; expr_t *e; int ind = 0; @@ -2242,59 +2592,106 @@ array_expr (expr_t *array, expr_t *index) if (index->type == ex_error) return index; - if (array_type->type != ev_pointer && !is_array (array_type)) + if (!is_ptr (array_type) && !is_array (array_type) + && !is_nonscalar (array_type)) return error (array, "not an array"); if (!is_integral (index_type)) return error (index, "invalid array index type"); if (is_short_val (index)) ind = expr_short (index); - if (is_integer_val (index)) - ind = expr_integer (index); - if (array_type->t.func.num_params + if (is_int_val (index)) + ind = expr_int (index); + if (is_array (array_type) + && array_type->t.array.size && is_constant (index) && (ind < array_type->t.array.base - || ind - array_type->t.array.base >= array_type->t.array.size)) - return error (index, "array index out of bounds"); - scale = new_integer_expr (type_size (array_type->t.array.type)); + || ind - array_type->t.array.base >= array_type->t.array.size)) { + return error (index, "array index out of bounds"); + } + if (is_nonscalar (array_type) + && is_constant (index) + && (ind < 0 || ind >= array_type->width)) { + return error (index, "array index out of bounds"); + } + if (is_array (array_type)) { + ele_type = array_type->t.array.type; + base = new_int_expr (array_type->t.array.base); + } else if (is_ptr (array_type)) { + ele_type = array_type->t.fldptr.type; + base = new_int_expr (0); + } else { + ele_type = ev_types[array_type->type]; + base = new_int_expr (0); + } + scale = new_int_expr (type_size (ele_type)); index = binary_expr ('*', index, scale); - base = new_integer_expr (array_type->t.array.base); offset = binary_expr ('*', base, scale); index = binary_expr ('-', index, offset); if (is_short_val (index)) ind = expr_short (index); - if (is_integer_val (index)) - ind = expr_integer (index); - if ((is_constant (index) && ind < 32768 && ind >= -32768)) - index = new_short_expr (ind); + if (is_int_val (index)) + ind = expr_int (index); if (is_array (array_type)) { - e = address_expr (array, index, array_type->t.array.type); - } else { - if (!is_short_val (index) || expr_short (index)) { - e = new_binary_expr ('&', array, index); - //e->e.expr.type = array_type->aux_type; - e->e.expr.type = array_type; + if (array->type == ex_uexpr && array->e.expr.op == '.') { + ptr = array->e.expr.e1; } else { - e = array; + expr_t *alias = new_offset_alias_expr (ele_type, array, 0); + ptr = new_address_expr (ele_type, alias, 0); } + } else if (is_nonscalar (array_type)) { + expr_t *alias = new_offset_alias_expr (ele_type, array, 0); + ptr = new_address_expr (ele_type, alias, 0); + } else { + ptr = array; } - e = unary_expr ('.', e); + ptr = offset_pointer_expr (ptr, index); + ptr = cast_expr (pointer_type (ele_type), ptr); + + e = unary_expr ('.', ptr); return e; } expr_t * -pointer_expr (expr_t *pointer) +deref_pointer_expr (expr_t *pointer) { type_t *pointer_type = get_type (pointer); if (pointer->type == ex_error) return pointer; - if (pointer_type->type != ev_pointer) + if (pointer_type->type != ev_ptr) return error (pointer, "not a pointer"); - return array_expr (pointer, new_integer_expr (0)); + return unary_expr ('.', pointer); } expr_t * -address_expr (expr_t *e1, expr_t *e2, type_t *t) +offset_pointer_expr (expr_t *pointer, expr_t *offset) +{ + type_t *ptr_type = get_type (pointer); + if (!is_ptr (ptr_type)) { + internal_error (pointer, "not a pointer"); + } + if (!is_integral (get_type (offset))) { + internal_error (offset, "pointer offset is not an integer type"); + } + expr_t *ptr; + if (pointer->type == ex_alias && !pointer->e.alias.offset + && is_integral (get_type (pointer->e.alias.expr))) { + ptr = pointer->e.alias.expr; + } else if (pointer->type == ex_address && is_constant (offset)) { + if (pointer->e.address.offset) { + offset = binary_expr ('+', pointer->e.address.offset, offset); + } + pointer->e.address.offset = offset; + return pointer; + } else { + ptr = cast_expr (&type_int, pointer); + } + ptr = binary_expr ('+', ptr, offset); + return cast_expr (ptr_type, ptr); +} + +expr_t * +address_expr (expr_t *e1, type_t *t) { expr_t *e; @@ -2310,6 +2707,12 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) def_t *def = e1->e.def; type_t *type = def->type; + //FIXME this test should be in statements.c + if (options.code.progsversion == PROG_VERSION + && (def->local || def->param)) { + e = new_address_expr (t, e1, 0); + return e; + } if (is_array (type)) { e = e1; e->type = ex_value; @@ -2326,6 +2729,13 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) def_t *def = e1->e.symbol->s.def; type_t *type = def->type; + //FIXME this test should be in statements.c + if (options.code.progsversion == PROG_VERSION + && (def->local || def->param)) { + e = new_address_expr (t, e1, 0); + return e; + } + if (is_array (type)) { e = e1; e->type = ex_value; @@ -2340,77 +2750,33 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) return error (e1, "invalid type for unary &"); case ex_expr: if (e1->e.expr.op == '.') { - e = e1; - e->e.expr.op = '&'; - e->e.expr.type = pointer_type (e->e.expr.type); + e = new_address_expr (e1->e.expr.type, + e1->e.expr.e1, e1->e.expr.e2); break; } - if (e1->e.expr.op == 'm') { - // direct move, so obtain the address of the source - e = address_expr (e1->e.expr.e2, 0, t); - break; - } - if (e1->e.expr.op == 'M') { - // indirect move, so we already have the address of the source - e = e1->e.expr.e2; - break; - } - if (e1->e.expr.op == 'A') { - if (!t) - t = e1->e.expr.type; - if (e2) { - e2 = binary_expr ('+', e1->e.expr.e2, e2); - } else { - e2 = e1->e.expr.e2; - } - return address_expr (e1->e.expr.e1, e2, t); - } return error (e1, "invalid type for unary &"); case ex_uexpr: if (e1->e.expr.op == '.') { e = e1->e.expr.e1; if (e->type == ex_expr && e->e.expr.op == '.') { - e->e.expr.type = pointer_type (e->e.expr.type); - e->e.expr.op = '&'; + e = new_address_expr (e->e.expr.type, e->e.expr.e1, e->e.expr.e2); } break; } - if (e1->e.expr.op == 'A') { - if (!t) - t = e1->e.expr.type; - return address_expr (e1->e.expr.e1, e2, t); - } return error (e1, "invalid type for unary &"); case ex_label: return new_label_ref (&e1->e.label); case ex_temp: - e = new_unary_expr ('&', e1); - e->e.expr.type = pointer_type (t); + e = new_address_expr (t, e1, 0); break; + case ex_alias: + if (!t) { + t = e1->e.alias.type; + } + return new_address_expr (t, e1, 0); default: return error (e1, "invalid type for unary &"); } - if (e2) { - if (e2->type == ex_error) - return e2; - if (is_pointer_val (e) && is_integral_val (e2)) { - int base = e->e.value->v.pointer.val; - int offset = expr_integral (e2); - def_t *def = e->e.value->v.pointer.def; - e->e.value = new_pointer_val (base + offset, t, def, 0); - } else { - if (!is_short_val (e2) || expr_short (e2)) { - if (e->type == ex_expr && e->e.expr.op == '&') { - e = new_binary_expr ('&', e->e.expr.e1, - binary_expr ('+', e->e.expr.e2, e2)); - } else { - e = new_binary_expr ('&', e, e2); - } - } - if (e->type == ex_expr || e->type == ex_uexpr) - e->e.expr.type = pointer_type (t); - } - } return e; } @@ -2418,7 +2784,7 @@ expr_t * build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) { int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *if_expr; expr_t *tl = new_label_expr (); expr_t *fl = new_label_expr (); @@ -2477,7 +2843,7 @@ build_while_statement (int not, expr_t *test, expr_t *statement, expr_t *break_label, expr_t *continue_label) { int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *l1 = new_label_expr (); expr_t *l2 = break_label; expr_t *while_expr; @@ -2517,7 +2883,7 @@ build_do_while_statement (expr_t *statement, int not, expr_t *test, { expr_t *l1 = new_label_expr (); int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *do_while_expr; if (!statement) { @@ -2563,7 +2929,7 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t *l1 = 0; expr_t *t; int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *for_expr; if (next) @@ -2621,7 +2987,7 @@ build_state_expr (expr_t *e) step = think->next; if (think->type == ex_symbol) think = think_expr (think->e.symbol); - if (is_integer_val (frame)) + if (is_int_val (frame)) convert_int (frame); if (!type_assignable (&type_float, get_type (frame))) return error (frame, "invalid type for frame number"); @@ -2630,7 +2996,7 @@ build_state_expr (expr_t *e) if (step) { if (step->next) return error (step->next, "too many state arguments"); - if (is_integer_val (step)) + if (is_int_val (step)) convert_int (step); if (!type_assignable (&type_float, get_type (step))) return error (step, "invalid type for step"); @@ -2652,7 +3018,7 @@ think_expr (symbol_t *think_sym) && sym->type->t.fldptr.type->type == ev_func) { think_sym->type = sym->type->t.fldptr.type; } else { - think_sym->type = &type_function; + think_sym->type = &type_func; } think_sym = function_symbol (think_sym, 0, 1); make_function (think_sym, 0, current_symtab->space, current_storage); @@ -2679,21 +3045,20 @@ cast_expr (type_t *dstType, expr_t *e) if ((dstType == type_default && is_enum (srcType)) || (is_enum (dstType) && srcType == type_default)) return e; - if ((is_pointer (dstType) && is_string (srcType)) - || (is_string (dstType) && is_pointer (srcType))) { + if ((is_ptr (dstType) && is_string (srcType)) + || (is_string (dstType) && is_ptr (srcType))) { c = new_alias_expr (dstType, e); return c; } - if (!(is_pointer (dstType) - && (is_pointer (srcType) || is_integral (srcType) - || is_array (srcType))) - && !(is_integral (dstType) && is_pointer (srcType)) + if (!(is_ptr (dstType) && (is_ptr (srcType) || is_integral (srcType) + || is_array (srcType))) + && !(is_integral (dstType) && is_ptr (srcType)) && !(is_func (dstType) && is_func (srcType)) && !(is_scalar (dstType) && is_scalar (srcType))) { return cast_error (e, srcType, dstType); } if (is_array (srcType)) { - return address_expr (e, 0, dstType->t.fldptr.type); + return address_expr (e, dstType->t.fldptr.type); } if (is_constant (e) && is_scalar (dstType) && is_scalar (srcType)) { ex_value_t *val = 0; @@ -2710,7 +3075,7 @@ cast_expr (type_t *dstType, expr_t *e) } else if (is_double (def->type)) { val = new_double_val (D_DOUBLE (def)); } else if (is_integral (def->type)) { - val = new_integer_val (D_INT (def)); + val = new_int_val (D_INT (def)); } } else if (e->type == ex_value) { val = e->e.value; @@ -2756,7 +3121,9 @@ sizeof_expr (expr_t *expr, struct type_s *type) internal_error (0, 0); if (!type) type = get_type (expr); - expr = new_integer_expr (type_size (type)); + if (type) { + expr = new_int_expr (type_size (type)); + } return expr; } diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 7126b5545..e193de6aa 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -112,18 +112,19 @@ is_lvalue (const expr_t *expr) if (expr->e.expr.op == '.') { return 1; } - if (expr->e.expr.op == 'A') { - return is_lvalue (expr->e.expr.e1); - } break; + case ex_alias: + return is_lvalue (expr->e.alias.expr); + case ex_address: + return 0; + case ex_assign: + return 0; case ex_uexpr: if (expr->e.expr.op == '.') { return 1; } - if (expr->e.expr.op == 'A') { - return is_lvalue (expr->e.expr.e1); - } break; + case ex_branch: case ex_memset: case ex_compound: case ex_state: @@ -136,6 +137,11 @@ is_lvalue (const expr_t *expr) case ex_value: case ex_error: case ex_selector: + case ex_return: + case ex_adjstk: + case ex_with: + case ex_args: + case ex_horizontal: break; case ex_count: internal_error (expr, "invalid expression"); @@ -285,7 +291,6 @@ is_memset (expr_t *e) expr_t * assign_expr (expr_t *dst, expr_t *src) { - int op = '='; expr_t *expr; type_t *dst_type, *src_type; @@ -328,10 +333,10 @@ assign_expr (expr_t *dst, expr_t *src) internal_error (src, "src_type broke in assign_expr"); } - if (is_pointer (dst_type) && is_array (src_type)) { + if (is_ptr (dst_type) && is_array (src_type)) { // assigning an array to a pointer is the same as taking the address of // the array but using the type of the array elements - src = address_expr (src, 0, src_type->t.fldptr.type); + src = address_expr (src, src_type->t.fldptr.type); src_type = get_type (src); } if (src->type == ex_bool) { @@ -357,7 +362,6 @@ assign_expr (expr_t *dst, expr_t *src) convert_nil (src, dst_type); } - expr = new_binary_expr (op, dst, src); - expr->e.expr.type = dst_type; + expr = new_assign_expr (dst, src); return expr; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 616dc7ac4..832abdc09 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -40,7 +40,7 @@ typedef struct { int op; - type_t *type; + type_t *result_type; type_t *a_cast; type_t *b_cast; expr_t *(*process)(int op, expr_t *e1, expr_t *e2); @@ -48,17 +48,22 @@ typedef struct { static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2); static expr_t *pointer_compare (int op, expr_t *e1, expr_t *e2); +static expr_t *func_compare (int op, expr_t *e1, expr_t *e2); static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); +static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2); +static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2); +static expr_t *vector_scale (int op, expr_t *e1, expr_t *e2); +static expr_t *entity_compare (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; @@ -74,19 +79,19 @@ static expr_type_t float_float[] = { {MOD, &type_float}, {SHL, &type_float}, {SHR, &type_float}, - {AND, &type_integer}, - {OR, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {AND, &type_int}, + {OR, &type_int}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; static expr_type_t float_vector[] = { - {'*', &type_vector}, + {'*', .process = vector_scale }, {0, 0} }; @@ -95,7 +100,7 @@ static expr_type_t float_quat[] = { {0, 0} }; -static expr_type_t float_integer[] = { +static expr_type_t float_int[] = { {'+', &type_float, 0, &type_float}, {'-', &type_float, 0, &type_float}, {'*', &type_float, 0, &type_float}, @@ -107,16 +112,16 @@ static expr_type_t float_integer[] = { {MOD, &type_float, 0, &type_float}, {SHL, &type_float, 0, &type_float}, {SHR, &type_float, 0, &type_float}, - {EQ, &type_integer, 0, &type_float}, - {NE, &type_integer, 0, &type_float}, - {LE, &type_integer, 0, &type_float}, - {GE, &type_integer, 0, &type_float}, - {LT, &type_integer, 0, &type_float}, - {GT, &type_integer, 0, &type_float}, + {EQ, &type_int, 0, &type_float}, + {NE, &type_int, 0, &type_float}, + {LE, &type_int, 0, &type_float}, + {GE, &type_int, 0, &type_float}, + {LT, &type_int, 0, &type_float}, + {GT, &type_int, 0, &type_float}, {0, 0} }; -#define float_uinteger float_integer -#define float_short float_integer +#define float_uint float_int +#define float_short float_int static expr_type_t float_double[] = { {'+', &type_double, &type_double, 0}, @@ -135,7 +140,7 @@ static expr_type_t float_double[] = { }; static expr_type_t vector_float[] = { - {'*', &type_vector}, + {'*', .process = vector_scale }, {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; @@ -143,37 +148,39 @@ static expr_type_t vector_float[] = { static expr_type_t vector_vector[] = { {'+', &type_vector}, {'-', &type_vector}, - {'*', &type_float}, - {EQ, &type_integer}, - {NE, &type_integer}, + {DOT, &type_vector}, + {CROSS, &type_vector}, + {'*', 0, 0, 0, vector_multiply}, + {EQ, 0, 0, 0, vector_compare}, + {NE, 0, 0, 0, vector_compare}, {0, 0} }; -#define vector_integer vector_float -#define vector_uinteger vector_float +#define vector_int vector_float +#define vector_uint vector_float #define vector_short vector_float static expr_type_t vector_double[] = { - {'*', &type_vector}, + {'*', &type_vector, 0, &type_float, vector_scale}, {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; static expr_type_t entity_entity[] = { - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int, 0, 0, entity_compare}, + {NE, &type_int, 0, 0, entity_compare}, {0, 0} }; static expr_type_t field_field[] = { - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, {0, 0} }; static expr_type_t func_func[] = { - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, 0, 0, 0, func_compare}, + {NE, 0, 0, 0, func_compare}, {0, 0} }; @@ -188,13 +195,13 @@ static expr_type_t pointer_pointer[] = { {0, 0} }; -static expr_type_t pointer_integer[] = { +static expr_type_t pointer_int[] = { {'+', 0, 0, 0, pointer_arithmetic}, {'-', 0, 0, 0, pointer_arithmetic}, {0, 0} }; -#define pointer_uinteger pointer_integer -#define pointer_short pointer_integer +#define pointer_uint pointer_int +#define pointer_short pointer_int static expr_type_t quat_float[] = { {'*', &type_quaternion}, @@ -211,18 +218,18 @@ static expr_type_t quat_quat[] = { {'+', &type_quaternion}, {'-', &type_quaternion}, {'*', &type_quaternion}, - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, {0, 0} }; -static expr_type_t quat_integer[] = { +static expr_type_t quat_int[] = { {'*', &type_quaternion, 0, &type_float}, {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; -#define quat_uinteger quat_integer -#define quat_short quat_integer +#define quat_uint quat_int +#define quat_short quat_int static expr_type_t quat_double[] = { {'*', &type_quaternion}, @@ -230,7 +237,7 @@ static expr_type_t quat_double[] = { {0, 0} }; -static expr_type_t integer_float[] = { +static expr_type_t int_float[] = { {'+', &type_float, &type_float, 0}, {'-', &type_float, &type_float, 0}, {'*', &type_float, &type_float, 0}, @@ -240,206 +247,206 @@ static expr_type_t integer_float[] = { {'^', &type_float, &type_float, 0}, {'%', &type_float, &type_float, 0}, {MOD, &type_float, &type_float, 0}, - {SHL, &type_integer, 0, &type_integer}, //FIXME? - {SHR, &type_integer, 0, &type_integer}, //FIXME? - {EQ, &type_integer, &type_float, 0}, - {NE, &type_integer, &type_float, 0}, - {LE, &type_integer, &type_float, 0}, - {GE, &type_integer, &type_float, 0}, - {LT, &type_integer, &type_float, 0}, - {GT, &type_integer, &type_float, 0}, + {SHL, &type_int, 0, &type_int}, //FIXME? + {SHR, &type_int, 0, &type_int}, //FIXME? + {EQ, &type_int, &type_float, 0}, + {NE, &type_int, &type_float, 0}, + {LE, &type_int, &type_float, 0}, + {GE, &type_int, &type_float, 0}, + {LT, &type_int, &type_float, 0}, + {GT, &type_int, &type_float, 0}, {0, 0} }; -static expr_type_t integer_vector[] = { - {'*', &type_vector, &type_float, 0}, +static expr_type_t int_vector[] = { + {'*', &type_vector, &type_float, 0, vector_scale}, {0, 0} }; -static expr_type_t integer_pointer[] = { +static expr_type_t int_pointer[] = { {'+', 0, 0, 0, pointer_arithmetic}, {0, 0} }; -static expr_type_t integer_quat[] = { +static expr_type_t int_quat[] = { {'*', &type_quaternion, &type_float, 0}, {0, 0} }; -static expr_type_t integer_integer[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, - {MOD, &type_integer}, - {SHL, &type_integer}, - {SHR, &type_integer}, - {AND, &type_integer}, - {OR, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t int_int[] = { + {'+', &type_int}, + {'-', &type_int}, + {'*', &type_int}, + {'/', &type_int}, + {'&', &type_int}, + {'|', &type_int}, + {'^', &type_int}, + {'%', &type_int}, + {MOD, &type_int}, + {SHL, &type_int}, + {SHR, &type_int}, + {AND, &type_int}, + {OR, &type_int}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -static expr_type_t integer_uinteger[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, - {MOD, &type_integer}, - {SHL, &type_integer}, - {SHR, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t int_uint[] = { + {'+', &type_int, 0, &type_int}, + {'-', &type_int, 0, &type_int}, + {'*', &type_int, 0, &type_int}, + {'/', &type_int, 0, &type_int}, + {'&', &type_int, 0, &type_int}, + {'|', &type_int, 0, &type_int}, + {'^', &type_int, 0, &type_int}, + {'%', &type_int, 0, &type_int}, + {MOD, &type_int, 0, &type_int}, + {SHL, &type_int, 0, &type_int}, + {SHR, &type_int, 0, &type_int}, + {EQ, &type_int, 0, &type_int}, + {NE, &type_int, 0, &type_int}, + {LE, &type_int, 0, &type_int}, + {GE, &type_int, 0, &type_int}, + {LT, &type_int, 0, &type_int}, + {GT, &type_int, 0, &type_int}, {0, 0} }; -static expr_type_t integer_short[] = { - {'+', &type_integer, 0, &type_integer}, - {'-', &type_integer, 0, &type_integer}, - {'*', &type_integer, 0, &type_integer}, - {'/', &type_integer, 0, &type_integer}, - {'&', &type_integer, 0, &type_integer}, - {'|', &type_integer, 0, &type_integer}, - {'^', &type_integer, 0, &type_integer}, - {'%', &type_integer, 0, &type_integer}, - {MOD, &type_integer, 0, &type_integer}, - {SHL, &type_integer, 0, &type_integer}, - {SHR, &type_integer, 0, &type_integer}, - {EQ, &type_integer, 0, &type_integer}, - {NE, &type_integer, 0, &type_integer}, - {LE, &type_integer, 0, &type_integer}, - {GE, &type_integer, 0, &type_integer}, - {LT, &type_integer, 0, &type_integer}, - {GT, &type_integer, 0, &type_integer}, +static expr_type_t int_short[] = { + {'+', &type_int, 0, &type_int}, + {'-', &type_int, 0, &type_int}, + {'*', &type_int, 0, &type_int}, + {'/', &type_int, 0, &type_int}, + {'&', &type_int, 0, &type_int}, + {'|', &type_int, 0, &type_int}, + {'^', &type_int, 0, &type_int}, + {'%', &type_int, 0, &type_int}, + {MOD, &type_int, 0, &type_int}, + {SHL, &type_int, 0, &type_int}, + {SHR, &type_int, 0, &type_int}, + {EQ, &type_int, 0, &type_int}, + {NE, &type_int, 0, &type_int}, + {LE, &type_int, 0, &type_int}, + {GE, &type_int, 0, &type_int}, + {LT, &type_int, 0, &type_int}, + {GT, &type_int, 0, &type_int}, {0, 0} }; -static expr_type_t integer_double[] = { +static expr_type_t int_double[] = { {'+', &type_double, &type_double, 0}, {'-', &type_double, &type_double, 0}, {'*', &type_double, &type_double, 0}, {'/', &type_double, &type_double, 0}, {'%', &type_double, &type_double, 0}, {MOD, &type_double, &type_double, 0}, - {EQ, &type_integer, &type_double, 0}, - {NE, &type_integer, &type_double, 0}, - {LE, &type_integer, &type_double, 0}, - {GE, &type_integer, &type_double, 0}, - {LT, &type_integer, &type_double, 0}, - {GT, &type_integer, &type_double, 0}, + {EQ, &type_int, &type_double, 0}, + {NE, &type_int, &type_double, 0}, + {LE, &type_int, &type_double, 0}, + {GE, &type_int, &type_double, 0}, + {LT, &type_int, &type_double, 0}, + {GT, &type_int, &type_double, 0}, {0, 0} }; -#define uinteger_float integer_float -#define uinteger_vector integer_vector -#define uinteger_pointer integer_pointer -#define uinteger_quat integer_quat +#define uint_float int_float +#define uint_vector int_vector +#define uint_pointer int_pointer +#define uint_quat int_quat -static expr_type_t uinteger_integer[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, - {MOD, &type_integer}, - {SHL, &type_uinteger}, - {SHR, &type_uinteger}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t uint_int[] = { + {'+', &type_int, &type_int, &type_int }, + {'-', &type_int, &type_int, &type_int }, + {'*', &type_int, &type_int, &type_int }, + {'/', &type_int, &type_int, &type_int }, + {'&', &type_int, &type_int, &type_int }, + {'|', &type_int, &type_int, &type_int }, + {'^', &type_int, &type_int, &type_int }, + {'%', &type_int, &type_int, &type_int }, + {MOD, &type_int, &type_int, &type_int }, + {SHL, &type_uint, &type_int, &type_int }, + {SHR, &type_uint, 0, &type_int }, + {EQ, &type_int, &type_int, &type_int }, + {NE, &type_int, &type_int, &type_int }, + {LE, &type_int, &type_int, &type_int }, + {GE, &type_int, &type_int, &type_int }, + {LT, &type_int, &type_int, &type_int }, + {GT, &type_int, &type_int, &type_int }, {0, 0} }; -static expr_type_t uinteger_uinteger[] = { - {'+', &type_uinteger}, - {'-', &type_uinteger}, - {'*', &type_uinteger}, - {'/', &type_uinteger}, - {'&', &type_uinteger}, - {'|', &type_uinteger}, - {'^', &type_uinteger}, - {'%', &type_uinteger}, - {MOD, &type_uinteger}, - {SHL, &type_uinteger}, - {SHR, &type_uinteger}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t uint_uint[] = { + {'+', &type_uint}, + {'-', &type_uint}, + {'*', &type_uint}, + {'/', &type_uint}, + {'&', &type_uint}, + {'|', &type_uint}, + {'^', &type_uint}, + {'%', &type_uint}, + {MOD, &type_uint}, + {SHL, &type_uint}, + {SHR, &type_uint}, + {EQ, &type_int, &type_int, &type_int}, + {NE, &type_int, &type_int, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -#define uinteger_short uinteger_integer -#define uinteger_double integer_double +#define uint_short uint_int +#define uint_double int_double -#define short_float integer_float -#define short_vector integer_vector -#define short_pointer integer_pointer -#define short_quat integer_quat +#define short_float int_float +#define short_vector int_vector +#define short_pointer int_pointer +#define short_quat int_quat -static expr_type_t short_integer[] = { - {'+', &type_integer, &type_integer, 0}, - {'-', &type_integer, &type_integer, 0}, - {'*', &type_integer, &type_integer, 0}, - {'/', &type_integer, &type_integer, 0}, - {'&', &type_integer, &type_integer, 0}, - {'|', &type_integer, &type_integer, 0}, - {'^', &type_integer, &type_integer, 0}, - {'%', &type_integer, &type_integer, 0}, - {MOD, &type_integer, &type_integer, 0}, +static expr_type_t short_int[] = { + {'+', &type_int, &type_int, 0}, + {'-', &type_int, &type_int, 0}, + {'*', &type_int, &type_int, 0}, + {'/', &type_int, &type_int, 0}, + {'&', &type_int, &type_int, 0}, + {'|', &type_int, &type_int, 0}, + {'^', &type_int, &type_int, 0}, + {'%', &type_int, &type_int, 0}, + {MOD, &type_int, &type_int, 0}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer, &type_integer, 0}, - {NE, &type_integer, &type_integer, 0}, - {LE, &type_integer, &type_integer, 0}, - {GE, &type_integer, &type_integer, 0}, - {LT, &type_integer, &type_integer, 0}, - {GT, &type_integer, &type_integer, 0}, + {EQ, &type_int, &type_int, 0}, + {NE, &type_int, &type_int, 0}, + {LE, &type_int, &type_int, 0}, + {GE, &type_int, &type_int, 0}, + {LT, &type_int, &type_int, 0}, + {GT, &type_int, &type_int, 0}, {0, 0} }; -static expr_type_t short_uinteger[] = { - {'+', &type_uinteger, &type_uinteger, 0}, - {'-', &type_uinteger, &type_uinteger, 0}, - {'*', &type_uinteger, &type_uinteger, 0}, - {'/', &type_uinteger, &type_uinteger, 0}, - {'&', &type_uinteger, &type_uinteger, 0}, - {'|', &type_uinteger, &type_uinteger, 0}, - {'^', &type_uinteger, &type_uinteger, 0}, - {'%', &type_uinteger, &type_uinteger, 0}, - {MOD, &type_uinteger, &type_uinteger, 0}, +static expr_type_t short_uint[] = { + {'+', &type_uint, &type_uint, 0}, + {'-', &type_uint, &type_uint, 0}, + {'*', &type_uint, &type_uint, 0}, + {'/', &type_uint, &type_uint, 0}, + {'&', &type_uint, &type_uint, 0}, + {'|', &type_uint, &type_uint, 0}, + {'^', &type_uint, &type_uint, 0}, + {'%', &type_uint, &type_uint, 0}, + {MOD, &type_uint, &type_uint, 0}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer, &type_uinteger, 0}, - {NE, &type_integer, &type_uinteger, 0}, - {LE, &type_integer, &type_uinteger, 0}, - {GE, &type_integer, &type_uinteger, 0}, - {LT, &type_integer, &type_uinteger, 0}, - {GT, &type_integer, &type_uinteger, 0}, + {EQ, &type_int, &type_uint, 0}, + {NE, &type_int, &type_uint, 0}, + {LE, &type_int, &type_uint, 0}, + {GE, &type_int, &type_uint, 0}, + {LT, &type_int, &type_uint, 0}, + {GT, &type_int, &type_uint, 0}, {0, 0} }; @@ -455,15 +462,15 @@ static expr_type_t short_short[] = { {MOD, &type_short}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -#define short_double integer_double +#define short_double int_double static expr_type_t double_float[] = { {'+', &type_double, 0, &type_double}, @@ -482,7 +489,7 @@ static expr_type_t double_float[] = { }; static expr_type_t double_vector[] = { - {'*', &type_vector}, + {'*', &type_vector, &type_float, 0, vector_scale}, {0, 0} }; @@ -491,7 +498,7 @@ static expr_type_t double_quat[] = { {0, 0} }; -static expr_type_t double_integer[] = { +static expr_type_t double_int[] = { {'+', &type_double, 0, &type_double}, {'-', &type_double, 0, &type_double}, {'*', &type_double, 0, &type_double}, @@ -506,8 +513,8 @@ static expr_type_t double_integer[] = { {GT, 0, 0, 0, double_compare}, {0, 0} }; -#define double_uinteger double_integer -#define double_short double_integer +#define double_uint double_int +#define double_short double_int static expr_type_t double_double[] = { {'+', &type_double}, @@ -516,227 +523,128 @@ static expr_type_t double_double[] = { {'/', &type_double}, {'%', &type_double}, {MOD, &type_double}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; static expr_type_t *string_x[ev_type_count] = { - 0, // ev_void - string_string, - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_pointer - 0, // ev_quat - 0, // ev_integer - 0, // ev_uinteger - 0, // ev_short - 0, // ev_double + [ev_string] = string_string, }; static expr_type_t *float_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - float_float, - float_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_pointer - float_quat, - float_integer, - float_uinteger, - float_short, - float_double, + [ev_float] = float_float, + [ev_vector] = float_vector, + [ev_quaternion] = float_quat, + [ev_int] = float_int, + [ev_uint] = float_uint, + [ev_short] = float_short, + [ev_double] = float_double, }; static expr_type_t *vector_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - vector_float, - vector_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_pointer - 0, // ev_quaternion - vector_integer, - vector_uinteger, - vector_short, - vector_double, + [ev_float] = vector_float, + [ev_vector] = vector_vector, + [ev_int] = vector_int, + [ev_uint] = vector_uint, + [ev_short] = vector_short, + [ev_double] = vector_double, }; static expr_type_t *entity_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - entity_entity, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_pointer - 0, // ev_quaternion - 0, // ev_integer - 0, // ev_uinteger - 0, // ev_short - 0, // ev_double + [ev_entity] = entity_entity, }; static expr_type_t *field_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - field_field, // ev_field - 0, // ev_func - 0, // ev_pointer - 0, // ev_quaternion - 0, // ev_integer - 0, // ev_uinteger - 0, // ev_short - 0, // ev_double + [ev_field] = field_field, }; static expr_type_t *func_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - 0, // ev_field - func_func, // ev_func - 0, // ev_pointer - 0, // ev_quaternion - 0, // ev_integer - 0, // ev_uinteger - 0, // ev_short - 0, // ev_double + [ev_func] = func_func, }; static expr_type_t *pointer_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - 0, // ev_field - 0, // ev_func - pointer_pointer, - 0, // ev_quat - pointer_integer, - pointer_uinteger, - pointer_short, - 0, // ev_double + [ev_ptr] = pointer_pointer, + [ev_int] = pointer_int, + [ev_uint] = pointer_uint, + [ev_short] = pointer_short, }; static expr_type_t *quat_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - quat_float, - quat_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_pointer - quat_quat, - quat_integer, - quat_uinteger, - quat_short, - quat_double, + [ev_float] = quat_float, + [ev_vector] = quat_vector, + [ev_quaternion] = quat_quat, + [ev_int] = quat_int, + [ev_uint] = quat_uint, + [ev_short] = quat_short, + [ev_double] = quat_double, }; -static expr_type_t *integer_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - integer_float, - integer_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - integer_pointer, - integer_quat, - integer_integer, - integer_uinteger, - integer_short, - integer_double, +static expr_type_t *int_x[ev_type_count] = { + [ev_float] = int_float, + [ev_vector] = int_vector, + [ev_ptr] = int_pointer, + [ev_quaternion] = int_quat, + [ev_int] = int_int, + [ev_uint] = int_uint, + [ev_short] = int_short, + [ev_double] = int_double, }; -static expr_type_t *uinteger_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - uinteger_float, - uinteger_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - uinteger_pointer, - uinteger_quat, - uinteger_integer, - uinteger_uinteger, - uinteger_short, - uinteger_double, +static expr_type_t *uint_x[ev_type_count] = { + [ev_float] = uint_float, + [ev_vector] = uint_vector, + [ev_ptr] = uint_pointer, + [ev_quaternion] = uint_quat, + [ev_int] = uint_int, + [ev_uint] = uint_uint, + [ev_short] = uint_short, + [ev_double] = uint_double, }; static expr_type_t *short_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - short_float, - short_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - short_pointer, - short_quat, - short_integer, - short_uinteger, - short_short, - short_double, + [ev_float] = short_float, + [ev_vector] = short_vector, + [ev_ptr] = short_pointer, + [ev_quaternion] = short_quat, + [ev_int] = short_int, + [ev_uint] = short_uint, + [ev_short] = short_short, + [ev_double] = short_double, }; static expr_type_t *double_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - double_float, - double_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_pointer - double_quat, - double_integer, - double_uinteger, - double_short, - double_double, + [ev_float] = double_float, + [ev_vector] = double_vector, + [ev_quaternion] = double_quat, + [ev_int] = double_int, + [ev_uint] = double_uint, + [ev_short] = double_short, + [ev_double] = double_double, }; static expr_type_t **binary_expr_types[ev_type_count] = { - 0, // ev_void - string_x, - float_x, - vector_x, - entity_x, - field_x, - func_x, - pointer_x, - quat_x, - integer_x, - uinteger_x, - short_x, - double_x + [ev_string] = string_x, + [ev_float] = float_x, + [ev_vector] = vector_x, + [ev_entity] = entity_x, + [ev_field] = field_x, + [ev_func] = func_x, + [ev_ptr] = pointer_x, + [ev_quaternion] = quat_x, + [ev_int] = int_x, + [ev_uint] = uint_x, + [ev_short] = short_x, + [ev_double] = double_x }; static expr_t * pointer_arithmetic (int op, expr_t *e1, expr_t *e2) { - expr_t *e; type_t *t1 = get_type (e1); type_t *t2 = get_type (e2); expr_t *ptr; @@ -744,10 +652,10 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) expr_t *psize; type_t *ptype; - if (!is_pointer (t1) && !is_pointer (t2)) { + if (!is_ptr (t1) && !is_ptr (t2)) { internal_error (e1, "pointer arithmetic on non-pointers"); } - if (is_pointer (t1) && is_pointer (t2)) { + if (is_ptr (t1) && is_ptr (t2)) { if (op != '-') { return error (e2, "invalid pointer operation"); } @@ -755,22 +663,23 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) return error (e2, "cannot use %c on pointers of different types", op); } - e1 = cast_expr (&type_integer, e1); - e2 = cast_expr (&type_integer, e2); - psize = new_integer_expr (type_size (t1->t.fldptr.type)); + e1 = cast_expr (&type_int, e1); + e2 = cast_expr (&type_int, e2); + psize = new_int_expr (type_size (t1->t.fldptr.type)); return binary_expr ('/', binary_expr ('-', e1, e2), psize); - } else if (is_pointer (t1)) { - offset = cast_expr (&type_integer, e2); - ptr = cast_expr (&type_integer, e1); + } else if (is_ptr (t1)) { + offset = cast_expr (&type_int, e2); + ptr = e1; ptype = t1; - } else if (is_pointer (t2)) { - offset = cast_expr (&type_integer, e1); - ptr = cast_expr (&type_integer, e2); + } else if (is_ptr (t2)) { + offset = cast_expr (&type_int, e1); + ptr = e2; ptype = t2; } - psize = new_integer_expr (type_size (ptype->t.fldptr.type)); - e = binary_expr (op, ptr, binary_expr ('*', offset, psize)); - return cast_expr (ptype, e); + // op is known to be + or - + psize = new_int_expr (type_size (ptype->t.fldptr.type)); + offset = unary_expr (op, binary_expr ('*', offset, psize)); + return offset_pointer_expr (ptr, offset); } static expr_t * @@ -784,8 +693,28 @@ pointer_compare (int op, expr_t *e1, expr_t *e2) return error (e2, "cannot use %s on pointers of different types", get_op_string (op)); } - e = new_binary_expr (op, e1, e2); - e->e.expr.type = &type_integer; + if (options.code.progsversion < PROG_VERSION) { + e = new_binary_expr (op, e1, e2); + } else { + e = new_binary_expr (op, cast_expr (&type_int, e1), + cast_expr (&type_int, e2)); + } + e->e.expr.type = &type_int; + return e; +} + +static expr_t * +func_compare (int op, expr_t *e1, expr_t *e2) +{ + expr_t *e; + + if (options.code.progsversion < PROG_VERSION) { + e = new_binary_expr (op, e1, e2); + } else { + e = new_binary_expr (op, new_alias_expr (&type_int, e1), + new_alias_expr (&type_int, e2)); + } + e->e.expr.type = &type_int; return e; } @@ -798,6 +727,57 @@ inverse_multiply (int op, expr_t *e1, expr_t *e2) return binary_expr ('*', e1, binary_expr ('/', one, e2)); } +static expr_t * +vector_compare (int op, expr_t *e1, expr_t *e2) +{ + if (options.code.progsversion < PROG_VERSION) { + expr_t *e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_int; + return e; + } + int hop = op == EQ ? '&' : '|'; + e1 = new_alias_expr (&type_vec3, e1); + e2 = new_alias_expr (&type_vec3, e2); + expr_t *e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_ivec3; + return new_horizontal_expr (hop, e, &type_int); +} + +static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2) +{ + expr_t *e = new_binary_expr ('*', e1, e2); + if (options.math.vector_mult == DOT) { + // vector * vector is dot product in v6 progs (ick) + e->e.expr.op = DOT; + if (options.code.progsversion == PROG_VERSION) { + e->e.expr.type = &type_vector; + e = new_alias_expr (&type_float, e); + } else { + e->e.expr.type = &type_float; + } + } else { + // component-wise multiplication + e->e.expr.type = &type_vector; + } + + return e; +} + +static expr_t *vector_scale (int op, expr_t *e1, expr_t *e2) +{ + // Ensure the expression is always vector * scalar. The operation is + // always commutative, and the Ruamoko ISA supports only vector * scalar + // (though v6 does support scalar * vector, one less if). + if (is_scalar (get_type (e1))) { + expr_t *t = e1; + e1 = e2; + e2 = t; + } + expr_t *e = new_binary_expr (SCALE, e1, e2); + e->e.expr.type = get_type (e1); + return e; +} + static expr_t * double_compare (int op, expr_t *e1, expr_t *e2) { @@ -817,19 +797,31 @@ double_compare (int op, expr_t *e1, expr_t *e2) if (is_float (t2)) { warning (e2, "comparison between double and float"); } else if (!is_constant (e2)) { - warning (e2, "comparison between double and integer"); + warning (e2, "comparison between double and int"); } e2 = cast_expr (&type_double, e2); } else if (is_double (t2)) { if (is_float (t1)) { warning (e1, "comparison between float and double"); } else if (!is_constant (e1)) { - warning (e1, "comparison between integer and double"); + warning (e1, "comparison between int and double"); } e1 = cast_expr (&type_double, e1); } e = new_binary_expr (op, e1, e2); - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; + return e; +} + +static expr_t * +entity_compare (int op, expr_t *e1, expr_t *e2) +{ + if (options.code.progsversion == PROG_VERSION) { + e1 = new_alias_expr (&type_int, e1); + e2 = new_alias_expr (&type_int, e2); + } + expr_t *e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_int; return e; } @@ -873,7 +865,7 @@ check_precedence (int op, expr_t *e1, expr_t *e2) { if (e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) { if (options.traditional) { - if (op != AND && op != OR && op != '=') { + if (op != AND && op != OR) { notice (e1, "precedence of `!' and `%s' inverted for " "traditional code", get_op_string (op)); e1->e.expr.e1->paren = 1; @@ -890,8 +882,7 @@ check_precedence (int op, expr_t *e1, expr_t *e2) if (e2->type == ex_expr && !e2->paren) { if (((op == '&' || op == '|') && (is_math_op (e2->e.expr.op) || is_compare (e2->e.expr.op))) - || (op == '=' - && (e2->e.expr.op == OR || e2->e.expr.op == AND))) { + || (e2->e.expr.op == OR || e2->e.expr.op == AND)) { notice (e1, "precedence of `%s' and `%s' inverted for " "traditional code", get_op_string (op), get_op_string (e2->e.expr.op)); @@ -912,8 +903,7 @@ check_precedence (int op, expr_t *e1, expr_t *e2) } else if (e1->type == ex_expr && !e1->paren) { if (((op == '&' || op == '|') && (is_math_op (e1->e.expr.op) || is_compare (e1->e.expr.op))) - || (op == '=' - && (e1->e.expr.op == OR || e1->e.expr.op == AND))) { + || (e1->e.expr.op == OR || e1->e.expr.op == AND)) { notice (e1, "precedence of `%s' and `%s' inverted for " "traditional code", get_op_string (op), get_op_string (e1->e.expr.op)); @@ -970,12 +960,11 @@ binary_expr (int op, expr_t *e1, expr_t *e2) e1 = convert_vector (e1); // FIXME this is target-specific info and should not be in the // expression tree - if ((e1->type == ex_expr || e1->type == ex_uexpr) && e1->e.expr.op == 'A' - && is_call (e1->e.expr.e1)) { + if (e1->type == ex_alias && is_call (e1->e.alias.expr)) { // move the alias expression inside the block so the following check // can detect the call and move the temp assignment into the block - expr_t *block = e1->e.expr.e1; - e1->e.expr.e1 = block->e.block.result; + expr_t *block = e1->e.alias.expr; + e1->e.alias.expr = block->e.block.result; block->e.block.result = e1; e1 = block; } @@ -1035,6 +1024,16 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return invalid_binary_expr(op, e1, e2); if (et2 >= ev_type_count || !binary_expr_types[et1][et2]) return invalid_binary_expr(op, e1, e2); + + if ((t1->width > 1 || t2->width > 1)) { + if (t1 != t2) { + return invalid_binary_expr (op, e1, e2); + } + e = new_binary_expr (op, e1, e2); + e->e.expr.type = t1; + return e; + } + expr_type = binary_expr_types[et1][et2]; while (expr_type->op && expr_type->op != op) expr_type++; @@ -1053,7 +1052,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return fold_constants (e); e = new_binary_expr (op, e1, e2); - e->e.expr.type = expr_type->type; + e->e.expr.type = expr_type->result_type; if (is_compare (op) || is_logic (op)) { if (options.code.progsversion == PROG_ID_VERSION) { e->e.expr.type = &type_float; diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index fd21de053..4d3431769 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -94,10 +94,14 @@ test_expr (expr_t *e) return new_alias_expr (type_default, e); new = new_string_expr (0); break; - case ev_uinteger: - case ev_integer: + case ev_long: + case ev_ulong: + case ev_ushort: + internal_error (e, "long not implemented"); + case ev_uint: + case ev_int: case ev_short: - if (!is_integer(type_default)) { + if (!is_int(type_default)) { if (is_constant (e)) { return cast_expr (type_default, e); } @@ -105,8 +109,9 @@ test_expr (expr_t *e) } return e; case ev_float: - if (options.code.fast_float - || options.code.progsversion == PROG_ID_VERSION) { + if (options.code.progsversion < PROG_VERSION + && (options.code.fast_float + || options.code.progsversion == PROG_ID_VERSION)) { if (!is_float(type_default)) { if (is_constant (e)) { return cast_expr (type_default, e); @@ -129,9 +134,9 @@ test_expr (expr_t *e) return new_alias_expr (type_default, e); case ev_func: return new_alias_expr (type_default, e); - case ev_pointer: + case ev_ptr: return new_alias_expr (type_default, e); - case ev_quat: + case ev_quaternion: new = new_quaternion_expr (zero); break; case ev_invalid: @@ -162,12 +167,9 @@ backpatch (ex_list_t *list, expr_t *label) for (i = 0; i < list->size; i++) { e = list->e[i]; - if (e->type == ex_uexpr && e->e.expr.op == 'g') - e->e.expr.e1 = label; - else if (e->type == ex_expr && (e->e.expr.op == 'i' - || e->e.expr.op == 'n')) - e->e.expr.e2 = label; - else { + if (e->type == ex_branch && e->e.branch.type < pr_branch_call) { + e->e.branch.target = label; + } else { internal_error (e, 0); } label->e.label.used++; @@ -246,16 +248,16 @@ convert_bool (expr_t *e, int block) { expr_t *b; - if (e->type == ex_expr && e->e.expr.op == '=') { + if (e->type == ex_assign) { expr_t *src; if (!e->paren && options.warnings.precedence) warning (e, "suggest parentheses around assignment " "used as truth value"); - src = e->e.expr.e2; + src = e->e.assign.src; if (src->type == ex_block) { src = new_temp_def_expr (get_type (src)); - e = new_binary_expr (e->e.expr.op, e->e.expr.e1, - assign_expr (src, e->e.expr.e2)); + e = new_assign_expr (e->e.assign.dst, + assign_expr (src, e->e.assign.src)); } b = convert_bool (src, 1); if (b->type == ex_error) @@ -285,8 +287,8 @@ convert_bool (expr_t *e, int block) int val; b = goto_expr (0); - if (is_integer_val (e)) { - val = expr_integer (e); + if (is_int_val (e)) { + val = expr_int (e); } else { val = expr_float (e) != 0; } @@ -296,7 +298,7 @@ convert_bool (expr_t *e, int block) e = new_bool_expr (0, make_list (b), b); } else { b = new_block_expr (); - append_expr (b, branch_expr ('i', e, 0)); + append_expr (b, branch_expr (NE, e, 0)); append_expr (b, goto_expr (0)); e = new_bool_expr (make_list (b->e.block.head), make_list (b->e.block.head->next), b); diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index e75bb5b70..e8b81747d 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -82,6 +82,31 @@ new_compound_init (void) return c; } +static element_t * +build_array_element_chain(element_chain_t *element_chain, + int array_size, type_t *array_type, + element_t *ele, + int base_offset) +{ + for (int i = 0; i < array_size; i++) { + int offset = base_offset + i * type_size (array_type); + if (ele && ele->expr && ele->expr->type == ex_compound) { + build_element_chain (element_chain, array_type, + ele->expr, offset); + } else { + element_t *element = new_element (0, 0); + element->type = array_type; + element->offset = offset; + element->expr = ele ? ele->expr : 0; // null -> nil + append_init_element (element_chain, element); + } + if (ele) { + ele = ele->next; + } + } + return ele; +} + void build_element_chain (element_chain_t *element_chain, const type_t *type, expr_t *eles, int base_offset) @@ -93,25 +118,9 @@ build_element_chain (element_chain_t *element_chain, const type_t *type, if (is_array (type)) { type_t *array_type = type->t.array.type; int array_size = type->t.array.size; - int i; - - for (i = 0; i < array_size; i++) { - int offset = base_offset + i * type_size (array_type); - if (ele && ele->expr && ele->expr->type == ex_compound) { - build_element_chain (element_chain, array_type, - ele->expr, offset); - } else { - element_t *element = new_element (0, 0); - element->type = array_type; - element->offset = offset; - element->expr = ele ? ele->expr : 0; // null -> nil - append_init_element (element_chain, element); - } - if (ele) { - ele = ele->next; - } - } - } else if (is_struct (type) || is_vector (type) || is_quaternion (type)) { + ele = build_array_element_chain (element_chain, array_size, array_type, + ele, base_offset); + } else if (is_struct (type) || (is_nonscalar (type) && type->t.symtab)) { symtab_t *symtab = type->t.symtab; symbol_t *field; @@ -135,6 +144,12 @@ build_element_chain (element_chain_t *element_chain, const type_t *type, ele = ele->next; } } + } else if (is_nonscalar (type)) { + // vector type with unnamed components + int vec_width = type_width (type); + type_t *vec_type = ev_types[type->type]; + ele = build_array_element_chain (element_chain, vec_width, vec_type, + ele, base_offset); } else { error (eles, "invalid initializer"); } diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 9c3984055..b2463e4d1 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -112,8 +112,8 @@ selector_expr (keywordarg_t *selector) reloc_def_def (sel_table->s.def, sel_sym->s.def); } sel_ref = new_symbol_expr (sel_sym); - sel_ref = new_binary_expr ('&', sel_ref, new_short_expr (index)); - sel_ref->e.expr.type = &type_SEL; + sel_ref = new_address_expr (&type_selector, sel_ref, + new_short_expr (index)); expr_t *sel = new_expr (); sel->type = ex_selector; @@ -156,7 +156,8 @@ super_expr (class_type_t *class_type) sym = symtab_lookup (current_symtab, ".super"); if (!sym || sym->table != current_symtab) { sym = new_symbol_type (".super", &type_super); - initialize_def (sym, 0, current_symtab->space, sc_local); + initialize_def (sym, 0, current_symtab->space, sc_local, + current_symtab); } super = new_symbol_expr (sym); @@ -171,7 +172,7 @@ super_expr (class_type_t *class_type) field_expr (e, new_name_expr ("super_class"))); append_expr (super_block, e); - e = address_expr (super, 0, 0); + e = address_expr (super, 0); super_block->e.block.result = e; return super_block; } @@ -248,6 +249,9 @@ message_expr (expr_t *receiver, keywordarg_t *message) if (call->type == ex_error) return receiver; - call->e.block.result = new_ret_expr (return_type); + if (!is_function_call (call)) { + internal_error (call, "unexpected call expression type"); + } + call->e.block.result->e.branch.ret_type = return_type; return call; } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 37d0c1814..4e86fc0c3 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -609,7 +609,7 @@ flow_build_vars (function_t *func) // set up pseudo address space for temp vars so accessing tmp vars // though aliases analyses correctly - func->pseudo_addr = func->num_statements + func->symtab->space->size; + func->pseudo_addr = func->num_statements + func->locals->space->size; func->num_vars = 0; // incremented by add_operand // first, add .return and .param_[0-7] as they are always needed @@ -1127,7 +1127,7 @@ flow_analyze_pointer_operand (operand_t *ptrop, set_t *def) { operand_t *op = 0; - if (ptrop->op_type == op_value && ptrop->value->lltype == ev_pointer) { + if (ptrop->op_type == op_value && ptrop->value->lltype == ev_ptr) { ex_pointer_t *ptr = &ptrop->value->v.pointer; if (ptrop->value->v.pointer.def) { def_t *alias; @@ -1149,9 +1149,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, operand_t *operands[FLOW_OPERANDS]) { int i, start, calln = -1; + operand_t *src_op = 0; operand_t *res_op = 0; operand_t *aux_op1 = 0; operand_t *aux_op2 = 0; + operand_t *aux_op3 = 0; if (use) { set_empty (use); @@ -1179,6 +1181,18 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, switch (s->type) { case st_none: internal_error (s->expr, "not a statement"); + case st_address: + if (s->opb) { + flow_add_op_var (use, s->opa, 1); + flow_add_op_var (use, s->opb, 1); + } + flow_add_op_var (def, s->opc, 0); + if (operands) { + operands[0] = s->opc; + operands[1] = s->opa; + operands[2] = s->opb; + } + break; case st_expr: flow_add_op_var (def, s->opc, 0); flow_add_op_var (use, s->opa, 1); @@ -1191,11 +1205,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_assign: - flow_add_op_var (def, s->opb, 0); - flow_add_op_var (use, s->opa, 1); + flow_add_op_var (def, s->opa, 0); + flow_add_op_var (use, s->opc, 1); if (operands) { - operands[0] = s->opb; - operands[1] = s->opa; + operands[0] = s->opa; + operands[1] = s->opc; } break; case st_ptrassign: @@ -1205,23 +1219,28 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, case st_ptrmemset: flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); - if (!strcmp (s->opcode, "") - || !strcmp (s->opcode, "")) { + aux_op1 = s->opb; + if (!strcmp (s->opcode, "move") + || !strcmp (s->opcode, "memset")) { flow_add_op_var (def, s->opc, 0); + src_op = s->opa; res_op = s->opc; - } else if (!strcmp (s->opcode, "")) { + } else if (!strcmp (s->opcode, "movep")) { flow_add_op_var (use, s->opc, 0); - aux_op2 = flow_analyze_pointer_operand (s->opa, use); + aux_op3 = flow_analyze_pointer_operand (s->opa, use); res_op = flow_analyze_pointer_operand (s->opc, def); - aux_op1 = s->opc; - } else if (!strcmp (s->opcode, "")) { + src_op = s->opa; + aux_op2 = s->opc; + } else if (!strcmp (s->opcode, "memsetp")) { flow_add_op_var (use, s->opc, 0); res_op = flow_analyze_pointer_operand (s->opc, def); - aux_op1 = s->opc; - } else if (!strcmp (s->opcode, ".=")) { + src_op = s->opa; + aux_op2 = s->opc; + } else if (!strcmp (s->opcode, "store")) { flow_add_op_var (use, s->opc, 1); - res_op = flow_analyze_pointer_operand (s->opb, def); - aux_op1 = s->opc; + res_op = flow_analyze_pointer_operand (s->opa, def); + src_op = s->opc; + aux_op2 = s->opa; } else { internal_error (s->expr, "unexpected opcode '%s' for %d", s->opcode, s->type); @@ -1231,10 +1250,10 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } if (operands) { operands[0] = res_op; - operands[1] = s->opa; - operands[2] = s->opb; - operands[3] = aux_op1; - operands[4] = aux_op2; + operands[1] = src_op; + operands[2] = aux_op1; + operands[3] = aux_op2; + operands[4] = aux_op3; } break; case st_state: @@ -1250,19 +1269,41 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_func: - if (strcmp (s->opcode, "") == 0 - || strcmp (s->opcode, "") == 0) { - flow_add_op_var (use, s->opa, 1); - } else if (strcmp (s->opcode, "") == 0) { + if (statement_is_return (s)) { + if (s->opc) { + // ruamoko + // opc always short + short ret_mode = s->opc->value->v.short_val; + // -1 is void + // FIXME size and addressing + if (ret_mode >= 0) { + flow_add_op_var (use, s->opa, 1); + } + } else { + // v6/v6p + if (s->opa) { + flow_add_op_var (use, s->opa, 1); + } + } if (use) { flow_add_op_var (use, &flow_params[0].op, 1); } } - if (strncmp (s->opcode, "opcode, "call") == 0) { + // call uses opc to specify the destination of the return value + // parameter usage is taken care of by the statement's use + // list + flow_add_op_var (def, s->opc, 0); + // don't want old argument processing + calln = -1; + if (operands && s->opc->op_type != op_value) { + operands[0] = s->opc; + } + } else if (strncmp (s->opcode, "call", 4) == 0) { start = 0; calln = s->opcode[5] - '0'; flow_add_op_var (use, s->opa, 1); - } else if (strncmp (s->opcode, "opcode, "rcall", 5) == 0) { start = 2; calln = s->opcode[6] - '0'; flow_add_op_var (use, s->opa, 1); @@ -1296,14 +1337,21 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_flow: - if (strcmp (s->opcode, "") != 0) { + if (statement_is_goto (s)) { + // opa is just a label + } else if (statement_is_jumpb (s)) { flow_add_op_var (use, s->opa, 1); - if (strcmp (s->opcode, "") == 0) - flow_add_op_var (use, s->opb, 1); + flow_add_op_var (use, s->opb, 1); + } else if (statement_is_cond (s)) { + flow_add_op_var (use, s->opc, 1); + } else { + internal_error (s->expr, "unexpected flow statement: %s", + s->opcode); } if (operands) { operands[1] = s->opa; operands[2] = s->opb; + operands[3] = s->opc; } break; } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index e448990b2..e9371ea81 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -71,6 +71,13 @@ static function_t *functions_freelist; static hashtab_t *overloaded_functions; static hashtab_t *function_map; +// standardized base register to use for all locals (arguments, local defs, +// params) +#define LOCALS_REG 1 +// keep the stack aligned to 8 words (32 bytes) so lvec etc can be used without +// having to do shenanigans with mixed-alignment stack frames +#define STACK_ALIGN 8 + static const char * ol_func_get_key (const void *_f, void *unused) { @@ -181,6 +188,7 @@ parse_params (type_t *type, param_t *parms) new = new_type (); new->type = ev_func; new->alignment = 1; + new->width = 1; new->t.func.type = type; new->t.func.num_params = 0; @@ -482,32 +490,18 @@ check_function (symbol_t *fsym) } static void -build_scope (symbol_t *fsym, symtab_t *parent) +build_v6p_scope (symbol_t *fsym) { int i; param_t *p; symbol_t *args = 0; symbol_t *param; - symtab_t *symtab; - symtab_t *cs = current_symtab; + symtab_t *parameters = fsym->s.func->parameters; + symtab_t *locals = fsym->s.func->locals; - check_function (fsym); - - symtab = new_symtab (parent, stab_local); - fsym->s.func->symtab = symtab; - fsym->s.func->label_scope = new_symtab (0, stab_local); - symtab->space = defspace_new (ds_virtual); - current_symtab = symtab; - - if (!fsym->s.func) { - internal_error (0, "function %s not defined", fsym->name); - } - if (!is_func (fsym->s.func->type)) { - internal_error (0, "function type %s not a funciton", fsym->name); - } if (fsym->s.func->type->t.func.num_params < 0) { args = new_symbol_type (".args", &type_va_list); - initialize_def (args, 0, symtab->space, sc_param); + initialize_def (args, 0, parameters->space, sc_param, locals); } for (p = fsym->params, i = 0; p; p = p->next) { @@ -520,18 +514,91 @@ build_scope (symbol_t *fsym, symtab_t *parent) p->name = save_string (""); } param = new_symbol_type (p->name, p->type); - initialize_def (param, 0, symtab->space, sc_param); + initialize_def (param, 0, parameters->space, sc_param, locals); i++; } if (args) { - while (i < MAX_PARMS) { + while (i < PR_MAX_PARAMS) { param = new_symbol_type (va (0, ".par%d", i), &type_param); - initialize_def (param, 0, symtab->space, sc_param); + initialize_def (param, 0, parameters->space, sc_param, locals); i++; } } - current_symtab = cs; +} + +static void +create_param (symtab_t *parameters, symbol_t *param) +{ + defspace_t *space = parameters->space; + def_t *def = new_def (param->name, 0, space, sc_param); + int size = type_size (param->type); + int alignment = param->type->alignment; + if (alignment < 4) { + alignment = 4; + } + def->offset = defspace_alloc_aligned_highwater (space, size, alignment); + def->type = param->type; + param->s.def = def; + param->sy_type = sy_var; + symtab_addsymbol (parameters, param); + if (is_vector(param->type) && options.code.vector_components) + init_vector_components (param, 0, parameters); +} + +static void +build_rua_scope (symbol_t *fsym) +{ + for (param_t *p = fsym->params; p; p = p->next) { + symbol_t *param; + if (!p->selector && !p->type && !p->name) { + // ellipsis marker + param = new_symbol_type (".args", &type_va_list); + } else { + if (!p->type) { + continue; // non-param selector + } + if (!p->name) { + error (0, "parameter name omitted"); + p->name = save_string (""); + } + param = new_symbol_type (p->name, p->type); + } + create_param (fsym->s.func->parameters, param); + param->s.def->reg = fsym->s.func->temp_reg;; + } +} + +static void +build_scope (symbol_t *fsym, symtab_t *parent) +{ + symtab_t *parameters; + symtab_t *locals; + + if (!fsym->s.func) { + internal_error (0, "function %s not defined", fsym->name); + } + if (!is_func (fsym->s.func->type)) { + internal_error (0, "function type %s not a funciton", fsym->name); + } + + check_function (fsym); + + fsym->s.func->label_scope = new_symtab (0, stab_local); + + parameters = new_symtab (parent, stab_local); + parameters->space = defspace_new (ds_virtual); + fsym->s.func->parameters = parameters; + + locals = new_symtab (parameters, stab_local); + locals->space = defspace_new (ds_virtual); + fsym->s.func->locals = locals; + + if (options.code.progsversion == PROG_VERSION) { + build_rua_scope (fsym); + } else { + build_v6p_scope (fsym); + } } function_t * @@ -590,7 +657,7 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, if (sym->sy_type != sy_func) { error (0, "%s is not a function", sym->name); - sym = new_symbol_type (sym->name, &type_function); + sym = new_symbol_type (sym->name, &type_func); sym = function_symbol (sym, 1, 1); } if (sym->s.func && sym->s.func->def && sym->s.func->def->initialized) { @@ -608,6 +675,9 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, sym->s.func->def->nosave = 1; add_function (sym->s.func); reloc_def_func (sym->s.func, sym->s.func->def); + + sym->s.func->def->file = pr.source_file; + sym->s.func->def->line = pr.source_line; } sym->s.func->code = pr.code->size; @@ -625,14 +695,35 @@ static void build_function (symbol_t *fsym) { const type_t *func_type = fsym->s.func->type; - if (func_type->t.func.num_params > MAX_PARMS) { + if (func_type->t.func.num_params > PR_MAX_PARAMS) { error (0, "too many params"); } - // FIXME -// f->def->constant = 1; -// f->def->nosave = 1; -// f->def->initialized = 1; -// G_FUNCTION (f->def->ofs) = f->function_num; +} + +static void +merge_spaces (defspace_t *dst, defspace_t *src, int alignment) +{ + int offset; + + for (def_t *def = src->defs; def; def = def->next) { + if (def->type->alignment > alignment) { + alignment = def->type->alignment; + } + } + offset = defspace_alloc_aligned_highwater (dst, src->size, alignment); + for (def_t *def = src->defs; def; def = def->next) { + def->offset += offset; + def->space = dst; + } + + if (src->defs) { + *dst->def_tail = src->defs; + dst->def_tail = src->def_tail; + src->def_tail = &src->defs; + *src->def_tail = 0; + } + + defspace_delete (src); } function_t * @@ -642,11 +733,93 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) return 0; build_function (fsym); if (state_expr) { - state_expr->next = statements; - statements = state_expr; + prepend_expr (statements, state_expr); + } + function_t *func = fsym->s.func; + if (options.code.progsversion == PROG_VERSION) { + /* Create a function entry block to set up the stack frame and add the + * actual function code to that block. This ensure that the adjstk and + * with statements always come first, regardless of what ideas the + * optimizer gets. + */ + expr_t *e; + expr_t *entry = new_block_expr (); + entry->file = func->def->file; + entry->line = func->def->line; + + e = new_adjstk_expr (0, 0); + e->file = func->def->file; + e->line = func->def->line; + append_expr (entry, e); + + e = new_with_expr (2, LOCALS_REG, new_short_expr (0)); + e->file = func->def->file; + e->line = func->def->line; + append_expr (entry, e); + + append_expr (entry, statements); + statements = entry; + + /* Mark all local defs as using the base register used for stack + * references. + */ + func->temp_reg = LOCALS_REG; + for (def_t *def = func->locals->space->defs; def; def = def->next) { + if (def->local || def->param) { + def->reg = LOCALS_REG; + } + } + for (def_t *def = func->parameters->space->defs; def; def = def->next) { + if (def->local || def->param) { + def->reg = LOCALS_REG; + } + } + } + emit_function (func, statements); + if (options.code.progsversion < PROG_VERSION) { + // stitch parameter and locals data together with parameters coming + // first + defspace_t *space = defspace_new (ds_virtual); + + func->params_start = 0; + + merge_spaces (space, func->parameters->space, 1); + func->parameters->space = space; + + merge_spaces (space, func->locals->space, 1); + func->locals->space = space; + } else { + defspace_t *space = defspace_new (ds_virtual); + + if (func->arguments) { + func->arguments->size = func->arguments->max_size; + merge_spaces (space, func->arguments, STACK_ALIGN); + func->arguments = 0; + } + + merge_spaces (space, func->locals->space, STACK_ALIGN); + func->locals->space = space; + + // allocate 0 words to force alignment and get the address + func->params_start = defspace_alloc_aligned_highwater (space, 0, + STACK_ALIGN); + + dstatement_t *st = &pr.code->code[func->code]; + if (st->op == OP_ADJSTK) { + if (func->params_start) { + st->b = -func->params_start; + } else { + // skip over adjstk so a zero adjustment doesn't get executed + func->code += 1; + } + } + merge_spaces (space, func->parameters->space, STACK_ALIGN); + func->parameters->space = space; + + // force the alignment again so the full stack slot is counted when + // the final parameter is smaller than STACK_ALIGN words + defspace_alloc_aligned_highwater (space, 0, STACK_ALIGN); } - emit_function (fsym->s.func, statements); - finish_function (fsym->s.func); return fsym->s.func; } @@ -665,7 +838,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, error (bi_val, "%s redefined", sym->name); return 0; } - if (!is_integer_val (bi_val) && !is_float_val (bi_val)) { + if (!is_int_val (bi_val) && !is_float_val (bi_val)) { error (bi_val, "invalid constant for = #"); return 0; } @@ -681,8 +854,8 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, sym->s.func->def->nosave = 1; add_function (sym->s.func); - if (is_integer_val (bi_val)) - bi = expr_integer (bi_val); + if (is_int_val (bi_val)) + bi = expr_int (bi_val); else bi = expr_float (bi_val); if (bi < 0) { @@ -692,19 +865,14 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, sym->s.func->builtin = bi; reloc_def_func (sym->s.func, sym->s.func->def); build_function (sym); - finish_function (sym->s.func); // for debug info build_scope (sym, current_symtab); - sym->s.func->symtab->space->size = 0; + sym->s.func->parameters->space->size = 0; + sym->s.func->locals->space = sym->s.func->parameters->space; return sym->s.func; } -void -finish_function (function_t *f) -{ -} - void emit_function (function_t *f, expr_t *e) { diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index 1bc222f49..34e9c4d7b 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -212,10 +212,10 @@ WriteProgdefs (dprograms_t *progs, const char *filename) "\n\ntypedef struct\n{\tint\tpad[%i];\n", RESERVED_OFS); - strings = (char *) progs + progs->ofs_strings; - for (i = 0; i < progs->numglobaldefs; i++) { - def = (ddef_t *) ((char *) progs + progs->ofs_globaldefs) + i; - name = strings + def->s_name; + strings = (char *) progs + progs->strings.offset; + for (i = 0; i < progs->globaldefs.count; i++) { + def = (ddef_t *) ((char *) progs + progs->globaldefs.offset) + i; + name = strings + def->name; if (!strcmp (name, "end_sys_globals")) break; if (!def->ofs) @@ -230,7 +230,7 @@ WriteProgdefs (dprograms_t *progs, const char *filename) case ev_vector: dasprintf (dstr, "\tvec3_t\t%s;\n", name); break; - case ev_quat: + case ev_quaternion: dasprintf (dstr, "\tquat_t\t%s;\n", name); break; case ev_string: @@ -251,9 +251,9 @@ WriteProgdefs (dprograms_t *progs, const char *filename) // print all fields dasprintf (dstr, "typedef struct\n{\n"); - for (i = 0, j = 0; i < progs->numglobaldefs; i++) { - def = (ddef_t *) ((char *) progs + progs->ofs_globaldefs) + i; - name = strings + def->s_name; + for (i = 0, j = 0; i < progs->globaldefs.count; i++) { + def = (ddef_t *) ((char *) progs + progs->globaldefs.offset) + i; + name = strings + def->name; if (!strcmp (name, "end_sys_fields")) break; @@ -264,8 +264,8 @@ WriteProgdefs (dprograms_t *progs, const char *filename) if (!strcmp (name, ".imm")) continue; - fdef = (ddef_t *) ((char *) progs + progs->ofs_fielddefs) + j++; - if (fdef->s_name != def->s_name) + fdef = (ddef_t *) ((char *) progs + progs->fielddefs.offset) + j++; + if (fdef->name != def->name) internal_error (0, "def and field order messup"); switch (fdef->type) { diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 4b0fb7d74..cc34e79b6 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -245,7 +245,7 @@ defs_get_key (const void *_r, void *unused) int linker_add_string (const char *str) { - string_t new; + pr_string_t new; new = strpool_addstr (work_strings, str); work->spaces[qfo_strings_space].strings = work_strings->strings; work->spaces[qfo_strings_space].data_size = work_strings->size; @@ -875,7 +875,7 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) // while we're at it, relocate all references in the type encoding // space so the type encodings are always correct. if (reloc->type == rel_def_string) { - string_t str; + pr_string_t str; str = linker_add_string (QFOSTR (qfo, reloc->target)); QFO_STRING (work, reloc->space, reloc->offset) = str; } else if (reloc->type == rel_def_def || reloc->type == -1) { @@ -1148,6 +1148,10 @@ linker_add_lib (const char *libname) linker_error ("error opening"); return 1; } + if (qfo->progs_version != options.code.progsversion) { + linker_error ("qfo progs version does not match target"); + return 1; + } for (j = 0; j < qfo->num_defs; j++) { qfo_def_t *def = qfo->defs + j; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 55a4f2344..f36a1fd20 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -41,9 +41,10 @@ #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/pr_obj.h" #include "QF/va.h" +#include "QF/progs/pr_obj.h" + #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/expr.h" @@ -486,12 +487,12 @@ get_selector (expr_t *sel) if (sel->type == ex_selector) { return sel->e.selector.sel; } - if (sel->type != ex_expr && sel->e.expr.op != '&' - && !is_SEL(sel->e.expr.type)) { + if (sel->type != ex_address && !sel->e.address.offset + && !is_SEL(sel->e.address.type)) { error (sel, "not a selector"); return 0; } - _sel.index = expr_short (sel->e.expr.e2); + _sel.index = expr_short (sel->e.address.offset); _sel.index /= type_size (type_SEL.t.fldptr.type); return (selector_t *) Hash_FindElement (sel_index_hash, &_sel); } @@ -532,7 +533,7 @@ emit_selectors (void) static void emit_methods_next (def_t *def, void *data, int index) { - if (!is_pointer(def->type)) + if (!is_ptr(def->type)) internal_error (0, "%s: expected pointer def", __FUNCTION__); D_INT (def) = 0; } @@ -542,8 +543,8 @@ emit_methods_count (def_t *def, void *data, int index) { methodlist_t *methods = (methodlist_t *) data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = methods->count; } @@ -584,9 +585,9 @@ def_t * emit_methods (methodlist_t *methods, const char *name, int instance) { static struct_def_t methods_struct[] = { - {"method_next", &type_pointer, emit_methods_next}, - {"method_count", &type_integer, emit_methods_count}, - {"method_list", 0, emit_methods_list_item}, + {"method_next", &type_ptr, emit_methods_next}, + {"method_count", &type_int, emit_methods_count}, + {"method_list", 0, emit_methods_list_item}, {0, 0} }; const char *type = instance ? "INSTANCE" : "CLASS"; @@ -621,8 +622,8 @@ emit_method_list_count (def_t *def, void *data, int index) { methodlist_t *methods = (methodlist_t *) data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = methods->count; } @@ -659,7 +660,7 @@ emit_method_descriptions (methodlist_t *methods, const char *name, int instance) { static struct_def_t method_list_struct[] = { - {"count", &type_integer, emit_method_list_count}, + {"count", &type_int, emit_method_list_count}, {"method_list", 0, emit_method_list_item}, {0, 0} }; @@ -709,8 +710,8 @@ method_check_params (method_t *method, expr_t *args) for (count = 0, a = args; a; a = a->next) count++; - if (count > MAX_PARMS) - return error (args, "more than %d parameters", MAX_PARMS); + if (count > PR_MAX_PARAMS) + return error (args, "more than %d parameters", PR_MAX_PARAMS); if (mtype->t.func.num_params >= 0) param_count = mtype->t.func.num_params; @@ -745,8 +746,8 @@ method_check_params (method_t *method, expr_t *args) } } } else { - if (is_integer_val (e) && options.warnings.vararg_integer) { - warning (e, "passing integer consant into ... function"); + if (is_int_val (e) && options.warnings.vararg_integer) { + warning (e, "passing int consant into ... function"); } } } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index afe295961..d7144ae27 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -31,8 +31,6 @@ # include "config.h" #endif -#define _GNU_SOURCE // for qsort_r - #ifdef HAVE_STRING_H # include #endif @@ -171,9 +169,9 @@ qfo_count_function_stuff (qfo_t *qfo, function_t *functions) for (func = functions; func; func = func->next) { qfo->num_funcs++; qfo->num_relocs += count_relocs (func->refs); - if (func->symtab && func->symtab->space) { + if (func->locals && func->locals->space) { qfo->num_spaces++; - qfo_count_space_stuff (qfo, func->symtab->space); + qfo_count_space_stuff (qfo, func->locals->space); } } } @@ -306,14 +304,15 @@ qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, if (f->builtin) // FIXME redundant q->code = -f->builtin; q->def = f->def->qfo_def; - if (f->symtab && f->symtab->space) { - space->id = f->symtab->space->qfo_space; - qfo_init_data_space (qfo, defs, relocs, space++, f->symtab->space); - q->locals_space = f->symtab->space->qfo_space; + if (f->locals && f->locals->space) { + space->id = f->locals->space->qfo_space; + qfo_init_data_space (qfo, defs, relocs, space++, f->locals->space); + q->locals_space = f->locals->space->qfo_space; } q->line_info = f->line_info; q->relocs = *relocs - qfo->relocs; q->num_relocs = qfo_encode_relocs (f->refs, relocs, q - qfo->funcs); + q->params_start = f->params_start; } } @@ -434,7 +433,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type) case qfos_type: case qfos_debug: for (val = (pr_type_t *) space, c = 0; c < size; c++, val++) - val->integer_var = LittleLong (val->integer_var); + val->int_var = LittleLong (val->int_var); break; } } @@ -480,6 +479,7 @@ qfo_write (qfo_t *qfo, const char *filename) header->num_funcs = LittleLong (qfo->num_funcs); header->num_lines = LittleLong (qfo->num_lines); header->num_loose_relocs = LittleLong (qfo->num_loose_relocs); + header->progs_version = LittleLong (options.code.progsversion); spaces = (qfo_space_t *) &header[1]; relocs = (qfo_reloc_t *) &spaces[qfo->num_spaces]; defs = (qfo_def_t *) &relocs[qfo->num_relocs]; @@ -529,6 +529,7 @@ qfo_write (qfo_t *qfo, const char *filename) funcs[i].line_info = LittleLong (qfo->funcs[i].line_info); funcs[i].relocs = LittleLong (qfo->funcs[i].relocs); funcs[i].num_relocs = LittleLong (qfo->funcs[i].num_relocs); + funcs[i].params_start = LittleLong (qfo->funcs[i].params_start); } for (i = 0; i < qfo->num_lines; i++) { lines[i].fa.addr = LittleLong (qfo->lines[i].fa.addr); @@ -562,6 +563,21 @@ qfo_read (QFile *file) free (data); return 0; } + header->progs_version = LittleLong (header->progs_version); + if (header->progs_version != PROG_ID_VERSION + && header->progs_version != PROG_V6P_VERSION + && header->progs_version != PROG_VERSION) { + fprintf (stderr, "not a compatible qfo file\n"); + free (data); + return 0; + } + // qfprogs leaves progsversion as 0 + if (options.code.progsversion + && header->progs_version != options.code.progsversion) { + fprintf (stderr, "qfo file target VM does not match current target\n"); + free (data); + return 0; + } qfo = calloc (1, sizeof (qfo_t)); qfo->num_spaces = LittleLong (header->num_spaces); @@ -570,6 +586,7 @@ qfo_read (QFile *file) qfo->num_funcs = LittleLong (header->num_funcs); qfo->num_lines = LittleLong (header->num_lines); qfo->num_loose_relocs = LittleLong (header->num_loose_relocs); + qfo->progs_version = header->progs_version; //already swapped spaces = (qfo_space_t *) &header[1]; qfo->data = data; @@ -668,7 +685,7 @@ qfo_delete (qfo_t *qfo) } static etype_t -get_def_type (qfo_t *qfo, pointer_t type) +get_def_type (qfo_t *qfo, pr_ptr_t type) { qfot_type_t *type_def; if (type >= qfo->spaces[qfo_type_space].data_size) @@ -686,7 +703,7 @@ get_def_type (qfo_t *qfo, pointer_t type) case ty_enum: if (options.code.progsversion == PROG_ID_VERSION) return ev_float; - return ev_integer; + return ev_int; case ty_array: case ty_class: return ev_invalid; @@ -695,7 +712,7 @@ get_def_type (qfo_t *qfo, pointer_t type) } static __attribute__((pure)) int -get_type_size (qfo_t *qfo, pointer_t type) +get_type_size (qfo_t *qfo, pr_ptr_t type) { qfot_type_t *type_def; int i, size; @@ -722,7 +739,7 @@ get_type_size (qfo_t *qfo, pointer_t type) } return size; case ty_enum: - return pr_type_size[ev_integer]; + return pr_type_size[ev_int]; case ty_array: return type_def->array.size * get_type_size (qfo, type_def->array.type); @@ -745,7 +762,7 @@ qfo_log2 (unsigned x) } static __attribute__((pure)) int -get_type_alignment_log (qfo_t *qfo, pointer_t type) +get_type_alignment_log (qfo_t *qfo, pr_ptr_t type) { qfot_type_t *type_def; int i, alignment; @@ -771,7 +788,7 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) } return alignment; case ty_enum: - return qfo_log2 (ev_types[ev_integer]->alignment); + return qfo_log2 (ev_types[ev_int]->alignment); case ty_array: return get_type_alignment_log (qfo, type_def->array.type); case ty_class: @@ -781,13 +798,13 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) } static __attribute__((pure)) dparmsize_t -get_parmsize (qfo_t *qfo, pointer_t type) +get_paramsize (qfo_t *qfo, pr_ptr_t type) { - dparmsize_t parmsize = { + dparmsize_t paramsize = { get_type_size (qfo, type), get_type_alignment_log (qfo, type), }; - return parmsize; + return paramsize; } static void @@ -806,11 +823,11 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) } if (type->meta != ty_basic || type->type != ev_func) return; - df->numparms = num_params = type->func.num_params; + df->numparams = num_params = type->func.num_params; if (num_params < 0) num_params = ~num_params; for (i = 0; i < num_params; i++) { - df->parm_size[i] = get_parmsize (qfo, type->func.param_types[i]); + df->param_size[i] = get_paramsize (qfo, type->func.param_types[i]); } } @@ -819,7 +836,7 @@ qfo_def_to_ddef (qfo_t *qfo, const qfo_def_t *def, ddef_t *ddef) { ddef->type = get_def_type (qfo, def->type); ddef->ofs = def->offset; - ddef->s_name = def->name; + ddef->name = def->name; if (!(def->flags & QFOD_NOSAVE) && !(def->flags & QFOD_CONSTANT) && (def->flags & QFOD_GLOBAL) @@ -907,21 +924,79 @@ align_globals_size (unsigned size) return RUP (size, 16 / sizeof (pr_type_t)); } -static int -qfo_def_compare (const void *i1, const void *i2, void *d) +static pr_uint_t +qfo_count_locals (const qfo_t *qfo, pr_uint_t *big_locals) { - __auto_type defs = (const qfo_def_t *) d; - unsigned ind1 = *(unsigned *) i1; - unsigned ind2 = *(unsigned *) i2; - const qfo_def_t *def1 = defs + ind1; - const qfo_def_t *def2 = defs + ind2; - return def1->offset - def2->offset; + if (options.code.progsversion == PROG_VERSION) { + // Ruamoko progs keep their locals on the stack rather than a + // "protected" area in the globals + *big_locals = 0; + return 0; + } + + pr_uint_t locals_size = 0; + for (pr_uint_t i = qfo_num_spaces; i < qfo->num_spaces; i++) { + if (options.code.local_merging) { + if (locals_size < qfo->spaces[i].data_size) { + locals_size = qfo->spaces[i].data_size; + *big_locals = i; + } + } else { + locals_size += align_globals_size (qfo->spaces[i].data_size); + } + } + return locals_size; +} + +typedef struct globals_info_s { + pr_uint_t locals_start; + pr_uint_t locals_size; + pr_uint_t big_locals; + pr_uint_t near_data_size; + pr_uint_t type_encodings_start; + pr_uint_t xdefs_start; + pr_uint_t xdefs_size; + pr_uint_t globals_size; +} globals_info_t; + + +static globals_info_t +qfo_count_globals (qfo_t *qfo, dprograms_t *progs, int word_align) +{ + globals_info_t info = {}; + info.globals_size = qfo->spaces[qfo_near_data_space].data_size; + info.globals_size = RUP (info.globals_size, word_align); + + info.locals_start = info.globals_size; + info.locals_size = qfo_count_locals (qfo, &info.big_locals); + info.globals_size += info.locals_size; + info.near_data_size = info.globals_size; + + info.globals_size = RUP (info.globals_size, word_align); + info.globals_size += qfo->spaces[qfo_far_data_space].data_size; + + info.type_encodings_start = info.globals_size; + info.globals_size += qfo->spaces[qfo_type_space].data_size; + info.globals_size = RUP (info.globals_size, type_xdef.alignment); + + info.xdefs_start = info.globals_size; + info.xdefs_size = progs->globaldefs.count + progs->fielddefs.count; + info.xdefs_size *= type_size (&type_xdef); + info.globals_size += info.xdefs_size; + + return info; +} + +static pr_uint_t +qfo_next_offset (pr_chunk_t chunk, pr_uint_t size, pr_uint_t align) +{ + size *= chunk.count; + return RUP (chunk.offset + size, align); } dprograms_t * qfo_to_progs (qfo_t *in_qfo, int *size) { - byte *data; char *strings; dstatement_t *statements; dfunction_t *functions; @@ -936,18 +1011,19 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo_def_t *types_def = 0; qfo_def_t *xdefs_def = 0; unsigned i, j; - unsigned near_data_size = 0; - unsigned locals_size = 0; - int locals_start; - int type_encodings_start; - int xdefs_start; - unsigned big_locals = 0; int big_func = 0; pr_xdefs_t *xdefs = 0; xdef_t *xdef; - unsigned *def_indices; - unsigned *far_def_indices; - unsigned *field_def_indices; + + // id progs were aligned to only 4 bytes, but 8 is much more reasonable + pr_uint_t byte_align = 8; + if (options.code.progsversion == PROG_VERSION) { + byte_align = __alignof__ (pr_lvec4_t); + } else if (options.code.progsversion == PROG_V6P_VERSION) { + byte_align = 16; + } + pr_uint_t word_align = byte_align / sizeof (pr_int_t); + qfo_t *qfo = alloca (sizeof (qfo_t) + in_qfo->num_spaces * sizeof (qfo_mspace_t)); @@ -960,102 +1036,65 @@ qfo_to_progs (qfo_t *in_qfo, int *size) *size = RUP (sizeof (dprograms_t), 16); progs = calloc (1, *size); progs->version = options.code.progsversion; - progs->numstatements = qfo->spaces[qfo_code_space].data_size; - progs->numglobaldefs = qfo->spaces[qfo_near_data_space].num_defs; + // crc is set in qfcc.c if enabled + + // these are in order in which they usually appear in the file rather + // than the order they appear in the struct, though with the offsets + // it doesn't matter too much. However, as people expect a certain + // layout, ti does matter enough to preserve the traditional file order. + progs->strings.offset = *size; + progs->strings.count = qfo->spaces[qfo_strings_space].data_size; + + progs->statements.offset = qfo_next_offset (progs->strings, + sizeof (char), + byte_align); + progs->statements.count = qfo->spaces[qfo_code_space].data_size; + + progs->functions.offset = qfo_next_offset (progs->statements, + sizeof (dstatement_t), + byte_align); + progs->functions.count = qfo->num_funcs + 1; + + progs->globaldefs.offset = qfo_next_offset (progs->functions, + sizeof (dfunction_t), + byte_align); + progs->globaldefs.count = qfo->spaces[qfo_near_data_space].num_defs; //ddef offsets are 16 bits so the ddef ofs will likely be invalid //thus it will be forced invalid and the true offset written to the //.xdefs array in the progs file - progs->numglobaldefs += qfo->spaces[qfo_far_data_space].num_defs; - progs->numfielddefs = qfo->spaces[qfo_entity_space].num_defs; - progs->numfunctions = qfo->num_funcs + 1; - progs->numstrings = qfo->spaces[qfo_strings_space].data_size; - progs->numglobals = qfo->spaces[qfo_near_data_space].data_size; - progs->numglobals = align_globals_size (progs->numglobals); - locals_start = progs->numglobals; - for (i = qfo_num_spaces; i < qfo->num_spaces; i++) { - if (options.code.local_merging) { - if (locals_size < qfo->spaces[i].data_size) { - locals_size = qfo->spaces[i].data_size; - big_locals = i; - } - } else { - locals_size += align_globals_size (qfo->spaces[i].data_size); - } - } - progs->numglobals += locals_size; - near_data_size = progs->numglobals; - progs->numglobals = RUP (progs->numglobals, 16 / sizeof (pr_type_t)); - progs->numglobals += qfo->spaces[qfo_far_data_space].data_size; - type_encodings_start = progs->numglobals; - progs->numglobals += qfo->spaces[qfo_type_space].data_size; - progs->numglobals = RUP (progs->numglobals, type_xdef.alignment); - xdefs_start = progs->numglobals; - progs->numglobals += progs->numglobaldefs * type_size (&type_xdef); - progs->numglobals += progs->numfielddefs * type_size (&type_xdef); + progs->globaldefs.count += qfo->spaces[qfo_far_data_space].num_defs; + + progs->fielddefs.offset = qfo_next_offset (progs->globaldefs, + sizeof (ddef_t), + byte_align); + progs->fielddefs.count = qfo->spaces[qfo_entity_space].num_defs; + + progs->globals.offset = qfo_next_offset (progs->fielddefs, + sizeof (ddef_t), + byte_align); + globals_info_t globals_info = qfo_count_globals (qfo, progs, word_align); + progs->globals.count = globals_info.globals_size; + progs->entityfields = qfo->spaces[qfo_entity_space].data_size; // qfo_debug_space does not go in the progs file - *size += progs->numstatements * sizeof (dstatement_t); - *size += progs->numglobaldefs * sizeof (ddef_t); - *size += progs->numfielddefs * sizeof (ddef_t); - *size += progs->numfunctions * sizeof (dfunction_t); - *size += RUP (progs->numstrings * sizeof (char), 16); - *size += progs->numglobals * sizeof (pr_type_t); + + *size = qfo_next_offset (progs->globals, sizeof (pr_type_t), 1); progs = realloc (progs, *size); - data = (byte *) progs; memset (progs + 1, 0, *size - sizeof (dprograms_t)); - data += RUP (sizeof (dprograms_t), 16); - def_indices = alloca ((progs->numglobaldefs + progs->numfielddefs) - * sizeof (*def_indices)); - far_def_indices = def_indices + qfo->spaces[qfo_near_data_space].num_defs; - field_def_indices = def_indices + progs->numglobaldefs; - for (unsigned i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { - def_indices[i] = i; - } - for (unsigned i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { - far_def_indices[i] = i; - } - for (unsigned i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { - field_def_indices[i] = i; - } - qsort_r (def_indices, qfo->spaces[qfo_near_data_space].num_defs, - sizeof (unsigned), qfo_def_compare, - qfo->spaces[qfo_near_data_space].defs); - qsort_r (far_def_indices, qfo->spaces[qfo_far_data_space].num_defs, - sizeof (unsigned), qfo_def_compare, - qfo->spaces[qfo_far_data_space].defs); - qsort_r (field_def_indices, qfo->spaces[qfo_entity_space].num_defs, - sizeof (unsigned), qfo_def_compare, - qfo->spaces[qfo_entity_space].defs); - - progs->ofs_strings = data - (byte *) progs; - strings = (char *) data; - data += RUP (progs->numstrings * sizeof (char), 16); - - progs->ofs_statements = data - (byte *) progs; - statements = (dstatement_t *) data; - data += progs->numstatements * sizeof (dstatement_t); - - progs->ofs_functions = data - (byte *) progs; - functions = (dfunction_t *) data; +#define qfo_block(t,b) (t *) ((byte *) progs + progs->b.offset) + strings = qfo_block (char, strings); + statements = qfo_block (dstatement_t, statements); + functions = qfo_block (dfunction_t, functions); functions++; // skip over null function - data += progs->numfunctions * sizeof (dfunction_t); - - progs->ofs_globaldefs = data - (byte *) progs; - globaldefs = (ddef_t *) data; - data += progs->numglobaldefs * sizeof (ddef_t); - - progs->ofs_fielddefs = data - (byte *) progs; - fielddefs = (ddef_t *) (globaldefs + progs->numglobaldefs); - data += progs->numfielddefs * sizeof (ddef_t); - - progs->ofs_globals = data - (byte *) progs; - globals = (pr_type_t*) data; - locals = globals + locals_start; - far_data = globals + near_data_size; - type_data = globals + type_encodings_start; - xdef_data = globals + xdefs_start; + globaldefs = qfo_block (ddef_t, globaldefs); + fielddefs = qfo_block (ddef_t, fielddefs); + globals = qfo_block (pr_type_t, globals); + locals = globals + globals_info.locals_start; + far_data = globals + globals_info.near_data_size; + type_data = globals + globals_info.type_encodings_start; + xdef_data = globals + globals_info.xdefs_start; memcpy (strings, qfo->spaces[qfo_strings_space].strings, qfo->spaces[qfo_strings_space].data_size * sizeof (char)); @@ -1071,22 +1110,26 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo_mspace_t *space = qfo->spaces + qf->locals_space; df->first_statement = qf->code; - df->parm_start = locals_start; df->locals = space->data_size; - // finalize the offsets of the local defs - for (j = 0; j < space->num_defs; j++) - space->defs[j].offset += locals_start; - if (!options.code.local_merging) - locals_start += align_globals_size (df->locals); + if (options.code.progsversion < PROG_VERSION) { + df->params_start = globals_info.locals_start; + // finalize the offsets of the local defs + for (j = 0; j < space->num_defs; j++) + space->defs[j].offset += globals_info.locals_start; + if (!options.code.local_merging) + globals_info.locals_start += align_globals_size (df->locals); + } else { + // relative to start of locals for Ruamoko progs + df->params_start = qf->params_start; + } df->profile = 0; - df->s_name = qf->name; - df->s_file = qf->file; + df->name = qf->name; + df->file = qf->file; function_params (qfo, qf, df); } for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { - unsigned ind = def_indices[i]; - qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + ind; + qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; const char *defname = QFO_GETSTR (qfo, def->name); if (!strcmp (defname, ".type_encodings")) types_def = def; @@ -1096,8 +1139,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { - unsigned ind = far_def_indices[i]; - qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + ind; + qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; def->offset += far_data - globals; qfo_def_to_ddef (qfo, def, globaldefs); // the correct offset will be written to the far data space @@ -1106,13 +1148,12 @@ qfo_to_progs (qfo_t *in_qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_type_space].num_defs; i++) { - qfo->spaces[qfo_type_space].defs[i].offset += type_encodings_start; + qfo->spaces[qfo_type_space].defs[i].offset += globals_info.type_encodings_start; } for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { - unsigned ind = field_def_indices[i]; - qfo_def_to_ddef (qfo, qfo->spaces[qfo_entity_space].defs + ind, - fielddefs + i); + qfo_def_to_ddef (qfo, qfo->spaces[qfo_entity_space].defs + i, + fielddefs + i); } // copy near data @@ -1120,7 +1161,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo->spaces[qfo_near_data_space].data_size * sizeof (pr_type_t)); qfo->spaces[qfo_near_data_space].data = globals; // clear locals data - memset (locals, 0, locals_size * sizeof (pr_type_t)); + memset (locals, 0, globals_info.locals_size * sizeof (pr_type_t)); // copy far data memcpy (far_data, qfo->spaces[qfo_far_data_space].data, qfo->spaces[qfo_far_data_space].data_size * sizeof (pr_type_t)); @@ -1134,30 +1175,30 @@ qfo_to_progs (qfo_t *in_qfo, int *size) if (types_def) { qfot_type_encodings_t *encodings; encodings = (qfot_type_encodings_t *) &globals[types_def->offset]; - encodings->types = type_encodings_start; + encodings->types = globals_info.type_encodings_start; encodings->size = qfo->spaces[qfo_type_space].data_size; } if (xdefs_def) { xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; xdef = (xdef_t *) xdef_data; - xdefs->xdefs = xdefs_start; - xdefs->num_xdefs = progs->numglobaldefs + progs->numfielddefs; + xdefs->xdefs = globals_info.xdefs_start; + xdefs->num_xdefs = progs->globaldefs.count + progs->fielddefs.count; for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; - xdef->type = def->type + type_encodings_start; + xdef->type = def->type + globals_info.type_encodings_start; xdef->ofs = def->offset; } for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; - xdef->type = def->type + type_encodings_start; + xdef->type = def->type + globals_info.type_encodings_start; xdef->ofs = def->offset; } for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_entity_space].defs + i; - xdef->type = def->type + type_encodings_start; + xdef->type = def->type + globals_info.type_encodings_start; xdef->ofs = def->offset; } } @@ -1169,24 +1210,25 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo_func_t *qf = qfo->funcs + i; qfo_mspace_t *space = qfo->spaces + qf->locals_space; - if (qf->locals_space == big_locals) + if (qf->locals_space == globals_info.big_locals) big_func = i; for (j = 0; j < space->num_defs; j++) - space->defs[j].offset -= df->parm_start; + space->defs[j].offset -= df->params_start; } if (options.verbosity >= 0) { const char *big_function = ""; if (big_func) big_function = va (0, " (%s)", strings + qfo->funcs[big_func].name); - printf ("%6i strofs\n", progs->numstrings); - printf ("%6i statements\n", progs->numstatements); - printf ("%6i functions\n", progs->numfunctions); - printf ("%6i global defs\n", progs->numglobaldefs); - printf ("%6i field defs\n", progs->numfielddefs); - printf ("%6i globals\n", progs->numglobals); - printf (" %6i near globals\n", near_data_size); - printf (" %6i locals size%s\n", locals_size, big_function); + printf ("%6i strofs\n", progs->strings.count); + printf ("%6i statements\n", progs->statements.count); + printf ("%6i functions\n", progs->functions.count); + printf ("%6i global defs\n", progs->globaldefs.count); + printf ("%6i field defs\n", progs->fielddefs.count); + printf ("%6i globals\n", progs->globals.count); + printf (" %6i near globals\n", globals_info.near_data_size); + printf (" %6i locals size%s\n", + globals_info.locals_size, big_function); printf (" %6i far globals\n", qfo->spaces[qfo_far_data_space].data_size); printf (" %6i type globals\n", diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 7f87e43df..c00f2f43e 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -65,7 +65,7 @@ typedef def_t *(*encode_f) (type_t *type, defspace_t *space); -static string_t +static pr_string_t encoding_string (const char *string) { int str; @@ -149,12 +149,13 @@ qfo_encode_basic (type_t *type, defspace_t *space) if (type->type == ev_func) return qfo_encode_func (type, space); - else if (type->type == ev_pointer || type->type == ev_field) + else if (type->type == ev_ptr || type->type == ev_field) return qfo_encode_fldptr (type, space); - def = qfo_new_encoding (type, sizeof (enc->type), space); + def = qfo_new_encoding (type, sizeof (enc->basic), space); enc = D_POINTER (qfot_type_t, def); - enc->type = type->type; + enc->basic.type = type->type; + enc->basic.width = type->width; return def; } @@ -214,7 +215,7 @@ qfo_encode_struct (type_t *type, defspace_t *space) if (i == num_fields) internal_error (0, "whoa, what happened?"); if (sym->sy_type == sy_const) - offset = sym->s.value->v.integer_val; + offset = sym->s.value->v.int_val; else offset = sym->s.offset; ENC_DEF (strct->fields[i].type, field_types[i]); diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index a9bda7a3c..5c97f780c 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -47,15 +47,49 @@ #include "tools/qfcc/include/statements.h" #include "tools/qfcc/include/type.h" -hashtab_t *opcode_type_table; -hashtab_t *opcode_void_table; +typedef struct v6p_uint_opcode_s { + pr_opcode_v6p_e op; + v6p_opcode_t opcode; +} v6p_uint_opcode_t; + +static v6p_uint_opcode_t v6p_uint_opcodes[] = { + {OP_LOAD_I_v6p, {"load", "load.i", ev_entity, ev_field, ev_uint }}, + {OP_LOADBI_I_v6p, {"load", "loadbi.i", ev_ptr, ev_short, ev_uint }}, + {OP_ADDRESS_I_v6p, {"lea", "address.i",ev_uint, ev_invalid, ev_ptr }}, + {OP_STORE_I_v6p, {"assign", "store.i", ev_uint, ev_uint, ev_invalid }}, + {OP_STOREP_I_v6p, {"store", "storep.i", ev_uint, ev_ptr, ev_invalid }}, + {OP_STOREB_I_v6p, {"store", "storeb.i", ev_uint, ev_ptr, ev_int }}, + {OP_STOREBI_I_v6p, {"store", "storebi.i",ev_uint, ev_ptr, ev_short }}, + {OP_IF_v6p, {"ifnz", "if", ev_uint, ev_short, ev_invalid }}, + {OP_IFNOT_v6p, {"ifz", "ifnot", ev_uint, ev_short, ev_invalid }}, + {OP_ADD_I_v6p, {"add", "add.i", ev_uint, ev_uint, ev_uint }}, + {OP_SUB_I_v6p, {"sub", "sub.i", ev_uint, ev_uint, ev_uint }}, + {OP_MUL_I_v6p, {"mul", "mul.i", ev_uint, ev_uint, ev_uint }}, + {OP_DIV_I_v6p, {"div", "div.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITAND_I_v6p, {"bitand", "bitand.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITOR_I_v6p, {"bitor", "bitor.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITXOR_I_v6p, {"bitxor", "bitxor.i", ev_uint, ev_uint, ev_uint }}, + {OP_REM_I_v6p, {"rem", "rem.i", ev_uint, ev_uint, ev_uint }}, + {OP_MOD_I_v6p, {"mod", "mod.i", ev_uint, ev_uint, ev_uint }}, + {OP_SHL_I_v6p, {"shl", "shl.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITNOT_I_v6p, {"bitnot", "bitnot.i", ev_uint, ev_invalid, ev_int }}, + {} +}; + +static hashtab_t *v6p_opcode_type_table; +static hashtab_t *v6p_opcode_void_table; +static hashtab_t *v6p_opcode_uint_table; +static v6p_opcode_t *v6p_opcode_map; + +static hashtab_t *rua_opcode_type_table; +static hashtab_t *rua_opcode_void_table; #define ROTL(x,n) ((((unsigned)(x))<<(n))|((unsigned)(x))>>(32-n)) static uintptr_t -get_hash (const void *_op, void *_tab) +v6p_get_hash (const void *_op, void *_tab) { - opcode_t *op = (opcode_t *) _op; + v6p_opcode_t *op = (v6p_opcode_t *) _op; uintptr_t hash; hash = ROTL (~op->type_a, 8) + ROTL (~op->type_b, 16) @@ -64,10 +98,10 @@ get_hash (const void *_op, void *_tab) } static int -compare (const void *_opa, const void *_opb, void *unused) +v6p_compare (const void *_opa, const void *_opb, void *unused) { - opcode_t *opa = (opcode_t *) _opa; - opcode_t *opb = (opcode_t *) _opb; + v6p_opcode_t *opa = (v6p_opcode_t *) _opa; + v6p_opcode_t *opb = (v6p_opcode_t *) _opb; int cmp; cmp = (opa->type_a == opb->type_a) @@ -77,9 +111,59 @@ compare (const void *_opa, const void *_opb, void *unused) } static const char * -get_key (const void *op, void *unused) +v6p_get_key (const void *op, void *unused) { - return ((opcode_t *) op)->name; + return ((v6p_opcode_t *) op)->name; +} + +static uintptr_t +v6p_uint_get_hash (const void *_op, void *_tab) +{ + __auto_type uint_op = (v6p_uint_opcode_t *) _op; + return v6p_get_hash (&uint_op->opcode, _tab); +} + +static int +v6p_uint_compare (const void *_opa, const void *_opb, void *data) +{ + __auto_type uint_opa = (v6p_uint_opcode_t *) _opa; + __auto_type uint_opb = (v6p_uint_opcode_t *) _opb; + return v6p_compare (&uint_opa->opcode, &uint_opb->opcode, data); +} + +static uintptr_t +rua_get_hash (const void *_op, void *_tab) +{ + opcode_t *op = (opcode_t *) _op; + uintptr_t hash; + + hash = ROTL (~op->types[0], 8) + ROTL (~op->types[1], 16) + + ROTL (~op->types[2], 24); + hash += ROTL (~op->widths[0], 12) + ROTL (~op->widths[1], 20) + + ROTL (~op->widths[2], 28); + return hash + Hash_String (op->opname); +} + +static int +rua_compare (const void *_opa, const void *_opb, void *unused) +{ + opcode_t *opa = (opcode_t *) _opa; + opcode_t *opb = (opcode_t *) _opb; + int cmp; + + cmp = (opa->types[0] == opb->types[0]) + && (opa->types[1] == opb->types[1]) + && (opa->types[2] == opb->types[2]); + cmp &= (opa->widths[0] == opb->widths[0]) + && (opa->widths[1] == opb->widths[1]) + && (opa->widths[2] == opb->widths[2]); + return cmp && !strcmp (opa->opname, opb->opname); +} + +static const char * +rua_get_key (const void *op, void *unused) +{ + return ((opcode_t *) op)->opname; } static int @@ -91,78 +175,338 @@ check_operand_type (etype_t ot1, etype_t ot2) return 0; } -opcode_t * -opcode_find (const char *name, operand_t *op_a, operand_t *op_b, - operand_t *op_c) +static int +check_operand_width (int ow1, int ow2) { - opcode_t search_op; - opcode_t *op; - opcode_t *sop; + return (ow1 == -1 || ow1 == ow2); +} + +pr_ushort_t +opcode_get (instruction_t *op) +{ + if (options.code.progsversion < PROG_VERSION) { + return (v6p_opcode_t *) op - v6p_opcode_map; + } else { + return (opcode_t *) op - pr_opcodes; + } +} + +static v6p_opcode_t * +v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, + operand_t *op_c) +{ + v6p_uint_opcode_t search_op = { + .opcode = { + .name = name, + .type_a = op_a ? low_level_type (op_a->type) : ev_invalid, + .type_b = op_b ? low_level_type (op_b->type) : ev_invalid, + .type_c = op_c ? low_level_type (op_c->type) : ev_invalid, + }, + }; + v6p_uint_opcode_t *uint_op; + v6p_opcode_t *op; + v6p_opcode_t *sop; void **op_list; int i; - search_op.name = name; - search_op.type_a = op_a ? low_level_type (op_a->type) : ev_invalid; - search_op.type_b = op_b ? low_level_type (op_b->type) : ev_invalid; - search_op.type_c = op_c ? low_level_type (op_c->type) : ev_invalid; - op = Hash_FindElement (opcode_type_table, &search_op); + uint_op = Hash_FindElement (v6p_opcode_uint_table, &search_op); + if (uint_op) { + return v6p_opcode_map + uint_op->op; + } + op = Hash_FindElement (v6p_opcode_type_table, &search_op.opcode); if (op) return op; - op_list = Hash_FindList (opcode_void_table, name); + op_list = Hash_FindList (v6p_opcode_void_table, name); if (!op_list) return op; for (i = 0; !op && op_list[i]; i++) { sop = op_list[i]; - if (check_operand_type (sop->type_a, search_op.type_a) - && check_operand_type (sop->type_b, search_op.type_b) - && check_operand_type (sop->type_c, search_op.type_c)) + if (check_operand_type (sop->type_a, search_op.opcode.type_a) + && check_operand_type (sop->type_b, search_op.opcode.type_b) + && check_operand_type (sop->type_c, search_op.opcode.type_c)) op = sop; } free (op_list); return op; } -static void -opcode_free (void *_op, void *unused) +static const char *unsigned_demote_ops[] = { + "add", + "bitand", + "bitnot", + "bitor", + "bitxor", + "eq", + "ifnz", + "ifz", + "mul", + "ne", + "sub", +}; + +static int +ud_compare (const void *_a, const void *_b) { - free (_op); + const char *a = _a; + const char *b = *(const char **)_b; + return strcmp (a, b); } -void -opcode_init (void) +static etype_t __attribute__((pure)) +operand_type (const operand_t *op, const char *name) { - const opcode_t *op; - opcode_t *mop; - - if (opcode_type_table) { - Hash_FlushTable (opcode_void_table); - Hash_FlushTable (opcode_type_table); - } else { - PR_Opcode_Init (); - opcode_type_table = Hash_NewTable (1021, 0, opcode_free, 0, 0); - Hash_SetHashCompare (opcode_type_table, get_hash, compare); - opcode_void_table = Hash_NewTable (1021, get_key, 0, 0, 0); + if (!op) { + return ev_invalid; } - for (op = pr_opcodes; op->name; op++) { + etype_t type = low_level_type (op->type); + if (type == ev_vector || type == ev_quaternion) { + return ev_float; + } + if (type == ev_uint || type == ev_ulong) { + if (bsearch (name, unsigned_demote_ops, + sizeof (unsigned_demote_ops) + / sizeof (unsigned_demote_ops[0]), + sizeof (unsigned_demote_ops[0]), + ud_compare)) { + if (type == ev_uint) { + type = ev_int; + } + if (type == ev_ulong) { + type = ev_long; + } + } + } + return type; +} + +static int +operand_width (const char *opname, operand_t *op) +{ + if (!op) { + return 0; + } + etype_t type = low_level_type (op->type); + if (type == ev_vector) { + return 3; + } + if (type == ev_quaternion) { + return 4; + } + // FIXME see FIXME in rua_opcode_find + if ((type == ev_long || type == ev_ulong || type == ev_double) + && (!strcmp (opname, "load") || !strcmp (opname, "store") + || !strcmp (opname, "assign"))) { + if (op->width < 3) { + return op->width * 2; + } + } + return op->width; +} + +static opcode_t * +rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, + operand_t *op_c) +{ + // FIXME this is a bit of an ugly hack to map 64-bit load and store/assign + // instructions: 1 and 2 component instructions become 2 and 4 components + // using the 32-bit instructions, while 3 and 4 remain unchanged but use + // the 64-bit versions of the instructs (of which there are only 3 and 4 + // component versions). That bit of fun can't be helped without wasting a + // lot of instructions, but this mapping scheme leaves a lot to be desired. + const char *opname_a = ""; + const char *opname_c = ""; + etype_t type; + if ((!strcmp (name, "load") || !strcmp (name, "store") + || !strcmp (name, "assign")) + && ((type = low_level_type (op_c->type)) == ev_long + || type == ev_ulong || type == ev_double)) { + opname_c = name; + if (!strcmp (name, "assign")) { + opname_a = name; + if (op_c->width > 2) { + name = "assign64"; + } + } + if (!strcmp (name, "load")) { + if (op_c->width > 2) { + name = "load64"; + } + } + if (!strcmp (name, "store")) { + if (op_c->width > 2) { + name = "store64"; + } + } + } + + opcode_t search_op = { + .opname = name, + .types = { + operand_type (op_a, name), + operand_type (op_b, name), + operand_type (op_c, name), + }, + .widths = { + operand_width (opname_a, op_a), + operand_width ("", op_b), + operand_width (opname_c, op_c), + }, + }; + opcode_t *op; + opcode_t *sop; + void **op_list; + int i; + +#if 0 + printf ("%s [%s %d] [%s %d] [%s %d]\n", search_op.opname, + pr_type_name[search_op.types[0]], search_op.widths[0], + pr_type_name[search_op.types[1]], search_op.widths[1], + pr_type_name[search_op.types[2]], search_op.widths[2]); +#endif + op = Hash_FindElement (rua_opcode_type_table, &search_op); + if (op) + return op; + op_list = Hash_FindList (rua_opcode_void_table, name); + if (!op_list) + return op; + for (i = 0; !op && op_list[i]; i++) { + sop = op_list[i]; + if (!(check_operand_type (sop->types[0], search_op.types[0]) + && check_operand_type (sop->types[1], search_op.types[1]) + && check_operand_type (sop->types[2], search_op.types[2]))) { + continue; + } + if (!(check_operand_width (sop->widths[0], search_op.widths[0]) + && check_operand_width (sop->widths[1], search_op.widths[1]) + && check_operand_width (sop->widths[2], search_op.widths[2]))) { +#if 0 + printf ("%s [%s %d] [%s %d] [%s %d]\n", sop->opname, + pr_type_name[sop->types[0]], sop->widths[0], + pr_type_name[sop->types[1]], sop->widths[1], + pr_type_name[sop->types[2]], sop->widths[2]); +#endif + continue; + } + op = sop; + } + free (op_list); + return op; +} + +instruction_t * +opcode_find (const char *name, operand_t *op_a, operand_t *op_b, + operand_t *op_c) +{ + if (options.code.progsversion < PROG_VERSION) { + return (instruction_t *) v6p_opcode_find (name, op_a, op_b, op_c); + } else { + return (instruction_t *) rua_opcode_find (name, op_a, op_b, op_c); + } +} + +static void +v6p_opcode_init (void) +{ + const v6p_opcode_t *op; + v6p_opcode_t *mop; + + if (v6p_opcode_type_table) { + Hash_FlushTable (v6p_opcode_void_table); + Hash_FlushTable (v6p_opcode_type_table); + Hash_FlushTable (v6p_opcode_uint_table); + } else { + v6p_opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); + Hash_SetHashCompare (v6p_opcode_type_table, v6p_get_hash, v6p_compare); + v6p_opcode_void_table = Hash_NewTable (1021, v6p_get_key, 0, 0, 0); + v6p_opcode_uint_table = Hash_NewTable (1021, 0, 0, 0, 0); + Hash_SetHashCompare (v6p_opcode_uint_table, + v6p_uint_get_hash, v6p_uint_compare); + } + + int num_opcodes = 0; + for (op = pr_v6p_opcodes; op->name; op++) { + num_opcodes++; + } + if (!v6p_opcode_map) { + v6p_opcode_map = calloc (num_opcodes, sizeof (v6p_opcode_t)); + } + for (int i = 0; i < num_opcodes; i++) { + op = pr_v6p_opcodes + i; if (op->min_version > options.code.progsversion) continue; - mop = malloc (sizeof (opcode_t)); + mop = v6p_opcode_map + i; *mop = *op; if (options.code.progsversion == PROG_ID_VERSION) { // v6 progs have no concept of integer, but the QF engine // treats the operands of certain operands as integers // irrespective the progs version, so convert the engine's // view of the operands to the prog's view. - if (mop->type_a == ev_integer) + if (mop->type_a == ev_int) mop->type_a = ev_float; - if (mop->type_b == ev_integer) + if (mop->type_b == ev_int) mop->type_b = ev_float; - if (mop->type_c == ev_integer) + if (mop->type_c == ev_int) mop->type_c = ev_float; } - Hash_AddElement (opcode_type_table, mop); + Hash_AddElement (v6p_opcode_type_table, mop); if (mop->type_a == ev_void || mop->type_b == ev_void || mop->type_c == ev_void) - Hash_Add (opcode_void_table, mop); + Hash_Add (v6p_opcode_void_table, mop); + } + if (options.code.progsversion != PROG_ID_VERSION) { + for (__auto_type uiop = &v6p_uint_opcodes[0]; uiop->op; uiop++) { + Hash_AddElement (v6p_opcode_uint_table, uiop); + } } } + +static void +rua_opcode_init (void) +{ + if (rua_opcode_type_table) { + return; + } + + rua_opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); + Hash_SetHashCompare (rua_opcode_type_table, rua_get_hash, rua_compare); + rua_opcode_void_table = Hash_NewTable (1021, rua_get_key, 0, 0, 0); + + int num_opcodes = sizeof (pr_opcodes) / sizeof (pr_opcodes[0]); + for (int i = 0; i < num_opcodes; i++) { + const opcode_t *op = pr_opcodes + i; + if (!op->opname) { + continue; + } + Hash_AddElement (rua_opcode_type_table, (opcode_t *) op); + if (op->types[0] == ev_void || op->types[1] == ev_void + || op->types[2] == ev_void) { + Hash_Add (rua_opcode_void_table, (opcode_t *) op); + } + } +} + +void +opcode_init (void) +{ + if (options.code.progsversion < PROG_VERSION) { + v6p_opcode_init (); + } else { + rua_opcode_init (); + } +} + +void +opcode_print_statement (pr_uint_t addr, dstatement_t *st) +{ + const char *mnemonic; + // this is ok because v6p has < 300 instructions + int st_op = st->op & 0x1ff; + + if (options.code.progsversion < PROG_VERSION) { + mnemonic = v6p_opcode_map[st_op].opname; + } else { + mnemonic = pr_opcodes[st_op].mnemonic; + } + printf ("%04x (%03x)%-8s %04x %04x %04x\n", + addr, st_op & 0x1ff, mnemonic, st->a, st->b, st->c); +} diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 09989684c..c9cec0127 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -42,14 +42,18 @@ #include -#include "QF/pr_comp.h" #include "QF/va.h" +#include "QF/progs/pr_comp.h" + #include "tools/qfcc/include/cpp.h" #include "tools/qfcc/include/linker.h" #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/type.h" + +#include "tools/qfcc/source/qc-parse.h" const char *this_program; const char **source_files; @@ -68,6 +72,7 @@ enum { OPT_NO_DEFAULT_PATHS, OPT_PROGDEFS, OPT_QCCX_ESCAPES, + OPT_RUAMOKO, OPT_TRADITIONAL, OPT_BUG, }; @@ -91,7 +96,9 @@ static struct option const long_options[] = { {"progs-src", required_argument, 0, 'P'}, {"qccx-escapes", no_argument, 0, OPT_QCCX_ESCAPES}, {"quiet", no_argument, 0, 'q'}, + {"raumoko", no_argument, 0, OPT_RUAMOKO}, {"relocatable", no_argument, 0, 'r'}, + {"ruamoko", no_argument, 0, OPT_RUAMOKO}, {"save-temps", no_argument, 0, 'S'}, {"source", required_argument, 0, 's'}, {"traditional", no_argument, 0, OPT_TRADITIONAL}, @@ -138,7 +145,6 @@ usage (int status) printf ( "Options:\n" " --advanced Advanced Ruamoko mode\n" -" default for separate compilation mode\n" " --bug OPTION,... Set bug options\n" " -C, --code OPTION,... Set code generation options\n" " -c Only compile, don't link\n" @@ -168,6 +174,10 @@ usage (int status) " C/QuakeForge sequences.\n" " -q, --quiet Inhibit usual output\n" " -r, --relocatable Incremental linking\n" +" --raumoko Use both Ruamoko language features and the\n" +" --ruamoko Ruamoko ISA, providing access to SIMD types\n" +" and a stack for locals.\n" +" default for separate compilation mode\n" " -S, --save-temps Do not delete temporary files\n" " -s, --source DIR Look for progs.src in DIR instead of \".\"\n" " --traditional Traditional QuakeC mode: implies v6only\n" @@ -207,8 +217,10 @@ code_usage (void) " passing\n" " vectors to functiosn.\n" " [no-]vector-components Create *_[xyz] symbols for vector variables.\n" -" [no-]v6only Restrict output code to version 6 progs\n" -" features.\n" +" target=v6|v6p|ruamoko Generate code for the specified target VM\n" +" v6 Standard Quake VM (qcc compatible)\n" +" v6p *QuakeForge extended v6 instructions\n" +" ruamoko QuakeForge SIMD instructions\n" "\n" "For details, see the qfcc(1) manual page\n" ); @@ -391,13 +403,19 @@ DecodeArgs (int argc, char **argv) break; case OPT_TRADITIONAL: options.traditional = 2; - options.advanced = false; + options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; options.code.const_initializers = true; break; case OPT_ADVANCED: options.traditional = 0; - options.advanced = true; + options.advanced = 1; + options.code.progsversion = PROG_V6P_VERSION; + options.code.const_initializers = false; + break; + case OPT_RUAMOKO: + options.traditional = 0; + options.advanced = 2; options.code.progsversion = PROG_VERSION; options.code.const_initializers = false; break; @@ -469,6 +487,19 @@ DecodeArgs (int argc, char **argv) while (temp) { qboolean flag = true; + if (!(strncasecmp (temp, "target=", 7))) { + const char *tgt = temp + 7; + if (!strcasecmp (tgt, "v6")) { + options.code.progsversion = PROG_ID_VERSION; + } else if (!strcasecmp (tgt, "v6p")) { + options.code.progsversion = PROG_V6P_VERSION; + } else if (!strcasecmp (tgt, "ruamoko")) { + options.code.progsversion = PROG_VERSION; + } else { + fprintf (stderr, "unknown target: %s\n", tgt); + exit (1); + } + } if (!strncasecmp (temp, "no-", 3)) { flag = false; temp += 3; @@ -501,11 +532,6 @@ DecodeArgs (int argc, char **argv) options.code.vector_calls = flag; } else if (!(strcasecmp (temp, "vector-components"))) { options.code.vector_components = flag; - } else if (!(strcasecmp (temp, "v6only"))) { - if (flag) - options.code.progsversion = PROG_ID_VERSION; - else - options.code.progsversion = PROG_VERSION; } else if (!(strcasecmp (temp, "const-initializers"))) { options.code.const_initializers = flag; } @@ -682,7 +708,7 @@ DecodeArgs (int argc, char **argv) if (saw_MD) options.preprocess_only = 0; if (!source_files && !options.advanced) { - // progs.src mode without --advanced implies --traditional + // progs.src mode without --advanced or --ruamoko implies --traditional // but --extended overrides if (!options.traditional) options.traditional = 2; @@ -697,13 +723,16 @@ DecodeArgs (int argc, char **argv) options.code.local_merging = false; if (options.code.vector_components == (qboolean) -1) options.code.vector_components = true; + if (options.math.vector_mult == 0) + options.math.vector_mult = DOT; } if (!options.code.progsversion) options.code.progsversion = PROG_VERSION; if (!options.traditional) { - options.advanced = true; - add_cpp_def ("-D__RUAMOKO__=1"); - add_cpp_def ("-D__RAUMOKO__=1"); + // avanced=2 requires the Ruamoko ISA + options.advanced = 2 - (options.code.progsversion < PROG_VERSION); + const char *ruamoko = va (0, "-D__RUAMOKO__=%d", options.advanced); + add_cpp_def (save_string (ruamoko)); if (options.code.ifstring == (qboolean) -1) options.code.ifstring = false; if (options.code.short_circuit == (qboolean) -1) @@ -712,6 +741,8 @@ DecodeArgs (int argc, char **argv) options.code.local_merging = true; if (options.code.vector_components == (qboolean) -1) options.code.vector_components = false; + if (options.math.vector_mult == 0) + options.math.vector_mult = options.advanced == 1 ? DOT : '*'; } else { options.code.promote_float = 0; } @@ -725,6 +756,13 @@ DecodeArgs (int argc, char **argv) options.code.crc = false; } + if (options.traditional && options.advanced) { + fprintf (stderr, + "%s: internal error: traditional and advanced twisted\n", + this_program); + abort (); + } + // add the default paths if (!options.no_default_paths) { add_cpp_sysinc ("-isystem"); diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index d82f2aef4..2ee208ca5 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -40,7 +40,8 @@ #include #include "QF/alloc.h" -#include "QF/pr_comp.h" + +#include "QF/progs/pr_comp.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/opcodes.h" @@ -49,6 +50,8 @@ #include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/type.h" +#include "tools/qfcc/source/qc-parse.h" + typedef struct pragma_arg_s { struct pragma_arg_s *next; const char *arg; @@ -62,21 +65,31 @@ static void set_traditional (int traditional) { switch (traditional) { + case -1: + options.traditional = 0; + options.advanced = 2; + options.code.progsversion = PROG_VERSION; + type_default = &type_int; + type_long_int = &type_long; + type_ulong_uint = &type_ulong; + break; case 0: options.traditional = 0; - options.advanced = true; - options.code.progsversion = PROG_VERSION; - type_default = &type_integer; + options.advanced = 1; + options.code.progsversion = PROG_V6P_VERSION; + type_default = &type_int; + type_long_int = &type_int; + type_ulong_uint = &type_uint; break; case 1: options.traditional = 1; - options.advanced = false; + options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; type_default = &type_float; break; case 2: options.traditional = 2; - options.advanced = false; + options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; type_default = &type_float; break; @@ -106,6 +119,73 @@ set_bug (pragma_arg_t *args) } } +static void +set_warn (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing warn flag"); + return; + } + const char *flag = args->arg; + if (!strcmp (flag, "error")) { + options.warnings.promote = true; + } else if (!strcmp (flag, "!error")) { + options.warnings.promote = false; + } + if (args->next) { + warning (0, "pragma warn: ignoring extra arguments"); + } +} + +static void +set_optimize (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing optimize flag"); + return; + } + const char *flag = args->arg; + if (!strcmp (flag, "on") || !strcmp (flag, "!off")) { + options.code.optimize = true; + } else if (!strcmp (flag, "!on") || !strcmp (flag, "off")) { + options.code.optimize = false; + } + if (args->next) { + warning (0, "pragma optimize: ignoring extra arguments"); + } +} + +static pragma_arg_t * +set_vector_mult (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing vector_mult arg"); + return args; + } + const char *op = args->arg; + if (!strcmp (op, "@dot")) { + options.math.vector_mult = DOT; + } else { + warning (0, "unknown vector_mult arg: %s", op); + } + return args->next; +} + +static void +set_math (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing math arg"); + return; + } + while (args) { + const char *a = args->arg; + if (!strcmp (a, "vector_mult")) { + args = set_vector_mult (args->next); + } + } +} + void pragma_process () { @@ -120,8 +200,16 @@ pragma_process () set_traditional (1); } else if (!strcmp (id, "advanced")) { set_traditional (0); + } else if (!strcmp (id, "ruamoko") || !strcmp (id, "raumoko")) { + set_traditional (-1); } else if (!strcmp (id, "bug")) { set_bug (pragma_args->next); + } else if (!strcmp (id, "warn")) { + set_warn (pragma_args->next); + } else if (!strcmp (id, "optimize")) { + set_optimize (pragma_args->next); + } else if (!strcmp (id, "math")) { + set_math (pragma_args->next); } else { warning (0, "unknown pragma: '%s'", id); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 1a3cb9d99..c74dcea4a 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -131,9 +131,9 @@ STRING \"(\\.|[^"\\])*\" else i = strtol (yytext, 0, 0); if (*c == 'u' || *c == 'U') - qc_yylval.expr = new_integer_expr (i);//FIXME + qc_yylval.expr = new_int_expr (i);//FIXME else - qc_yylval.expr = new_integer_expr (i); + qc_yylval.expr = new_int_expr (i); return VALUE; } @@ -208,7 +208,7 @@ STRING \"(\\.|[^"\\])*\" if (str[1]) warning (0, "multibyte char constant"); - qc_yylval.expr = new_integer_expr (*str); + qc_yylval.expr = new_int_expr (*str); return VALUE; } @@ -269,7 +269,7 @@ STRING \"(\\.|[^"\\])*\" "$"{s}*{FRAMEID} { int ret = do_grab (yytext); if (ret >= 0) { - qc_yylval.expr = new_integer_expr (ret); + qc_yylval.expr = new_int_expr (ret); return VALUE; } else { BEGIN (-ret); @@ -284,6 +284,7 @@ STRING \"(\\.|[^"\\])*\" BEGIN (GRAB_OTHER); // ignore rest of line } {ID} { pragma_add_arg (yytext); } +@{ID} { pragma_add_arg (yytext); } <*>\r*\n { if (YY_START == PRAGMA) { @@ -311,6 +312,13 @@ typedef struct { type_t *type; } keyword_t; +// These keywords are part of the Ruamoko language and require the QuakeForge +// Ruamoko VM. +static keyword_t rua_keywords[] = { +#define VEC_TYPE(type_name, base_type) { #type_name, TYPE, &type_##type_name }, +#include "tools/qfcc/include/vec_types.h" +}; + // These keywords are all part of the Ruamoko (Objective-QC) language. // The first time any one of them is encountered, the class system will be // initialized. @@ -367,7 +375,6 @@ static keyword_t at_keywords[] = { {"extern", EXTERN }, {"static", STATIC }, {"sizeof", SIZEOF }, - {"nosave", NOSAVE }, {"not", NOT }, }; @@ -376,16 +383,23 @@ static keyword_t at_keywords[] = { static keyword_t qf_keywords[] = { {"quaternion", TYPE, &type_quaternion}, {"double", TYPE, &type_double}, - {"int", TYPE, &type_integer }, - {"unsigned", TYPE, &type_integer },//FIXME + {"int", TYPE, &type_int }, + {"unsigned", UNSIGNED, 0 }, + {"signed", SIGNED, 0 }, + {"long", LONG, 0 }, + {"short", SHORT, 0 }, - {"@function", TYPE, &type_function }, + {"@function", TYPE, &type_func }, {"@args", ARGS, 0 }, {"@va_list", TYPE, &type_va_list }, {"@param", TYPE, &type_param }, + {"@return", AT_RETURN, 0 }, + + {"@cross", CROSS, 0 }, + {"@dot", DOT, 0 }, }; -// These keywors are always available. Other than @system and @overload, they +// These keywors are always available. Other than the @ keywords, they // form traditional QuakeC. static keyword_t keywords[] = { {"void", TYPE, &type_void }, @@ -401,6 +415,7 @@ static keyword_t keywords[] = { {"else", ELSE, 0 }, {"@system", SYSTEM, 0 }, {"@overload", OVERLOAD, 0 }, + {"@attribute", ATTRIBUTE, 0 }, }; static const char * @@ -419,6 +434,18 @@ process_keyword (keyword_t *keyword, const char *token) sym = symtab_lookup (current_symtab, token); qc_yylval.symbol = sym; + // the global id symbol is always just a name so attempts to redefine + // it globally can be caught and treated as an error, but it needs to + // be redefinable when in an enclosing scope. + if (sym->sy_type == sy_name) { + // this is the global id (object) + return OBJECT; + } else if (sym->sy_type == sy_type) { + // id has been redeclared via a typedef + return TYPE_NAME; + } + // id has been redelcared as a variable (hopefully) + return NAME; } else { qc_yylval.type = keyword->type; } @@ -432,6 +459,7 @@ keyword_or_id (char *token) static hashtab_t *qf_keyword_tab; static hashtab_t *at_keyword_tab; static hashtab_t *obj_keyword_tab; + static hashtab_t *rua_keyword_tab; keyword_t *keyword = 0; symbol_t *sym; @@ -443,6 +471,7 @@ keyword_or_id (char *token) qf_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); at_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); obj_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); + rua_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); #define NUMKEYS(_k) (sizeof (_k) / sizeof (_k[0])) @@ -454,12 +483,19 @@ keyword_or_id (char *token) Hash_Add (at_keyword_tab, &at_keywords[i]); for (i = 0; i < NUMKEYS(obj_keywords); i++) Hash_Add (obj_keyword_tab, &obj_keywords[i]); + for (i = 0; i < NUMKEYS(rua_keywords); i++) + Hash_Add (rua_keyword_tab, &rua_keywords[i]); } if (options.traditional < 1) { - keyword = Hash_Find (obj_keyword_tab, token); - if (keyword) { - if (!obj_initialized) - class_init (); + if (options.code.progsversion == PROG_VERSION) { + keyword = Hash_Find (rua_keyword_tab, token); + } + if (!keyword) { + keyword = Hash_Find (obj_keyword_tab, token); + if (keyword) { + if (!obj_initialized) + class_init (); + } } if (!keyword) keyword = Hash_Find (qf_keyword_tab, token); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f75621a17..2874965a2 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -44,6 +44,7 @@ #include #include +#include "tools/qfcc/include/attribute.h" #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/def.h" @@ -112,6 +113,7 @@ int yylex (void); struct methodlist_s *methodlist; struct symbol_s *symbol; struct symtab_s *symtab; + struct attribute_s *attribute; } // these tokens are common between qc and qp @@ -132,12 +134,14 @@ int yylex (void); %left '^' %left '&' %left EQ NE -%left LE GE LT GT +%left LT GT GE LE +%token NAND NOR XNOR // end of tokens common between qc and qp %left SHL SHR %left '+' '-' -%left '*' '/' '%' MOD +%left '*' '/' '%' MOD SCALE +%left CROSS DOT %right SIZEOF UNARY INCOP %left HYPERUNARY %left '.' '(' '[' @@ -145,9 +149,11 @@ int yylex (void); %token CLASS_NAME NAME %token VALUE STRING -%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS -%token NIL IFBE IFB IFAE IFA GOTO SWITCH CASE DEFAULT ENUM -%token ARGS TYPEDEF EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT +%token LOCAL WHILE DO IF ELSE FOR BREAK CONTINUE +%token RETURN AT_RETURN ELLIPSIS +%token NIL GOTO SWITCH CASE DEFAULT ENUM +%token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE +%token UNSIGNED SIGNED LONG SHORT %token STRUCT %token TYPE %token OBJECT TYPE_NAME @@ -159,6 +165,8 @@ int yylex (void); %type type_specifier type_specifier_or_storage_class %type type +%type attribute_list attribute + %type function_params var_list param_declaration %type qc_func_params qc_var_list qc_param_decl %type new_name @@ -235,6 +243,24 @@ make_spec (type_t *type, storage_class_t storage, int is_typedef, return spec; } +static specifier_t +parse_attributes (attribute_t *attr_list) +{ + specifier_t spec = {}; + for (attribute_t *attr = attr_list; attr; attr = attr->next) { + if (!strcmp (attr->name, "no_va_list")) { + spec.no_va_list = 1; + } else if (!strcmp (attr->name, "nosave")) { + spec.nosave = 1; + } else if (!strcmp (attr->name, "void_return")) { + spec.void_return = 1; + } else { + warning (0, "skipping unknown attribute '%s'", attr->name); + } + } + return spec; +} + static specifier_t spec_merge (specifier_t spec, specifier_t new) { @@ -253,14 +279,80 @@ spec_merge (specifier_t spec, specifier_t new) spec.storage = new.storage; spec.is_typedef = new.is_typedef; } - spec.is_overload |= new.is_overload; - spec.nosave |= new.nosave; + if ((new.is_unsigned && spec.is_signed) + || (new.is_signed && spec.is_unsigned)) { + if (!spec.multi_type) { + error (0, "both signed and unsigned in declaration specifiers"); + spec.multi_type = 1; + } + } + if ((new.is_long && spec.is_short) || (new.is_short && spec.is_long)) { + if (!spec.multi_store) { + error (0, "both long and short in declaration specifiers"); + spec.multi_store = 1; + } + } + spec.sym = new.sym; + spec.spec_bits |= new.spec_bits; return spec; } static specifier_t default_type (specifier_t spec, symbol_t *sym) { + if (spec.type) { + if (is_float (spec.type) && !spec.multi_type) { + // no modifieres allowed + if (spec.is_unsigned) { + spec.multi_type = 1; + error (0, "both unsigned and float in declaration specifiers"); + } else if (spec.is_signed) { + spec.multi_type = 1; + error (0, "both signed and float in declaration specifiers"); + } else if (spec.is_short) { + spec.multi_type = 1; + error (0, "both short and float in declaration specifiers"); + } else if (spec.is_long) { + spec.multi_type = 1; + error (0, "both long and float in declaration specifiers"); + } + } + if (is_double (spec.type)) { + // long is allowed but ignored + if (spec.is_unsigned) { + spec.multi_type = 1; + error (0, "both unsigned and double in declaration specifiers"); + } else if (spec.is_signed) { + spec.multi_type = 1; + error (0, "both signed and double in declaration specifiers"); + } else if (spec.is_short) { + spec.multi_type = 1; + error (0, "both short and double in declaration specifiers"); + } + } + if (is_int (spec.type)) { + // signed and short are ignored + if (spec.is_unsigned && spec.is_long) { + spec.type = &type_ulong; + } else if (spec.is_long) { + spec.type = &type_long; + } + } + } else { + if (spec.is_long) { + if (spec.is_unsigned) { + spec.type = type_ulong_uint; + } else { + spec.type = type_long_int; + } + } else { + if (spec.is_unsigned) { + spec.type = &type_uint; + } else if (spec.is_signed || spec.is_short) { + spec.type = &type_int; + } + } + } if (!spec.type) { spec.type = type_default; warning (0, "type defaults to '%s' in declaration of '%s'", @@ -296,6 +388,49 @@ is_null_spec (specifier_t spec) return memcmp (&spec, &null_spec, sizeof (spec)) == 0; } +static int +use_type_name (specifier_t spec) +{ + spec.sym = new_symbol (spec.sym->name); + spec.sym->type = spec.type; + spec.sym->sy_type = sy_var; + symtab_addsymbol (current_symtab, spec.sym); + return !!spec.sym->table; +} + +static void +check_specifiers (specifier_t spec) +{ + if (!is_null_spec (spec)) { + if (!spec.type && !spec.sym) { + warning (0, "useless specifiers"); + } else if (spec.type && !spec.sym) { + if (is_anonymous_struct (spec)){ + warning (0, "unnamed struct/union that defines " + "no instances"); + } else if (!is_enum (spec.type) && !is_struct (spec.type)) { + warning (0, "useless type name in empty declaration"); + } + } else if (!spec.type && spec.sym) { + bug (0, "wha? %p %p", spec.type, spec.sym); + } else { + // a type name (id, typedef, etc) was used as a variable name. + // this is allowed in C, so long as it's in a different scope + if (!use_type_name (spec)) { + error (0, "%s redeclared as different kind of symbol", + spec.sym->name); + } + } + } +} + +static void +set_func_type_attrs (type_t *func, specifier_t spec) +{ + func->t.func.no_va_list = spec.no_va_list; + func->t.func.void_return = spec.void_return; +} + %} %expect 0 @@ -346,22 +481,7 @@ external_def : optional_specifiers external_decl_list ';' { } | optional_specifiers ';' { - if (!is_null_spec ($1)) { - if (!$1.type && !$1.sym) { - warning (0, "useless specifiers"); - } else if ($1.type && !$1.sym) { - if (is_anonymous_struct ($1)){ - warning (0, "unnamed struct/union that defines " - "no instances"); - } else if (!is_enum ($1.type) && !is_struct ($1.type)) { - warning (0, "useless type name in empty declaration"); - } - } else if (!$1.type && $1.sym) { - bug (0, "wha? %p %p", $1.type, $1.sym); - } else { - bug (0, "wha? %p %p", $1.type, $1.sym); - } - } + check_specifiers ($1); } | optional_specifiers qc_func_params { @@ -376,6 +496,7 @@ external_def ret_type = *type; *type = 0; *type = parse_params (0, $2); + set_func_type_attrs ((*type), $1); $$.type = find_type (append_type ($1.type, ret_type)); if ($$.type->type != ev_field) $$.params = $2; @@ -414,18 +535,18 @@ function_body : optional_state_expr { symbol_t *sym = $0; + specifier_t spec = default_type ($-1, sym); - if (!$-1.type) - $-1.type = type_default; - sym->type = find_type (append_type (sym->type, $-1.type)); - $$ = function_symbol (sym, $-1.is_overload, 1); + set_func_type_attrs (sym->type, spec); + sym->type = find_type (append_type (sym->type, spec.type)); + $$ = function_symbol (sym, spec.is_overload, 1); } save_storage { $$ = current_symtab; current_func = begin_function ($2, 0, current_symtab, 0, $-1.storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; } compound_statement @@ -438,12 +559,12 @@ function_body | '=' '#' expr ';' { symbol_t *sym = $0; + specifier_t spec = default_type ($-1, sym); - if (!$-1.type) - $-1.type = type_default; - sym->type = find_type (append_type (sym->type, $-1.type)); - sym = function_symbol (sym, $-1.is_overload, 1); - build_builtin_function (sym, $3, 0, $-1.storage); + set_func_type_attrs (sym->type, spec); + sym->type = find_type (append_type (sym->type, spec.type)); + sym = function_symbol (sym, spec.is_overload, 1); + build_builtin_function (sym, $3, 0, spec.storage); } ; @@ -463,7 +584,8 @@ external_decl $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { - initialize_def ($1, 0, current_symtab->space, spec.storage); + initialize_def ($1, 0, current_symtab->space, spec.storage, + current_symtab); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } @@ -479,7 +601,8 @@ external_decl $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { - initialize_def ($1, $2, current_symtab->space, spec.storage); + initialize_def ($1, $2, current_symtab->space, spec.storage, + current_symtab); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } @@ -487,6 +610,7 @@ external_decl | function_decl { specifier_t spec = default_type ($0, $1); + set_func_type_attrs ($1->type, spec); $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; @@ -504,13 +628,30 @@ storage_class | SYSTEM { $$ = make_spec (0, sc_system, 0, 0); } | TYPEDEF { $$ = make_spec (0, sc_global, 1, 0); } | OVERLOAD { $$ = make_spec (0, current_storage, 0, 1); } - | NOSAVE + | ATTRIBUTE '(' attribute_list ')' { - $$ = make_spec (0, current_storage, 0, 0); - $$.nosave = 1; + $$ = parse_attributes ($3); } ; +attribute_list + : attribute + | attribute_list ',' attribute + { + if ($3) { + $3->next = $1; + $$ = $3; + } else { + $$ = $1; + } + } + ; + +attribute + : NAME { $$ = new_attribute ($1->name, 0); } + | NAME '(' expr_list ')' { $$ = new_attribute ($1->name, $3); } + ; + optional_specifiers : specifiers { @@ -539,7 +680,9 @@ type // deal with eg "int id" $1.sym = $2.sym; - if (!$1.sym) { + if (!$1.sym && !$1.type) { + $1 = spec_merge ($1, $2); + } else if (!$1.sym) { error (0, "two or more data types in declaration specifiers"); } $$ = $1; @@ -556,6 +699,26 @@ type_specifier { $$ = make_spec ($1, 0, 0, 0); } + | UNSIGNED + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_unsigned = 1; + } + | SIGNED + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_signed = 1; + } + | LONG + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_long = 1; + } + | SHORT + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_short = 1; + } | enum_specifier | struct_specifier | TYPE_NAME @@ -732,11 +895,7 @@ struct_def if ($1.sym && $1.sym->type != $1.type) { // a type name (id, typedef, etc) was used as a field name. // this is allowed in C - $1.sym = new_symbol ($1.sym->name); - $1.sym->type = $1.type; - $1.sym->sy_type = sy_var; - symtab_addsymbol (current_symtab, $1.sym); - if (!$1.sym->table) { + if (!use_type_name ($1)) { error (0, "duplicate field `%s'", $1.sym->name); } } else if (is_anonymous_struct ($1)) { @@ -768,8 +927,7 @@ struct_decl_list struct_decl : function_decl { - if (!$0.type) - $0.type = type_default; + $0 = default_type ($-0, $1); $1->type = find_type (append_type ($1->type, $0.type)); $1->sy_type = sy_var; $1->visibility = current_visibility; @@ -780,8 +938,7 @@ struct_decl } | var_decl { - if (!$0.type) - $0.type = type_default; + $0 = default_type ($-0, $1); $1->type = find_type (append_type ($1->type, $0.type)); $1->sy_type = sy_var; $1->visibility = current_visibility; @@ -900,24 +1057,31 @@ qc_var_list param_declaration : type var_decl { - if (!$1.type) - $1.type = type_default; + $1 = default_type ($1, $2); $2->type = find_type (append_type ($2->type, $1.type)); $$ = new_param (0, $2->type, $2->name); } - | abstract_decl { $$ = new_param (0, $1->type, 0); } + | abstract_decl { $$ = new_param (0, $1->type, $1->name); } | ELLIPSIS { $$ = new_param (0, 0, 0); } ; abstract_decl : type abs_decl { + // abs_decl's symbol is just a carrier for the type + if ($2->name) { + bug (0, "unexpected name in abs_decl"); + } + if ($1.sym) { + $1.sym = new_symbol ($1.sym->name); + $1.sym->type = $2->type; + $2 = $1.sym; + } $$ = $2; - if (!$1.type) - $1.type = type_default; + $1 = default_type ($1, $2); $$->type = find_type (append_type ($$->type, $1.type)); } - | error { $$ = new_symbol (""); } + | error { $$ = new_symbol (0); } ; qc_param_decl @@ -935,6 +1099,7 @@ qc_param_decl type = &(*type)->t.fldptr.type) ; *type = parse_params (*type, $2); + set_func_type_attrs ((*type), $1); $3->type = find_type ($1.type); if ($3->type->type != ev_field) $3->params = $2; @@ -944,7 +1109,7 @@ qc_param_decl ; abs_decl - : /* empty */ { $$ = new_symbol (""); } + : /* empty */ { $$ = new_symbol (0); } | '(' abs_decl ')' function_params { $$ = $2; @@ -969,11 +1134,11 @@ abs_decl array_decl : '[' expr ']' { - if (!is_integer_val ($2) || expr_integer ($2) < 1) { + if (!is_int_val ($2) || expr_int ($2) < 1) { error (0, "invalid array size"); $$ = 0; } else { - $$ = expr_integer ($2); + $$ = expr_int ($2); } } | '[' ']' { $$ = 0; } @@ -1013,6 +1178,7 @@ local_decl_list type = &(*type)->t.fldptr.type) ; *type = parse_params (*type, $1); + set_func_type_attrs ((*type), spec); spec.type = find_type (spec.type); $$ = spec; } @@ -1038,7 +1204,7 @@ decl if (sc == sc_static) space = pr.near_data; $1->type = find_type (append_type ($1->type, spec.type)); - initialize_def ($1, $2, space, sc); + initialize_def ($1, $2, space, sc, current_symtab); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } @@ -1100,11 +1266,12 @@ non_code_func if (local_expr) { symbol_t *sym = $0; specifier_t spec = $-1; - initialize_def (sym, $2, current_symtab->space, spec.storage); + initialize_def (sym, $2, current_symtab->space, spec.storage, + current_symtab); if (sym->s.def) sym->s.def->nosave |= spec.nosave; } else { - if (is_integer_val ($2) || is_float_val ($2)) { + if (is_int_val ($2) || is_float_val ($2)) { error (0, "invalid function initializer." " did you forget #?"); } else { @@ -1121,7 +1288,8 @@ non_code_func if (sym->sy_type == sy_func) make_function (sym, 0, sym->table->space, spec.storage); } else { - initialize_def (sym, 0, current_symtab->space, spec.storage); + initialize_def (sym, 0, current_symtab->space, spec.storage, + current_symtab); if (sym->s.def) sym->s.def->nosave |= spec.nosave; } @@ -1135,7 +1303,7 @@ code_func $$ = current_symtab; current_func = begin_function ($0, 0, current_symtab, 0, $-1.storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; } compound_statement @@ -1244,22 +1412,7 @@ local_def } | specifiers ';' { - if (!is_null_spec ($1)) { - if (!$1.type && !$1.sym) { - warning (0, "useless specifiers"); - } else if ($1.type && !$1.sym) { - if (is_anonymous_struct ($1)){ - warning (0, "unnamed struct/union that defines " - "no instances"); - } else if (!is_enum ($1.type) && !is_struct ($1.type)) { - warning (0, "useless type name in empty declaration"); - } - } else if (!$1.type && $1.sym) { - bug (0, "wha? %p %p", $1.type, $1.sym); - } else { - bug (0, "wha? %p %p", $1.type, $1.sym); - } - } + check_specifiers ($1); $$ = 0; } ; @@ -1271,6 +1424,7 @@ statement | local_def { $$ = $1; } | RETURN opt_expr ';' { $$ = return_expr (current_func, $2); } | RETURN compound_init ';' { $$ = return_expr (current_func, $2); } + | AT_RETURN expr ';' { $$ = at_return_expr (current_func, $2); } | BREAK ';' { $$ = 0; @@ -1425,7 +1579,8 @@ init_var_decl specifier_t spec = $0; $1->type = find_type (append_type ($1->type, spec.type)); $1->sy_type = sy_var; - initialize_def ($1, 0, current_symtab->space, spec.storage); + initialize_def ($1, 0, current_symtab->space, spec.storage, + current_symtab); $$ = assign_expr (new_symbol_expr ($1), $2); } ; @@ -1455,8 +1610,8 @@ unary_expr | '-' cast_expr %prec UNARY { $$ = unary_expr ('-', $2); } | '!' cast_expr %prec UNARY { $$ = unary_expr ('!', $2); } | '~' cast_expr %prec UNARY { $$ = unary_expr ('~', $2); } - | '&' cast_expr %prec UNARY { $$ = address_expr ($2, 0, 0); } - | '*' cast_expr %prec UNARY { $$ = pointer_expr ($2); } + | '&' cast_expr %prec UNARY { $$ = address_expr ($2, 0); } + | '*' cast_expr %prec UNARY { $$ = deref_pointer_expr ($2); } | SIZEOF unary_expr %prec UNARY { $$ = sizeof_expr ($2, 0); } | SIZEOF '(' abstract_decl ')' %prec HYPERUNARY { @@ -1516,6 +1671,8 @@ expr | expr '^' expr { $$ = binary_expr ('^', $1, $3); } | expr '%' expr { $$ = binary_expr ('%', $1, $3); } | expr MOD expr { $$ = binary_expr (MOD, $1, $3); } + | expr CROSS expr { $$ = binary_expr (CROSS, $1, $3); } + | expr DOT expr { $$ = binary_expr (DOT, $1, $3); } ; texpr @@ -1967,10 +2124,10 @@ methoddef current_func = begin_function (sym, nicename, ivar_scope, 1, sc_static); class_finish_ivar_scope (current_class, ivar_scope, - current_func->symtab); + current_func->locals); method->func = sym->s.func; method->def = sym->s.func->def; - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; } compound_statement diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 1a8406186..5cc8c7aa4 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -212,41 +212,41 @@ WriteProgs (dprograms_t *progs, int size) pr_type_t *globals; #define P(t,o) ((t *)((char *)progs + progs->o)) - statements = P (dstatement_t, ofs_statements); - functions = P (dfunction_t, ofs_functions); - globaldefs = P (ddef_t, ofs_globaldefs); - fielddefs = P (ddef_t, ofs_fielddefs); - globals = P (pr_type_t, ofs_globals); + statements = P (dstatement_t, statements.offset); + functions = P (dfunction_t, functions.offset); + globaldefs = P (ddef_t, globaldefs.offset); + fielddefs = P (ddef_t, fielddefs.offset); + globals = P (pr_type_t, globals.offset); #undef P - for (i = 0; i < progs->numstatements; i++) { + for (i = 0; i < progs->statements.count; i++) { statements[i].op = LittleShort (statements[i].op); statements[i].a = LittleShort (statements[i].a); statements[i].b = LittleShort (statements[i].b); statements[i].c = LittleShort (statements[i].c); } - for (i = 0; i < (unsigned) progs->numfunctions; i++) { + for (i = 0; i < (unsigned) progs->functions.count; i++) { dfunction_t *func = functions + i; func->first_statement = LittleLong (func->first_statement); - func->parm_start = LittleLong (func->parm_start); + func->params_start = LittleLong (func->params_start); func->locals = LittleLong (func->locals); func->profile = LittleLong (func->profile); - func->s_name = LittleLong (func->s_name); - func->s_file = LittleLong (func->s_file); - func->numparms = LittleLong (func->numparms); + func->name = LittleLong (func->name); + func->file = LittleLong (func->file); + func->numparams = LittleLong (func->numparams); } - for (i = 0; i < progs->numglobaldefs; i++) { + for (i = 0; i < progs->globaldefs.count; i++) { globaldefs[i].type = LittleShort (globaldefs[i].type); globaldefs[i].ofs = LittleShort (globaldefs[i].ofs); - globaldefs[i].s_name = LittleLong (globaldefs[i].s_name); + globaldefs[i].name = LittleLong (globaldefs[i].name); } - for (i = 0; i < progs->numfielddefs; i++) { + for (i = 0; i < progs->fielddefs.count; i++) { fielddefs[i].type = LittleShort (fielddefs[i].type); fielddefs[i].ofs = LittleShort (fielddefs[i].ofs); - fielddefs[i].s_name = LittleLong (fielddefs[i].s_name); + fielddefs[i].name = LittleLong (fielddefs[i].name); } - for (i = 0; i < progs->numglobals; i++) - globals[i].integer_var = LittleLong (globals[i].integer_var); + for (i = 0; i < progs->globals.count; i++) + globals[i].int_var = LittleLong (globals[i].int_var); if (!(h = Qopen (options.output_file, "wb"))) Sys_Error ("%s: %s\n", options.output_file, strerror(errno)); @@ -307,7 +307,7 @@ WriteSym (pr_debug_header_t *sym, int size) debug_defs[i].type_encoding = LittleLong (debug_defs[i].type_encoding); } for (i = 0; i < sym->debug_data_size; i++) { - debug_data[i].integer_var = LittleLong (debug_data[i].integer_var); + debug_data[i].int_var = LittleLong (debug_data[i].int_var); } if (!(h = Qopen (options.debug_file, "wb"))) @@ -441,12 +441,16 @@ finish_link (void) if (options.code.progsversion != PROG_ID_VERSION) { pr_int_t param_size = type_size (&type_param); pr_int_t param_alignment = qfo_log2 (type_param.alignment); - linker_add_def (".param_size", &type_integer, flags, + linker_add_def (".param_size", &type_int, flags, ¶m_size); - linker_add_def (".param_alignment", &type_integer, flags, + linker_add_def (".param_alignment", &type_int, flags, ¶m_alignment); linker_add_def (".xdefs", &type_xdefs, flags, 0); } + if (options.code.progsversion == PROG_VERSION) { + int stk = (QFOD_GLOBAL | QFOD_INITIALIZED | QFOD_NOSAVE); + linker_add_def (".stack", &type_uint, stk, 0); + } if (options.code.debug) { pr_int_t str; diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index eea6aa7e8..b468cc5b3 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -56,13 +56,14 @@ #include "QF/cvar.h" #include "QF/hash.h" #include "QF/mathlib.h" -#include "QF/pr_comp.h" #include "QF/progs.h" #include "QF/quakeio.h" #include "QF/sys.h" #include "QF/va.h" #include "QF/zone.h" +#include "QF/progs/pr_comp.h" + #include "tools/qfcc/include/obj_file.h" #include "tools/qfcc/include/obj_type.h" #include "tools/qfcc/include/qfprogs.h" @@ -125,8 +126,8 @@ static const char *short_options = ; static edict_t *edicts; -static int num_edicts; -static int reserved_edicts = 1; +static pr_uint_t num_edicts; +static pr_uint_t reserved_edicts = 1; static progs_t pr; static qfo_t *qfo; @@ -292,7 +293,7 @@ load_progs (const char *name) PR_LoadStrings (&pr); PR_LoadDebug (&pr); } - for (i = 0; i < pr.progs->numfunctions; i++) { + for (i = 0; i < pr.progs->functions.count; i++) { // don't bother with builtins if (pr.pr_functions[i].first_statement > 0) Hash_AddElement (func_tab, &pr.pr_functions[i]); diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index a57185209..7bb6d160b 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -113,7 +113,7 @@ FRAMEID {ID}(\.{ID})* i = strtol (yytext + 2, 0, 2); else i = strtol (yytext, 0, 0); - qp_yylval.expr = new_integer_expr (i); + qp_yylval.expr = new_int_expr (i); return VALUE; } @@ -170,7 +170,7 @@ FRAMEID {ID}(\.{ID})* "$"{s}*{FRAMEID} { int ret = do_grab (yytext); if (ret >= 0) { - qp_yylval.expr = new_integer_expr (ret); + qp_yylval.expr = new_int_expr (ret); return VALUE; } else { BEGIN (-ret); @@ -209,7 +209,7 @@ static keyword_t keywords[] = { {"vector", TYPE, &type_vector}, {"entity", TYPE, &type_entity}, {"quaternion", TYPE, &type_quaternion}, - {"integer", TYPE, &type_integer}, + {"integer", TYPE, &type_int}, {"program", PROGRAM, 0}, {"var", VAR, 0}, diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 28f54bb87..8a809bacb 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -113,7 +113,8 @@ int yylex (void); %left '^' %left '&' %left EQ NE -%left LE GE LT GT +%left LT GT GE LE +%token NAND NOR XNOR // end of tokens common between qc and qp %left RELOP @@ -148,7 +149,7 @@ build_dotmain (symbol_t *program) expr_t *exitcode; dotmain->params = 0; - dotmain->type = parse_params (&type_integer, 0); + dotmain->type = parse_params (&type_int, 0); dotmain->type = find_type (dotmain->type); dotmain = function_symbol (dotmain, 0, 1); @@ -156,13 +157,39 @@ build_dotmain (symbol_t *program) current_func = begin_function (dotmain, 0, current_symtab, 0, current_storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; code = new_block_expr (); append_expr (code, function_expr (new_symbol_expr (program), 0)); append_expr (code, return_expr (current_func, exitcode)); build_code_function (dotmain, 0, code); } +static symbol_t * +function_value (function_t *func) +{ + symbol_t *ret = 0; + if (func->type->t.func.type) { + ret = symtab_lookup (func->locals, ".ret"); + if (!ret || ret->table != func->locals) { + ret = new_symbol_type (".ret", func->type->t.func.type); + initialize_def (ret, 0, func->locals->space, sc_local, + func->locals); + } + } + return ret; +} + +static expr_t * +function_return (function_t *func) +{ + symbol_t *ret = function_value (func); + expr_t *ret_val = 0; + if (ret) { + ret_val = new_symbol_expr (ret); + } + return ret_val; +} + %} %% @@ -180,7 +207,7 @@ program current_func = begin_function ($1, 0, current_symtab, 0, current_storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; build_code_function ($1, 0, $4); current_symtab = st; @@ -198,8 +225,9 @@ program_head // FIXME need units and standard units { symbol_t *sym = new_symbol ("ExitCode"); - sym->type = &type_integer; - initialize_def (sym, 0, current_symtab->space, sc_global); + sym->type = &type_int; + initialize_def (sym, 0, current_symtab->space, sc_global, + current_symtab); if (sym->s.def) { sym->s.def->nosave = 1; } @@ -234,7 +262,8 @@ declarations while ($3) { symbol_t *next = $3->next; $3->type = $5; - initialize_def ($3, 0, current_symtab->space, current_storage); + initialize_def ($3, 0, current_symtab->space, current_storage, + current_symtab); $3 = next; } } @@ -245,7 +274,7 @@ type : standard_type | ARRAY '[' VALUE RANGE VALUE ']' OF standard_type { - $$ = based_array_type ($8, expr_integer ($3), expr_integer ($5)); + $$ = based_array_type ($8, expr_int ($3), expr_int ($5)); } ; @@ -265,14 +294,15 @@ subprogram_declaration $$ = current_storage; current_func = begin_function ($1, 0, current_symtab, 0, current_storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; + function_value (current_func); } declarations compound_statement ';' { - append_expr ($5, new_unary_expr ('r', 0)); + append_expr ($5, new_return_expr (function_return (current_func))); build_code_function ($1, 0, $5); - current_symtab = current_symtab->parent; + current_symtab = current_func->parameters->parent; current_storage = $3; } | subprogram_head ASSIGNOP '#' VALUE ';' @@ -373,8 +403,18 @@ statement : variable ASSIGNOP expression { $$ = $1; - if ($$->type == ex_symbol && extract_type ($$) == ev_func) - $$ = new_ret_expr ($$->e.symbol->type->t.func.type); + if ($$->type == ex_symbol && $$->e.symbol->sy_type == sy_func) { + if ($$->e.symbol->s.func != current_func) { + $$ = error ($$, "cannot assign to other function"); + } else { + symbol_t *ret = function_value (current_func); + if (!ret) { + $$ = error ($$, "cannot assign to procedure"); + } else { + $$ = new_symbol_expr (ret); + } + } + } $$ = assign_expr ($$, $3); } | procedure_statement @@ -395,7 +435,7 @@ statement } | RETURN { - $$ = return_expr (current_func, 0); + $$ = return_expr (current_func, function_return (current_func)); } ; @@ -480,7 +520,7 @@ name { if (!$1->table) { error (0, "%s undefined", $1->name); - $1->type = &type_integer; + $1->type = &type_int; symtab_addsymbol (current_symtab, $1); } $$ = new_symbol_expr ($1); diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index c1d471d0a..d235008d0 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -73,7 +73,7 @@ static const char *reloc_name[] = { "rel_def_field_ofs", }; -#define RELOC(r) (r)->space->data[(r)->offset].integer_var +#define RELOC(r) (r)->space->data[(r)->offset].int_var void relocate_refs (reloc_t *reloc, int offset) @@ -168,8 +168,8 @@ relocate_refs (reloc_t *reloc, int offset) break; case rel_def_field_ofs: //FIXME what is correct here? - //RELOC (reloc) += pr.data->data[offset].integer_var; - RELOC (reloc) += pr.near_data->data[offset].integer_var; + //RELOC (reloc) += pr.data->data[offset].int_var; + RELOC (reloc) += pr.near_data->data[offset].int_var; break; } reloc = reloc->next; diff --git a/tools/qfcc/source/shared.c b/tools/qfcc/source/shared.c index cee0d06c1..acdbf149f 100644 --- a/tools/qfcc/source/shared.c +++ b/tools/qfcc/source/shared.c @@ -72,7 +72,7 @@ check_undefined (symbol_t *sym) if (options.code.progsversion == PROG_ID_VERSION) sym->type = &type_float; else - sym->type = &type_integer; + sym->type = &type_int; } return sym; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ecd759818..78a4eb469 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -38,6 +38,7 @@ #endif #include +#include #include "qfalloca.h" @@ -47,6 +48,7 @@ #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/defspace.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/dot.h" #include "tools/qfcc/include/expr.h" @@ -85,6 +87,7 @@ const char *st_type_names[] = { "st_state", "st_func", "st_flow", + "st_address", }; const char * @@ -133,13 +136,13 @@ operand_string (operand_t *op) op->value->v.vector_val[0], op->value->v.vector_val[1], op->value->v.vector_val[2]); - case ev_quat: + case ev_quaternion: return va (0, "'%g %g %g %g'", op->value->v.quaternion_val[0], op->value->v.quaternion_val[1], op->value->v.quaternion_val[2], op->value->v.quaternion_val[3]); - case ev_pointer: + case ev_ptr: if (op->value->v.pointer.def) { return va (0, "ptr %s+%d", op->value->v.pointer.def->name, @@ -154,15 +157,21 @@ operand_string (operand_t *op) case ev_field: return va (0, "field %d", op->value->v.pointer.val); case ev_entity: - return va (0, "ent %d", op->value->v.integer_val); + return va (0, "ent %d", op->value->v.int_val); case ev_func: - return va (0, "func %d", op->value->v.integer_val); - case ev_integer: - return va (0, "int %d", op->value->v.integer_val); - case ev_uinteger: - return va (0, "uint %u", op->value->v.uinteger_val); + return va (0, "func %d", op->value->v.int_val); + case ev_int: + return va (0, "int %d", op->value->v.int_val); + case ev_uint: + return va (0, "uint %u", op->value->v.uint_val); + case ev_long: + return va (0, "long %"PRIi64, op->value->v.long_val); + case ev_ulong: + return va (0, "ulong %"PRIu64, op->value->v.ulong_val); case ev_short: return va (0, "short %d", op->value->v.short_val); + case ev_ushort: + return va (0, "ushort %d", op->value->v.ushort_val); case ev_void: return "(void)"; case ev_invalid: @@ -216,13 +225,13 @@ _print_operand (operand_t *op) printf (" %g", op->value->v.vector_val[1]); printf (" %g'", op->value->v.vector_val[2]); break; - case ev_quat: + case ev_quaternion: printf ("'%g", op->value->v.quaternion_val[0]); printf (" %g", op->value->v.quaternion_val[1]); printf (" %g", op->value->v.quaternion_val[2]); printf (" %g'", op->value->v.quaternion_val[3]); break; - case ev_pointer: + case ev_ptr: printf ("(%s)[%d]", pr_type_name[op->value->v.pointer.type->type], op->value->v.pointer.val); @@ -232,15 +241,24 @@ _print_operand (operand_t *op) break; case ev_entity: case ev_func: - case ev_integer: - printf ("%d", op->value->v.integer_val); + case ev_int: + printf ("%d", op->value->v.int_val); break; - case ev_uinteger: - printf ("%u", op->value->v.uinteger_val); + case ev_uint: + printf ("%u", op->value->v.uint_val); + break; + case ev_long: + printf ("%"PRIu64, op->value->v.long_val); + break; + case ev_ulong: + printf ("%"PRIu64, op->value->v.ulong_val); break; case ev_short: printf ("%d", op->value->v.short_val); break; + case ev_ushort: + printf ("%d", op->value->v.ushort_val); + break; case ev_void: case ev_invalid: case ev_type_count: @@ -410,6 +428,7 @@ nil_operand (type_t *type, expr_t *expr) op = new_operand (op_nil, expr, __builtin_return_address (0)); op->type = type; op->size = type_size (type); + op->width = type_width (type); return op; } @@ -423,6 +442,7 @@ def_operand (def_t *def, type_t *type, expr_t *expr) op = new_operand (op_def, expr, __builtin_return_address (0)); op->type = type; op->size = type_size (type); + op->width = type_width (type); op->def = def; return op; } @@ -433,7 +453,11 @@ return_operand (type_t *type, expr_t *expr) symbol_t *return_symbol; return_symbol = make_symbol (".return", &type_param, pr.symtab->space, sc_extern); - return def_operand (return_symbol->s.def, type, expr); + if (!return_symbol->table) { + symtab_addsymbol (pr.symtab, return_symbol); + } + def_t *return_def = return_symbol->s.def; + return def_operand (alias_def (return_def, type, 0), 0, expr); } operand_t * @@ -442,6 +466,8 @@ value_operand (ex_value_t *value, expr_t *expr) operand_t *op; op = new_operand (op_value, expr, __builtin_return_address (0)); op->type = value->type; + op->size = type_size (value->type); + op->width = type_width (value->type); op->value = value; return op; } @@ -454,6 +480,7 @@ temp_operand (type_t *type, expr_t *expr) op->tempop.type = type; op->type = type; op->size = type_size (type); + op->width = type_width (type); return op; } @@ -528,6 +555,7 @@ alias_operand (type_t *type, operand_t *op, expr_t *expr) aop->alias = op; aop->type = type; aop->size = type_size (type); + aop->width = type_width (type); return aop; } @@ -555,37 +583,31 @@ static const char * convert_op (int op) { switch (op) { - case OR: return "||"; - case AND: return "&&"; - case EQ: return "=="; - case NE: return "!="; - case LE: return "<="; - case GE: return ">="; - case LT: return "<"; - case GT: return ">"; - case '=': return "="; - case '+': return "+"; - case '-': return "-"; - case '*': return "*"; - case '/': return "/"; - case '%': return "%"; - case MOD: return "%%"; - case '&': return "&"; - case '|': return "|"; - case '^': return "^"; - case '~': return "~"; - case '!': return "!"; - case SHL: return "<<"; - case SHR: return ">>"; - case '.': return "."; - case 'i': return ""; - case 'n': return ""; - case IFBE: return ""; - case IFB: return ""; - case IFAE: return ""; - case IFA: return ""; - case 'm': return ""; - case 'M': return ""; + case OR: return "or"; + case AND: return "and"; + case EQ: return "eq"; + case NE: return "ne"; + case LE: return "le"; + case GE: return "ge"; + case LT: return "lt"; + case GT: return "gt"; + case '+': return "add"; + case '-': return "sub"; + case '*': return "mul"; + case '/': return "div"; + case '%': return "rem"; + case MOD: return "mod"; + case '&': return "bitand"; + case '|': return "bitor"; + case '^': return "bitxor"; + case '~': return "bitnot"; + case '!': return "not"; + case SHL: return "shl"; + case SHR: return "shr"; + case '.': return "load"; + case CROSS: return "cross"; + case DOT: return "dot"; + case SCALE: return "scale"; default: return 0; } @@ -596,7 +618,7 @@ statement_is_cond (statement_t *s) { if (!s) return 0; - return !strncmp (s->opcode, "opcode, "if", 2); } int @@ -604,7 +626,7 @@ statement_is_goto (statement_t *s) { if (!s) return 0; - return !strcmp (s->opcode, ""); + return !strcmp (s->opcode, "jump") && !s->opb; } int @@ -612,7 +634,7 @@ statement_is_jumpb (statement_t *s) { if (!s) return 0; - return !strcmp (s->opcode, ""); + return !strcmp (s->opcode, "jump") && s->opb; } int @@ -620,9 +642,9 @@ statement_is_call (statement_t *s) { if (!s) return 0; - if (!strncmp (s->opcode, "opcode, "call", 4)) return 1; - if (!strncmp (s->opcode, "opcode, "rcall", 5)) return 2; return 0; } @@ -632,17 +654,25 @@ statement_is_return (statement_t *s) { if (!s) return 0; - return !strncmp (s->opcode, "opcode, "return", 6); +} + +static ex_label_t ** +statement_get_labelref (statement_t *s) +{ + if (statement_is_cond (s) + || statement_is_goto (s) + || statement_is_jumpb (s)) { + return &s->opa->label; + } + return 0; } sblock_t * statement_get_target (statement_t *s) { - if (statement_is_cond (s)) - return s->opb->label->dest; - if (statement_is_goto (s)) - return s->opa->label->dest; - return 0; + ex_label_t **label = statement_get_labelref (s); + return label ? (*label)->dest : 0; } sblock_t ** @@ -680,18 +710,18 @@ statement_get_targetlist (statement_t *s) static void invert_conditional (statement_t *s) { - if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; + if (!strcmp (s->opcode, "ifnz")) + s->opcode = "ifz"; + else if (!strcmp (s->opcode, "ifz")) + s->opcode = "ifnz"; + else if (!strcmp (s->opcode, "ifbe")) + s->opcode = "ifa"; + else if (!strcmp (s->opcode, "ifb")) + s->opcode = "ifae"; + else if (!strcmp (s->opcode, "ifae")) + s->opcode = "ifb"; + else if (!strcmp (s->opcode, "ifa")) + s->opcode = "ifbe"; } typedef sblock_t *(*statement_f) (sblock_t *, expr_t *); @@ -701,40 +731,26 @@ static sblock_t *statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op); static sblock_t *statement_slist (sblock_t *sblock, expr_t *e); -static sblock_t * -statement_branch (sblock_t *sblock, expr_t *e) -{ - statement_t *s = 0; - const char *opcode; - - if (e->type == ex_uexpr && e->e.expr.op == 'g') { - s = new_statement (st_flow, "", e); - s->opa = label_operand (e->e.expr.e1); - } else { - if (e->e.expr.op == 'g') { - s = new_statement (st_flow, "", e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); - } else { - opcode = convert_op (e->e.expr.op); - s = new_statement (st_flow, opcode, e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opb = label_operand (e->e.expr.e2); - } - } - - sblock_add_statement (sblock, s); - sblock->next = new_sblock (); - return sblock->next; -} - static sblock_t * expr_address (sblock_t *sblock, expr_t *e, operand_t **op) { statement_t *s; - s = new_statement (st_expr, "&", e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opc = temp_operand (e->e.expr.type, e); + expr_t *lvalue = e->e.address.lvalue; + expr_t *offset = e->e.address.offset; + + if (lvalue->type == ex_alias && offset && is_constant (offset)) { + lvalue = new_offset_alias_expr (lvalue->e.alias.type, + lvalue->e.alias.expr, + expr_int (offset)); + offset = 0; + } + + s = new_statement (st_address, "lea", e); + sblock = statement_subexpr (sblock, lvalue, &s->opa); + if (offset) { + sblock = statement_subexpr (sblock, offset, &s->opb); + } + s->opc = temp_operand (e->e.address.type, e); sblock_add_statement (sblock, s); *(op) = s->opc; return sblock; @@ -780,17 +796,6 @@ operand_address (operand_t *reference, expr_t *e) op_type_names[reference->op_type]); } -static __attribute__((pure)) int -is_const_ptr (expr_t *e) -{ - if ((e->type != ex_value || e->e.value->lltype != ev_pointer) - || !(POINTER_VAL (e->e.value->v.pointer) >= 0 - && POINTER_VAL (e->e.value->v.pointer) < 65536)) { - return 0; - } - return 1; -} - static __attribute__((pure)) int is_indirect (expr_t *e) { @@ -801,12 +806,18 @@ is_indirect (expr_t *e) return 0; } +static sblock_t *addressing_mode (sblock_t *sblock, expr_t *ref, + operand_t **base, operand_t **offset, + pr_ushort_t *mode); +static statement_t *lea_statement (operand_t *pointer, operand_t *offset, + expr_t *e); + static sblock_t * expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) { statement_t *s; - expr_t *dst_expr = e->e.expr.e1; - expr_t *src_expr = e->e.expr.e2; + expr_t *dst_expr = e->e.assign.dst; + expr_t *src_expr = e->e.assign.src; type_t *dst_type = get_type (dst_expr); type_t *src_type = get_type (src_expr); unsigned count; @@ -814,19 +825,22 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) operand_t *dst = 0; operand_t *size = 0; static const char *opcode_sets[][2] = { - {"", ""}, - {"", ""}, + {"move", "movep"}, + {"memset", "memsetp"}, }; const unsigned max_count = 1 << 16; const char **opcode_set = opcode_sets[0]; const char *opcode; int need_ptr = 0; st_type_t type = st_move; + operand_t *use = 0; + operand_t *def = 0; + operand_t *kill = 0; if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) { // switch to memset because nil is type agnostic 0 and structures // can be any size - src_expr = new_integer_expr (0); + src_expr = new_int_expr (0); sblock = statement_subexpr (sblock, src_expr, &src); opcode_set = opcode_sets[1]; if (op) { @@ -838,7 +852,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) } } else { if (is_indirect (src_expr)) { - src_expr = expr_file_line (address_expr (src_expr, 0, 0), e); + src_expr = expr_file_line (address_expr (src_expr, 0), e); need_ptr = 1; } if (!src) { @@ -854,7 +868,25 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) *op = src; } if (is_indirect (dst_expr)) { - src = operand_address (src, src_expr); + if (is_variable (src_expr)) { + // FIXME this probably needs to be more agressive + // shouldn't emit code... + sblock = statement_subexpr (sblock, src_expr, &use); + } + if (options.code.progsversion == PROG_VERSION) { + // FIXME it was probably a mistake extracting the operand + // type from the statement expression in dags. Also, can't + // use address_expr() because src_expr may be a function call + // and unary_expr doesn't like that + src_expr = expr_file_line ( + new_address_expr (get_type (src_expr), src_expr, 0), + src_expr); + s = lea_statement (src, 0, src_expr); + sblock_add_statement (sblock, s); + src = s->opc; + } else { + src = operand_address (src, src_expr); + } need_ptr = 1; } } @@ -862,7 +894,13 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) // dst_expr and/or src_expr are dereferenced pointers, so need to // un-dereference dst_expr to get the pointer and switch to movep // or memsetp instructions. - dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); + if (is_variable (dst_expr)) { + // FIXME this probably needs to be more agressive + // shouldn't emit code... + sblock = statement_subexpr (sblock, dst_expr, &def); + sblock = statement_subexpr (sblock, dst_expr, &kill); + } + dst_expr = expr_file_line (address_expr (dst_expr, 0), e); need_ptr = 1; } sblock = statement_subexpr (sblock, dst_expr, &dst); @@ -875,7 +913,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) if (count < (1 << 16)) { count_expr = expr_file_line (new_short_expr (count), e); } else { - count_expr = expr_file_line (new_integer_expr (count), e); + count_expr = expr_file_line (new_int_expr (count), e); } sblock = statement_subexpr (sblock, count_expr, &size); @@ -890,6 +928,9 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) s->opa = src; s->opb = size; s->opc = dst; + s->use = use; + s->def = def; + s->kill = kill; sblock_add_statement (sblock, s); return sblock; } @@ -898,16 +939,17 @@ static sblock_t * expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) { statement_t *s; - expr_t *src_expr = e->e.expr.e2; - expr_t *dst_expr = e->e.expr.e1; + expr_t *src_expr = e->e.assign.src; + expr_t *dst_expr = e->e.assign.dst; type_t *dst_type = get_type (dst_expr); operand_t *src = 0; operand_t *dst = 0; operand_t *ofs = 0; - const char *opcode = convert_op (e->e.expr.op); - st_type_t type; + pr_ushort_t mode = 0; // assign + const char *opcode = "assign"; + st_type_t type = st_assign; - if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { + if (src_expr->type == ex_assign) { sblock = statement_subexpr (sblock, src_expr, &src); if (is_structural (dst_type)) { return expr_assign_copy (sblock, e, op, src); @@ -941,22 +983,18 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, src_expr, &src); } } - type = st_assign; if (0) { dereference_dst: - // dst_expr is a dereferenced pointer, so need to un-dereference it - // to get the pointer and switch to storep instructions. - dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); - opcode = ".="; // FIXME find a nicer representation (lose strings?) - if (dst_expr->type == ex_expr && !is_const_ptr (dst_expr->e.expr.e1)) { - sblock = statement_subexpr (sblock, dst_expr->e.expr.e1, &dst); - sblock = statement_subexpr (sblock, dst_expr->e.expr.e2, &ofs); + // dst_expr is a dereferenced pointer, so need to get its addressing + // parameters (base and offset) and switch to storep instructions. + sblock = addressing_mode (sblock, dst_expr, &dst, &ofs, &mode); + if (mode != 0) { + opcode = "store"; + type = st_ptrassign; } else { - sblock = statement_subexpr (sblock, dst_expr, &dst); ofs = 0; } - type = st_ptrassign; } if (op) { *op = src; @@ -965,52 +1003,28 @@ dereference_dst: return sblock; } - if (is_entity (dst->type) && ofs && is_field (ofs->type)) { - s = new_statement (st_expr, "&", dst_expr); + if (options.code.progsversion < PROG_VERSION + && is_entity (dst->type) && ofs && is_field (ofs->type)) { + // need to get a pointer type, entity.field expressions do not provide + // one directly. FIXME it was probably a mistake extracting the operand + // type from the statement expression in dags + dst_expr = expr_file_line (address_expr (dst_expr, 0), dst_expr); + s = new_statement (st_address, "lea", dst_expr); s->opa = dst; s->opb = ofs; - s->opc = temp_operand (&type_pointer, dst_expr); + s->opc = temp_operand (&type_ptr, dst_expr); sblock_add_statement (sblock, s); dst = s->opc; ofs = 0; } s = new_statement (type, opcode, e); - s->opa = src; - s->opb = dst; - s->opc = ofs; + s->opa = dst; + s->opb = ofs; + s->opc = src; sblock_add_statement (sblock, s); return sblock; } -static sblock_t * -expr_move (sblock_t *sblock, expr_t *e, operand_t **op) -{ - statement_t *s; - type_t *type = e->e.expr.type; - expr_t *dst_expr = e->e.expr.e1; - expr_t *src_expr = e->e.expr.e2; - expr_t *size_expr; - operand_t *dst = 0; - operand_t *src = 0; - operand_t *size = 0; - - if (!op) - op = &dst; - size_expr = new_short_expr (type_size (type)); - sblock = statement_subexpr (sblock, dst_expr, op); - dst = *op; - sblock = statement_subexpr (sblock, src_expr, &src); - sblock = statement_subexpr (sblock, size_expr, &size); - s = new_statement (e->e.expr.op == 'm' ? st_move : st_ptrmove, - convert_op (e->e.expr.op), e); - s->opa = src; - s->opb = size; - s->opc = dst; - sblock_add_statement (sblock, s); - - return sblock; -} - static sblock_t * vector_call (sblock_t *sblock, expr_t *earg, expr_t *param, int ind, operand_t **op) @@ -1033,12 +1047,11 @@ vector_call (sblock_t *sblock, expr_t *earg, expr_t *param, int ind, return sblock; } - static sblock_t * -expr_call (sblock_t *sblock, expr_t *call, operand_t **op) +expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) { - expr_t *func = call->e.expr.e1; - expr_t *args = call->e.expr.e2; + expr_t *func = call->e.branch.target; + expr_t *args = call->e.branch.args; expr_t *a; expr_t *param; operand_t *arguments[2] = {0, 0}; @@ -1049,14 +1062,23 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) statement_t *s; // function arguments are in reverse order - for (a = args; a; a = a->next) + for (a = args; a; a = a->next) { + if (a->type == ex_args) { + // v6p uses callN and pr_argc + continue; + } count++; + } ind = count; for (a = args; a; a = a->next) { + if (a->type == ex_args) { + // v6p uses callN and pr_argc + continue; + } ind--; param = new_param_expr (get_type (a), ind); if (count && options.code.progsversion != PROG_ID_VERSION && ind < 2) { - pref = "R"; + pref = "r"; sblock = statement_subexpr (sblock, param, &arguments[ind]); if (options.code.vector_calls && a->type == ex_value && a->e.value->lltype == ev_vector) @@ -1081,94 +1103,482 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) arg = p; sblock = statement_subexpr (sblock, a, &arg); if (arg != p) { - s = new_statement (st_assign, "=", a); - s->opa = arg; - s->opb = p; + s = new_statement (st_assign, "assign", a); + s->opa = p; + s->opc = arg; sblock_add_statement (sblock, s); } } } } - opcode = va (0, "<%sCALL%d>", pref, count); + opcode = va (0, "%scall%d", pref, count); s = new_statement (st_func, opcode, call); sblock = statement_subexpr (sblock, func, &s->opa); s->opb = arguments[0]; s->opc = arguments[1]; + if (op) { + *op = return_operand (call->e.branch.ret_type, call); + } sblock_add_statement (sblock, s); sblock->next = new_sblock (); return sblock->next; } +static sblock_t * +expr_call (sblock_t *sblock, expr_t *call, operand_t **op) +{ + if (options.code.progsversion < PROG_VERSION) { + return expr_call_v6p (sblock, call, op); + } + if (!current_func->arguments) { + current_func->arguments = defspace_new (ds_virtual); + } + defspace_t *arg_space = current_func->arguments; + expr_t *func = call->e.branch.target; + expr_t **args = 0; + expr_t *args_va_list = 0; // .args (...) parameter + expr_t *args_params = 0; // first arg in ... + operand_t *use = 0; + operand_t *kill = 0; + int num_params = 0; + + defspace_reset (arg_space); + + int num_args = 0; + for (expr_t *a = call->e.branch.args; a; a = a->next) { + num_args++; + } + if (num_args) { + int i = num_args; + args = alloca (num_args * sizeof (expr_t *)); + for (expr_t *a = call->e.branch.args; a; a = a->next) { + args[--i] = a; + } + } + int arg_num = 0; + for (int i = 0; i < num_args; i++) { + expr_t *a = args[i]; + const char *arg_name = va (0, ".arg%d", arg_num++); + def_t *def = new_def (arg_name, 0, current_func->arguments, + sc_local); + type_t *arg_type = get_type (a); + int size = type_size (arg_type); + int alignment = arg_type->alignment; + if (alignment < 4) { + alignment = 4; + } + def->offset = defspace_alloc_aligned_highwater (arg_space, size, + alignment); + def->type = arg_type; + def->reg = current_func->temp_reg; + expr_t *def_expr = expr_file_line (new_def_expr (def), call); + if (a->type == ex_args) { + args_va_list = def_expr; + } else { + if (args_va_list && !args_params) { + args_params = def_expr; + } + if (args_va_list) { + num_params++; + } + expr_t *assign = assign_expr (def_expr, a); + expr_file_line (assign, call); + sblock = statement_slist (sblock, assign); + } + + // The call both uses and kills the arguments: use is obvious, but kill + // is because the callee has direct access to them and might modify + // them + // need two ops for the one def because there's two lists + operand_t *u = def_operand (def, arg_type, call); + operand_t *k = def_operand (def, arg_type, call); + u->next = use; + use = u; + k->next = kill; + kill = k; + } + if (args_va_list) { + expr_t *assign; + expr_t *count; + expr_t *list; + expr_t *args_count = field_expr (args_va_list, + new_name_expr ("count")); + expr_t *args_list = field_expr (args_va_list, + new_name_expr ("list")); + expr_file_line (args_count, call); + expr_file_line (args_list, call); + + count = new_short_expr (num_params); + assign = assign_expr (args_count, count); + expr_file_line (assign, call); + sblock = statement_slist (sblock, assign); + + if (args_params) { + list = address_expr (args_params, &type_param); + } else { + list = new_nil_expr (); + } + expr_file_line (list, call); + assign = assign_expr (args_list, list); + expr_file_line (assign, call); + sblock = statement_slist (sblock, assign); + } + statement_t *s = new_statement (st_func, "call", call); + sblock = statement_subexpr (sblock, func, &s->opa); + if (!op) { + s->opc = short_operand (0, call); + } else { + if (!*op) { + *op = temp_operand (call->e.branch.ret_type, call); + } + s->opc = *op; + } + s->use = use; + s->kill = kill; + sblock_add_statement (sblock, s); + sblock->next = new_sblock (); + return sblock->next; +} + +static sblock_t * +expr_branch (sblock_t *sblock, expr_t *e, operand_t **op) +{ + if (e->e.branch.type != pr_branch_call) { + internal_error (e, "unexpected branch type in expression: %d", + e->e.branch.type); + } + return expr_call (sblock, e, op); +} + +static sblock_t * +statement_branch (sblock_t *sblock, expr_t *e) +{ + static const char *opcodes[] = { + "ifz", + "ifb", + "ifa", + 0, // special handling + "ifnz", + "ifae", + "ifbe", + 0, // not used here + }; + statement_t *s = 0; + const char *opcode; + + if (e->e.branch.type == pr_branch_call) { + return expr_call (sblock, e, 0); + } + if (e->e.branch.type == pr_branch_jump) { + if (e->e.branch.index) { + s = new_statement (st_flow, "jump", e); + sblock = statement_subexpr (sblock, e->e.branch.target, &s->opa); + sblock = statement_subexpr (sblock, e->e.branch.index, &s->opb); + } else { + s = new_statement (st_flow, "jump", e); + s->opa = label_operand (e->e.branch.target); + } + } else { + opcode = opcodes [e->e.branch.type]; + s = new_statement (st_flow, opcode, e); + sblock = statement_subexpr (sblock, e->e.branch.test, &s->opc); + s->opa = label_operand (e->e.branch.target); + } + + sblock_add_statement (sblock, s); + sblock->next = new_sblock (); + return sblock->next; +} + +static sblock_t * +ptr_addressing_mode (sblock_t *sblock, expr_t *ref, + operand_t **base, operand_t **offset, pr_ushort_t *mode) +{ + type_t *type = get_type (ref); + if (!is_ptr (type)) { + internal_error (ref, "expected pointer in ref"); + } + if (ref->type == ex_address + && (!ref->e.address.offset || is_constant (ref->e.address.offset)) + && ref->e.address.lvalue->type == ex_alias + && (!ref->e.address.lvalue->e.alias.offset + || is_constant (ref->e.address.lvalue->e.alias.offset))) { + expr_t *lvalue = ref->e.address.lvalue; + expr_t *offs = ref->e.address.offset; + expr_t *alias; + if (lvalue->e.alias.offset) { + if (offs) { + offs = binary_expr ('+', offs, lvalue->e.alias.offset); + } else { + offs = lvalue->e.alias.offset; + } + } + type = type->t.fldptr.type; + if (offs) { + expr_t *lv = lvalue->e.alias.expr; + type_t *lvtype = get_type (lv); + int o = expr_int (offs); + if (o < 0 || o + type_size (type) > type_size (lvtype)) { + // not a valid offset for the type, which technically should + // be an error, but there may be legitimate reasons for doing + // such pointer shenanigans + goto just_a_pointer; + } + alias = new_offset_alias_expr (type, lv, expr_int (offs)); + } else { + alias = new_alias_expr (type, lvalue->e.alias.expr); + } + expr_file_line (alias, ref); + return addressing_mode (sblock, alias, base, offset, mode); + } else if (ref->type != ex_alias || ref->e.alias.offset) { + // probably just a pointer +just_a_pointer: + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 2; // mode C: ptr + constant index + } else if (is_ptr (get_type (ref->e.alias.expr))) { + // cast of one pointer type to another + return ptr_addressing_mode (sblock, ref->e.alias.expr, base, offset, + mode); + } else { + // alias with no offset + if (!is_integral (get_type (ref->e.alias.expr))) { + internal_error (ref, "expected integer expr in ref"); + } + expr_t *intptr = ref->e.alias.expr; + if (intptr->type != ex_expr + || (intptr->e.expr.op != '+' + && intptr->e.expr.op != '-')) { + // treat ref as simple pointer + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 2; // mode C: ptr + constant index + } else { + expr_t *ptr = intptr->e.expr.e1; + expr_t *offs = intptr->e.expr.e2; + int const_offs; + // move the +/- to the offset + offs = unary_expr (intptr->e.expr.op, offs); + // make the base a pointer again + ptr = new_alias_expr (ref->e.alias.type, ptr); + sblock = statement_subexpr (sblock, ptr, base); + if (is_constant (offs) + && (const_offs = expr_int (offs)) < 32768 + && const_offs >= -32768) { + *mode = 2; + *offset = short_operand (const_offs, ref); + } else { + *mode = 3; + sblock = statement_subexpr (sblock, offs, offset); + } + } + } + return sblock; +} + +static sblock_t * +addressing_mode (sblock_t *sblock, expr_t *ref, + operand_t **base, operand_t **offset, pr_ushort_t *mode) +{ + if (is_indirect (ref)) { + // ref is known to be either ex_expr or ex_uexpr, with '.' for + // the operator + if (ref->type == ex_expr) { + expr_t *ent_expr = ref->e.expr.e1; + expr_t *fld_expr = ref->e.expr.e2; + if (!is_entity (get_type (ent_expr)) + || !is_field (get_type (fld_expr))) { + print_expr (ref); + internal_error (ref, "expected entity.field"); + } + sblock = statement_subexpr (sblock, ent_expr, base); + sblock = statement_subexpr (sblock, fld_expr, offset); + *mode = 1;//entity.field + } else if (ref->type == ex_uexpr) { + sblock = ptr_addressing_mode (sblock, ref->e.expr.e1, base, offset, + mode); + } else { + internal_error (ref, "unexpected expression type for indirect: %s", + expr_names[ref->type]); + } + } else { + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 0; + } + return sblock; +} + +static sblock_t * +statement_return (sblock_t *sblock, expr_t *e) +{ + const char *opcode; + statement_t *s; + + debug (e, "RETURN"); + opcode = "return"; + if (!e->e.retrn.ret_val) { + if (options.code.progsversion == PROG_ID_VERSION) { + e->e.retrn.ret_val = new_float_expr (0); + } + } + s = new_statement (st_func, opcode, e); + if (options.code.progsversion < PROG_VERSION) { + if (e->e.retrn.ret_val) { + expr_t *ret_val = e->e.retrn.ret_val; + type_t *ret_type = get_type (ret_val); + + // at_return is used for passing the result of a void_return + // function through void. v6 progs always use .return for the + // return value, so don't need to do anything special: just call + // the function and do a normal void return + if (!e->e.retrn.at_return) { + s->opa = return_operand (ret_type, e); + } + sblock = statement_subexpr (sblock, ret_val, &s->opa); + } + } else { + if (!e->e.retrn.at_return && e->e.retrn.ret_val) { + expr_t *ret_val = e->e.retrn.ret_val; + type_t *ret_type = get_type (ret_val); + pr_ushort_t ret_crtl = type_size (ret_type) - 1; + pr_ushort_t mode = 0; + sblock = addressing_mode (sblock, ret_val, &s->opa, &s->opb, &mode); + ret_crtl |= mode << 5; + s->opc = short_operand (ret_crtl, e); + } else { + if (e->e.retrn.at_return) { + expr_t *call = e->e.retrn.ret_val; + if (!call || !is_function_call (call)) { + internal_error (e, "@return with no call"); + } + // FIXME hard-coded reg, and assumes 3 is free + #define REG 3 + expr_t *with = new_with_expr (11, REG, new_short_expr (0)); + def_t *ret_ptr = new_def (0, 0, 0, sc_local); + operand_t *ret_op = def_operand (ret_ptr, &type_void, e); + ret_ptr->reg = REG; + expr_file_line (with, e); + sblock = statement_slist (sblock, with); + sblock = statement_subexpr (sblock, call, &ret_op); + } + s->opa = short_operand (0, e); + s->opb = short_operand (0, e); + s->opc = short_operand (-1, e); // void return + } + } + sblock_add_statement (sblock, s); + sblock->next = new_sblock (); + sblock = sblock->next; + + return sblock; +} + +static sblock_t * +statement_adjstk (sblock_t *sblock, expr_t *e) +{ + statement_t *s = new_statement (st_func, "adjstk", e); + s->opa = short_operand (e->e.adjstk.mode, e); + s->opb = short_operand (e->e.adjstk.offset, e); + + sblock_add_statement (sblock, s); + return sblock; +} + +static sblock_t * +statement_with (sblock_t *sblock, expr_t *e) +{ + statement_t *s = new_statement (st_func, "with", e); + s->opa = short_operand (e->e.with.mode, e); + s->opc = short_operand (e->e.with.reg, e); + sblock = statement_subexpr (sblock, e->e.with.with, &s->opb); + sblock_add_statement (sblock, s); + return sblock; +} + static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { - statement_t *s = new_statement (st_expr, "&", e); + statement_t *s = new_statement (st_address, "lea", e); s->opa = pointer; s->opb = offset; - s->opc = temp_operand (&type_pointer, e); + s->opc = temp_operand (&type_ptr, e); + return s; +} + +static statement_t * +movep_statement (operand_t *dst, operand_t *src, type_t *type, expr_t *e) +{ + operand_t *dst_addr = operand_address (dst, e); + statement_t *s = new_statement (st_ptrmove, "movep", e); + s->opa = src; + //FIXME large types + s->opb = short_operand (type_size (type), e); + s->opc = dst_addr; + return s; +} + +static statement_t * +load_statement (operand_t *ptr, operand_t *offs, operand_t *op, expr_t *e) +{ + statement_t *s = new_statement (st_expr, "load", e); + s->opa = ptr; + s->opb = offs; + s->opc = op; + return s; +} + +static statement_t * +assign_statement (operand_t *dst, operand_t *src, expr_t *e) +{ + statement_t *s = new_statement (st_assign, "assign", e); + s->opa = dst; + s->opc = src; return s; } static sblock_t * expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) { - type_t *type = deref->e.expr.type; - expr_t *e; + type_t *load_type = deref->e.expr.type; + expr_t *ptr_expr = deref->e.expr.e1; + operand_t *base = 0; + operand_t *offset = 0; + pr_ushort_t mode; + statement_t *s; - e = deref->e.expr.e1; - if (e->type == ex_uexpr && e->e.expr.op == '&' - && e->e.expr.e1->type == ex_symbol) { - if (e->e.expr.e1->e.symbol->sy_type != sy_var) - internal_error (e, "address of non-var"); - *op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e); - } else if (e->type == ex_expr && e->e.expr.op == '&') { - statement_t *s; - operand_t *ptr = 0; - operand_t *offs = 0; - sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr); - sblock = statement_subexpr (sblock, e->e.expr.e2, &offs); - if (!*op) - *op = temp_operand (type, e); - if (low_level_type (type) == ev_void) { - operand_t *src_addr; - operand_t *dst_addr; + sblock = addressing_mode (sblock, deref, &base, &offset, &mode); - s = lea_statement (ptr, offs, e); - src_addr = s->opc; + if (!*op) { + *op = temp_operand (load_type, deref); + } + + switch (mode) { + case 0://direct def access + // FIXME should check that offset is 0, but currently, + // addressing_mode always sets offset to 0 for mode 0 + s = assign_statement (*op, base, deref); sblock_add_statement (sblock, s); + return sblock; + case 1://entity.field + case 2://const indexed pointer + case 3://var indexed pointer + break; + default: + internal_error (deref, "unexpected addressing mode: %d", mode); + } - dst_addr = operand_address (*op, e); + if (low_level_type (load_type) == ev_void) { + s = lea_statement (base, offset, ptr_expr); + sblock_add_statement (sblock, s); - s = new_statement (st_ptrmove, "", deref); - s->opa = src_addr; - //FIXME large types - s->opb = short_operand (type_size (type), e); - s->opc = dst_addr; - sblock_add_statement (sblock, s); - } else { - s = new_statement (st_expr, ".", deref); - s->opa = ptr; - s->opb = offs; - s->opc = *op; - sblock_add_statement (sblock, s); - } - } else if (e->type == ex_value && e->e.value->lltype == ev_pointer) { - ex_pointer_t *ptr = &e->e.value->v.pointer; - *op = def_operand (alias_def (ptr->def, ptr->type, ptr->val), - ptr->type, e); + s = movep_statement (*op, s->opc, load_type, deref); + sblock_add_statement (sblock, s); } else { - statement_t *s; - operand_t *ptr = 0; - - sblock = statement_subexpr (sblock, e, &ptr); - if (!*op) - *op = temp_operand (type, e); - s = new_statement (st_expr, ".", deref); - s->opa = ptr; - s->opb = short_operand (0, e); - s->opc = *op; + s = load_statement (base, offset, *op, deref); sblock_add_statement (sblock, s); } + return sblock; } @@ -1191,14 +1601,15 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) def_t *def; int offset = 0; - if (e->type == ex_expr) { - offset = expr_integer (e->e.expr.e2); + if (e->e.alias.offset) { + offset = expr_int (e->e.alias.offset); } - type = e->e.expr.type; - sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); + type = e->e.alias.type; + sblock = statement_subexpr (sblock, e->e.alias.expr, &aop); if (type_compatible (aop->type, type)) { - //FIXME type_compatible??? shouldn't that be type_size ==? if (offset) { + //For types to be compatible, they must be the same size, thus this + //seemingly mismatched error internal_error (e, "offset alias of same size type"); } *op = aop; @@ -1246,36 +1657,42 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) const char *opcode; statement_t *s; - switch (e->e.expr.op) { - case 'c': - sblock = expr_call (sblock, e, op); - break; - case '=': - sblock = expr_assign (sblock, e, op); - break; - case 'm': - case 'M': - sblock = expr_move (sblock, e, op); - break; - case 'A': - sblock = expr_alias (sblock, e, op); - break; - default: - opcode = convert_op (e->e.expr.op); - if (!opcode) - internal_error (e, "ice ice baby"); - s = new_statement (st_expr, opcode, e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); - if (!*op) - *op = temp_operand (e->e.expr.type, e); - s->opc = *op; - sblock_add_statement (sblock, s); - break; + opcode = convert_op (e->e.expr.op); + if (!opcode) + internal_error (e, "ice ice baby"); + if (strcmp (opcode, "ne") == 0 && is_string (get_type (e->e.expr.e1))) { + opcode = "cmp"; } + if (strcmp (opcode, "dot") == 0) { + if (is_vector (get_type (e->e.expr.e1))) { + opcode = "vdot"; + } + if (is_quaternion (get_type (e->e.expr.e1))) { + opcode = "qdot"; + } + } + s = new_statement (st_expr, opcode, e); + sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); + sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); + if (!*op) + *op = temp_operand (e->e.expr.type, e); + s->opc = *op; + sblock_add_statement (sblock, s); + return sblock; } +static int type_map[ev_type_count] = { + [ev_int] = 0, + [ev_float] = 1, + [ev_long] = 2, + [ev_double] = 3, + [ev_uint] = 4, + //[ev_bool32] = 5, + [ev_ulong] = 6, + //[ev_bool64] = 7, +}; + static sblock_t * expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1288,8 +1705,15 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *src = 0; sblock = statement_subexpr (sblock, e->e.expr.e1, &src); *op = temp_operand (e->e.expr.type, e); - s = new_statement (st_expr, "", e); + s = new_statement (st_expr, "conv", e); s->opa = src; + if (options.code.progsversion == PROG_VERSION) { + int from = type_map[src_type->type]; + int to = type_map[type->type]; + int width = type_width (src_type) - 1; + int conv = (width << 6) | (from << 3) | to; + s->opb = short_operand (conv, e); + } s->opc = *op; sblock_add_statement (sblock, s); } else { @@ -1321,15 +1745,9 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) statement_t *s; switch (e->e.expr.op) { - case '&': - sblock = expr_address (sblock, e, op); - break; case '.': sblock = expr_deref (sblock, e, op); break; - case 'A': - sblock = expr_alias (sblock, e, op); - break; case 'C': sblock = expr_cast (sblock, e, op); break; @@ -1351,6 +1769,59 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_horizontal (sblock_t *sblock, expr_t *e, operand_t **op) +{ + const char *opcode = "hops"; + statement_t *s; + int hop; + type_t *res_type = e->e.hop.type; + type_t *vec_type = get_type (e->e.hop.vec); + + switch (e->e.hop.op) { + case '&': + hop = 0; + break; + case '|': + hop = 1; + break; + case '^': + hop = 2; + break; + case '+': + if (is_integral (vec_type)) { + hop = 3; + } else { + hop = 7; + } + break; + case NAND: + hop = 4; + break; + case NOR: + hop = 5; + break; + case XNOR: + hop = 6; + break; + default: + internal_error (e, "invalid horizontal op"); + } + hop |= (type_width (vec_type) - 1) << 3; + hop |= (pr_type_size[vec_type->type] - 1) << 5; + + s = new_statement (st_expr, opcode, e); + sblock = statement_subexpr (sblock, e->e.hop.vec, &s->opa); + s->opb = short_operand (hop, e); + if (!*op) { + *op = temp_operand (res_type, e); + } + s->opc = *op; + sblock_add_statement (sblock, s); + + return sblock; +} + static sblock_t * expr_def (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1477,12 +1948,12 @@ expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) if (nil_size < 0x10000) { size_expr = new_short_expr (nil_size); } else { - size_expr = new_integer_expr (nil_size); + size_expr = new_int_expr (nil_size); } - sblock = statement_subexpr (sblock, new_integer_expr(0), &zero); + sblock = statement_subexpr (sblock, new_int_expr(0), &zero); sblock = statement_subexpr (sblock, size_expr, &size); - s = new_statement (st_memset, "", e); + s = new_statement (st_memset, "memset", e); s->opa = zero; s->opb = size; s->opc = *op; @@ -1511,6 +1982,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_block] = expr_block, [ex_expr] = expr_expr, [ex_uexpr] = expr_uexpr, + [ex_horizontal] = expr_horizontal, [ex_def] = expr_def, [ex_symbol] = expr_symbol, [ex_temp] = expr_temp, @@ -1518,6 +1990,10 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_nil] = expr_nil, [ex_value] = expr_value, [ex_selector] = expr_selector, + [ex_alias] = expr_alias, + [ex_address] = expr_address, + [ex_assign] = expr_assign, + [ex_branch] = expr_branch, }; if (!e) { *op = 0; @@ -1525,7 +2001,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) } if (e->type >= ex_count) - internal_error (e, "bad sub-expression type"); + internal_error (e, "bad sub-expression type: %d", e->type); if (!sfuncs[e->type]) internal_error (e, "unexpected sub-expression type: %s", expr_names[e->type]); @@ -1545,7 +2021,7 @@ statement_state (sblock_t *sblock, expr_t *e) { statement_t *s; - s = new_statement (st_state, "", e); + s = new_statement (st_state, "state", e); sblock = statement_subexpr (sblock, e->e.state.frame, &s->opa); sblock = statement_subexpr (sblock, e->e.state.think, &s->opb); sblock = statement_subexpr (sblock, e->e.state.step, &s->opc); @@ -1564,27 +2040,24 @@ build_bool_block (expr_t *block, expr_t *e) e->next = 0; append_expr (block, e); return; + case ex_assign: + e->next = 0; + append_expr (block, e); + return; + case ex_branch: + e->next = 0; + append_expr (block, e); + return; case ex_expr: if (e->e.expr.op == OR || e->e.expr.op == AND) { build_bool_block (block, e->e.expr.e1); build_bool_block (block, e->e.expr.e2); - } else if (e->e.expr.op == 'i') { - e->next = 0; - append_expr (block, e); - } else if (e->e.expr.op == 'n') { - e->next = 0; - append_expr (block, e); } else { e->next = 0; append_expr (block, e); } return; case ex_uexpr: - if (e->e.expr.op == 'g') { - e->next = 0; - append_expr (block, e); - return; - } break; case ex_block: if (!e->e.block.result) { @@ -1605,19 +2078,20 @@ build_bool_block (expr_t *block, expr_t *e) static int is_goto_expr (expr_t *e) { - return e && e->type == ex_uexpr && e->e.expr.op == 'g'; + return e && e->type == ex_branch && e->e.branch.type == pr_branch_jump + && !e->e.branch.index; } static int is_if_expr (expr_t *e) { - return e && e->type == ex_expr && e->e.expr.op == 'i'; + return e && e->type == ex_branch && e->e.branch.type == pr_branch_ne; } static int is_ifnot_expr (expr_t *e) { - return e && e->type == ex_expr && e->e.expr.op == 'n'; + return e && e->type == ex_branch && e->e.branch.type == pr_branch_eq; } static sblock_t * @@ -1632,33 +2106,33 @@ statement_bool (sblock_t *sblock, expr_t *e) s = &block->e.block.head; while (*s) { if (is_if_expr (*s) && is_goto_expr ((*s)->next)) { - l = (*s)->e.expr.e2; + l = (*s)->e.branch.target; for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) { if (e == l) { l->e.label.used--; e = *s; - e->e.expr.op = 'n'; - e->e.expr.e2 = e->next->e.expr.e1; + e->e.branch.type = pr_branch_eq; + e->e.branch.target = e->next->e.branch.target; e->next = e->next->next; break; } } s = &(*s)->next; } else if (is_ifnot_expr (*s) && is_goto_expr ((*s)->next)) { - l = (*s)->e.expr.e2; + l = (*s)->e.branch.target; for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) { if (e == l) { l->e.label.used--; e = *s; - e->e.expr.op = 'i'; - e->e.expr.e2 = e->next->e.expr.e1; + e->e.branch.type = pr_branch_ne; + e->e.branch.target = e->next->e.branch.target; e->next = e->next->next; break; } } s = &(*s)->next; } else if (is_goto_expr (*s)) { - l = (*s)->e.expr.e1; + l = (*s)->e.branch.target; for (e = (*s)->next; e && e->type == ex_label; e = e->next) { if (e == l) { l->e.label.used--; @@ -1706,79 +2180,32 @@ statement_block (sblock_t *sblock, expr_t *e) sblock = sblock->next; } sblock = statement_slist (sblock, e->e.block.head); + if (e->e.block.is_call) { + // for a fuction call, the call expresion is in only the result, not + // the actual block + sblock = statement_slist (sblock, e->e.block.result); + } return sblock; } static sblock_t * statement_expr (sblock_t *sblock, expr_t *e) { - switch (e->e.expr.op) { - case 'c': - sblock = expr_call (sblock, e, 0); - break; - case 'g': - case 'i': - case 'n': - case IFBE: - case IFB: - case IFAE: - case IFA: - sblock = statement_branch (sblock, e); - break; - case '=': - sblock = expr_assign (sblock, e, 0); - break; - case 'm': - case 'M': - sblock = expr_move (sblock, e, 0); - break; - default: - if (e->e.expr.op < 256) - debug (e, "e %c", e->e.expr.op); - else - debug (e, "e %d", e->e.expr.op); - if (options.warnings.executable) - warning (e, "Non-executable statement;" - " executing programmer instead."); - } + if (e->e.expr.op < 256) + debug (e, "e %c", e->e.expr.op); + else + debug (e, "e %d", e->e.expr.op); + if (options.warnings.executable) + warning (e, "Non-executable statement; executing programmer instead."); return sblock; } static sblock_t * statement_uexpr (sblock_t *sblock, expr_t *e) { - const char *opcode; - statement_t *s; - - switch (e->e.expr.op) { - case 'r': - debug (e, "RETURN"); - opcode = ""; - if (!e->e.expr.e1) { - if (options.code.progsversion != PROG_ID_VERSION) { - opcode = ""; - } else { - e->e.expr.e1 = new_float_expr (0); - } - } - s = new_statement (st_func, opcode, e); - if (e->e.expr.e1) { - s->opa = return_operand (get_type (e->e.expr.e1), e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - } - sblock_add_statement (sblock, s); - sblock->next = new_sblock (); - sblock = sblock->next; - break; - case 'g': - sblock = statement_branch (sblock, e); - break; - default: - debug (e, "e ue %d", e->e.expr.op); - if (options.warnings.executable) - warning (e, "Non-executable statement;" - " executing programmer instead."); - } + debug (e, "e ue %d", e->e.expr.op); + if (options.warnings.executable) + warning (e, "Non-executable statement; executing programmer instead."); return sblock; } @@ -1788,16 +2215,16 @@ statement_memset (sblock_t *sblock, expr_t *e) expr_t *dst = e->e.memset.dst; expr_t *val = e->e.memset.val; expr_t *count = e->e.memset.count; - const char *opcode = ""; + const char *opcode = "memset"; statement_t *s; if (is_constant (count)) { - if (is_integer (get_type (count)) - && (unsigned) expr_integer (count) < 0x10000) { - count = new_short_expr (expr_integer (count)); + if (is_int (get_type (count)) + && (unsigned) expr_int (count) < 0x10000) { + count = new_short_expr (expr_int (count)); } - if (is_uinteger (get_type (count)) && expr_integer (count) < 0x10000) { - count = new_short_expr (expr_uinteger (count)); + if (is_uint (get_type (count)) && expr_int (count) < 0x10000) { + count = new_short_expr (expr_uint (count)); } } s = new_statement (st_move, opcode, e); @@ -1808,6 +2235,12 @@ statement_memset (sblock_t *sblock, expr_t *e) return sblock; } +static sblock_t * +statement_assign (sblock_t *sblock, expr_t *e) +{ + return expr_assign (sblock, e, 0); +} + static sblock_t * statement_nonexec (sblock_t *sblock, expr_t *e) { @@ -1834,6 +2267,11 @@ statement_slist (sblock_t *sblock, expr_t *e) [ex_nil] = statement_nonexec, [ex_value] = statement_nonexec, [ex_memset] = statement_memset, + [ex_assign] = statement_assign, + [ex_branch] = statement_branch, + [ex_return] = statement_return, + [ex_adjstk] = statement_adjstk, + [ex_with] = statement_with, }; for (/**/; e; e = e->next) { @@ -1971,14 +2409,15 @@ thread_jumps (sblock_t *blocks) (*label)->symbol = 0; } } else if (statement_is_cond (s)) { - label = &s->opb->label; + label = &s->opa->label; } else { continue; } for (l = *label; l->dest && l->dest->statements && statement_is_goto (l->dest->statements); - l = l->dest->statements->opa->label) { + l = *statement_get_labelref (l->dest->statements)) { + // empty loop } if (l != *label) { unuse_label (*label); @@ -2031,11 +2470,12 @@ remove_dead_blocks (sblock_t *blocks) s = (statement_t *) sblock->tail; if (statement_is_cond (s) && sb->statements && statement_is_goto (sb->statements) - && s->opb->label->dest == sb->next) { + && statement_get_target (s) == sb->next) { debug (0, "merging if/goto %p %p", sblock, sb); - unuse_label (s->opb->label); - s->opb->label = sb->statements->opa->label; - s->opb->label->used++; + ex_label_t **labelref = statement_get_labelref(s); + unuse_label (*labelref); + *labelref = *statement_get_labelref (sb->statements); + (*labelref)->used++; invert_conditional (s); sb->reachable = 0; for (sb = sb->next; sb; sb = sb->next) @@ -2057,10 +2497,8 @@ remove_dead_blocks (sblock_t *blocks) if (sb->statements) { s = (statement_t *) sb->tail; - if (statement_is_goto (s)) - label = s->opa->label; - else if (statement_is_cond (s)) - label = s->opb->label; + ex_label_t **labelref = statement_get_labelref (s); + label = labelref ? *labelref : 0; } unuse_label (label); did_something = 1; @@ -2102,24 +2540,19 @@ search_for_super_dealloc (sblock_t *sblock) if (!statement_is_call (st)) { continue; } + // effectively checks target if (st->opa->op_type != op_def || strcmp (st->opa->def->name, "obj_msgSend_super") != 0) { continue; } - // FIXME this is messy (calls should have their own expression - // type) - // have effectively checked e1 above - if (st->expr->type != ex_expr) { - continue; - } // function arguments are in reverse order, and the selector // is the second argument (or second last in the list) expr_t *arg; - for (arg = st->expr->e.expr.e2; + for (arg = st->expr->e.branch.args; arg && arg->next && arg->next->next; arg = arg->next) { } if (arg && arg->next && is_selector (arg)) { - selector_t *sel = get_selector (st->expr->e.expr.e2); + selector_t *sel = get_selector (st->expr->e.branch.args); if (sel && strcmp (sel->name, "dealloc") == 0) { op = pseudo_operand (super_dealloc, st->expr); op->next = st->use; @@ -2161,10 +2594,16 @@ check_final_block (sblock_t *sblock) sblock->next = new_sblock (); sblock = sblock->next; } - s = new_statement (st_func, "", 0); - if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { - s->opcode = save_string (""); - s->opa = return_operand (&type_void, 0); + s = new_statement (st_func, "return", 0); + if (options.code.progsversion == PROG_VERSION) { + s->opa = short_operand (0, 0); + s->opb = short_operand (0, 0); + s->opc = short_operand (-1, 0); + } else { + if (options.traditional + || options.code.progsversion == PROG_ID_VERSION) { + s->opa = return_operand (&type_void, 0); + } } sblock_add_statement (sblock, s); } diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index ef9bd7389..4a9f64bce 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -43,10 +43,11 @@ #include #include -#include #include #include +#include + #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" @@ -171,7 +172,9 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) if (!type) sym->type = find_type (sym->type); // checks the tag, not the symtab sym->type->t.symtab = symtab; - sym->type->alignment = alignment; + if (alignment > sym->type->alignment) { + sym->type->alignment = alignment; + } if (!type && sym->type->type_def->external) //FIXME should not be necessary sym->type->type_def = qfo_encode_type (sym->type, pr.type_data); return sym; @@ -191,6 +194,8 @@ start_enum (symbol_t *sym) sym = find_enum (0); } sym->type->t.symtab = new_symtab (current_symtab, stab_local); + sym->type->alignment = 1; + sym->type->width = 1; return sym->type->t.symtab; } @@ -204,7 +209,6 @@ finish_enum (symbol_t *sym) enum_type = sym->type = find_type (sym->type); enum_tab = enum_type->t.symtab; - enum_type->alignment = 1; for (name = enum_tab->symbols; name; name = name->next) { name->type = sym->type; @@ -232,17 +236,17 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val) name->type = enum_type; value = 0; if (enum_tab->symbols) - value = ((symbol_t *)(enum_tab->symtail))->s.value->v.integer_val + 1; + value = ((symbol_t *)(enum_tab->symtail))->s.value->v.int_val + 1; if (val) { convert_name (val); if (!is_constant (val)) error (val, "non-constant initializer"); - else if (!is_integer_val (val)) + else if (!is_int_val (val)) error (val, "invalid initializer type"); else - value = expr_integer (val); + value = expr_int (val); } - name->s.value = new_integer_val (value); + name->s.value = new_int_val (value); symtab_addsymbol (enum_tab, name); } @@ -260,12 +264,12 @@ enum_as_bool (type_t *enm, expr_t **zero, expr_t **one) for (sym = symtab->symbols; sym; sym = sym->next) { if (sym->sy_type != sy_const) continue; - val = sym->s.value->v.integer_val; + val = sym->s.value->v.int_val; if (!val) { zero_sym = sym; } else { if (one_sym) { - v = one_sym->s.value->v.integer_val; + v = one_sym->s.value->v.int_val; if (val * val > v * v) continue; } diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 4a0315d4a..12b98e1e6 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -32,7 +32,7 @@ pr_info_t pr; type_t type_Class; type_t type_SEL; type_t type_id; -__attribute__((const)) string_t ReuseString (const char *str) {return 0;} +__attribute__((const)) pr_string_t ReuseString (const char *str) {return 0;} __attribute__((const)) codespace_t *codespace_new (void) {return 0;} void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {} __attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;} diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index e1b6d4aa7..f275af673 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -49,6 +49,7 @@ #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" #include "tools/qfcc/include/switch.h" #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" @@ -136,14 +137,14 @@ case_label_expr (switch_block_t *switch_block, expr_t *value) if (!type_assignable (type, get_type (value))) return error (value, "type mismatch in case label"); if (is_integral (type) && is_integral (val_type)) { - value = new_integer_expr (expr_integer (value)); + value = new_int_expr (expr_int (value)); debug (value, "integeral label used in integral switch"); } else if (is_integral (type) && is_float (val_type)) { warning (value, "float label used in integral switch"); - value = new_integer_expr (expr_float (value)); + value = new_int_expr (expr_float (value)); } else if (is_float (type) && is_integral (val_type)) { debug (value, "integeral label used in float switch"); - value = new_float_expr (expr_integer (value)); + value = new_float_expr (expr_int (value)); } else if (is_float (type) && is_float (val_type)) { value = new_float_expr (expr_float (value)); debug (value, "float label used in float switch"); @@ -189,8 +190,8 @@ label_compare (const void *_a, const void *_b) return strcmp (s1, s2); } else if (is_float_val ((*a)->value)) { return expr_float ((*a)->value) - expr_float ((*b)->value); - } else if (is_integer_val ((*a)->value)) { - return expr_integer ((*a)->value) - expr_integer ((*b)->value); + } else if (is_int_val ((*a)->value)) { + return expr_int ((*a)->value) - expr_int ((*b)->value); } internal_error (0, "in switch"); } @@ -210,9 +211,9 @@ new_case_node (expr_t *low, expr_t *high) } else { int size; - if (!is_integer_val (low)) + if (!is_int_val (low)) internal_error (low, "switch"); - size = expr_integer (high) - expr_integer (low) + 1; + size = expr_int (high) - expr_int (low) + 1; node->labels = calloc (size, sizeof (expr_t *)); } node->left = node->right = 0; @@ -253,18 +254,18 @@ build_case_tree (case_label_t **labels, int count, int range) if (!nodes) Sys_Error ("out of memory"); - if (range && is_integer_val (labels[0]->value)) { + if (range && is_int_val (labels[0]->value)) { for (i = 0; i < count - 1; i = j, num_nodes++) { for (j = i + 1; j < count; j++) { - if (expr_integer (labels[j]->value) - - expr_integer (labels[j - 1]->value) > 1) + if (expr_int (labels[j]->value) + - expr_int (labels[j - 1]->value) > 1) break; } nodes[num_nodes] = new_case_node (labels[i]->value, labels[j - 1]->value); for (k = i; k < j; k++) - nodes[num_nodes]->labels[expr_integer (labels[k]->value) - - expr_integer (labels[i]->value)] + nodes[num_nodes]->labels[expr_int (labels[k]->value) + - expr_int (labels[i]->value)] = labels[k]->label; } if (i < count) { @@ -311,12 +312,12 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, append_expr (sw, test); if (tree->low == tree->high) { - branch = branch_expr ('n', new_alias_expr (&type_integer, temp), + branch = branch_expr (EQ, new_alias_expr (&type_int, temp), tree->labels[0]); append_expr (sw, branch); if (tree->left) { - branch = branch_expr (IFA, new_alias_expr (&type_integer, temp), + branch = branch_expr (GT, new_alias_expr (&type_int, temp), high_label); append_expr (sw, branch); @@ -329,8 +330,8 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, build_switch (sw, tree->right, op, sw_val, temp, default_label); } } else { - int low = expr_integer (tree->low); - int high = expr_integer (tree->high); + int low = expr_int (tree->low); + int high = expr_int (tree->high); symbol_t *table_sym; expr_t *table_expr; expr_t *table_init; @@ -342,24 +343,25 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, table_init = new_compound_init (); for (i = 0; i <= high - low; i++) { tree->labels[i]->e.label.used++; - label = address_expr (tree->labels[i], 0, 0); + label = address_expr (tree->labels[i], 0); append_element (table_init, new_element (label, 0)); } table_sym = new_symbol_type (table_name, - array_type (&type_integer, + array_type (&type_int, high - low + 1)); - initialize_def (table_sym, table_init, pr.near_data, sc_static); + initialize_def (table_sym, table_init, pr.near_data, sc_static, + current_symtab); table_expr = new_symbol_expr (table_sym); if (tree->left) { - branch = branch_expr (IFB, temp, low_label); + branch = branch_expr (LT, temp, low_label); append_expr (sw, branch); } - test = binary_expr (GT, cast_expr (&type_uinteger, temp), - cast_expr (&type_uinteger, range)); - branch = branch_expr ('i', test, high_label); + test = binary_expr (GT, cast_expr (&type_uint, temp), + cast_expr (&type_uint, range)); + branch = branch_expr (NE, test, high_label); append_expr (sw, branch); - branch = new_binary_expr ('g', table_expr, temp); + branch = jump_table_expr (table_expr, temp); append_expr (sw, branch); debug (sw, "switch using jump table"); if (tree->left) { @@ -382,7 +384,7 @@ check_enum_switch (switch_block_t *switch_block) for (enum_val = type->t.symtab->symbols; enum_val; enum_val = enum_val->next) { - cl.value = new_integer_expr (enum_val->s.value->v.integer_val); + cl.value = new_int_expr (enum_val->s.value->v.int_val); if (!Hash_FindElement (switch_block->labels, &cl)) { warning (switch_block->test, "enumeration value `%s' not handled in switch", @@ -408,7 +410,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, expr_t *default_expr; int num_labels = 0; int saved_line = pr.source_line; - string_t saved_file = pr.source_file; + pr_string_t saved_file = pr.source_file; pr.source_line = sw_val->line = switch_block->test->line; pr.source_file = sw_val->file = switch_block->test->file; @@ -433,7 +435,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, || num_labels < 8) { for (l = labels; *l; l++) { expr_t *cmp = binary_expr (EQ, sw_val, (*l)->value); - expr_t *test = branch_expr ('i', test_expr (cmp), + expr_t *test = branch_expr (NE, test_expr (cmp), (*l)->label); append_expr (sw, test); @@ -446,7 +448,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, case_node_t *case_tree; if (is_string(type)) - temp = new_temp_def_expr (&type_integer); + temp = new_temp_def_expr (&type_int); else temp = new_temp_def_expr (type); case_tree = build_case_tree (labels, num_labels, is_integral (type)); diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index ca08069bf..6261b66ee 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -75,7 +75,9 @@ new_symbol (const char *name) { symbol_t *symbol; ALLOC (256, symbol_t, symbols, symbol); - symbol->name = save_string (name); + if (name) { + symbol->name = save_string (name); + } return symbol; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 3c6a4a683..a695e9f50 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -60,56 +60,88 @@ #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" -// simple types. function types are dynamically allocated -type_t type_invalid = { ev_invalid, "invalid" }; -type_t type_void = { ev_void, "void", 1 }; -type_t type_string = { ev_string, "string", 1 }; -type_t type_float = { ev_float, "float", 1 }; -type_t type_vector = { ev_vector, "vector", 1 }; -type_t type_entity = { ev_entity, "entity", 1 }; -type_t type_field = {ev_field, "field", 1, ty_basic, {{&type_void}} }; +#define EV_TYPE(t) \ + type_t type_##t = { \ + .type = ev_##t, \ + .name = #t, \ + .alignment = PR_ALIGNOF(t), \ + .width = __builtin_choose_expr (ev_##t == ev_short \ + || ev_##t == ev_ushort, 0, 1), \ + .meta = ty_basic, \ + {{ __builtin_choose_expr (ev_##t == ev_field \ + || ev_##t == ev_func \ + || ev_##t == ev_ptr, &type_void, 0 ) }}, \ + }; +#include "QF/progs/pr_type_names.h" -// type_function is a void() function used for state defs -type_t type_function = { ev_func, "function", 1, ty_basic, - {{&type_void}} }; -type_t type_pointer = { ev_pointer, "pointer", 1, ty_basic, - {{&type_void}} }; -type_t type_quaternion = { ev_quat, "quaternion", 1 }; -type_t type_integer = { ev_integer, "int", 1 }; -type_t type_uinteger = { ev_uinteger, "uint", 1 }; -type_t type_short = { ev_short, "short", 1 }; -type_t type_double = { ev_double, "double", 2 }; +type_t type_invalid = { + .type = ev_invalid, + .name = "invalid", +}; + +#define VEC_TYPE(type_name, base_type) \ + type_t type_##type_name = { \ + .type = ev_##base_type, \ + .name = #type_name, \ + .alignment = PR_ALIGNOF(type_name), \ + .width = PR_SIZEOF(type_name) / PR_SIZEOF (base_type), \ + .meta = ty_basic, \ + }; +#include "tools/qfcc/include/vec_types.h" type_t *type_nil; type_t *type_default; +type_t *type_long_int; +type_t *type_ulong_uint; // these will be built up further -type_t type_va_list = { ev_invalid, 0, 0, ty_struct }; -type_t type_param = { ev_invalid, 0, 0, ty_struct }; -type_t type_zero = { ev_invalid, 0, 0, ty_struct }; -type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, - ty_struct }; -type_t type_xdef = { ev_invalid, "@xdef", 0, ty_struct }; -type_t type_xdef_pointer = { ev_pointer, 0, 1, ty_basic, {{&type_xdef}} }; -type_t type_xdefs = { ev_invalid, "@xdefs", 0, ty_struct }; +type_t type_va_list = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_param = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_zero = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_type_encodings = { + .type = ev_invalid, + .name = "@type_encodings", + .meta = ty_struct, +}; +type_t type_xdef = { + .type = ev_invalid, + .name = "@xdef", + .meta = ty_struct, +}; +type_t type_xdef_pointer = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_xdef}}, +}; +type_t type_xdefs = { + .type = ev_invalid, + .name = "@xdefs", + .meta = ty_struct, +}; -type_t type_floatfield = { ev_field, ".float", 1, ty_basic, - {{&type_float}} }; +type_t type_floatfield = { + .type = ev_field, + .name = ".float", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_float}}, +}; +#define EV_TYPE(type) &type_##type, type_t *ev_types[ev_type_count] = { - &type_void, - &type_string, - &type_float, - &type_vector, - &type_entity, - &type_field, - &type_function, - &type_pointer, - &type_quaternion, - &type_integer, - &type_uinteger, - &type_short, - &type_double, +#include "QF/progs/pr_type_names.h" &type_invalid, }; @@ -185,14 +217,17 @@ free_type (type_t *type) case ev_vector: case ev_entity: case ev_type_count: - case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_quaternion: + case ev_int: + case ev_uint: + case ev_long: + case ev_ulong: case ev_short: + case ev_ushort: case ev_double: break; case ev_field: - case ev_pointer: + case ev_ptr: free_type (type->t.fldptr.type); break; case ev_func: @@ -225,14 +260,17 @@ copy_chain (type_t *type, type_t *append) case ev_vector: case ev_entity: case ev_type_count: - case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_quaternion: + case ev_int: + case ev_uint: + case ev_long: + case ev_ulong: case ev_short: + case ev_ushort: case ev_double: internal_error (0, "copy basic type"); case ev_field: - case ev_pointer: + case ev_ptr: n = &(*n)->t.fldptr.type; type = type->t.fldptr.type; break; @@ -276,20 +314,25 @@ append_type (type_t *type, type_t *new) case ev_vector: case ev_entity: case ev_type_count: - case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_quaternion: + case ev_int: + case ev_uint: + case ev_long: + case ev_ulong: case ev_short: + case ev_ushort: case ev_double: internal_error (0, "append to basic type"); case ev_field: - case ev_pointer: + case ev_ptr: t = &(*t)->t.fldptr.type; type->alignment = 1; + type->width = 1; break; case ev_func: t = &(*t)->t.func.type; type->alignment = 1; + type->width = 1; break; case ev_invalid: internal_error (0, "invalid basic type"); @@ -299,6 +342,7 @@ append_type (type_t *type, type_t *new) case ty_array: t = &(*t)->t.array.type; type->alignment = new->alignment; + type->width = new->width; break; case ty_struct: case ty_union: @@ -329,12 +373,13 @@ types_same (type_t *a, type_t *b) case ty_basic: switch (a->type) { case ev_field: - case ev_pointer: + case ev_ptr: if (a->t.fldptr.type != b->t.fldptr.type) return 0; case ev_func: if (a->t.func.type != b->t.func.type - || a->t.func.num_params != b->t.func.num_params) + || a->t.func.num_params != b->t.func.num_params + || a->t.func.attribute_bits != b->t.func.attribute_bits) return 0; count = a->t.func.num_params; if (count < 0) @@ -345,7 +390,7 @@ types_same (type_t *a, type_t *b) return 0; return 1; default: // other types don't have aux data - return 1; + return a->width == b->width; } break; case ty_struct: @@ -395,7 +440,7 @@ find_type (type_t *type) case ty_basic: switch (type->type) { case ev_field: - case ev_pointer: + case ev_ptr: type->t.fldptr.type = find_type (type->t.fldptr.type); break; case ev_func: @@ -453,6 +498,7 @@ field_type (type_t *aux) new = new_type (); new->type = ev_field; new->alignment = 1; + new->width = 1; if (aux) { new = find_type (append_type (new, aux)); } @@ -469,8 +515,9 @@ pointer_type (type_t *aux) memset (&_new, 0, sizeof (_new)); else new = new_type (); - new->type = ev_pointer; + new->type = ev_ptr; new->alignment = 1; + new->width = 1; if (aux) { new = find_type (append_type (new, aux)); } @@ -491,6 +538,7 @@ array_type (type_t *aux, int size) new->type = ev_invalid; if (aux) { new->alignment = aux->alignment; + new->width = aux->width; } new->t.array.size = size; if (aux) { @@ -512,6 +560,7 @@ based_array_type (type_t *aux, int base, int top) new->type = ev_invalid; if (aux) { new->alignment = aux->alignment; + new->width = aux->width; } new->meta = ty_array; new->t.array.type = aux; @@ -529,6 +578,7 @@ alias_type (type_t *type, type_t *alias_chain, const char *name) alias->meta = ty_alias; alias->type = type->type; alias->alignment = type->alignment; + alias->width = type->width; if (type == alias_chain && type->meta == ty_alias) { // typedef of a type that contains a typedef somewhere // grab the alias-free branch for type @@ -562,7 +612,7 @@ unalias_type (const type_t *type) const type_t * dereference_type (const type_t *type) { - if (!is_pointer (type) && !is_field (type)) { + if (!is_ptr (type) && !is_field (type)) { internal_error (0, "dereference non pointer/field type"); } if (type->meta == ty_alias) { @@ -633,7 +683,7 @@ print_type_str (dstring_t *str, const type_t *type) dasprintf (str, ")"); } return; - case ev_pointer: + case ev_ptr: if (is_id (type)) { dasprintf (str, "id"); if (type->t.fldptr.type->protos) @@ -653,10 +703,13 @@ print_type_str (dstring_t *str, const type_t *type) case ev_float: case ev_vector: case ev_entity: - case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_quaternion: + case ev_int: + case ev_uint: + case ev_long: + case ev_ulong: case ev_short: + case ev_ushort: case ev_double: dasprintf (str, " %s", pr_type_name[type->type]); return; @@ -774,10 +827,18 @@ encode_type (dstring_t *encoding, const type_t *type) dasprintf (encoding, "*"); return; case ev_double: - dasprintf (encoding, "d"); + if (type->width > 1) { + dasprintf (encoding, "d%d", type->width); + } else { + dasprintf (encoding, "d"); + } return; case ev_float: - dasprintf (encoding, "f"); + if (type->width > 1) { + dasprintf (encoding, "f%d", type->width); + } else { + dasprintf (encoding, "f"); + } return; case ev_vector: dasprintf (encoding, "V"); @@ -794,7 +855,7 @@ encode_type (dstring_t *encoding, const type_t *type) encode_type (encoding, type->t.func.type); dasprintf (encoding, "%s)", encode_params (type)); return; - case ev_pointer: + case ev_ptr: if (is_id(type)) { dasprintf (encoding, "@"); return; @@ -811,18 +872,43 @@ encode_type (dstring_t *encoding, const type_t *type) dasprintf (encoding, "^"); encode_type (encoding, type); return; - case ev_quat: + case ev_quaternion: dasprintf (encoding, "Q"); return; - case ev_integer: - dasprintf (encoding, "i"); + case ev_int: + if (type->width > 1) { + dasprintf (encoding, "i%d", type->width); + } else { + dasprintf (encoding, "i"); + } return; - case ev_uinteger: - dasprintf (encoding, "I"); + case ev_uint: + if (type->width > 1) { + dasprintf (encoding, "I%d", type->width); + } else { + dasprintf (encoding, "I"); + } + return; + case ev_long: + if (type->width > 1) { + dasprintf (encoding, "l%d", type->width); + } else { + dasprintf (encoding, "l"); + } + return; + case ev_ulong: + if (type->width > 1) { + dasprintf (encoding, "L%d", type->width); + } else { + dasprintf (encoding, "L"); + } return; case ev_short: dasprintf (encoding, "s"); return; + case ev_ushort: + dasprintf (encoding, "S"); + return; case ev_invalid: case ev_type_count: break; @@ -832,12 +918,13 @@ encode_type (dstring_t *encoding, const type_t *type) internal_error (0, "bad type meta:type %d:%d", type->meta, type->type); } -int -is_void (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_void; +#define EV_TYPE(t) \ +int is_##t (const type_t *type) \ +{ \ + type = unalias_type (type); \ + return type->type == ev_##t; \ } +#include "QF/progs/pr_type_names.h" int is_enum (const type_t *type) @@ -848,90 +935,58 @@ is_enum (const type_t *type) return 0; } -int -is_integer (const type_t *type) -{ - type = unalias_type (type); - etype_t t = type->type; - - if (t == ev_integer) - return 1; - return is_enum (type); -} - -int -is_uinteger (const type_t *type) -{ - type = unalias_type (type); - etype_t t = type->type; - - if (t == ev_uinteger) - return 1; - return is_enum (type); -} - -int -is_short (const type_t *type) -{ - type = unalias_type (type); - etype_t t = type->type; - - if (t == ev_short) - return 1; - return is_enum (type); -} - int is_integral (const type_t *type) { type = unalias_type (type); - if (is_integer (type) || is_uinteger (type) || is_short (type)) + if (is_int (type) || is_uint (type) || is_short (type)) return 1; return is_enum (type); } int -is_double (const type_t *type) +is_real (const type_t *type) { type = unalias_type (type); - return type->type == ev_double; -} - -int -is_float (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_float; + return is_float (type) || is_double (type); } int is_scalar (const type_t *type) { type = unalias_type (type); - return is_float (type) || is_integral (type) || is_double (type); + if (is_short (type) || is_ushort (type)) { + // shorts have width 0 + return 1; + } + if (type->width != 1) { + return 0; + } + return is_real (type) || is_integral (type); } int -is_vector (const type_t *type) +is_nonscalar (const type_t *type) { type = unalias_type (type); - return type->type == ev_vector; -} - -int -is_quaternion (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_quat; + if (is_vector (type) || is_quaternion (type)) { + return 1; + } + if (type->width < 2) { + return 0; + } + return is_real (type) || is_integral (type); } int is_math (const type_t *type) { type = unalias_type (type); - etype_t t = type->type; - return t == ev_vector || t == ev_quat || is_scalar (type); + if (is_vector (type) || is_quaternion (type)) { + return 1; + } + return is_scalar (type) || is_nonscalar (type); } int @@ -944,33 +999,6 @@ is_struct (const type_t *type) return 0; } -int -is_pointer (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_pointer) - return 1; - return 0; -} - -int -is_field (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_field) - return 1; - return 0; -} - -int -is_entity (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_entity) - return 1; - return 0; -} - int is_array (const type_t *type) { @@ -980,15 +1008,6 @@ is_array (const type_t *type) return 0; } -int -is_func (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_func) - return 1; - return 0; -} - int is_structural (const type_t *type) { @@ -996,15 +1015,6 @@ is_structural (const type_t *type) return is_struct (type) || is_array (type); } -int -is_string (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_string) - return 1; - return 0; -} - int type_compatible (const type_t *dst, const type_t *src) { @@ -1018,7 +1028,7 @@ type_compatible (const type_t *dst, const type_t *src) if (is_func (dst) && is_func (src)) { return 1; } - if (is_pointer (dst) && is_pointer (src)) { + if (is_ptr (dst) && is_ptr (src)) { return 1; } return 0; @@ -1038,12 +1048,12 @@ type_assignable (const type_t *dst, const type_t *src) if (dst->type == ev_field && src->type == ev_field) return 1; // pointer = array - if (is_pointer (dst) && is_array (src)) { + if (is_ptr (dst) && is_array (src)) { if (dst->t.fldptr.type == src->t.array.type) return 1; return 0; } - if (!is_pointer (dst) || !is_pointer (src)) + if (!is_ptr (dst) || !is_ptr (src)) return is_scalar (dst) && is_scalar (src); // pointer = pointer @@ -1080,7 +1090,7 @@ type_size (const type_t *type) { switch (type->meta) { case ty_basic: - return pr_type_size[type->type]; + return pr_type_size[type->type] * type->width; case ty_struct: case ty_union: if (!type->t.symtab) @@ -1089,7 +1099,7 @@ type_size (const type_t *type) case ty_enum: if (!type->t.symtab) return 0; - return type_size (&type_integer); + return type_size (&type_int); case ty_array: return type->t.array.size * type_size (type->t.array.type); case ty_class: @@ -1106,28 +1116,69 @@ type_size (const type_t *type) case ty_alias: return type_size (type->t.alias.aux_type); } - return 0; + internal_error (0, "invalid type meta: %d", type->meta); +} + +int +type_width (const type_t *type) +{ + switch (type->meta) { + case ty_basic: + if (type->type == ev_vector) { + return 3; + } + if (type->type == ev_quaternion) { + return 4; + } + return type->width; + case ty_struct: + case ty_union: + return 1; + case ty_enum: + if (!type->t.symtab) + return 0; + return type_width (&type_int); + case ty_array: + return type_width (type->t.array.type); + case ty_class: + return 1; + case ty_alias: + return type_width (type->t.alias.aux_type); + } + internal_error (0, "invalid type meta: %d", type->meta); } static void chain_basic_types (void) { + type_entity.t.symtab = pr.entity_fields; + if (options.code.progsversion == PROG_VERSION) { + type_quaternion.alignment = 4; + } + chain_type (&type_void); chain_type (&type_string); chain_type (&type_float); chain_type (&type_vector); - type_entity.t.symtab = pr.entity_fields; chain_type (&type_entity); chain_type (&type_field); - chain_type (&type_function); - chain_type (&type_pointer); + chain_type (&type_func); + chain_type (&type_ptr); chain_type (&type_floatfield); if (!options.traditional) { chain_type (&type_quaternion); - chain_type (&type_integer); - chain_type (&type_uinteger); + chain_type (&type_int); + chain_type (&type_uint); chain_type (&type_short); chain_type (&type_double); + + if (options.code.progsversion == PROG_VERSION) { + chain_type (&type_long); + chain_type (&type_ulong); + chain_type (&type_ushort); +#define VEC_TYPE(name, type) chain_type (&type_##name); +#include "tools/qfcc/include/vec_types.h" + } } } @@ -1158,13 +1209,13 @@ init_types (void) {"float_val", &type_float}, {"entity_val", &type_entity}, {"field_val", &type_field}, - {"func_val", &type_function}, - {"pointer_val", &type_pointer}, + {"func_val", &type_func}, + {"pointer_val", &type_ptr}, {"vector_val", &type_vector}, - {"int_val", &type_integer}, - {"uint_val", &type_uinteger}, - {"integer_val", &type_integer}, - {"uinteger_val", &type_uinteger}, + {"int_val", &type_int}, + {"uint_val", &type_uint}, + {"int_val", &type_int}, + {"uint_val", &type_uint}, {"quaternion_val", &type_quaternion}, {"double_val", &type_double}, {0, 0} @@ -1175,12 +1226,10 @@ init_types (void) {"vector_val", &type_vector}, {"entity_val", &type_entity}, {"field_val", &type_field}, - {"func_val", &type_function}, - {"pointer_val", &type_pointer}, - {"int_val", &type_integer}, - {"uint_val", &type_uinteger}, - {"integer_val", &type_integer}, - {"uinteger_val", &type_uinteger}, + {"func_val", &type_func}, + {"pointer_val", &type_ptr}, + {"int_val", &type_int}, + {"uint_val", &type_uint}, {"quaternion_val", &type_quaternion}, {"double_val", &type_double}, {0, 0} @@ -1197,22 +1246,22 @@ init_types (void) {0, 0} }; static struct_def_t type_encoding_struct[] = { - {"types", &type_pointer}, - {"size", &type_integer}, + {"types", &type_ptr}, + {"size", &type_uint}, {0, 0} }; static struct_def_t xdef_struct[] = { - {"types", &type_pointer}, - {"offset", &type_pointer}, + {"types", &type_ptr}, + {"offset", &type_ptr}, {0, 0} }; static struct_def_t xdefs_struct[] = { {"xdefs", &type_xdef_pointer}, - {"num_xdefs", &type_pointer}, + {"num_xdefs", &type_uint}, {0, 0} }; static struct_def_t va_list_struct[] = { - {"count", &type_integer}, + {"count", &type_int}, {"list", 0}, // type will be filled in at runtime {0, 0} }; @@ -1220,7 +1269,15 @@ init_types (void) chain_basic_types (); type_nil = &type_quaternion; - type_default = &type_integer; + type_default = &type_int; + type_long_int = &type_long; + type_ulong_uint = &type_ulong; + if (options.code.progsversion < PROG_VERSION) { + // even v6p doesn't support long, and I don't feel like adding it + // use ruamoko :P + type_long_int = &type_int; + type_ulong_uint = &type_uint; + } if (options.code.progsversion == PROG_ID_VERSION) { // vector can't be part of .zero for v6 progs because for v6 progs, // .zero is only one word wide. @@ -1246,7 +1303,7 @@ init_types (void) make_structure ("@va_list", 's', va_list_struct, &type_va_list); make_structure ("@quaternion", 's', quaternion_struct, &type_quaternion); - type_quaternion.type = ev_quat; + type_quaternion.type = ev_quaternion; type_quaternion.meta = ty_basic; { symbol_t *sym; diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index db98cd60a..f96e5c720 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -60,7 +60,7 @@ typedef struct { def_t *def; union { - string_t string_val; + pr_string_t string_val; float float_val; float vector_val[3]; int entity_val; @@ -68,7 +68,7 @@ typedef struct { int func_val; ex_pointer_t pointer; float quaternion_val[4]; - int integer_val; + int int_val; double double_val; } i; } immediate_t; @@ -224,22 +224,22 @@ new_quaternion_val (const float *quaternion_val) } ex_value_t * -new_integer_val (int integer_val) +new_int_val (int int_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - set_val_type (&val, &type_integer); - val.v.integer_val = integer_val; + set_val_type (&val, &type_int); + val.v.int_val = int_val; return find_value (&val); } ex_value_t * -new_uinteger_val (int uinteger_val) +new_uint_val (int uint_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - set_val_type (&val, &type_uinteger); - val.v.uinteger_val = uinteger_val; + set_val_type (&val, &type_uint); + val.v.uint_val = uint_val; return find_value (&val); } @@ -262,7 +262,7 @@ new_nil_val (type_t *type) if (val.lltype == ev_void) { val.lltype = type_nil->type; } - if (val.lltype == ev_pointer || val.lltype == ev_field ) + if (val.lltype == ev_ptr || val.lltype == ev_field ) val.v.pointer.type = type->t.fldptr.type; if (val.lltype == ev_func) val.v.func_val.type = type; @@ -277,7 +277,7 @@ static hashtab_t *field_imm_defs; static hashtab_t *func_imm_defs; static hashtab_t *pointer_imm_defs; static hashtab_t *quaternion_imm_defs; -static hashtab_t *integer_imm_defs; +static hashtab_t *int_imm_defs; static hashtab_t *double_imm_defs; static void @@ -296,15 +296,15 @@ imm_get_hash (const void *_imm, void *_tab) const char *str = pr.strings->strings + imm->i.string_val; return str ? Hash_String (str) : 0; } else if (tab == &float_imm_defs) { - return imm->i.integer_val; + return imm->i.int_val; } else if (tab == &vector_imm_defs) { return Hash_Buffer (&imm->i.vector_val, sizeof (&imm->i.vector_val)); } else if (tab == &entity_imm_defs) { - return imm->i.integer_val; + return imm->i.int_val; } else if (tab == &field_imm_defs) { return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); } else if (tab == &func_imm_defs) { - return imm->i.integer_val; + return imm->i.int_val; } else if (tab == &pointer_imm_defs) { return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); } else if (tab == &quaternion_imm_defs) { @@ -312,8 +312,8 @@ imm_get_hash (const void *_imm, void *_tab) sizeof (&imm->i.quaternion_val)); } else if (tab == &double_imm_defs) { return Hash_Buffer (&imm->i.double_val, sizeof (&imm->i.double_val)); - } else if (tab == &integer_imm_defs) { - return imm->i.integer_val; + } else if (tab == &int_imm_defs) { + return imm->i.int_val; } else { internal_error (0, 0); } @@ -348,8 +348,8 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab) return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val); } else if (tab == &double_imm_defs) { return imm1->i.double_val == imm2->i.double_val; - } else if (tab == &integer_imm_defs) { - return imm1->i.integer_val == imm2->i.integer_val; + } else if (tab == &int_imm_defs) { + return imm1->i.int_val == imm2->i.int_val; } else { internal_error (0, 0); } @@ -364,10 +364,10 @@ ReuseString (const char *str) static float value_as_float (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -380,10 +380,10 @@ value_as_float (ex_value_t *value) static double value_as_double (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -396,10 +396,10 @@ value_as_double (ex_value_t *value) static int value_as_int (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -412,10 +412,10 @@ value_as_int (ex_value_t *value) static unsigned value_as_uint (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -441,13 +441,13 @@ convert_value (ex_value_t *value, type_t *type) } else if (type->type == ev_short) { int val = value_as_int (value); return new_short_val (val); - } else if (type->type == ev_uinteger) { + } else if (type->type == ev_uint) { unsigned val = value_as_uint (value); - return new_uinteger_val (val); + return new_uint_val (val); } else { //FIXME handle enums separately? int val = value_as_int (value); - return new_integer_val (val); + return new_int_val (val); } } @@ -505,27 +505,27 @@ emit_value (ex_value_t *value, def_t *def) break; case ev_func: tab = func_imm_defs; - type = &type_function; + type = &type_func; break; - case ev_pointer: + case ev_ptr: tab = pointer_imm_defs; - type = &type_pointer; + type = &type_ptr; break; - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: if (!def || !is_float(def->type)) { - tab = integer_imm_defs; - type = &type_integer; + tab = int_imm_defs; + type = &type_int; break; } - val.v.float_val = val.v.integer_val; + val.v.float_val = val.v.int_val; val.lltype = ev_float; case ev_float: tab = float_imm_defs; type = &type_float; break; case ev_string: - val.v.integer_val = ReuseString (val.v.string_val); + val.v.int_val = ReuseString (val.v.string_val); tab = string_imm_defs; type = &type_string; break; @@ -533,7 +533,7 @@ emit_value (ex_value_t *value, def_t *def) tab = vector_imm_defs; type = &type_vector; break; - case ev_quat: + case ev_quaternion: tab = quaternion_imm_defs; type = &type_quaternion; break; @@ -604,7 +604,7 @@ emit_value (ex_value_t *value, def_t *def) if (val.v.pointer.def) reloc_def_field_ofs (val.v.pointer.def, cn); break; - case ev_pointer: + case ev_ptr: if (val.v.pointer.def) { EMIT_DEF_OFS (pr.near_data, D_INT (cn), val.v.pointer.def); @@ -637,7 +637,7 @@ clear_immediates (void) Hash_FlushTable (func_imm_defs); Hash_FlushTable (pointer_imm_defs); Hash_FlushTable (quaternion_imm_defs); - Hash_FlushTable (integer_imm_defs); + Hash_FlushTable (int_imm_defs); Hash_FlushTable (double_imm_defs); } else { value_table = Hash_NewTable (16381, 0, 0, 0, 0); @@ -675,9 +675,9 @@ clear_immediates (void) &quaternion_imm_defs, 0); Hash_SetHashCompare (quaternion_imm_defs, imm_get_hash, imm_compare); - integer_imm_defs = Hash_NewTable (16381, 0, imm_free, - &integer_imm_defs, 0); - Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare); + int_imm_defs = Hash_NewTable (16381, 0, imm_free, + &int_imm_defs, 0); + Hash_SetHashCompare (int_imm_defs, imm_get_hash, imm_compare); double_imm_defs = Hash_NewTable (16381, 0, imm_free, &double_imm_defs, 0); @@ -691,5 +691,5 @@ clear_immediates (void) make_def_imm (def, float_imm_defs, &zero_val); make_def_imm (def, entity_imm_defs, &zero_val); make_def_imm (def, pointer_imm_defs, &zero_val); - make_def_imm (def, integer_imm_defs, &zero_val); + make_def_imm (def, int_imm_defs, &zero_val); } diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 08137d7e3..f5111177e 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -16,6 +16,7 @@ test_progs_dat=\ tools/qfcc/test/chewed-return.dat \ tools/qfcc/test/comma-expr.dat \ tools/qfcc/test/compound.dat \ + tools/qfcc/test/const-fold-int.dat \ tools/qfcc/test/deadbool.dat \ tools/qfcc/test/dealloc-nowarn.dat \ tools/qfcc/test/dealloc-nowarn2.dat \ @@ -29,8 +30,10 @@ test_progs_dat=\ tools/qfcc/test/func-static.dat \ tools/qfcc/test/gcd.dat \ tools/qfcc/test/infloop.dat \ + tools/qfcc/test/iterfunc.dat \ tools/qfcc/test/ivar-struct-return.dat \ tools/qfcc/test/link_order.dat \ + tools/qfcc/test/lost-use.dat \ tools/qfcc/test/methodparams.dat \ tools/qfcc/test/modulo.dat \ tools/qfcc/test/nilparamret.dat \ @@ -52,7 +55,9 @@ test_progs_dat=\ tools/qfcc/test/structptr.dat \ tools/qfcc/test/structstruct.dat \ tools/qfcc/test/swap.dat \ + tools/qfcc/test/temp-component.dat \ tools/qfcc/test/triangle.dat \ + tools/qfcc/test/twice-called.dat \ tools/qfcc/test/typedef.dat \ tools/qfcc/test/typelinker.dat \ tools/qfcc/test/unaryminus.dat \ @@ -100,6 +105,8 @@ check_PROGRAMS += \ $(test_progs_dat) \ $(test_bins) +qfcc-tests: tools/qfcc/test/test-harness $(test_progs_dat) $(test_bins) + tools_qfcc_test_test_defspace_SOURCES= tools/qfcc/test/test-defspace.c $(test_defspace_src) tools_qfcc_test_test_defspace_LDADD= $(QFCC_LIBS) tools_qfcc_test_test_defspace_DEPENDENCIES= $(QFCC_DEPS) @@ -164,7 +171,7 @@ tools_qfcc_test_chewed_return_dat_SOURCES=tools/qfcc/test/chewed-return.r chewed_return_obj=$(tools_qfcc_test_chewed_return_dat_SOURCES:.r=.o) chewed_return_dep=$(call qcautodep,$(tools_qfcc_test_chewed_return_dat_SOURCES)) tools/qfcc/test/chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) - $(V_QFCCLD)$(QLINK) -o $@ $(chewed_return_obj) + $(V_QFCCLD)$(QLINK) -Ctarget=v6 -o $@ $(chewed_return_obj) tools/qfcc/test/chewed-return.run: $(qfcc_test_run_deps) @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ include $(chewed_return_dep) # am--include-marker @@ -190,6 +197,16 @@ tools/qfcc/test/compound.run: $(qfcc_test_run_deps) include $(compound_dep) # am--include-marker r_depfiles_remade += $(compound_dep) +tools_qfcc_test_const_fold_int_dat_SOURCES=tools/qfcc/test/const-fold-int.r +const_fold_int_obj=$(tools_qfcc_test_const_fold_int_dat_SOURCES:.r=.o) +const_fold_int_dep=$(call qcautodep,$(tools_qfcc_test_const_fold_int_dat_SOURCES)) +tools/qfcc/test/const-fold-int.dat$(EXEEXT): $(const_fold_int_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(const_fold_int_obj) +tools/qfcc/test/const-fold-int.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(const_fold_int_dep) # am--include-marker +r_depfiles_remade += $(const_fold_int_dep) + tools_qfcc_test_deadbool_dat_SOURCES=tools/qfcc/test/deadbool.r deadbool_obj=$(tools_qfcc_test_deadbool_dat_SOURCES:.r=.o) deadbool_dep=$(call qcautodep,$(tools_qfcc_test_deadbool_dat_SOURCES)) @@ -362,6 +379,16 @@ tools/qfcc/test/infloop.run: $(qfcc_test_run_deps) include $(infloop_dep) # am--include-marker r_depfiles_remade += $(infloop_dep) +tools_qfcc_test_iterfunc_dat_SOURCES=tools/qfcc/test/iterfunc.r +iterfunc_obj=$(tools_qfcc_test_iterfunc_dat_SOURCES:.r=.o) +iterfunc_dep=$(call qcautodep,$(tools_qfcc_test_iterfunc_dat_SOURCES)) +tools/qfcc/test/iterfunc.dat$(EXEEXT): $(iterfunc_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(iterfunc_obj) +tools/qfcc/test/iterfunc.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(iterfunc_dep) # am--include-marker +r_depfiles_remade += $(iterfunc_dep) + tools_qfcc_test_ivar_struct_return_dat_SOURCES=tools/qfcc/test/ivar-struct-return.r ivar_struct_return_obj=$(tools_qfcc_test_ivar_struct_return_dat_SOURCES:.r=.o) ivar_struct_return_dep=$(call qcautodep,$(tools_qfcc_test_ivar_struct_return_dat_SOURCES)) @@ -382,6 +409,16 @@ tools/qfcc/test/link_order.run: $(qfcc_test_run_deps) include $(link_order_dep) # am--include-marker r_depfiles_remade += $(link_order_dep) +tools_qfcc_test_lost_use_dat_SOURCES=tools/qfcc/test/lost-use.r +lost_use_obj=$(tools_qfcc_test_lost_use_dat_SOURCES:.r=.o) +lost_use_dep=$(call qcautodep,$(tools_qfcc_test_lost_use_dat_SOURCES)) +tools/qfcc/test/lost-use.dat$(EXEEXT): $(lost_use_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(lost_use_obj) +tools/qfcc/test/lost-use.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(lost_use_dep) # am--include-marker +r_depfiles_remade += $(lost_use_dep) + tools_qfcc_test_methodparams_dat_SOURCES=tools/qfcc/test/methodparams.r methodparams_obj=$(tools_qfcc_test_methodparams_dat_SOURCES:.r=.o) methodparams_dep=$(call qcautodep,$(tools_qfcc_test_methodparams_dat_SOURCES)) @@ -592,6 +629,16 @@ tools/qfcc/test/swap.run: $(qfcc_test_run_deps) include $(swap_dep) # am--include-marker r_depfiles_remade += $(swap_dep) +tools_qfcc_test_temp_component_dat_SOURCES=tools/qfcc/test/temp-component.r +temp_component_obj=$(tools_qfcc_test_temp_component_dat_SOURCES:.r=.o) +temp_component_dep=$(call qcautodep,$(tools_qfcc_test_temp_component_dat_SOURCES)) +tools/qfcc/test/temp-component.dat$(EXEEXT): $(temp_component_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(temp_component_obj) +tools/qfcc/test/temp-component.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(temp_component_dep) # am--include-marker +r_depfiles_remade += $(temp_component_dep) + tools_qfcc_test_triangle_dat_SOURCES=tools/qfcc/test/triangle.r triangle_obj=$(tools_qfcc_test_triangle_dat_SOURCES:.r=.o) triangle_dep=$(call qcautodep,$(tools_qfcc_test_triangle_dat_SOURCES)) @@ -602,6 +649,16 @@ tools/qfcc/test/triangle.run: $(qfcc_test_run_deps) include $(triangle_dep) # am--include-marker r_depfiles_remade += $(triangle_dep) +tools_qfcc_test_twice_called_dat_SOURCES=tools/qfcc/test/twice-called.r +twice_called_obj=$(tools_qfcc_test_twice_called_dat_SOURCES:.r=.o) +twice_called_dep=$(call qcautodep,$(tools_qfcc_test_twice_called_dat_SOURCES)) +tools/qfcc/test/twice-called.dat$(EXEEXT): $(twice_called_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(twice_called_obj) +tools/qfcc/test/twice-called.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ 100000 100000 1.00005 50002.4961 +include $(twice_called_dep) # am--include-marker +r_depfiles_remade += $(twice_called_dep) + tools_qfcc_test_typedef_dat_SOURCES=tools/qfcc/test/typedef.r typedef_obj=$(tools_qfcc_test_typedef_dat_SOURCES:.r=.o) typedef_dep=$(call qcautodep,$(tools_qfcc_test_typedef_dat_SOURCES)) diff --git a/tools/qfcc/test/chewed-alias.r b/tools/qfcc/test/chewed-alias.r index 08c060534..409254c39 100644 --- a/tools/qfcc/test/chewed-alias.r +++ b/tools/qfcc/test/chewed-alias.r @@ -18,7 +18,7 @@ int main () { return 0; // test succeeds if compile succeeds } -id obj_msgSend (id receiver, SEL op, ...) = #0; +@attribute(no_va_list) id obj_msgSend (id receiver, SEL op, ...) = #0; void __obj_exec_class (struct obj_module *msg) = #0; @implementation Object @end diff --git a/tools/qfcc/test/classarray.r b/tools/qfcc/test/classarray.r index fa33d8264..972c1c3d7 100644 --- a/tools/qfcc/test/classarray.r +++ b/tools/qfcc/test/classarray.r @@ -1,3 +1,5 @@ +#pragma warn error + @interface foo { id isa; diff --git a/tools/qfcc/test/const-fold-int.r b/tools/qfcc/test/const-fold-int.r new file mode 100644 index 000000000..d7fa31920 --- /dev/null +++ b/tools/qfcc/test/const-fold-int.r @@ -0,0 +1,76 @@ +int mul_e_c_t_c (int x) { return x * 6 * 7; } +int mul_c_e_t_c (int x) { return 6 * x * 7; } +int mul_c_c_t_e (int x) { return 6 * 7 * x; } +int mul_e_t_c_c (int x) { return x * (6 * 7); } +int mul_c_t_e_c (int x) { return 6 * (x * 7); } +int mul_c_t_c_e (int x) { return 6 * (7 * x); } + +int addadd_e_c_t_c (int x) { return x + 6 + 7; } +int addadd_c_e_t_c (int x) { return 6 + x + 7; } +int addadd_c_c_t_e (int x) { return 6 + 7 + x; } +int addadd_e_t_c_c (int x) { return x + (6 + 7); } +int addadd_c_t_e_c (int x) { return 6 + (x + 7); } +int addadd_c_t_c_e (int x) { return 6 + (7 + x); } + +int addsub_e_c_t_c (int x) { return x + 6 - 7; } +int addsub_c_e_t_c (int x) { return 6 + x - 7; } +int addsub_c_c_t_e (int x) { return 6 + 7 - x; } +int addsub_e_t_c_c (int x) { return x + (6 - 7); } +int addsub_c_t_e_c (int x) { return 6 + (x - 7); } +int addsub_c_t_c_e (int x) { return 6 + (7 - x); } + +int subadd_e_c_t_c (int x) { return x - 6 + 7; } +int subadd_c_e_t_c (int x) { return 6 - x + 7; } +int subadd_c_c_t_e (int x) { return 6 - 7 + x; } +int subadd_e_t_c_c (int x) { return x - (6 + 7); } +int subadd_c_t_e_c (int x) { return 6 - (x + 7); } +int subadd_c_t_c_e (int x) { return 6 - (7 + x); } + +int subsub_e_c_t_c (int x) { return x - 6 - 7; } +int subsub_c_e_t_c (int x) { return 6 - x - 7; } +int subsub_c_c_t_e (int x) { return 6 - 7 - x; } +int subsub_e_t_c_c (int x) { return x - (6 - 7); } +int subsub_c_t_e_c (int x) { return 6 - (x - 7); } +int subsub_c_t_c_e (int x) { return 6 - (7 - x); } + +int +main () +{ + int fail = 0; + + fail |= mul_e_c_t_c (10) != 420; + fail |= mul_c_e_t_c (10) != 420; + fail |= mul_c_c_t_e (10) != 420; + fail |= mul_e_t_c_c (10) != 420; + fail |= mul_c_t_e_c (10) != 420; + fail |= mul_c_t_c_e (10) != 420; + + fail |= addadd_e_c_t_c (29) != 42; + fail |= addadd_c_e_t_c (29) != 42; + fail |= addadd_c_c_t_e (29) != 42; + fail |= addadd_e_t_c_c (29) != 42; + fail |= addadd_c_t_e_c (29) != 42; + fail |= addadd_c_t_c_e (29) != 42; + + fail |= addsub_e_c_t_c (43) != 42; + fail |= addsub_c_e_t_c (43) != 42; + fail |= addsub_c_c_t_e (-29) != 42; + fail |= addsub_e_t_c_c (43) != 42; + fail |= addsub_c_t_e_c (43) != 42; + fail |= addsub_c_t_c_e (-29) != 42; + + fail |= subadd_e_c_t_c (41) != 42; + fail |= subadd_c_e_t_c (-29) != 42; + fail |= subadd_c_c_t_e (43) != 42; + fail |= subadd_e_t_c_c (55) != 42; + fail |= subadd_c_t_e_c (-43) != 42; + fail |= subadd_c_t_c_e (-43) != 42; + + fail |= subsub_e_c_t_c (55) != 42; + fail |= subsub_c_e_t_c (-43) != 42; + fail |= subsub_c_c_t_e (-43) != 42; + fail |= subsub_e_t_c_c (41) != 42; + fail |= subsub_c_t_e_c (-29) != 42; + fail |= subsub_c_t_c_e (43) != 42; + return fail; +} diff --git a/tools/qfcc/test/dealloc-warn.r b/tools/qfcc/test/dealloc-warn.r index bf218ca9c..86dd53a75 100644 --- a/tools/qfcc/test/dealloc-warn.r +++ b/tools/qfcc/test/dealloc-warn.r @@ -1,3 +1,5 @@ +#pragma warn error + @interface Object { Class isa; diff --git a/tools/qfcc/test/dealloc-warn2.r b/tools/qfcc/test/dealloc-warn2.r index 0cd10d3ef..921db1566 100644 --- a/tools/qfcc/test/dealloc-warn2.r +++ b/tools/qfcc/test/dealloc-warn2.r @@ -1,3 +1,5 @@ +#pragma warn error + @interface Object { Class isa; diff --git a/tools/qfcc/test/dealloc-warn3.r b/tools/qfcc/test/dealloc-warn3.r index 3d505c987..a8dd2d2b4 100644 --- a/tools/qfcc/test/dealloc-warn3.r +++ b/tools/qfcc/test/dealloc-warn3.r @@ -1,3 +1,6 @@ +#pragma warn error +#pragma optimize on + @interface Object { Class isa; diff --git a/tools/qfcc/test/double-alias.r b/tools/qfcc/test/double-alias.r index 6050d2f6d..5df0d3398 100644 --- a/tools/qfcc/test/double-alias.r +++ b/tools/qfcc/test/double-alias.r @@ -23,12 +23,12 @@ alias_printf (string fmt, ...) { int fail = 0; // this will fail on big-endian systems - fail = (@args.list[2].integer_val != 0x54442d18 - || @args.list[1].integer_val != 0x400921fb); - printf ("%g %08x%08x\n", - @args.list[0].integer_val, - @args.list[2].integer_val, - @args.list[1].integer_val); + fail = (@args.list[2].int_val != 0x54442d18 + || @args.list[1].int_val != 0x400921fb); + printf ("%.17g %08x%08x\n", + @args.list[0].double_val, + @args.list[2].int_val, + @args.list[1].int_val); return fail; } diff --git a/tools/qfcc/test/double-demote-float-ainit.r b/tools/qfcc/test/double-demote-float-ainit.r index 6d380447d..7ebbb1467 100644 --- a/tools/qfcc/test/double-demote-float-ainit.r +++ b/tools/qfcc/test/double-demote-float-ainit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b[] = {1.0d}; int main () diff --git a/tools/qfcc/test/double-demote-float-ginit.r b/tools/qfcc/test/double-demote-float-ginit.r index c88b5e987..a23f98939 100644 --- a/tools/qfcc/test/double-demote-float-ginit.r +++ b/tools/qfcc/test/double-demote-float-ginit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; float b = 1.0d; int main () diff --git a/tools/qfcc/test/double-demote-float-linit.r b/tools/qfcc/test/double-demote-float-linit.r index 796b2040f..2eba60432 100644 --- a/tools/qfcc/test/double-demote-float-linit.r +++ b/tools/qfcc/test/double-demote-float-linit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int main () { diff --git a/tools/qfcc/test/double-demote-float.r b/tools/qfcc/test/double-demote-float.r index 330a0bdef..f38db3a96 100644 --- a/tools/qfcc/test/double-demote-float.r +++ b/tools/qfcc/test/double-demote-float.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; float b; int main () diff --git a/tools/qfcc/test/double-demote-int-ainit.r b/tools/qfcc/test/double-demote-int-ainit.r index 6d380447d..7ebbb1467 100644 --- a/tools/qfcc/test/double-demote-int-ainit.r +++ b/tools/qfcc/test/double-demote-int-ainit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b[] = {1.0d}; int main () diff --git a/tools/qfcc/test/double-demote-int-ginit.r b/tools/qfcc/test/double-demote-int-ginit.r index 767328715..80fa7857a 100644 --- a/tools/qfcc/test/double-demote-int-ginit.r +++ b/tools/qfcc/test/double-demote-int-ginit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b = 1.0d; int main () diff --git a/tools/qfcc/test/double-demote-int-linit.r b/tools/qfcc/test/double-demote-int-linit.r index 3a206f4b5..523cca503 100644 --- a/tools/qfcc/test/double-demote-int-linit.r +++ b/tools/qfcc/test/double-demote-int-linit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int main () { diff --git a/tools/qfcc/test/double-demote-int.r b/tools/qfcc/test/double-demote-int.r index bebef5436..dd921215f 100644 --- a/tools/qfcc/test/double-demote-int.r +++ b/tools/qfcc/test/double-demote-int.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b; int main () diff --git a/tools/qfcc/test/double-float-compare.r b/tools/qfcc/test/double-float-compare.r index a219b0d4a..37a4bfb03 100644 --- a/tools/qfcc/test/double-float-compare.r +++ b/tools/qfcc/test/double-float-compare.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; float b; int main () diff --git a/tools/qfcc/test/double-int-compare.r b/tools/qfcc/test/double-int-compare.r index 221516ed8..374b32edc 100644 --- a/tools/qfcc/test/double-int-compare.r +++ b/tools/qfcc/test/double-int-compare.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b; int main () diff --git a/tools/qfcc/test/double.r b/tools/qfcc/test/double.r index 326ccf906..de0649b19 100644 --- a/tools/qfcc/test/double.r +++ b/tools/qfcc/test/double.r @@ -11,7 +11,7 @@ test_format () { int fail = 0; type_pun.d = M_PI; - printf ("%g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]); + printf ("%.17g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]); // this will fail on big-endian systems fail = type_pun.i[0] != 0x54442d18 || type_pun.i[1] != 0x400921fb; return fail; diff --git a/tools/qfcc/test/iterfunc.r b/tools/qfcc/test/iterfunc.r new file mode 100644 index 000000000..803b6a6f6 --- /dev/null +++ b/tools/qfcc/test/iterfunc.r @@ -0,0 +1,33 @@ +#include + +// can't link against libr.a (may not be built) +void *PR_FindGlobal (string name) = #0; +void printf (string fmt, ...) = #0; + +qfot_type_encodings_t *encodings; +qfot_type_t *next_type (qfot_type_t *type); + +int +main (void) +{ + int found_param = 0; + int found_zero = 0; + qfot_type_t *type; + + encodings = PR_FindGlobal (".type_encodings"); + + for (type = encodings.types; + ((int *)type - (int *) encodings.types) < encodings.size; + type = next_type (type)) { + } + return 0; +} + +qfot_type_t * +next_type (qfot_type_t *type) +{ + int size = type.size; + if (!size) + size = 4; + return (qfot_type_t *) ((int *) type + size); +} diff --git a/tools/qfcc/test/lost-use.r b/tools/qfcc/test/lost-use.r new file mode 100644 index 000000000..dc9d79142 --- /dev/null +++ b/tools/qfcc/test/lost-use.r @@ -0,0 +1,29 @@ +void printf (string fmt, ...) = #0; +int getval(void) +{ + return 42; +} + +void magic (void) +{ +} + +void storeval (int *p) +{ + int x = getval (); + magic (); + *p = x; +} + +int val; + +int +main(void) +{ + storeval (&val); + if (val != 42) { + printf ("val is dead: %d\n", val); + return 1; + } + return 0; +} diff --git a/tools/qfcc/test/methodparams.r b/tools/qfcc/test/methodparams.r index b29e6954b..d2e71591b 100644 --- a/tools/qfcc/test/methodparams.r +++ b/tools/qfcc/test/methodparams.r @@ -15,7 +15,7 @@ typedef struct { int x, y; } Point; [textContext mvvprintf: pos, fmt, @args]; } @end -id obj_msgSend (id receiver, SEL op, ...) = #0; +@attribute(no_va_list) id obj_msgSend (id receiver, SEL op, ...) = #0; void __obj_exec_class (struct obj_module *msg) = #0; @interface Object @end diff --git a/tools/qfcc/test/modulo.r b/tools/qfcc/test/modulo.r index 2d31a69a2..6fb69490c 100644 --- a/tools/qfcc/test/modulo.r +++ b/tools/qfcc/test/modulo.r @@ -1,3 +1,7 @@ +#if !defined(__RUAMOKO__) || __RUAMOKO__ < 2 +# define test_traditional +#endif + void printf (string ftm, ...) = #0; float snafu (float a, float b) @@ -21,6 +25,7 @@ double dmodulo (double a, double b) return a %% b; } +#ifdef test_traditional #pragma traditional float foo (float a, float b) { @@ -45,6 +50,7 @@ float baz (float a, float b) return c; } #pragma advanced +#endif @overload int test (string name, string op, int (func)(int a, int b), int a, int b, int c) @@ -53,10 +59,12 @@ test (string name, string op, int (func)(int a, int b), int a, int b, int c) ret = func (a, b); if (ret != c) { +#ifdef test_traditional if (func == baz) printf ("%s: (%d + %d) %% (%d - %d): %d != %d\n", name, a, b, a, b, ret, c); else +#endif printf ("%s: %d %s %d: %d != %d\n", name, a, op, b, ret, c); return 1; @@ -72,10 +80,12 @@ test (string name, string op, float (func)(float a, float b), ret = func (a, b); if (ret != c) { +#ifdef test_traditional if (func == baz) printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n", name, a, b, a, b, ret, c); else +#endif printf ("%s: %g %s %g: %g != %g\n", name, a, op, b, ret, c); return 1; @@ -91,42 +101,55 @@ test (string name, string op, double (func)(double a, double b), ret = func (a, b); if (ret != c) { +#ifdef test_traditional if (func == baz) printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n", name, a, b, a, b, ret, c); else +#endif printf ("%s: %g %s %g: %g != %g\n", name, a, op, b, ret, c); return 1; } return 0; } +#ifdef test_traditional +typedef float restype; +#else +typedef int restype; +#endif -float main (void) +restype main (void) { - float res = 0; + restype res = 0; +#ifdef test_traditional res |= test ("foo", "%", foo, 5, 3, 2); res |= test ("bar", "%", bar, 5, 3, 2); res |= test ("baz", "%", baz, 5, 3, 0); +#endif res |= test ("snafu", "%", snafu, 5, 3, 2); - +#ifdef test_traditional res |= test ("foo", "%", foo, -5, 3, -2); res |= test ("bar", "%", bar, -5, 3, -2); res |= test ("baz", "%", baz, -5, 3, -2); +#endif res |= test ("snafu", "%", snafu, -5, 3, -2); - +#ifdef test_traditional res |= test ("foo", "%", foo, 5, -3, 2); res |= test ("bar", "%", bar, 5, -3, 2); res |= test ("baz", "%", baz, 5, -3, 2); +#endif res |= test ("snafu", "%", snafu, 5, -3, 2); - +#ifdef test_traditional res |= test ("foo", "%", foo, -5, -3, -2); res |= test ("bar", "%", bar, -5, -3, -2); res |= test ("baz", "%", baz, -5, -3, 0); +#endif res |= test ("snafu", "%", snafu, -5, -3, -2); - +#ifdef test_traditional res |= test ("foo", "%", foo, 5, 3.5, 1.5); res |= test ("foo", "%", foo, -5, 3.5, -1.5); +#endif res |= test ("snafu", "%", snafu, 5, 3.5, 1.5); res |= test ("snafu", "%", snafu, -5, 3.5, -1.5); diff --git a/tools/qfcc/test/ptraliasenc.r b/tools/qfcc/test/ptraliasenc.r index 2f305617f..8e8a58e9c 100644 --- a/tools/qfcc/test/ptraliasenc.r +++ b/tools/qfcc/test/ptraliasenc.r @@ -10,16 +10,22 @@ typedef struct xdef_s { void *ofs; ///< 32-bit version of ddef_t.ofs } xdef_t; +typedef struct xdefs_s { + xdef_t *xdefs; + unsigned num_xdefs; +} xdefs_t; + void *PR_FindGlobal (string name) = #0; int main (void) { //FIXME need a simple way to get at a def's meta-data - xdef_t *xdefs = PR_FindGlobal (".xdefs"); - while (xdefs.ofs != &int32_ptr) { - xdefs++; + xdefs_t *xdefs = PR_FindGlobal (".xdefs"); + xdef_t *xdef = xdefs.xdefs; + while (xdef - xdefs.xdefs < xdefs.num_xdefs && xdef.ofs != &int32_ptr) { + xdef++; } - printf ("int32_ptr: %s\n", xdefs.type.encoding); - return xdefs.type.encoding != "{>^i}"; + printf ("int32_ptr: %s\n", xdef.type.encoding); + return xdef.type.encoding != "{>^i}"; } diff --git a/tools/qfcc/test/return-postop.r b/tools/qfcc/test/return-postop.r index 5ec27f4a1..bdf244f98 100644 --- a/tools/qfcc/test/return-postop.r +++ b/tools/qfcc/test/return-postop.r @@ -1,3 +1,4 @@ +#pragma optimize on #include "test-harness.h" int counter; diff --git a/tools/qfcc/test/sendv.r b/tools/qfcc/test/sendv.r index aa2cb6665..aaf7e19cd 100644 --- a/tools/qfcc/test/sendv.r +++ b/tools/qfcc/test/sendv.r @@ -15,7 +15,7 @@ send (id obj, string cmd, string str) params[0].pointer_val = obj; params[1].pointer_val = sel; params[2].string_val = str; - obj_msg_sendv (obj, sel, va_list); + @return obj_msg_sendv (obj, sel, va_list); } @interface Object //just so the runtime doesn't complain @@ -54,5 +54,5 @@ main () } @end -id (id receiver, SEL op, ...) obj_msgSend = #0; +@attribute(no_va_list) id (id receiver, SEL op, ...) obj_msgSend = #0; void __obj_exec_class (struct obj_module *msg) = #0; diff --git a/tools/qfcc/test/temp-component.r b/tools/qfcc/test/temp-component.r new file mode 100644 index 000000000..2db18a401 --- /dev/null +++ b/tools/qfcc/test/temp-component.r @@ -0,0 +1,13 @@ +float +gety(vector v, vector z) +{ + return (v + z).y; +} + +int +main () +{ + vector a = [1, 2, 3]; + vector b = [1, 2, 6]; + return gety (a, b) != 4; +} diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index bec2b247e..1965db082 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -40,24 +40,25 @@ #include "QF/dstring.h" #include "QF/progs.h" +#include "rua_internal.h" #include "test-bi.h" static void bi_printf (progs_t *pr) { - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; static dstring_t *dstr; - if (!dstr) + if (!dstr) { dstr = dstring_new (); - else + } else { dstring_clear (dstr); + } - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) + RUA_Sprintf (pr, dstr, "printf", 0); + + if (dstr->str) { fputs (dstr->str, stdout); + } } static void @@ -95,18 +96,20 @@ bi_remove (progs_t *pr) ED_Free (pr, ed); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"printf", bi_printf, -1}, - {"errno", bi_errno, -1}, - {"strerror", bi_strerror, -1}, - {"exit", bi_exit, -1}, - {"spawn", bi_spawn, -1}, - {"remove", bi_remove, -1}, + bi(printf, -2, p(string)), + bi(errno, 0), + bi(strerror, 1, p(int)), + bi(exit, 1, p(int)), + bi(spawn, 0), + bi(remove, 1, p(entity)), {0} }; void BI_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 5b0199317..a0a4bfd0c 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -75,8 +75,8 @@ static const char *short_options = static edict_t test_edicts[MAX_EDICTS]; static edict_t *edicts; -static int num_edicts; -static int reserved_edicts; +static pr_uint_t num_edicts; +static pr_uint_t reserved_edicts; static progs_t test_pr; static const char *this_program; @@ -120,10 +120,14 @@ load_file (progs_t *pr, const char *name, off_t *_size) return sym; } +#define ALIGN 32 + static void * allocate_progs_mem (progs_t *pr, int size) { - return malloc (size); + intptr_t mem = (intptr_t) malloc (size + ALIGN); + mem = (mem + ALIGN - 1) & ~(ALIGN - 1); + return (void *) mem; } static void @@ -259,9 +263,9 @@ int main (int argc, char **argv) { dfunction_t *dfunc; - func_t main_func = 0; + pr_func_t main_func = 0; const char *name = "progs.dat"; - string_t *pr_argv; + pr_string_t *pr_argv; int pr_argc = 1, i; i = parse_options (argc, argv); @@ -276,24 +280,29 @@ main (int argc, char **argv) if (!load_progs (name)) Sys_Error ("couldn't load %s", name); + if ((dfunc = PR_FindFunction (&test_pr, ".main")) + || (dfunc = PR_FindFunction (&test_pr, "main"))) { + main_func = dfunc - test_pr.pr_functions; + } else { + PR_Undefined (&test_pr, "function", "main"); + } + PR_PushFrame (&test_pr); - if (argc > 2) + if (argc) { pr_argc = argc; + } pr_argv = PR_Zone_Malloc (&test_pr, (pr_argc + 1) * 4); pr_argv[0] = PR_SetTempString (&test_pr, name); - for (i = 1; i < pr_argc; i++) + for (i = 1; i < pr_argc; i++) { pr_argv[i] = PR_SetTempString (&test_pr, argv[i]); + } pr_argv[i] = 0; - if ((dfunc = PR_FindFunction (&test_pr, ".main")) - || (dfunc = PR_FindFunction (&test_pr, "main"))) - main_func = dfunc - test_pr.pr_functions; - else - PR_Undefined (&test_pr, "function", "main"); PR_RESET_PARAMS (&test_pr); P_INT (&test_pr, 0) = pr_argc; P_POINTER (&test_pr, 1) = PR_SetPointer (&test_pr, pr_argv); test_pr.pr_argc = 2; + PR_ExecuteProgram (&test_pr, main_func); PR_PopFrame (&test_pr); if (options.flote) diff --git a/tools/qfcc/test/twice-called.r b/tools/qfcc/test/twice-called.r new file mode 100644 index 000000000..9542af0f6 --- /dev/null +++ b/tools/qfcc/test/twice-called.r @@ -0,0 +1,28 @@ +#include "test-harness.h" + +int counter; + +int +function (void) +{ + return ++counter; +} + +int +main (void) +{ + int ret = 0; + counter = 0; + //function (); + //if (counter != 1) { + //printf ("discarded return not called only once\n"); + // ret = 1; + //} + counter = 0; + printf ("function: %d\n", function ()); + if (counter != 1) { + //printf ("used return not called only once\n"); + ret = 1; + } + return ret; +} diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r index 9dbd7f40b..61df8f9b6 100644 --- a/tools/qfcc/test/typedef.r +++ b/tools/qfcc/test/typedef.r @@ -24,9 +24,9 @@ next_type (qfot_type_t *type) int check_alias (string name, qfot_type_t *alias) { - if (alias.meta != ty_basic || alias.type != ev_pointer + if (alias.meta != ty_basic || alias.type != ev_ptr || alias.fldptr.aux_type.meta != ty_basic - || alias.fldptr.aux_type.type != ev_integer) { + || alias.fldptr.aux_type.type != ev_int) { printf ("%s is not a *int alias\n", name); return 0; } diff --git a/tools/qfcc/test/vecaddr.r b/tools/qfcc/test/vecaddr.r index 323d9205c..965fbf716 100644 --- a/tools/qfcc/test/vecaddr.r +++ b/tools/qfcc/test/vecaddr.r @@ -1,8 +1,26 @@ void printf (string fmt, ...) = #0; -float foo (vector v, float z) +#if __RUAMOKO__ > 1 +#define dot @dot +#define X .y +#else +#define dot * +#define X +#endif + +void forcelive (float z) { - return v * *(vector*)(&v.y); +} + +float foo (vector _v, float _z) +{ + vector v = _v; + float z = _z; + _v = nil; + _z = 0; + forcelive (_z); + forcelive (z); + return (v dot *(vector*)(&v.y))X; } int @@ -11,6 +29,6 @@ main (int argc, string *argv) vector v = [1, 2, 3]; vector w = [2, 3, 4]; float f; - printf ("%v %g %g %g\n", v, v*v, v*w, f=foo (v, 4)); - return f != v*w; + printf ("%v %g %g %g\n", v, v dot v, v dot w, f=foo (v, 4)); + return f != (v dot w)X; } diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 27399eead..93ee0ec96 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -156,7 +156,7 @@ calc_plane (vec4f_t v1, vec4f_t v2, int flip, vec4f_t p, vec4f_t *plane) if (length[0] < ON_EPSILON) return 0; - *plane /= vsqrtf (length); + *plane /= vsqrt4f (length); (*plane)[3] = -dotf (p, *plane)[0]; return 1; } @@ -371,7 +371,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) // get plane of target_portal, point normal into the neighbor cluster backplane = -target_portal->plane; - vec4f_t diff = vabsf (pass_plane - backplane); + vec4f_t diff = vabs4f (pass_plane - backplane); vec4i_t cmp = diff > (vec4f_t) {0.001, 0.001, 0.001, 0.001}; if (!(cmp[0] || cmp[1] || cmp[2])) { // dist isn't interesting continue; // can't go out a coplanar face