145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ORG bytecode
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  Copyright (C) 2005-2007  Peter Johnson
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Redistribution and use in source and binary forms, with or without
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * modification, are permitted provided that the following conditions
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * are met:
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1. Redistributions of source code must retain the above copyright
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer.
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer in the
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    documentation and/or other materials provided with the distribution.
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * POSSIBILITY OF SUCH DAMAGE.
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "util.h"
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "libyasm-stdint.h"
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "coretype.h"
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "file.h"
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "errwarn.h"
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "intnum.h"
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "expr.h"
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "value.h"
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "bytecode.h"
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bytecode_org {
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long start;        /* target starting offset within section */
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long fill;         /* fill value */
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bytecode_org;
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bc_org_destroy(void *contents);
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bc_org_print(const void *contents, FILE *f, int indent_level);
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           void *add_span_data);
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int bc_org_expand(yasm_bytecode *bc, int span, long old_val,
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         long new_val, /*@out@*/ long *neg_thres,
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         /*@out@*/ long *pos_thres);
54d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgstatic int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
55d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org                          unsigned char *bufstart, void *d,
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          yasm_output_value_func output_value,
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                          /*@null@*/ yasm_output_reloc_func output_reloc);
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_bytecode_callback bc_org_callback = {
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_org_destroy,
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_org_print,
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_org_finalize,
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL,
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_org_calc_len,
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_org_expand,
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_org_tobytes,
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    YASM_BC_SPECIAL_OFFSET
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_org_destroy(void *contents)
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(contents);
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_org_print(const void *contents, FILE *f, int indent_level)
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const bytecode_org *org = (const bytecode_org *)contents;
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*s_Org_\n", indent_level, "");
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                void *add_span_data)
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_org *org = (bytecode_org *)bc->contents;
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long neg_thres = 0;
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    long pos_thres = org->start;
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bc_org_expand(bc, 0, 0, (long)bc->offset, &neg_thres, &pos_thres) < 0)
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_org_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org              /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_org *org = (bytecode_org *)bc->contents;
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Check for overrun */
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((unsigned long)new_val > org->start) {
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_GENERAL,
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("ORG overlap with already existing data"));
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return -1;
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Generate space to start offset */
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc->len = org->start - new_val;
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 1;
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
123d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgbc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
124d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org               unsigned char *bufstart, void *d,
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               yasm_output_value_func output_value,
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org               /*@unused@*/ yasm_output_reloc_func output_reloc)
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_org *org = (bytecode_org *)bc->contents;
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long len, i;
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Sanity check for overrun */
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bc->offset > org->start) {
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_error_set(YASM_ERROR_GENERAL,
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       N_("ORG overlap with already existing data"));
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return 1;
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    len = org->start - bc->offset;
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for (i=0; i<len; i++)
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        YASM_WRITE_8(*bufp, org->fill);     /* XXX: handle more than 8 bit? */
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_bytecode *
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_bc_create_org(unsigned long start, unsigned long fill, unsigned long line)
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    org->start = start;
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    org->fill = fill;
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return yasm_bc_create_common(&bc_org_callback, org, line);
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
153