145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Data (and LEB128) bytecode
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  Copyright (C) 2001-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
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "errwarn.h"
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "intnum.h"
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "expr.h"
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "value.h"
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "bytecode.h"
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "arch.h"
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct yasm_dataval {
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128, DV_RESERVE }
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        type;
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    union {
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_value val;
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        struct {
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*@only@*/ unsigned char *contents;
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            unsigned long len;
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        } raw;
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } data;
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* number of times data is repeated, NULL=1. */
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@only@*/ /*@null@*/ yasm_expr *multiple;
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgtypedef struct bytecode_data {
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* converted data (linked list) */
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_datavalhead datahead;
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int item_size;
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} bytecode_data;
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bc_data_destroy(void *contents);
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bc_data_print(const void *contents, FILE *f, int indent_level);
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int bc_data_item_size(yasm_bytecode *bc);
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            void *add_span_data);
72d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgstatic int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
73d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org                           unsigned char *bufstart, void *d,
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           yasm_output_value_func output_value,
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           /*@null@*/ yasm_output_reloc_func output_reloc);
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_bytecode_callback bc_data_callback = {
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_data_destroy,
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_data_print,
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_data_finalize,
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_data_item_size,
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_data_calc_len,
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_bc_expand_common,
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bc_data_tobytes,
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_data_destroy(void *contents)
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_data *bc_data = (bytecode_data *)contents;
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dvs_delete(&bc_data->datahead);
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(contents);
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_data_print(const void *contents, FILE *f, int indent_level)
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    const bytecode_data *bc_data = (const bytecode_data *)contents;
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*s_Data_\n", indent_level, "");
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*sElements:\n", indent_level+1, "");
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_data *bc_data = (bytecode_data *)bc->contents;
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *dv;
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *intn;
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Convert values from simple expr to value. */
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    STAILQ_FOREACH(dv, &bc_data->datahead, link) {
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (dv->type) {
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (yasm_value_finalize(&dv->data.val, prev_bc)) {
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_error_set(YASM_ERROR_TOO_COMPLEX,
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                   N_("data expression too complex"));
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return;
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_ULEB128:
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_SLEB128:
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!intn) {
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_error_set(YASM_ERROR_NOT_CONSTANT,
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                   N_("LEB128 requires constant values"));
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return;
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* Warn for negative values in unsigned environment.
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * This could be an error instead: the likelihood this is
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 * desired is very low!
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 */
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (yasm_intnum_sign(intn) == -1 && dv->type == DV_ULEB128)
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_warn_set(YASM_WARN_GENERAL,
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                  N_("negative value in unsigned LEB128"));
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            default:
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (dv->multiple) {
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_value val;
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (yasm_value_finalize_expr(&val, dv->multiple, prev_bc, 0))
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_TOO_COMPLEX,
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("multiple expression too complex"));
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else if (val.rel)
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("multiple expression not absolute"));
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dv->multiple = val.abs;
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_data_item_size(yasm_bytecode *bc)
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_data *bc_data = (bytecode_data *)bc->contents;
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return bc_data->item_size;
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 void *add_span_data)
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_data *bc_data = (bytecode_data *)bc->contents;
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *dv;
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *intn;
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long len = 0;
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long multiple;
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Count up element sizes, rounding up string length. */
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    STAILQ_FOREACH(dv, &bc_data->datahead, link) {
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (dv->type) {
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_EMPTY:
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len = 0;
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len = dv->data.val.size/8;
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RAW:
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len = dv->data.raw.len;
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_ULEB128:
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_SLEB128:
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!intn)
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_internal_error(N_("non-constant in data_tobytes"));
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len = yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RESERVE:
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len = dv->data.val.size/8;
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!yasm_dv_get_multiple(dv, &multiple))
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len *= multiple;
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bc->len += len;
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
206d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgbc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
207d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org                unsigned char *bufstart, void *d,
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_output_value_func output_value,
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /*@unused@*/ yasm_output_reloc_func output_reloc)
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_data *bc_data = (bytecode_data *)bc->contents;
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *dv;
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *intn;
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned int val_len;
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long multiple, i;
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    STAILQ_FOREACH(dv, &bc_data->datahead, link) {
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_dv_get_multiple(dv, &multiple) || multiple == 0)
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            continue;
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (dv->type) {
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_EMPTY:
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                val_len = dv->data.val.size/8;
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for (i=0; i<multiple; i++) {
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (output_value(&dv->data.val, *bufp, val_len,
227d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org                                     (unsigned long)(*bufp-bufstart), bc, 1,
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                     d))
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        return 1;
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *bufp += val_len;
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RAW:
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for (i=0; i<multiple; i++) {
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *bufp += dv->data.raw.len;
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_ULEB128:
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_SLEB128:
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = yasm_expr_get_intnum(&dv->data.val.abs, 234);
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (!intn)
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_internal_error(N_("non-constant in data_tobytes"));
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for (i=0; i<multiple; i++) {
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *bufp +=
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_intnum_get_leb128(intn, *bufp,
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                dv->type == DV_SLEB128);
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RESERVE:
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                val_len = dv->data.val.size/8;
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for (i=0; i<multiple; i++) {
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    memset(*bufp, 0, val_len);
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *bufp += val_len;
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_bytecode *
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    int append_zero, yasm_arch *arch, unsigned long line)
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line);
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *dv, *dv2, *dvo;
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_intnum *intn;
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long len = 0, rlen, i;
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dvs_initialize(&data->datahead);
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data->item_size = size;
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Prescan input data for length, etc.  Careful: this needs to be
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     * precisely paired with the second loop.
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     */
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    STAILQ_FOREACH(dv, datahead, link) {
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Flush previous data */
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len = 0;
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (dv->type) {
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_EMPTY:
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_ULEB128:
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_SLEB128:
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (intn && dv->type == DV_VALUE && (arch || size == 1))
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    len += size;
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (intn && dv->type == DV_ULEB128)
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    len += yasm_intnum_size_leb128(intn, 0);
29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if (intn && dv->type == DV_SLEB128)
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    len += yasm_intnum_size_leb128(intn, 1);
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else {
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (len > 0) {
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        /* Create bytecode for all previous len */
30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        len = 0;
30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /* Create bytecode for this value */
30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    dvo = yasm_xmalloc(sizeof(yasm_dataval));
30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    dvo->multiple = dv->multiple;
31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RAW:
31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                rlen = dv->data.raw.len;
31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* find count, rounding up to nearest multiple of size */
31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                rlen = (rlen + size - 1) / size;
31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len += rlen*size;
31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RESERVE:
32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len += size;
32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* Flush this data */
32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dvo->multiple = dv->multiple;
32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len = 0;
33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (append_zero)
33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len++;
33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Create final dataval for any trailing length */
33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (len > 0) {
33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Second iteration: copy data and delete input datavals. */
34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    dv = STAILQ_FIRST(datahead);
34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    dvo = STAILQ_FIRST(&data->datahead);
34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    len = 0;
34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (dv && dvo) {
34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dvo = STAILQ_NEXT(dvo, link);
34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len = 0;
35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (dv->type) {
35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_EMPTY:
35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_ULEB128:
35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_SLEB128:
35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (intn && dv->type == DV_VALUE && (arch || size == 1)) {
35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (size == 1)
36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_intnum_get_sized(intn,
36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                              &dvo->data.raw.contents[len],
36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                              1, 8, 0, 0, 1);
36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else
36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        yasm_arch_intnum_tobytes(arch, intn,
36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                 &dvo->data.raw.contents[len],
36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                 size, size*8, 0, bc, 1);
36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_value_delete(&dv->data.val);
36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    len += size;
36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                } else if (intn && dv->type == DV_ULEB128) {
37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    len += yasm_intnum_get_leb128(intn,
37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                  &dvo->data.raw.contents[len],
37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                  0);
37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_value_delete(&dv->data.val);
37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                } else if (intn && dv->type == DV_SLEB128) {
37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    len += yasm_intnum_get_leb128(intn,
37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                  &dvo->data.raw.contents[len],
37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                                  1);
37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    yasm_value_delete(&dv->data.val);
37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                } else {
38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (len > 0)
38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        dvo = STAILQ_NEXT(dvo, link);
38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    dvo->type = dv->type;
38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    dvo->data.val = dv->data.val;   /* structure copy */
38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    dvo->data.val.size = size*8;    /* remember size */
38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    dvo = STAILQ_NEXT(dvo, link);
38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    len = 0;
38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RAW:
39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                rlen = dv->data.raw.len;
39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                       rlen);
39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_xfree(dv->data.raw.contents);
39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len += rlen;
39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* pad with 0's to nearest multiple of size */
39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                rlen %= size;
39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (rlen > 0) {
39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    rlen = size-rlen;
39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    for (i=0; i<rlen; i++)
40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        dvo->data.raw.contents[len++] = 0;
40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RESERVE:
40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                memset(&dvo->data.raw.contents[len], 0, size);
40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                len += size;
40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dvo = STAILQ_NEXT(dvo, link);
41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            len = 0;
41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (append_zero)
41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            dvo->data.raw.contents[len++] = 0;
41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        dv2 = STAILQ_NEXT(dv, link);
41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(dv);
41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        dv = dv2;
41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return bc;
42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_bytecode *
42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *dv;
42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* Convert all values into LEB type, error on strings/raws */
43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    STAILQ_FOREACH(dv, datahead, link) {
43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (dv->type) {
43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                dv->type = sign ? DV_SLEB128 : DV_ULEB128;
43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RAW:
43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_error_set(YASM_ERROR_VALUE,
43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                               N_("LEB128 does not allow string constants"));
43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            default:
44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return yasm_bc_create_data(datahead, 0, 0, 0, line);
44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dataval *
44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dv_create_expr(yasm_expr *e)
44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->type = DV_VALUE;
45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_value_initialize(&retval->data.val, e, 0);
45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->multiple = NULL;
45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dataval *
46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dv_create_raw(unsigned char *contents, unsigned long len)
46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->type = DV_RAW;
46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->data.raw.contents = contents;
46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->data.raw.len = len;
46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->multiple = NULL;
46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dataval *
47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dv_create_reserve(void)
47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->type = DV_RESERVE;
47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    retval->multiple = NULL;
47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return retval;
48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
483d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgyasm_value *
484d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgyasm_dv_get_value(yasm_dataval *dv)
485d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org{
486d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org    if (dv->type != DV_VALUE)
487d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org        return NULL;
488d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org    return &dv->data.val;
489d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org}
490d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org
49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dv_set_multiple(yasm_dataval *dv, yasm_expr *e)
49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (dv->multiple)
49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        dv->multiple = yasm_expr_create_tree( dv->multiple, YASM_EXPR_MUL, e,
49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                             e->line);
49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        dv->multiple = e;
49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint
50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dv_get_multiple(yasm_dataval *dv, unsigned long *multiple)
50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *multiple = 1;
50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (dv->multiple) {
50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        num = yasm_expr_get_intnum(&dv->multiple, 0);
50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!num) {
51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE,
51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_("could not determine multiple"));
51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (yasm_intnum_sign(num) < 0) {
51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return 1;
51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *multiple = yasm_intnum_get_uint(num);
51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dvs_delete(yasm_datavalhead *headp)
52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *cur, *next;
52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    cur = STAILQ_FIRST(headp);
52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (cur) {
53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        next = STAILQ_NEXT(cur, link);
53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (cur->type) {
53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_value_delete(&cur->data.val);
53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RAW:
53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_xfree(cur->data.raw.contents);
53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            default:
53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (cur->multiple)
54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr_destroy(cur->multiple);
54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree(cur);
54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cur = next;
54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    STAILQ_INIT(headp);
54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
54945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dataval *
55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (dv) {
55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        STAILQ_INSERT_TAIL(headp, dv, link);
55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return dv;
55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return (yasm_dataval *)NULL;
55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_dataval *cur;
56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    unsigned long i;
56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    STAILQ_FOREACH(cur, head, link) {
56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        fprintf(f, "%*sMultiple=", indent_level, "");
56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (!cur->multiple)
56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            fprintf(f, "nil (1)");
56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_expr_print(cur->multiple, f);
57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        switch (cur->type) {
57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_EMPTY:
57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "%*sEmpty\n", indent_level, "");
57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_VALUE:
57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "%*sValue:\n", indent_level, "");
57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_value_print(&cur->data.val, f, indent_level+1);
57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RAW:
58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "%*sLength=%lu\n", indent_level, "",
58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        cur->data.raw.len);
58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "%*sBytes=[", indent_level, "");
58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for (i=0; i<cur->data.raw.len; i++)
58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    fprintf(f, "0x%02x, ", cur->data.raw.contents[i]);
58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "]\n");
58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_ULEB128:
58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "%*sULEB128 value:\n", indent_level, "");
58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_value_print(&cur->data.val, f, indent_level+1);
59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_SLEB128:
59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                yasm_value_print(&cur->data.val, f, indent_level+1);
59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            case DV_RESERVE:
59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fprintf(f, "%*sReserved\n", indent_level, "");
59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                break;
59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
601