mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-24 11:32:16 +00:00
Fix lshift/rshift for runtime and const-fold consistency.
This commit is contained in:
parent
0f506e768b
commit
a140b749ff
2 changed files with 27 additions and 14 deletions
4
fold.c
4
fold.c
|
@ -550,13 +550,13 @@ static GMQCC_INLINE ast_expression *fold_op_xor(fold_t *fold, ast_value *a, ast_
|
|||
|
||||
static GMQCC_INLINE ast_expression *fold_op_lshift(fold_t *fold, ast_value *a, ast_value *b) {
|
||||
if (fold_can_2(a, b) && isfloats(a, b))
|
||||
return fold_constgen_float(fold, (qcfloat_t)((qcuint_t)(fold_immvalue_float(a)) << (qcuint_t)(fold_immvalue_float(b))));
|
||||
return fold_constgen_float(fold, (qcfloat_t)(((qcuint_t)floorf(fold_immvalue_float(a) * powf(2, fold_immvalue_float(b)))) & 0xFFFFFF));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GMQCC_INLINE ast_expression *fold_op_rshift(fold_t *fold, ast_value *a, ast_value *b) {
|
||||
if (fold_can_2(a, b) && isfloats(a, b))
|
||||
return fold_constgen_float(fold, (qcfloat_t)((qcuint_t)(fold_immvalue_float(a)) >> (qcuint_t)(fold_immvalue_float(b))));
|
||||
return fold_constgen_float(fold, (qcfloat_t)(((qcuint_t)floorf(fold_immvalue_float(a) / powf(2, fold_immvalue_float(b)))) & 0xFFFFFF));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
37
intrin.c
37
intrin.c
|
@ -1940,28 +1940,41 @@ static ast_expression *intrin_logb(intrin_t *intrin) {
|
|||
}
|
||||
|
||||
static ast_expression *intrin_shift_variant(intrin_t *intrin, const char *name, size_t instr) {
|
||||
ast_value *value = NULL;
|
||||
ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", name));
|
||||
ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
|
||||
ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(intrin_ctx(intrin));
|
||||
ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
|
||||
/*
|
||||
* float [shift] (float a, float b) {
|
||||
* return floor(a [instr] pow(2, b));
|
||||
*/
|
||||
ast_value *value = NULL;
|
||||
ast_call *callpow = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "pow", name));
|
||||
ast_call *callfloor = ast_call_new (intrin_ctx(intrin), intrin_func_self(intrin, "floor", name));
|
||||
ast_value *a = ast_value_new(intrin_ctx(intrin), "a", TYPE_FLOAT);
|
||||
ast_value *b = ast_value_new(intrin_ctx(intrin), "b", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(intrin_ctx(intrin));
|
||||
ast_function *func = intrin_value(intrin, &value, name, TYPE_FLOAT);
|
||||
|
||||
vec_push(value->expression.params, a);
|
||||
vec_push(value->expression.params, b);
|
||||
|
||||
/* <callpow> = pow(2, b) */
|
||||
vec_push(callpow->params, (ast_expression*)intrin->fold->imm_float[3]);
|
||||
vec_push(callpow->params, (ast_expression*)b);
|
||||
|
||||
/* <callfloor> = floor(a [instr] <callpow>) */
|
||||
vec_push(
|
||||
callfloor->params,
|
||||
(ast_expression*)ast_binary_new(
|
||||
intrin_ctx(intrin),
|
||||
instr,
|
||||
(ast_expression*)a,
|
||||
(ast_expression*)callpow
|
||||
)
|
||||
);
|
||||
|
||||
/* return <callfloor> */
|
||||
vec_push(body->exprs,
|
||||
(ast_expression*)ast_return_new(
|
||||
intrin_ctx(intrin),
|
||||
(ast_expression*)ast_binary_new(
|
||||
intrin_ctx(intrin),
|
||||
instr,
|
||||
(ast_expression*)a,
|
||||
(ast_expression*)callpow
|
||||
)
|
||||
(ast_expression*)callfloor
|
||||
)
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue