/*
 * Align bytecode
 *
 *  Copyright (C) 2005-2007  Peter Johnson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include "util.h"
/*@unused@*/ RCSID("$Id$");

#include "libyasm-stdint.h"
#include "coretype.h"

#include "errwarn.h"
#include "intnum.h"
#include "expr.h"

#include "bytecode.h"


typedef struct bytecode_align {
    /*@only@*/ yasm_expr *boundary;     /* alignment boundary */

    /* What to fill intervening locations with, NULL if using code_fill */
    /*@only@*/ /*@null@*/ yasm_expr *fill;

    /* Maximum number of bytes to skip, NULL if no maximum. */
    /*@only@*/ /*@null@*/ yasm_expr *maxskip;

    /* Code fill, NULL if using 0 fill */
    /*@null@*/ const unsigned char **code_fill;
} bytecode_align;

static void bc_align_destroy(void *contents);
static void bc_align_print(const void *contents, FILE *f, int indent_level);
static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
static int bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                             void *add_span_data);
static int bc_align_expand(yasm_bytecode *bc, int span, long old_val,
                           long new_val, /*@out@*/ long *neg_thres,
                           /*@out@*/ long *pos_thres);
static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                            yasm_output_value_func output_value,
                            /*@null@*/ yasm_output_reloc_func output_reloc);

static const yasm_bytecode_callback bc_align_callback = {
    bc_align_destroy,
    bc_align_print,
    bc_align_finalize,
    NULL,
    bc_align_calc_len,
    bc_align_expand,
    bc_align_tobytes,
    YASM_BC_SPECIAL_OFFSET
};


static void
bc_align_destroy(void *contents)
{
    bytecode_align *align = (bytecode_align *)contents;
    if (align->boundary)
        yasm_expr_destroy(align->boundary);
    if (align->fill)
        yasm_expr_destroy(align->fill);
    if (align->maxskip)
        yasm_expr_destroy(align->maxskip);
    yasm_xfree(contents);
}

static void
bc_align_print(const void *contents, FILE *f, int indent_level)
{
    const bytecode_align *align = (const bytecode_align *)contents;
    fprintf(f, "%*s_Align_\n", indent_level, "");
    fprintf(f, "%*sBoundary=", indent_level, "");
    yasm_expr_print(align->boundary, f);
    fprintf(f, "\n%*sFill=", indent_level, "");
    yasm_expr_print(align->fill, f);
    fprintf(f, "\n%*sMax Skip=", indent_level, "");
    yasm_expr_print(align->maxskip, f);
    fprintf(f, "\n");
}

static void
bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
{
    bytecode_align *align = (bytecode_align *)bc->contents;
    if (!yasm_expr_get_intnum(&align->boundary, 0))
        yasm_error_set(YASM_ERROR_NOT_CONSTANT,
                       N_("align boundary must be a constant"));
    if (align->fill && !yasm_expr_get_intnum(&align->fill, 0))
        yasm_error_set(YASM_ERROR_NOT_CONSTANT,
                       N_("align fill must be a constant"));
    if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, 0))
        yasm_error_set(YASM_ERROR_NOT_CONSTANT,
                       N_("align maximum skip must be a constant"));
}

static int
bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                  void *add_span_data)
{
    long neg_thres = 0;
    long pos_thres = 0;

    if (bc_align_expand(bc, 0, 0, (long)bc->offset, &neg_thres,
                        &pos_thres) < 0)
        return -1;

    return 0;
}

static int
bc_align_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
                /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
{
    bytecode_align *align = (bytecode_align *)bc->contents;
    unsigned long end;
    unsigned long boundary =
        yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));

    if (boundary == 0) {
        bc->len = 0;
        *pos_thres = new_val;
        return 0;
    }

    end = (unsigned long)new_val;
    if ((unsigned long)new_val & (boundary-1))
        end = ((unsigned long)new_val & ~(boundary-1)) + boundary;

    *pos_thres = (long)end;
    bc->len = end - (unsigned long)new_val;

    if (align->maxskip) {
        unsigned long maxskip =
            yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
        if (bc->len > maxskip) {
            *pos_thres = (long)end-maxskip-1;
            bc->len = 0;
        }
    }
    return 1;
}

static int
bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
                 yasm_output_value_func output_value,
                 /*@unused@*/ yasm_output_reloc_func output_reloc)
{
    bytecode_align *align = (bytecode_align *)bc->contents;
    unsigned long len;
    unsigned long boundary =
        yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));

    if (boundary == 0)
        return 0;
    else {
        unsigned long end = bc->offset;
        if (bc->offset & (boundary-1))
            end = (bc->offset & ~(boundary-1)) + boundary;
        len = end - bc->offset;
        if (len == 0)
            return 0;
        if (align->maxskip) {
            unsigned long maxskip =
                yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
            if (len > maxskip)
                return 0;
        }
    }

    if (align->fill) {
        unsigned long v;
        v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, 0));
        memset(*bufp, (int)v, len);
        *bufp += len;
    } else if (align->code_fill) {
        unsigned long maxlen = 15;
        while (!align->code_fill[maxlen] && maxlen>0)
            maxlen--;
        if (maxlen == 0) {
            yasm_error_set(YASM_ERROR_GENERAL,
                           N_("could not find any code alignment size"));
            return 1;
        }

        /* Fill with maximum code fill as much as possible */
        while (len > maxlen) {
            memcpy(*bufp, align->code_fill[maxlen], maxlen);
            *bufp += maxlen;
            len -= maxlen;
        }

        if (!align->code_fill[len]) {
            yasm_error_set(YASM_ERROR_VALUE,
                           N_("invalid alignment size %d"), len);
            return 1;
        }
        /* Handle rest of code fill */
        memcpy(*bufp, align->code_fill[len], len);
        *bufp += len;
    } else {
        /* Just fill with 0 */
        memset(*bufp, 0, len);
        *bufp += len;
    }
    return 0;
}

yasm_bytecode *
yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill,
                     yasm_expr *maxskip, const unsigned char **code_fill,
                     unsigned long line)
{
    bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));

    align->boundary = boundary;
    align->fill = fill;
    align->maxskip = maxskip;
    align->code_fill = code_fill;

    return yasm_bc_create_common(&bc_align_callback, align, line);
}
