From ad687bb34a8444a1c016adad563a35c0e1c73cf5 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 10 Jun 2006 04:01:12 +0000 Subject: [PATCH] Get rid of origin_prevbc; it's no longer needed due to yasm_value handling of PC-relative values. Add new yasm_value_get_intnum(); this is a simplified variant of yasm_value_output_basic(). svn path=/branches/new-optimizer/; revision=1560 --- libyasm/bytecode.c | 2 +- libyasm/bytecode.h | 10 +++--- libyasm/section.c | 6 ++-- libyasm/value.c | 60 ++++++++++++++++++++++++++++++++++ libyasm/value.h | 12 ++++++- modules/arch/x86/x86arch.h | 1 - modules/arch/x86/x86bc.c | 11 ++++--- modules/arch/x86/x86id.c | 3 -- tools/python-yasm/bytecode.pxi | 4 +-- tools/python-yasm/value.pxi | 2 ++ 10 files changed, 90 insertions(+), 21 deletions(-) diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index 327e8751..b49b2d98 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -91,7 +91,7 @@ yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents, bc->line = line; - bc->offset = ~0UL; + bc->offset = ~0UL; /* obviously incorrect / uninitialized value */ bc->opt_flags = 0; diff --git a/libyasm/bytecode.h b/libyasm/bytecode.h index 3013eb00..7bd740d6 100644 --- a/libyasm/bytecode.h +++ b/libyasm/bytecode.h @@ -308,17 +308,17 @@ void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); /*@null@*/ /*@only@*/ yasm_intnum *yasm_calc_bc_dist (yasm_bytecode *precbc1, yasm_bytecode *precbc2); -/** +/** Add a dependent span for a bytecode. + * \param add_span_data add_span_data passed into bc_calc_len() + * \param bc bytecode containing span + * \param id non-zero identifier for span; may be any non-zero value * \param value dependent value for bytecode expansion - * \param origin_prevbc origin for distance computation to relative portion of - * value; value.rel and origin must be within the same - * section. * \param neg_thres negative threshold for long/short decision * \param pos_thres positive threshold for long/short decision */ typedef void (*yasm_bc_add_span_func) (void *add_span_data, yasm_bytecode *bc, int id, yasm_value *value, - /*@null@*/ yasm_bytecode *origin_prevbc, long neg_thres, long pos_thres); + long neg_thres, long pos_thres); /** Resolve EQUs in a bytecode and calculate its minimum size. * Generates dependent bytecode spans for cases where, if the length spanned diff --git a/libyasm/section.c b/libyasm/section.c index 241805ab..4e11cf59 100644 --- a/libyasm/section.c +++ b/libyasm/section.c @@ -170,6 +170,7 @@ yasm_object_get_general(yasm_object *object, const char *name, STAILQ_INIT(&s->bcs); bc = yasm_bc_create_common(NULL, NULL, 0); bc->section = s; + bc->offset = 0; STAILQ_INSERT_TAIL(&s->bcs, bc, link); /* Initialize relocs */ @@ -705,7 +706,6 @@ typedef struct yasm_span { /*@dependent@*/ yasm_bytecode *bc; yasm_value *depval; - yasm_bytecode *origin_prevbc; /* Special handling: see descriptions above */ enum { @@ -732,15 +732,13 @@ typedef struct optimize_data { static void optimize_add_span(void *add_span_data, yasm_bytecode *bc, int id, - yasm_value *value, /*@null@*/ yasm_bytecode *origin_prevbc, - long neg_thres, long pos_thres) + yasm_value *value, long neg_thres, long pos_thres) { optimize_data *optd = (optimize_data *)add_span_data; yasm_span *span = yasm_xmalloc(sizeof(yasm_span)); span->bc = bc; span->depval = value; - span->origin_prevbc = origin_prevbc; span->special = NOT_SPECIAL; span->cur_val = 0; span->new_val = 0; diff --git a/libyasm/value.c b/libyasm/value.c index 14d4d355..8e9f0a5b 100644 --- a/libyasm/value.c +++ b/libyasm/value.c @@ -477,6 +477,66 @@ yasm_value_finalize(yasm_value *value) return yasm_value_finalize_expr(value, value->abs, valsize); } +yasm_intnum * +yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc) +{ + /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL; + /*@only@*/ yasm_intnum *outval; + int sym_local; + + if (value->abs) { + /* Handle integer expressions, if non-integer go ahead and return + * NULL. + */ + intn = yasm_expr_get_intnum(&value->abs, 1); + if (!intn) + return NULL; + } + + if (value->rel) { + /* If relative portion is not in bc section, return NULL. + * Otherwise get the relative portion's offset. + */ + /*@dependent@*/ yasm_bytecode *rel_prevbc; + unsigned long dist; + + sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc); + if (value->wrt || value->seg_of || value->section_rel || !sym_local) + return NULL; /* we can't handle SEG, WRT, or external symbols */ + if (rel_prevbc->section != bc->section) + return NULL; /* not in this section */ + if (!value->curpos_rel) + return NULL; /* not PC-relative */ + + /* Calculate value relative to current assembly position */ + dist = rel_prevbc->offset + rel_prevbc->len; + if (dist < bc->offset) { + outval = yasm_intnum_create_uint(bc->offset - dist); + yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL); + } else { + dist -= bc->offset; + outval = yasm_intnum_create_uint(dist); + } + + if (value->rshift > 0) { + /*@only@*/ yasm_intnum *shamt = + yasm_intnum_create_uint((unsigned long)value->rshift); + yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt); + yasm_intnum_destroy(shamt); + } + /* Add in absolute portion */ + if (intn) + yasm_intnum_calc(outval, YASM_EXPR_ADD, intn); + return outval; + } + + if (intn) + return yasm_intnum_copy(intn); + + /* No absolute or relative portions: output 0 */ + return yasm_intnum_create_uint(0); +} + int yasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf, size_t destsize, yasm_bytecode *bc, int warn, diff --git a/libyasm/value.h b/libyasm/value.h index 1cde996c..66320554 100644 --- a/libyasm/value.h +++ b/libyasm/value.h @@ -100,6 +100,17 @@ int yasm_value_finalize_expr(/*@out@*/ yasm_value *value, /*@null@*/ /*@kept@*/ yasm_expr *e, unsigned int size); +/** Get value if absolute or PC-relative section-local relative. Returns NULL + * otherwise. + * \param value value + * \param bc current bytecode (for PC-relative calculation) + * \note Adds in value.rel (correctly) if PC-relative and in the same section + * as bc (and there is no WRT or SEG). + * \return Intnum if can be resolved to integer value, otherwise NULL. + */ +/*@null@*/ /*@only@*/ yasm_intnum *yasm_value_get_intnum + (yasm_value *value, yasm_bytecode *bc); + /** Output value if constant or PC-relative section-local. This should be * used from objfmt yasm_output_value_func() functions. * functions. @@ -113,7 +124,6 @@ int yasm_value_finalize_expr(/*@out@*/ yasm_value *value, * negative for signed integer warnings, * positive for unsigned integer warnings * \param arch architecture - * \param calc_bc_dist function used to determine bytecode distance * \note Adds in value.rel (correctly) if PC-relative and in the same section * as bc (and there is no WRT or SEG); if this is not the desired * behavior, e.g. a reloc is needed in this case, don't use this diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index 725d3d97..79942e27 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -223,7 +223,6 @@ typedef struct x86_jmp { x86_opcode shortop, nearop; yasm_value target; /* jump target */ - /*@dependent@*/ yasm_bytecode *origin_prevbc; /* jump origin */ /* which opcode are we using? */ /* The *FORCED forms are specified in the source as such */ diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c index 6c56ac4b..f65376f9 100644 --- a/modules/arch/x86/x86bc.c +++ b/modules/arch/x86/x86bc.c @@ -534,7 +534,7 @@ x86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, * critical expression. */ bc->len += 1; - add_span(add_span_data, bc, 1, &x86_ea->ea.disp, NULL, -128, 127); + add_span(add_span_data, bc, 1, &x86_ea->ea.disp, -128, 127); } else bc->len + x86_ea->ea.disp.size/8; @@ -583,7 +583,7 @@ x86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, * expression. */ immlen = 8; - add_span(add_span_data, bc, 2, &imm->val, NULL, -128, 127); + add_span(add_span_data, bc, 2, &imm->val, -128, 127); } } @@ -678,7 +678,7 @@ x86_bc_jmp_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, if (jmp->target.rel && (!yasm_symrec_get_label(jmp->target.rel, &target_prevbc) - || target_prevbc->section != jmp->origin_prevbc->section)) { + || target_prevbc->section != bc->section)) { /* External or out of segment, so we can't check distance. * Allowing forced short jumps depends on the objfmt supporting * 8-bit relocs. While most don't, some might, so allow it here. @@ -695,8 +695,9 @@ x86_bc_jmp_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, } /* Default to short jump and generate span */ + jmp->op_sel = JMP_SHORT; bc->len += jmp->shortop.len + 1; - add_span(add_span_data, bc, 1, &jmp->target, jmp->origin_prevbc, -128, 127); + add_span(add_span_data, bc, 1, &jmp->target, -128, 127); return 0; } @@ -945,6 +946,8 @@ x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, return 1; *bufp += i; break; + case JMP_NONE: + yasm_internal_error(N_("jump op_sel cannot be JMP_NONE in tobytes")); default: yasm_internal_error(N_("unrecognized relative jump op_sel")); } diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c index 514cc28d..326c1780 100644 --- a/modules/arch/x86/x86id.c +++ b/modules/arch/x86/x86id.c @@ -2125,9 +2125,6 @@ x86_finalize_jmp(yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc, yasm_error_set(YASM_ERROR_VALUE, N_("invalid jump target")); jmp->target.curpos_rel = 1; - /* Need to save jump origin for relative jumps. */ - jmp->origin_prevbc = prev_bc; - /* See if the user explicitly specified short/near/far. */ switch ((int)(jinfo->operands[0] & OPTM_MASK)) { case OPTM_Short: diff --git a/tools/python-yasm/bytecode.pxi b/tools/python-yasm/bytecode.pxi index a3f49594..b5528e88 100644 --- a/tools/python-yasm/bytecode.pxi +++ b/tools/python-yasm/bytecode.pxi @@ -94,8 +94,8 @@ cdef extern from "libyasm/bytecode.h": cdef yasm_intnum *yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2) ctypedef void (*yasm_bc_add_span_func) (void *add_span_data, - yasm_bytecode *bc, int id, yasm_value *value, - yasm_bytecode *origin_prevbc, long neg_thres, long pos_thres) + yasm_bytecode *bc, int id, yasm_value *value, long neg_thres, + long pos_thres) cdef int yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data) cdef int yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, diff --git a/tools/python-yasm/value.pxi b/tools/python-yasm/value.pxi index 11fe0d84..2e89c0f7 100644 --- a/tools/python-yasm/value.pxi +++ b/tools/python-yasm/value.pxi @@ -32,6 +32,8 @@ cdef extern from "libyasm/value.h": cdef int yasm_value_finalize(yasm_value *value) cdef int yasm_value_finalize_expr(yasm_value *value, yasm_expr *e, unsigned int size) + cdef yasm_intnum *yasm_value_get_intnum(yasm_value *value, + yasm_bytecode *bc) cdef int yasm_value_output_basic(yasm_value *value, unsigned char *buf, size_t destsize, yasm_bytecode *bc, int warn, yasm_arch *arch) cdef void yasm_value_print(yasm_value *value, FILE *f, int indent_level) -- 2.40.0