Esempio n. 1
0
/* Look for simple "left" identities like 0+x, 1*x, etc. */
static int
expr_can_destroy_int_left(yasm_expr_op op, yasm_intnum *intn)
{
    int iszero = yasm_intnum_is_zero(intn);
    return ((yasm_intnum_is_pos1(intn) && op == YASM_EXPR_MUL) ||
            (iszero && op == YASM_EXPR_ADD) ||
            (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
            (!iszero && op == YASM_EXPR_LAND) ||
            (iszero && op == YASM_EXPR_OR) ||
            (iszero && op == YASM_EXPR_LOR));
}
Esempio n. 2
0
/* Look for simple "right" identities like x+|-0, x*&/1 */
static int
expr_can_destroy_int_right(yasm_expr_op op, yasm_intnum *intn)
{
    int iszero = yasm_intnum_is_zero(intn);
    int ispos1 = yasm_intnum_is_pos1(intn);
    return ((ispos1 && op == YASM_EXPR_MUL) ||
            (ispos1 && op == YASM_EXPR_DIV) ||
            (iszero && op == YASM_EXPR_ADD) ||
            (iszero && op == YASM_EXPR_SUB) ||
            (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
            (!iszero && op == YASM_EXPR_LAND) ||
            (iszero && op == YASM_EXPR_OR) ||
            (iszero && op == YASM_EXPR_LOR) ||
            (iszero && op == YASM_EXPR_SHL) ||
            (iszero && op == YASM_EXPR_SHR));
}
Esempio n. 3
0
static int
run_input_test(Test_Entry *test)
{
    char *valstr = yasm__xstrdup(test->input);
    yasm_intnum *intn = yasm_intnum_create_hex(valstr);
    yasm_intnum *testn;
    unsigned long size;

    yasm_xfree(valstr);

    if (test->negate)
        yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);

    testn = yasm_intnum_create_leb128(test->result, test->sign, &size);
    if (size != test->outsize) {
        yasm_intnum_destroy(testn);
        yasm_intnum_destroy(intn);
        sprintf(failmsg, "%ssigned %s%s create() bad size: expected %lu, got %lu!",
                test->sign?"":"un", test->negate?"-":"", test->input,
                test->outsize, size);
        return 1;
    }

    yasm_intnum_calc(intn, YASM_EXPR_EQ, testn);
    if (!yasm_intnum_is_pos1(intn)) {
        yasm_intnum_destroy(testn);
        yasm_intnum_destroy(intn);
        sprintf(failmsg, "%ssigned %s%s create() bad output!",
                test->sign?"":"un", test->negate?"-":"", test->input);
        return 1;
    }

    yasm_intnum_destroy(testn);
    yasm_intnum_destroy(intn);
    return 0;
}
Esempio n. 4
0
/* Check for and simplify identities.  Returns new number of expr terms.
 * Sets e->op = EXPR_IDENT if numterms ends up being 1.
 * Uses numterms parameter instead of e->numterms for basis of "new" number
 * of terms.
 * Assumes int_term is *only* integer term in e.
 * NOTE: Really designed to only be used by expr_level_op().
 */
static int
expr_simplify_identity(yasm_expr *e, int numterms, int *int_term,
                       int simplify_reg_mul)
{
    int i;
    int save_numterms;

    /* Don't do this step if it's 1*REG.  Save and restore numterms so
     * yasm_expr__contains() works correctly.
     */
    save_numterms = e->numterms;
    e->numterms = numterms;
    if (simplify_reg_mul || e->op != YASM_EXPR_MUL
        || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn)
        || !yasm_expr__contains(e, YASM_EXPR_REG)) {
        /* Check for simple identities that delete the intnum.
         * Don't delete if the intnum is the only thing in the expn.
         */
        if ((*int_term == 0 && numterms > 1 &&
             expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) ||
            (*int_term > 0 &&
             expr_can_destroy_int_right(e->op,
                                        e->terms[*int_term].data.intn))) {
            /* Delete the intnum */
            yasm_intnum_destroy(e->terms[*int_term].data.intn);

            /* Slide everything to its right over by 1 */
            if (*int_term != numterms-1) /* if it wasn't last.. */
                memmove(&e->terms[*int_term], &e->terms[*int_term+1],
                        (numterms-1-*int_term)*sizeof(yasm_expr__item));

            /* Update numterms */
            numterms--;
            *int_term = -1;     /* no longer an int term */
        }
    }
    e->numterms = save_numterms;

    /* Check for simple identites that delete everything BUT the intnum.
     * Don't bother if the intnum is the only thing in the expn.
     */
    if (numterms > 1 && *int_term != -1 &&
        expr_is_constant(e->op, e->terms[*int_term].data.intn)) {
        /* Loop through, deleting everything but the integer term */
        for (i=0; i<e->numterms; i++)
            if (i != *int_term)
                expr_delete_term(&e->terms[i], 1);

        /* Move integer term to the first term (if not already there) */
        if (*int_term != 0)
            e->terms[0] = e->terms[*int_term];  /* structure copy */

        /* Set numterms to 1 */
        numterms = 1;
    }

    /* Compute NOT, NEG, and LNOT on single intnum. */
    if (numterms == 1 && *int_term == 0 &&
        (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG ||
         e->op == YASM_EXPR_LNOT))
        yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL);

    /* Change expression to IDENT if possible. */
    if (numterms == 1)
        e->op = YASM_EXPR_IDENT;

    /* Return the updated numterms */
    return numterms;
}