Fix lshift/rshift for runtime and const-fold consistency.

This commit is contained in:
Dale Weiler 2014-01-07 12:58:53 -05:00
parent 0f506e768b
commit a140b749ff
2 changed files with 27 additions and 14 deletions

4
fold.c
View file

@ -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;
}

View file

@ -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
)
);