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
bc->line = line;
- bc->offset = ~0UL;
+ bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
bc->opt_flags = 0;
/*@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
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 */
/*@dependent@*/ yasm_bytecode *bc;
yasm_value *depval;
- yasm_bytecode *origin_prevbc;
/* Special handling: see descriptions above */
enum {
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;
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,
/*@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.
* 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
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 */
* 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;
* 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);
}
}
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.
}
/* 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;
}
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"));
}
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:
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,
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)