mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 18:01:15 +00:00
Add support for doubles to Ruamoko
Only as scalars, I still need to think about what to do for vectors and quaternions due to param size issues. Also, doubles are not yet guaranteed to be correctly aligned.
This commit is contained in:
parent
13b608f40c
commit
df7c08a010
22 changed files with 958 additions and 86 deletions
|
@ -44,6 +44,7 @@ typedef enum {
|
|||
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
|
||||
|
@ -305,6 +306,7 @@ typedef enum {
|
|||
OP_PUSH_P,
|
||||
OP_PUSH_Q,
|
||||
OP_PUSH_I,
|
||||
OP_PUSH_D,
|
||||
|
||||
OP_PUSHB_S,
|
||||
OP_PUSHB_F,
|
||||
|
@ -315,6 +317,7 @@ typedef enum {
|
|||
OP_PUSHB_P,
|
||||
OP_PUSHB_Q,
|
||||
OP_PUSHB_I,
|
||||
OP_PUSHB_D,
|
||||
|
||||
OP_PUSHBI_S,
|
||||
OP_PUSHBI_F,
|
||||
|
@ -325,6 +328,7 @@ typedef enum {
|
|||
OP_PUSHBI_P,
|
||||
OP_PUSHBI_Q,
|
||||
OP_PUSHBI_I,
|
||||
OP_PUSHBI_D,
|
||||
|
||||
OP_POP_S,
|
||||
OP_POP_F,
|
||||
|
@ -335,6 +339,7 @@ typedef enum {
|
|||
OP_POP_P,
|
||||
OP_POP_Q,
|
||||
OP_POP_I,
|
||||
OP_POP_D,
|
||||
|
||||
OP_POPB_S,
|
||||
OP_POPB_F,
|
||||
|
@ -345,6 +350,7 @@ typedef enum {
|
|||
OP_POPB_P,
|
||||
OP_POPB_Q,
|
||||
OP_POPB_I,
|
||||
OP_POPB_D,
|
||||
|
||||
OP_POPBI_S,
|
||||
OP_POPBI_F,
|
||||
|
@ -355,6 +361,36 @@ typedef enum {
|
|||
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_MOD_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,
|
||||
} pr_opcode_e;
|
||||
|
||||
typedef struct opcode_s {
|
||||
|
@ -423,7 +459,7 @@ typedef struct pr_va_list_s {
|
|||
|(((0x##b) & 0xfff) << 12) \
|
||||
|(((0x##c) & 0xfff) << 0) )
|
||||
#define PROG_ID_VERSION 6
|
||||
#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,009)
|
||||
#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,00a)
|
||||
|
||||
typedef struct dprograms_s {
|
||||
pr_uint_t version;
|
||||
|
|
|
@ -320,6 +320,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define G_FLOAT(p,o) G_var (p, o, float)
|
||||
|
||||
/** Access a double global. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param p pointer to ::progs_t VM struct
|
||||
\param o offset into global data space
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define G_DOUBLE(p,o) (*(double *) ((p)->pr_globals + o))
|
||||
|
||||
/** Access an integer global. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
|
@ -510,6 +522,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define P_FLOAT(p,n) P_var (p, n, float)
|
||||
|
||||
/** Access a double parameter. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param p pointer to ::progs_t VM struct
|
||||
\param n parameter number (0-7)
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define P_DOUBLE(p,n) (*(double *) ((p)->pr_params[n]))
|
||||
|
||||
/** Access an integer parameter. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
|
@ -702,6 +726,17 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define R_FLOAT(p) R_var (p, float)
|
||||
|
||||
/** Access the VM function return value as a \c double
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param p pointer to ::progs_t VM struct
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define R_DOUBLE(p) (*(double *) ((p)->pr_return))
|
||||
|
||||
/** Access the VM function return value as a \c ::pr_int_t (AKA int32_t)
|
||||
|
||||
\par QC type:
|
||||
|
@ -868,6 +903,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
|
|||
*/
|
||||
#define E_FLOAT(e,o) E_var (e, o, float)
|
||||
|
||||
/** Access a double entity field. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
\c double
|
||||
\param e pointer to the entity
|
||||
\param o field offset into entity data space
|
||||
\return double lvalue
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define E_DOUBLE(e,o) (*(double *) ((e)->v + o))
|
||||
|
||||
/** Access an integer entity field. Can be assigned to.
|
||||
|
||||
\par QC type:
|
||||
|
@ -1560,6 +1607,7 @@ struct progs_s {
|
|||
struct hashtab_s *strref_hash;
|
||||
int num_strings;
|
||||
strref_t *pr_xtstr;
|
||||
int float_promoted; ///< for PR_Sprintf
|
||||
//@}
|
||||
|
||||
/// \name memory map
|
||||
|
|
|
@ -280,12 +280,15 @@ PR_BoundsCheck (progs_t *pr, int addr, etype_t type)
|
|||
#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)))
|
||||
|
||||
/*
|
||||
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 && (x).uinteger_var != 0x80000000u)
|
||||
|
||||
#define FNZ(x) ((x).uinteger_var & ~0x80000000u)
|
||||
|
||||
static int
|
||||
signal_hook (int sig, void *data)
|
||||
|
@ -421,6 +424,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
PR_PrintStatement (pr, st, 1);
|
||||
|
||||
switch (st->op) {
|
||||
case OP_ADD_D:
|
||||
OPC_double_var = OPA_double_var + OPB_double_var;
|
||||
break;
|
||||
case OP_ADD_F:
|
||||
OPC.float_var = OPA.float_var + OPB.float_var;
|
||||
break;
|
||||
|
@ -437,6 +443,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
PR_GetString (pr,
|
||||
OPB.string_var));
|
||||
break;
|
||||
case OP_SUB_D:
|
||||
OPC_double_var = OPA_double_var - OPB_double_var;
|
||||
break;
|
||||
case OP_SUB_F:
|
||||
OPC.float_var = OPA.float_var - OPB.float_var;
|
||||
break;
|
||||
|
@ -446,12 +455,31 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_SUB_Q:
|
||||
QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_MUL_D:
|
||||
OPC_double_var = OPA_double_var * OPB_double_var;
|
||||
break;
|
||||
case OP_MUL_F:
|
||||
OPC.float_var = OPA.float_var * OPB.float_var;
|
||||
break;
|
||||
case OP_MUL_V:
|
||||
OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var);
|
||||
break;
|
||||
case OP_MUL_DV:
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_VD:
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_FV:
|
||||
{
|
||||
// avoid issues with the likes of x = x.x * x;
|
||||
|
@ -474,6 +502,22 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_MUL_QV:
|
||||
QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var);
|
||||
break;
|
||||
case OP_MUL_DQ:
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_QD:
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
case OP_MUL_FQ:
|
||||
{
|
||||
// avoid issues with the likes of x = x.s * x;
|
||||
|
@ -493,6 +537,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_CONJ_Q:
|
||||
QuatConj (OPA.quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_DIV_D:
|
||||
OPC_double_var = OPA_double_var / OPB_double_var;
|
||||
break;
|
||||
case OP_DIV_F:
|
||||
OPC.float_var = OPA.float_var / OPB.float_var;
|
||||
break;
|
||||
|
@ -630,6 +677,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_STORE_Q:
|
||||
QuatCopy (OPA.quat_var, OPB.quat_var);
|
||||
break;
|
||||
case OP_STORE_D:
|
||||
OPB_double_var = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_STOREP_F:
|
||||
case OP_STOREP_ENT:
|
||||
|
@ -661,6 +711,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||
break;
|
||||
case OP_STOREP_D:
|
||||
pointer = OPB.integer_var;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_double);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
*(double *) ptr = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_ADDRESS:
|
||||
if (pr_boundscheck->int_val) {
|
||||
|
@ -687,6 +745,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
case OP_ADDRESS_FN:
|
||||
case OP_ADDRESS_I:
|
||||
case OP_ADDRESS_P:
|
||||
case OP_ADDRESS_D:
|
||||
OPC.integer_var = st->a;
|
||||
break;
|
||||
|
||||
|
@ -735,6 +794,19 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
memcpy (&OPC, &ed->v[OPB.integer_var], 4 * sizeof (OPC));
|
||||
break;
|
||||
case OP_LOAD_D:
|
||||
if (pr_boundscheck->int_val) {
|
||||
if (OPA.entity_var < 0
|
||||
|| OPA.entity_var >= pr->pr_edictareasize)
|
||||
PR_RunError (pr, "Progs attempted to read an out of "
|
||||
"bounds edict number");
|
||||
if (OPB.uinteger_var + 1 >= pr->progs->entityfields)
|
||||
PR_RunError (pr, "Progs attempted to read an invalid "
|
||||
"field in an edict");
|
||||
}
|
||||
ed = PROG_TO_EDICT (pr, OPA.entity_var);
|
||||
OPC_double_var = *(double *) (ed->v + OPB.integer_var);
|
||||
break;
|
||||
|
||||
case OP_LOADB_F:
|
||||
case OP_LOADB_S:
|
||||
|
@ -766,6 +838,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_LOADB_D:
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_double);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
OPC_double_var = *(double *) ptr;
|
||||
break;
|
||||
|
||||
case OP_LOADBI_F:
|
||||
case OP_LOADBI_S:
|
||||
|
@ -797,6 +877,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||
break;
|
||||
case OP_LOADBI_D:
|
||||
pointer = OPA.integer_var + (short) st->b;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
OPC_double_var = *(double *) ptr;
|
||||
break;
|
||||
|
||||
case OP_LEA:
|
||||
pointer = OPA.integer_var + OPB.integer_var;
|
||||
|
@ -838,6 +926,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||
break;
|
||||
case OP_STOREB_D:
|
||||
pointer = OPB.integer_var + OPC.integer_var;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
*(double *) ptr = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_STOREBI_F:
|
||||
case OP_STOREBI_S:
|
||||
|
@ -869,6 +965,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
|
|||
ptr = pr->pr_globals + pointer;
|
||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||
break;
|
||||
case OP_STOREBI_D:
|
||||
pointer = OPB.integer_var + (short) st->c;
|
||||
if (pr_boundscheck->int_val) {
|
||||
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||
}
|
||||
ptr = pr->pr_globals + pointer;
|
||||
*(double *) ptr = OPA_double_var;
|
||||
break;
|
||||
|
||||
case OP_PUSH_F:
|
||||
case OP_PUSH_FLD:
|
||||
|
@ -1322,20 +1426,19 @@ op_call:
|
|||
case OP_MUL_I:
|
||||
OPC.integer_var = OPA.integer_var * OPB.integer_var;
|
||||
break;
|
||||
/*
|
||||
case OP_DIV_VF:
|
||||
{
|
||||
float temp = 1.0f / OPB.float_var;
|
||||
VectorScale (OPA.vector_var, temp, OPC.vector_var);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case OP_DIV_I:
|
||||
OPC.integer_var = OPA.integer_var / OPB.integer_var;
|
||||
break;
|
||||
case OP_MOD_I:
|
||||
OPC.integer_var = OPA.integer_var % OPB.integer_var;
|
||||
break;
|
||||
case OP_MOD_D:
|
||||
{
|
||||
double a = OPA_double_var;
|
||||
double b = OPB_double_var;
|
||||
OPC_double_var = a - b * trunc (a / b);
|
||||
}
|
||||
break;
|
||||
case OP_MOD_F:
|
||||
{
|
||||
float a = OPA.float_var;
|
||||
|
@ -1432,6 +1535,41 @@ op_call:
|
|||
st->b * 4);
|
||||
break;
|
||||
|
||||
case OP_GE_D:
|
||||
OPC.float_var = OPA_double_var >= OPB_double_var;
|
||||
break;
|
||||
case OP_LE_D:
|
||||
OPC.float_var = OPA_double_var <= OPB_double_var;
|
||||
break;
|
||||
case OP_GT_D:
|
||||
OPC.float_var = OPA_double_var > OPB_double_var;
|
||||
break;
|
||||
case OP_LT_D:
|
||||
OPC.float_var = OPA_double_var < OPB_double_var;
|
||||
break;
|
||||
case OP_NOT_D:
|
||||
OPC.integer_var = (op_a[0].integer_var
|
||||
|| (op_a[1].integer_var & ~0x80000000u));
|
||||
break;
|
||||
case OP_EQ_D:
|
||||
OPC.integer_var = OPA_double_var == OPB_double_var;
|
||||
break;
|
||||
case OP_NE_D:
|
||||
OPC.integer_var = OPA_double_var != OPB_double_var;
|
||||
break;
|
||||
case OP_CONV_ID:
|
||||
OPC_double_var = OPA.integer_var;
|
||||
break;
|
||||
case OP_CONV_DI:
|
||||
OPC.integer_var = OPA_double_var;
|
||||
break;
|
||||
case OP_CONV_FD:
|
||||
OPC_double_var = OPA.float_var;
|
||||
break;
|
||||
case OP_CONV_DF:
|
||||
OPC.float_var = OPA_double_var;
|
||||
break;
|
||||
|
||||
// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
|
||||
/*
|
||||
case OP_BOUNDCHECK:
|
||||
|
|
|
@ -61,6 +61,7 @@ VISIBLE int pr_type_size[ev_type_count] = {
|
|||
1, // ev_integer
|
||||
1, // ev_uinteger
|
||||
0, // ev_short value in opcode
|
||||
2, // ev_double
|
||||
};
|
||||
|
||||
VISIBLE const char *pr_type_name[ev_type_count] = {
|
||||
|
@ -102,6 +103,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%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,
|
||||
|
@ -118,6 +123,14 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -130,6 +143,14 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -145,7 +166,19 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
ev_float, ev_float, ev_float,
|
||||
PROG_ID_VERSION,
|
||||
},
|
||||
{"/", "div.d", OP_DIV_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,
|
||||
|
@ -163,6 +196,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -176,6 +213,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -201,6 +242,10 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -226,10 +271,18 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -242,10 +295,18 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -264,6 +325,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -305,6 +371,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%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,
|
||||
|
@ -351,6 +422,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"*(%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,
|
||||
|
@ -408,6 +484,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
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,
|
||||
|
@ -475,7 +556,32 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "conv.id", OP_CONV_ID, false,
|
||||
ev_integer, ev_invalid, ev_double,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "conv.di", OP_CONV_DI, false,
|
||||
ev_double, ev_invalid, ev_integer,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "conv.fd", OP_CONV_FD, false,
|
||||
ev_float, ev_invalid, ev_double,
|
||||
PROG_VERSION,
|
||||
"%Ga, %gc",
|
||||
},
|
||||
{"<CONV>", "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,
|
||||
|
@ -522,6 +628,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%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,
|
||||
|
@ -568,6 +679,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%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,
|
||||
|
@ -614,6 +730,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"%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,
|
||||
|
@ -672,6 +793,11 @@ VISIBLE opcode_t pr_opcodes[] = {
|
|||
"",
|
||||
},
|
||||
|
||||
{"!", "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,
|
||||
|
|
|
@ -70,6 +70,7 @@ struct strref_s {
|
|||
#define FMT_ADDSIGN (1<<3)
|
||||
#define FMT_ADDBLANK (1<<4)
|
||||
#define FMT_HEX (1<<5)
|
||||
#define FMT_LONG (1<<6)
|
||||
|
||||
typedef struct fmt_item_s {
|
||||
byte type;
|
||||
|
@ -81,6 +82,7 @@ typedef struct fmt_item_s {
|
|||
int integer_var;
|
||||
unsigned uinteger_var;
|
||||
float float_var;
|
||||
double double_var;
|
||||
} data;
|
||||
struct fmt_item_s *next;
|
||||
} fmt_item_t;
|
||||
|
@ -596,11 +598,19 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting)
|
|||
break;
|
||||
case 'f':
|
||||
dstring_appendstr (tmp, "f");
|
||||
PRINT (float);
|
||||
if (current->flags & FMT_LONG) {
|
||||
PRINT (double);
|
||||
} else {
|
||||
PRINT (float);
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
dstring_appendstr (tmp, "g");
|
||||
PRINT (float);
|
||||
if (current->flags & FMT_LONG) {
|
||||
PRINT (double);
|
||||
} else {
|
||||
PRINT (float);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -650,7 +660,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
|||
int fmt_count = 0;
|
||||
|
||||
if (!name)
|
||||
name = "PF_InternalSprintf";
|
||||
name = "PR_Sprintf";
|
||||
|
||||
*fi = new_fmt_item ();
|
||||
c = l = format;
|
||||
|
@ -742,12 +752,19 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
|
|||
fi = &(*fi)->next;
|
||||
break;
|
||||
case 'f':
|
||||
// float
|
||||
// float or double
|
||||
case 'g':
|
||||
// float, no trailing zeroes, trim "." if nothing
|
||||
// after
|
||||
// float or double, no trailing zeroes, trim "."
|
||||
// if nothing after
|
||||
(*fi)->type = *c;
|
||||
(*fi)->data.float_var = P_FLOAT (pr, fmt_count);
|
||||
if (pr->float_promoted) {
|
||||
(*fi)->flags |= FMT_LONG;
|
||||
(*fi)->data.double_var
|
||||
= P_DOUBLE (pr, fmt_count);
|
||||
} else {
|
||||
(*fi)->data.float_var
|
||||
= P_FLOAT (pr, fmt_count);
|
||||
}
|
||||
|
||||
fmt_count++;
|
||||
(*fi)->next = new_fmt_item ();
|
||||
|
|
|
@ -42,55 +42,55 @@
|
|||
#include "rua_internal.h"
|
||||
|
||||
static void
|
||||
bi_sin (progs_t *pr)
|
||||
bi_sinf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = sinf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cos (progs_t *pr)
|
||||
bi_cosf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = cosf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tan (progs_t *pr)
|
||||
bi_tanf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = tanf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asin (progs_t *pr)
|
||||
bi_asinf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = asinf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acos (progs_t *pr)
|
||||
bi_acosf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = acosf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan (progs_t *pr)
|
||||
bi_atanf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = atanf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan2 (progs_t *pr)
|
||||
bi_atan2f (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = atan2f (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log (progs_t *pr)
|
||||
bi_logf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = logf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log2 (progs_t *pr)
|
||||
bi_log2f (progs_t *pr)
|
||||
{
|
||||
#ifdef HAVE_LOG2F
|
||||
R_FLOAT (pr) = log2f (P_FLOAT (pr, 0));
|
||||
|
@ -100,95 +100,238 @@ bi_log2 (progs_t *pr)
|
|||
}
|
||||
|
||||
static void
|
||||
bi_log10 (progs_t *pr)
|
||||
bi_log10f (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = log10f (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_pow (progs_t *pr)
|
||||
bi_powf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = powf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sqrt (progs_t *pr)
|
||||
bi_sqrtf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = sqrtf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cbrt (progs_t *pr)
|
||||
bi_cbrtf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = cbrtf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_hypot (progs_t *pr)
|
||||
bi_hypotf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = hypotf (P_FLOAT (pr, 0), P_FLOAT (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sinh (progs_t *pr)
|
||||
bi_sinhf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = sinhf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cosh (progs_t *pr)
|
||||
bi_coshf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = coshf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tanh (progs_t *pr)
|
||||
bi_tanhf (progs_t *pr)
|
||||
{
|
||||
R_FLOAT (pr) = tanhf (P_FLOAT (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asinh (progs_t *pr)
|
||||
bi_asinhf (progs_t *pr)
|
||||
{
|
||||
double y = P_FLOAT (pr, 0);
|
||||
R_FLOAT (pr) = logf (y + sqrtf (y * y + 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acosh (progs_t *pr)
|
||||
bi_acoshf (progs_t *pr)
|
||||
{
|
||||
double y = P_FLOAT (pr, 0);
|
||||
R_FLOAT (pr) = logf (y + sqrtf (y * y - 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atanh (progs_t *pr)
|
||||
bi_atanhf (progs_t *pr)
|
||||
{
|
||||
double y = P_FLOAT (pr, 0);
|
||||
R_FLOAT (pr) = logf ((1 + y) / (1 - y)) / 2;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sin (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = sin (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cos (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = cos (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tan (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = tan (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asin (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = asin (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acos (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = acos (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = atan (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atan2 (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = atan2 (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = log (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log2 (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = log (P_DOUBLE (pr, 0)) / M_LOG2E;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_log10 (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = log10 (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_pow (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = pow (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sqrt (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = sqrt (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cbrt (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = cbrt (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_hypot (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = hypot (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_sinh (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = sinh (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_cosh (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = cosh (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_tanh (progs_t *pr)
|
||||
{
|
||||
R_DOUBLE (pr) = tanh (P_DOUBLE (pr, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_asinh (progs_t *pr)
|
||||
{
|
||||
double y = P_DOUBLE (pr, 0);
|
||||
R_DOUBLE (pr) = log (y + sqrt (y * y + 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_acosh (progs_t *pr)
|
||||
{
|
||||
double y = P_DOUBLE (pr, 0);
|
||||
R_DOUBLE (pr) = log (y + sqrt (y * y - 1));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_atanh (progs_t *pr)
|
||||
{
|
||||
double y = P_DOUBLE (pr, 0);
|
||||
R_DOUBLE (pr) = log ((1 + y) / (1 - y)) / 2;
|
||||
}
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
{"sin", bi_sin, -1},
|
||||
{"cos", bi_cos, -1},
|
||||
{"tan", bi_tan, -1},
|
||||
{"asin", bi_asin, -1},
|
||||
{"acos", bi_acos, -1},
|
||||
{"atan", bi_atan, -1},
|
||||
{"atan2", bi_atan2, -1},
|
||||
{"log", bi_log, -1},
|
||||
{"log2", bi_log2, -1},
|
||||
{"log10", bi_log10, -1},
|
||||
{"pow", bi_pow, -1},
|
||||
{"sqrt", bi_sqrt, -1},
|
||||
{"cbrt", bi_cbrt, -1},
|
||||
{"hypot", bi_hypot, -1},
|
||||
{"sinh", bi_sinh, -1},
|
||||
{"cosh", bi_cosh, -1},
|
||||
{"tanh", bi_tanh, -1},
|
||||
{"asinh", bi_asinh, -1},
|
||||
{"acosh", bi_acosh, -1},
|
||||
{"atanh", bi_atanh, -1},
|
||||
{"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|f", bi_atan2f, -1},
|
||||
{"log|f", bi_logf, -1},
|
||||
{"log2|f", bi_log2f, -1},
|
||||
{"log10|f", bi_log10f, -1},
|
||||
{"pow|f", bi_powf, -1},
|
||||
{"sqrt|f", bi_sqrtf, -1},
|
||||
{"cbrt|f", bi_cbrtf, -1},
|
||||
{"hypot|f", 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},
|
||||
{"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|d", bi_atan2, -1},
|
||||
{"log|d", bi_log, -1},
|
||||
{"log2|d", bi_log2, -1},
|
||||
{"log10|d", bi_log10, -1},
|
||||
{"pow|d", bi_pow, -1},
|
||||
{"sqrt|d", bi_sqrt, -1},
|
||||
{"cbrt|d", bi_cbrt, -1},
|
||||
{"hypot|d", 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},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -210,6 +210,11 @@ extern progs_t sv_pr_state;
|
|||
#define SVentity(e,f) SVFIELD (e, f, entity)
|
||||
#define SVvector(e,f) SVFIELD (e, f, vector)
|
||||
#define SVinteger(e,f) SVFIELD (e, f, integer)
|
||||
#if TYPECHECK_PROGS
|
||||
#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__))
|
||||
#else
|
||||
#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f)
|
||||
#endif
|
||||
|
||||
typedef struct edict_leaf_s {
|
||||
struct edict_leaf_s *next;
|
||||
|
|
|
@ -361,6 +361,9 @@ set_address (sv_def_t *def, void *address)
|
|||
case ev_quat:
|
||||
*(float **)def->field = (float *) address;
|
||||
break;
|
||||
case ev_double:
|
||||
*(double **)def->field = (double *) address;
|
||||
break;
|
||||
case ev_string:
|
||||
case ev_entity:
|
||||
case ev_field:
|
||||
|
|
|
@ -195,6 +195,11 @@ extern progs_t sv_pr_state;
|
|||
#define SVentity(e,f) SVFIELD (e, f, entity)
|
||||
#define SVvector(e,f) SVFIELD (e, f, vector)
|
||||
#define SVinteger(e,f) SVFIELD (e, f, integer)
|
||||
#if TYPECHECK_PROGS
|
||||
#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__))
|
||||
#else
|
||||
#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f)
|
||||
#endif
|
||||
|
||||
typedef struct edict_leaf_s {
|
||||
struct edict_leaf_s *next;
|
||||
|
|
|
@ -371,6 +371,9 @@ set_address (sv_def_t *def, void *address)
|
|||
case ev_quat:
|
||||
*(float **)def->field = (float *) address;
|
||||
break;
|
||||
case ev_double:
|
||||
*(double **)def->field = (double *) address;
|
||||
break;
|
||||
case ev_string:
|
||||
case ev_entity:
|
||||
case ev_field:
|
||||
|
|
|
@ -60,17 +60,20 @@
|
|||
/**
|
||||
Returns \a f, rounded down to the next lower integer
|
||||
*/
|
||||
@extern float floor (float f);
|
||||
@extern @overload float floor (float f);
|
||||
@extern @overload double floor (double f);
|
||||
|
||||
/**
|
||||
Returns \a f, rounded up to the next highest integer
|
||||
*/
|
||||
@extern float ceil (float f);
|
||||
@extern @overload float ceil (float f);
|
||||
@extern @overload double ceil (double f);
|
||||
|
||||
/**
|
||||
Returns the absolute value of \a f
|
||||
*/
|
||||
@extern float fabs (float f);
|
||||
@extern @overload float fabs (float f);
|
||||
@extern @overload double fabs (double f);
|
||||
//\}
|
||||
|
||||
///\name Exponentials and Logarithms
|
||||
|
@ -78,32 +81,38 @@
|
|||
/**
|
||||
Returns the natural log of \a x.
|
||||
*/
|
||||
@extern float log (float x);
|
||||
@extern @overload float log (float x);
|
||||
@extern @overload double log (double x);
|
||||
|
||||
/**
|
||||
Returns the base-2 log of \a x.
|
||||
*/
|
||||
@extern float log2 (float x);
|
||||
@extern @overload float log2 (float x);
|
||||
@extern @overload double log2 (double x);
|
||||
|
||||
/**
|
||||
Returns the base-10 log of \a x.
|
||||
*/
|
||||
@extern float log10 (float x);
|
||||
@extern @overload float log10 (float x);
|
||||
@extern @overload double log10 (double x);
|
||||
|
||||
/**
|
||||
Returns \a x to the \a y power
|
||||
*/
|
||||
@extern float pow (float x, float y);
|
||||
@extern @overload float pow (float x, float y);
|
||||
@extern @overload double pow (double x, double y);
|
||||
|
||||
/**
|
||||
Returns the square root of \a x
|
||||
*/
|
||||
@extern float sqrt (float x);
|
||||
@extern @overload float sqrt (float x);
|
||||
@extern @overload double sqrt (double x);
|
||||
|
||||
/**
|
||||
Returns the cube root of \a x
|
||||
*/
|
||||
@extern float cbrt (float x);
|
||||
@extern @overload float cbrt (float x);
|
||||
@extern @overload double cbrt (double x);
|
||||
//\}
|
||||
|
||||
///\name Trigonometric functions
|
||||
|
@ -112,40 +121,52 @@
|
|||
/**
|
||||
Returns the sine of \a x.
|
||||
*/
|
||||
@extern float sin (float x);
|
||||
@extern @overload float sin (float x);
|
||||
@extern @overload double sin (double x);
|
||||
|
||||
/**
|
||||
Returns the cosine of \a x.
|
||||
*/
|
||||
@extern float cos (float x);
|
||||
@extern @overload float cos (float x);
|
||||
@extern @overload double cos (double x);
|
||||
|
||||
/**
|
||||
Returns the tangent of \a x.
|
||||
*/
|
||||
@extern float tan (float x);
|
||||
@extern @overload float tan (float x);
|
||||
@extern @overload double tan (double x);
|
||||
|
||||
/**
|
||||
Returns the arcsine of \a x.
|
||||
*/
|
||||
@extern float asin (float x);
|
||||
@extern @overload float asin (float x);
|
||||
@extern @overload double asin (double x);
|
||||
|
||||
/**
|
||||
Returns the arccosine of \a x.
|
||||
*/
|
||||
@extern float acos (float x);
|
||||
@extern @overload float acos (float x);
|
||||
@extern @overload double acos (double x);
|
||||
|
||||
/**
|
||||
Returns the arctangent of \a x.
|
||||
*/
|
||||
@extern float atan (float x);
|
||||
@extern float atan2 (float y, float x);
|
||||
@extern @overload float atan (float x);
|
||||
@extern @overload double atan (double x);
|
||||
|
||||
/**
|
||||
Returns the arctangent of \a y / \a x preserving the quadrant.
|
||||
*/
|
||||
@extern @overload float atan2 (float y, float x);
|
||||
@extern @overload double atan2 (double y, double x);
|
||||
|
||||
/**
|
||||
Returns the length of the hypotenuse of a right triangle with sides \a x
|
||||
and \a y. That is, this function returns
|
||||
<code>sqrt (\a x*\a x + \a y*\a y)</code>.
|
||||
*/
|
||||
@extern float hypot (float x, float y);
|
||||
@extern @overload float hypot (float x, float y);
|
||||
@extern @overload double hypot (double x, double y);
|
||||
//\}
|
||||
|
||||
///\name Hyperbolic functions
|
||||
|
@ -153,32 +174,38 @@
|
|||
/**
|
||||
Returns the hyperbolic sine of \a x
|
||||
*/
|
||||
@extern float sinh (float x);
|
||||
@extern @overload float sinh (float x);
|
||||
@extern @overload double sinh (double x);
|
||||
|
||||
/**
|
||||
Returns the hyperbolic cosine of \a x
|
||||
*/
|
||||
@extern float cosh (float x);
|
||||
@extern @overload float cosh (float x);
|
||||
@extern @overload double cosh (double x);
|
||||
|
||||
/**
|
||||
Returns the hyperbolic tangent of \a x
|
||||
*/
|
||||
@extern float tanh (float x);
|
||||
@extern @overload float tanh (float x);
|
||||
@extern @overload double tanh (double x);
|
||||
|
||||
/**
|
||||
Returns the area hyperbolic sine of \a x
|
||||
*/
|
||||
@extern float asinh (float x);
|
||||
@extern @overload float asinh (float x);
|
||||
@extern @overload double asinh (double x);
|
||||
|
||||
/**
|
||||
Returns the area hyperbolic cosine of \a x
|
||||
*/
|
||||
@extern float acosh (float x);
|
||||
@extern @overload float acosh (float x);
|
||||
@extern @overload double acosh (double x);
|
||||
|
||||
/**
|
||||
Returns the area hyperbolic tangent of \a x
|
||||
*/
|
||||
@extern float atanh (float x);
|
||||
@extern @overload float atanh (float x);
|
||||
@extern @overload double atanh (double x);
|
||||
//\}
|
||||
|
||||
///\name Vector Functions
|
||||
|
|
|
@ -34,3 +34,27 @@ float (float x) atanh = #0;
|
|||
float (float x) sqrt = #0;
|
||||
float (float x) cbrt = #0;
|
||||
float (float x, float y) hypot = #0;
|
||||
|
||||
double (double v) floor = #0;
|
||||
double (double v) ceil = #0;
|
||||
double (double f) fabs = #0;
|
||||
double (double x) sin = #0;
|
||||
double (double x) cos = #0;
|
||||
double (double x) tan = #0;
|
||||
double (double x) asin = #0;
|
||||
double (double x) acos = #0;
|
||||
double (double x) atan = #0;
|
||||
double (double y, double x) atan2 = #0;
|
||||
double (double x) log = #0;
|
||||
double (double x) log2 = #0;
|
||||
double (double x) log10 = #0;
|
||||
double (double x, double y) pow = #0;
|
||||
double (double x) sinh = #0;
|
||||
double (double x) cosh = #0;
|
||||
double (double x) tanh = #0;
|
||||
double (double x) asinh = #0;
|
||||
double (double x) acosh = #0;
|
||||
double (double x) atanh = #0;
|
||||
double (double x) sqrt = #0;
|
||||
double (double x) cbrt = #0;
|
||||
double (double x, double y) hypot = #0;
|
||||
|
|
|
@ -174,6 +174,7 @@ typedef struct ex_value_s {
|
|||
etype_t lltype;
|
||||
union {
|
||||
const char *string_val; ///< string constant
|
||||
float double_val; ///< double constant
|
||||
float float_val; ///< float constant
|
||||
float vector_val[3]; ///< vector constant
|
||||
int entity_val; ///< entity constant
|
||||
|
@ -397,6 +398,15 @@ expr_t *new_name_expr (const char *name);
|
|||
expr_t *new_string_expr (const char *string_val);
|
||||
const char *expr_string (expr_t *e) __attribute__((pure));
|
||||
|
||||
/** Create a new double constant expression node.
|
||||
|
||||
\param double_val The double constant being represented.
|
||||
\return The new double constant expression node
|
||||
(expr_t::e::double_val).
|
||||
*/
|
||||
expr_t *new_double_expr (double double_val);
|
||||
double expr_double (expr_t *e) __attribute__((pure));
|
||||
|
||||
/** Create a new float constant expression node.
|
||||
|
||||
\param float_val The float constant being represented.
|
||||
|
|
|
@ -98,6 +98,7 @@ typedef struct {
|
|||
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;
|
||||
|
@ -153,6 +154,7 @@ const char *type_get_encoding (const type_t *type);
|
|||
int is_void (const type_t *type) __attribute__((pure));
|
||||
int is_enum (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_scalar (const type_t *type) __attribute__((pure));
|
||||
int is_vector (const type_t *type) __attribute__((pure));
|
||||
|
|
|
@ -40,6 +40,7 @@ struct ex_value_s;
|
|||
struct type_s;
|
||||
|
||||
struct ex_value_s *new_string_val (const char *string_val);
|
||||
struct ex_value_s *new_double_val (double double_val);
|
||||
struct ex_value_s *new_float_val (float float_val);
|
||||
struct ex_value_s *new_vector_val (const float *vector_val);
|
||||
struct ex_value_s *new_entity_val (int entity_val);
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "qfcc.h"
|
||||
#include "strpool.h"
|
||||
#include "type.h"
|
||||
#include "value.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2);
|
||||
|
@ -163,6 +164,40 @@ convert_to_float (expr_t *e)
|
|||
}
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
convert_to_double (expr_t *e)
|
||||
{
|
||||
if (get_type (e) == &type_double)
|
||||
return e;
|
||||
|
||||
switch (e->type) {
|
||||
case ex_value:
|
||||
switch (e->e.value->lltype) {
|
||||
case ev_integer:
|
||||
e->e.value = new_double_val (expr_integer (e));
|
||||
return e;
|
||||
case ev_short:
|
||||
e->e.value = new_double_val (expr_short (e));
|
||||
return e;
|
||||
case ev_float:
|
||||
e->e.value = new_double_val (expr_float (e));
|
||||
return e;
|
||||
default:
|
||||
internal_error (e, 0);
|
||||
}
|
||||
break;
|
||||
case ex_symbol:
|
||||
case ex_expr:
|
||||
case ex_uexpr:
|
||||
case ex_temp:
|
||||
case ex_block:
|
||||
e = cf_cast_expr (&type_float, e);
|
||||
return e;
|
||||
default:
|
||||
internal_error (e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
|
@ -292,6 +327,111 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
double d1, d2;
|
||||
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 == '=' || op == PAS) {
|
||||
if ((type = get_type (e1)) != &type_double) {
|
||||
//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 (is_compare (op) || is_logic (op)) {
|
||||
type = &type_integer;
|
||||
}
|
||||
e->e.expr.type = type;
|
||||
|
||||
if (op == '*' && is_constant (e1) && expr_double (e1) == 1)
|
||||
return e2;
|
||||
if (op == '*' && is_constant (e2) && expr_double (e2) == 1)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e1) && expr_double (e1) == 0)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return e2;
|
||||
if (op == '/' && is_constant (e2) && expr_double (e2) == 1)
|
||||
return e1;
|
||||
if (op == '/' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return error (e, "division by zero");
|
||||
if (op == '/' && is_constant (e1) && expr_double (e1) == 0)
|
||||
return e1;
|
||||
if (op == '+' && is_constant (e1) && expr_double (e1) == 0)
|
||||
return e2;
|
||||
if (op == '+' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return e1;
|
||||
if (op == '-' && is_constant (e2) && expr_double (e2) == 0)
|
||||
return e1;
|
||||
|
||||
if (op == '=' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
d1 = expr_double (e1);
|
||||
d2 = expr_double (e2);
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
e = new_double_expr (d1 + d2);
|
||||
break;
|
||||
case '-':
|
||||
e = new_double_expr (d1 - d2);
|
||||
break;
|
||||
case '*':
|
||||
e = new_double_expr (d1 * d2);
|
||||
break;
|
||||
case '/':
|
||||
if (!d2)
|
||||
return error (e1, "divide by zero");
|
||||
e = new_double_expr (d1 / d2);
|
||||
break;
|
||||
case '%':
|
||||
e = new_double_expr ((int)d1 % (int)d2);
|
||||
break;
|
||||
case LT:
|
||||
e = new_integer_expr (d1 < d2);
|
||||
break;
|
||||
case GT:
|
||||
e = new_integer_expr (d1 > d2);
|
||||
break;
|
||||
case LE:
|
||||
e = new_integer_expr (d1 <= d2);
|
||||
break;
|
||||
case GE:
|
||||
e = new_integer_expr (d1 >= d2);
|
||||
break;
|
||||
case EQ:
|
||||
e = new_integer_expr (d1 == d2);
|
||||
break;
|
||||
case NE:
|
||||
e = new_integer_expr (d1 != d2);
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
|
@ -884,11 +1024,15 @@ do_op_compound (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
return do_op_struct (op, e, e1, e2);
|
||||
if (is_scalar (t1) && is_scalar (t2)) {
|
||||
if (is_enum (t1)) {
|
||||
if (t2->type == ev_float)
|
||||
if (t2->type == ev_double)
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
@ -947,6 +1091,7 @@ static operation_t op_void[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -963,6 +1108,7 @@ static operation_t op_string[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -979,6 +1125,7 @@ static operation_t op_float[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -995,6 +1142,7 @@ static operation_t op_vector[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1011,6 +1159,7 @@ static operation_t op_entity[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1027,6 +1176,7 @@ static operation_t op_field[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1043,6 +1193,7 @@ static operation_t op_func[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1059,6 +1210,7 @@ static operation_t op_pointer[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1075,6 +1227,7 @@ static operation_t op_quaternion[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1091,6 +1244,7 @@ static operation_t op_integer[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1107,6 +1261,7 @@ static operation_t op_uinteger[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1123,6 +1278,24 @@ static operation_t op_short[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
@ -1139,6 +1312,7 @@ static operation_t op_compound[ev_type_count] = {
|
|||
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
|
||||
};
|
||||
|
||||
|
@ -1155,6 +1329,7 @@ static operation_t *do_op[ev_type_count] = {
|
|||
op_integer, // ev_integer
|
||||
op_uinteger, // ev_uinteger
|
||||
op_short, // ev_short
|
||||
op_double, // ev_double
|
||||
op_compound, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1203,13 +1378,15 @@ static expr_t *
|
|||
uop_float (int op, expr_t *e, expr_t *e1)
|
||||
{
|
||||
static int valid[] = { '+', '-', '!', '~', 'C', 0 };
|
||||
type_t *type;
|
||||
|
||||
if (!valid_op (op, valid))
|
||||
return error (e1, "invalid unary operator for float: %s",
|
||||
get_op_string (op));
|
||||
if (op == '+')
|
||||
return e1;
|
||||
if (op == 'C' && get_type (e) != &type_integer)
|
||||
type = get_type (e);
|
||||
if (op == 'C' && type != &type_integer && type != &type_double)
|
||||
return error (e1, "invalid cast of float");
|
||||
if (!is_constant (e1))
|
||||
return e;
|
||||
|
@ -1222,7 +1399,11 @@ uop_float (int op, expr_t *e, expr_t *e1)
|
|||
case '~':
|
||||
return new_float_expr (~(int) expr_float (e1));
|
||||
case 'C':
|
||||
return new_integer_expr (expr_float (e1));
|
||||
if (type == &type_integer) {
|
||||
return new_integer_expr (expr_float (e1));
|
||||
} else {
|
||||
return new_double_expr (expr_float (e1));
|
||||
}
|
||||
}
|
||||
internal_error (e, "float unary op blew up");
|
||||
}
|
||||
|
@ -1420,6 +1601,38 @@ uop_short (int op, expr_t *e, expr_t *e1)
|
|||
internal_error (e, "short unary op blew up");
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
uop_double (int op, expr_t *e, expr_t *e1)
|
||||
{
|
||||
static int valid[] = { '+', '-', '!', 'C', 0 };
|
||||
type_t *type;
|
||||
|
||||
if (!valid_op (op, valid))
|
||||
return error (e1, "invalid unary operator for double: %s",
|
||||
get_op_string (op));
|
||||
if (op == '+')
|
||||
return e1;
|
||||
type = get_type (e);
|
||||
if (op == 'C' && type != &type_integer && type != &type_float)
|
||||
return error (e1, "invalid cast of double");
|
||||
if (!is_constant (e1))
|
||||
return e;
|
||||
switch (op) {
|
||||
case '-':
|
||||
return new_double_expr (-expr_double (e1));
|
||||
case '!':
|
||||
print_type (get_type (e));
|
||||
return new_integer_expr (!expr_double (e1));
|
||||
case 'C':
|
||||
if (type == &type_integer) {
|
||||
return new_integer_expr (expr_double (e1));
|
||||
} else {
|
||||
return new_float_expr (expr_double (e1));
|
||||
}
|
||||
}
|
||||
internal_error (e, "float unary op blew up");
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
uop_compound (int op, expr_t *e, expr_t *e1)
|
||||
{
|
||||
|
@ -1446,6 +1659,7 @@ static unaryop_t do_unary_op[ev_type_count] = {
|
|||
uop_integer, // ev_integer
|
||||
uop_uinteger, // ev_uinteger
|
||||
uop_short, // ev_short
|
||||
uop_double, // ev_double
|
||||
uop_compound, // ev_invalid
|
||||
};
|
||||
|
||||
|
@ -1487,7 +1701,7 @@ fold_constants (expr_t *e)
|
|||
|
||||
if (t1 >= ev_type_count || t2 >= ev_type_count
|
||||
|| !do_op[t1] || !do_op[t1][t2])
|
||||
internal_error (e, "invalid type");
|
||||
internal_error (e, "invalid type %d %d", t1, t2);
|
||||
return do_op[t1][t2] (op, e, e1, e2);
|
||||
}
|
||||
return e;
|
||||
|
|
|
@ -438,6 +438,9 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next)
|
|||
case ev_string:
|
||||
label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val));
|
||||
break;
|
||||
case ev_double:
|
||||
label = va ("f %g", e->e.value->v.double_val);
|
||||
break;
|
||||
case ev_float:
|
||||
label = va ("f %g", e->e.value->v.float_val);
|
||||
break;
|
||||
|
|
|
@ -611,6 +611,15 @@ new_string_expr (const char *string_val)
|
|||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_double_expr (double double_val)
|
||||
{
|
||||
expr_t *e = new_expr ();
|
||||
e->type = ex_value;
|
||||
e->e.value = new_double_val (double_val);
|
||||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_float_expr (float float_val)
|
||||
{
|
||||
|
@ -845,6 +854,23 @@ is_float_val (expr_t *e)
|
|||
return 0;
|
||||
}
|
||||
|
||||
double
|
||||
expr_double (expr_t *e)
|
||||
{
|
||||
if (e->type == ex_nil)
|
||||
return 0;
|
||||
if (e->type == ex_value && e->e.value->lltype == ev_double)
|
||||
return e->e.value->v.double_val;
|
||||
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const
|
||||
&& e->e.symbol->type->type == ev_double)
|
||||
return e->e.symbol->s.value->v.double_val;
|
||||
if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var
|
||||
&& e->e.symbol->s.def->constant
|
||||
&& is_double (e->e.symbol->s.def->type))
|
||||
return D_FLOAT (e->e.symbol->s.def);
|
||||
internal_error (e, "not a double constant");
|
||||
}
|
||||
|
||||
float
|
||||
expr_float (expr_t *e)
|
||||
{
|
||||
|
@ -1276,6 +1302,9 @@ test_expr (expr_t *e)
|
|||
}
|
||||
new = new_float_expr (0);
|
||||
break;
|
||||
case ev_double:
|
||||
new = new_double_expr (0);
|
||||
break;
|
||||
case ev_vector:
|
||||
new = new_vector_expr (zero);
|
||||
break;
|
||||
|
@ -1610,6 +1639,8 @@ unary_expr (int op, expr_t *e)
|
|||
case ev_func:
|
||||
case ev_pointer:
|
||||
internal_error (e, "type check failed!");
|
||||
case ev_double:
|
||||
return new_double_expr (-expr_double (e));
|
||||
case ev_float:
|
||||
return new_float_expr (-expr_float (e));
|
||||
case ev_vector:
|
||||
|
@ -1676,6 +1707,8 @@ unary_expr (int op, expr_t *e)
|
|||
case ev_string:
|
||||
s = expr_string (e);
|
||||
return new_integer_expr (!s || !s[0]);
|
||||
case ev_double:
|
||||
return new_integer_expr (!expr_double (e));
|
||||
case ev_float:
|
||||
return new_integer_expr (!expr_float (e));
|
||||
case ev_vector:
|
||||
|
@ -1735,6 +1768,7 @@ unary_expr (int op, expr_t *e)
|
|||
case ev_func:
|
||||
case ev_pointer:
|
||||
case ev_vector:
|
||||
case ev_double:
|
||||
return error (e, "invalid type for unary ~");
|
||||
case ev_float:
|
||||
return new_float_expr (~(int) expr_float (e));
|
||||
|
|
|
@ -333,6 +333,7 @@ static keyword_t at_keywords[] = {
|
|||
// be supported (sanely) by v6 progs.
|
||||
static keyword_t qf_keywords[] = {
|
||||
{"quaternion", TYPE, &type_quaternion},
|
||||
{"double", TYPE, &type_double},
|
||||
{"int", TYPE, &type_integer },
|
||||
{"unsigned", TYPE, &type_integer },//FIXME
|
||||
{"function", TYPE, &type_function },
|
||||
|
|
|
@ -87,6 +87,8 @@ operand_string (operand_t *op)
|
|||
case ev_string:
|
||||
return va ("\"%s\"",
|
||||
quote_string (op->o.value->v.string_val));
|
||||
case ev_double:
|
||||
return va ("%g", op->o.value->v.double_val);
|
||||
case ev_float:
|
||||
return va ("%g", op->o.value->v.float_val);
|
||||
case ev_vector:
|
||||
|
@ -159,6 +161,9 @@ print_operand (operand_t *op)
|
|||
case ev_string:
|
||||
printf ("\"%s\"", op->o.value->v.string_val);
|
||||
break;
|
||||
case ev_double:
|
||||
printf ("%g", op->o.value->v.double_val);
|
||||
break;
|
||||
case ev_float:
|
||||
printf ("%g", op->o.value->v.float_val);
|
||||
break;
|
||||
|
|
|
@ -76,6 +76,7 @@ type_t type_quaternion = { ev_quat, "quaternion" };
|
|||
type_t type_integer = { ev_integer, "int" };
|
||||
type_t type_uinteger = { ev_uinteger, "uint" };
|
||||
type_t type_short = { ev_short, "short" };
|
||||
type_t type_double = { ev_double, "double" };
|
||||
|
||||
type_t *type_nil;
|
||||
type_t *type_default;
|
||||
|
@ -101,6 +102,7 @@ type_t *ev_types[ev_type_count] = {
|
|||
&type_integer,
|
||||
&type_uinteger,
|
||||
&type_short,
|
||||
&type_double,
|
||||
&type_invalid,
|
||||
};
|
||||
|
||||
|
@ -180,6 +182,7 @@ free_type (type_t *type)
|
|||
case ev_integer:
|
||||
case ev_uinteger:
|
||||
case ev_short:
|
||||
case ev_double:
|
||||
break;
|
||||
case ev_field:
|
||||
case ev_pointer:
|
||||
|
@ -214,6 +217,7 @@ append_type (type_t *type, type_t *new)
|
|||
case ev_integer:
|
||||
case ev_uinteger:
|
||||
case ev_short:
|
||||
case ev_double:
|
||||
internal_error (0, "append to basic type");
|
||||
case ev_field:
|
||||
case ev_pointer:
|
||||
|
@ -582,6 +586,9 @@ encode_type (dstring_t *encoding, const type_t *type)
|
|||
case ev_string:
|
||||
dasprintf (encoding, "*");
|
||||
break;
|
||||
case ev_double:
|
||||
dasprintf (encoding, "d");
|
||||
break;
|
||||
case ev_float:
|
||||
dasprintf (encoding, "f");
|
||||
break;
|
||||
|
@ -685,6 +692,12 @@ is_integral (const type_t *type)
|
|||
return is_enum (type);
|
||||
}
|
||||
|
||||
int
|
||||
is_double (const type_t *type)
|
||||
{
|
||||
return type->type == ev_double;
|
||||
}
|
||||
|
||||
int
|
||||
is_float (const type_t *type)
|
||||
{
|
||||
|
@ -694,7 +707,7 @@ is_float (const type_t *type)
|
|||
int
|
||||
is_scalar (const type_t *type)
|
||||
{
|
||||
return is_float (type) || is_integral (type);
|
||||
return is_float (type) || is_integral (type) || is_double (type);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -830,6 +843,7 @@ type_size (const type_t *type)
|
|||
case ev_integer:
|
||||
case ev_uinteger:
|
||||
case ev_short:
|
||||
case ev_double:
|
||||
case ev_type_count:
|
||||
return pr_type_size[type->type];
|
||||
case ev_invalid:
|
||||
|
@ -869,6 +883,7 @@ init_types (void)
|
|||
{
|
||||
static struct_def_t zero_struct[] = {
|
||||
{"string_val", &type_string},
|
||||
{"double_val", &type_double},
|
||||
{"float_val", &type_float},
|
||||
{"entity_val", &type_entity},
|
||||
{"field_val", &type_field},
|
||||
|
@ -884,6 +899,7 @@ init_types (void)
|
|||
};
|
||||
static struct_def_t param_struct[] = {
|
||||
{"string_val", &type_string},
|
||||
{"double_val", &type_double},
|
||||
{"float_val", &type_float},
|
||||
{"vector_val", &type_vector},
|
||||
{"entity_val", &type_entity},
|
||||
|
@ -982,6 +998,7 @@ chain_initial_types (void)
|
|||
chain_type (&type_integer);
|
||||
chain_type (&type_uinteger);
|
||||
chain_type (&type_short);
|
||||
chain_type (&type_double);
|
||||
}
|
||||
|
||||
chain_type (&type_param);
|
||||
|
|
|
@ -132,6 +132,16 @@ new_string_val (const char *string_val)
|
|||
return find_value (&val);
|
||||
}
|
||||
|
||||
ex_value_t *
|
||||
new_double_val (double double_val)
|
||||
{
|
||||
ex_value_t val;
|
||||
memset (&val, 0, sizeof (val));
|
||||
set_val_type (&val, &type_double);
|
||||
val.v.double_val = double_val;
|
||||
return find_value (&val);
|
||||
}
|
||||
|
||||
ex_value_t *
|
||||
new_float_val (float float_val)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue