From: Dale Weiler Date: Tue, 7 Jan 2014 17:58:53 +0000 (-0500) Subject: Fix lshift/rshift for runtime and const-fold consistency. X-Git-Tag: xonotic-v0.8.0~16 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a140b749ff5aaa6fe0af7432e9a9be420a8d2ce4;p=xonotic%2Fgmqcc.git Fix lshift/rshift for runtime and const-fold consistency. --- diff --git a/fold.c b/fold.c index dd78beb..173d613 100644 --- a/fold.c +++ b/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; } diff --git a/intrin.c b/intrin.c index 339d0c3..8c78ba7 100644 --- a/intrin.c +++ b/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); + /* = pow(2, b) */ vec_push(callpow->params, (ast_expression*)intrin->fold->imm_float[3]); vec_push(callpow->params, (ast_expression*)b); + /* = floor(a [instr] ) */ + vec_push( + callfloor->params, + (ast_expression*)ast_binary_new( + intrin_ctx(intrin), + instr, + (ast_expression*)a, + (ast_expression*)callpow + ) + ); + + /* return */ 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 ) );