From 53d9be87577bf0caee15cc9ccd58cf923f694e31 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 10 Jun 2006 20:34:32 +0000 Subject: [PATCH] Reimplement optimizer pass 1b and fix x86 so that jumps handle one pass of expansion. svn path=/branches/new-optimizer/; revision=1566 --- libyasm/section.c | 66 +++---- libyasm/tests/Makefile.inc | 5 + libyasm/tests/jmpsize1-err.asm | 264 ++++++++++++++++++++++++++++ libyasm/tests/jmpsize1-err.errwarn | 2 + libyasm/tests/jmpsize1.asm | 264 ++++++++++++++++++++++++++++ libyasm/tests/jmpsize1.errwarn | 0 libyasm/tests/jmpsize1.hex | 265 +++++++++++++++++++++++++++++ modules/arch/x86/x86bc.c | 10 +- 8 files changed, 842 insertions(+), 34 deletions(-) create mode 100644 libyasm/tests/jmpsize1-err.asm create mode 100644 libyasm/tests/jmpsize1-err.errwarn create mode 100644 libyasm/tests/jmpsize1.asm create mode 100644 libyasm/tests/jmpsize1.errwarn create mode 100644 libyasm/tests/jmpsize1.hex diff --git a/libyasm/section.c b/libyasm/section.c index b7552857..e0402c1d 100644 --- a/libyasm/section.c +++ b/libyasm/section.c @@ -39,6 +39,7 @@ #include "errwarn.h" #include "intnum.h" #include "expr.h" +#include "value.h" #include "symrec.h" #include "bytecode.h" @@ -672,9 +673,9 @@ yasm_section_print(const yasm_section *sect, FILE *f, int indent_level, * of all bytecodes assuming minimum length, building a list of all * dependent spans as we go. * "minimum" here means absolute minimum: - * - align 0 length + * - align 0 length, but bumps offset * - times values (with span-dependent values) assumed to be 0 - * - org bumps offset + * - org 0 length, but bumps offset * b. Iterate over spans. Set span length based on bytecode offsets * determined in 1a. If span is "certainly" long because the span * is an absolute reference to another section (or external) or the @@ -785,7 +786,10 @@ yasm_object_optimize(yasm_object *object, yasm_arch *arch, int saw_error = 0; optimize_data optd; yasm_span *span; + yasm_value val; + /*@only@*/ /*@null@*/ yasm_intnum *num; long neg_thres, pos_thres; + int retval; STAILQ_INIT(&optd.spans); @@ -823,45 +827,47 @@ yasm_object_optimize(yasm_object *object, yasm_arch *arch, if (saw_error) return; -#if 0 + /* Step 1b */ STAILQ_FOREACH(span, &optd.spans, link) { - /* Handle absolute portion */ - if (span->depval->abs) { - yasm_expr *depcopy = yasm_expr_copy(span->depval->abs); - yasm_intnum *intn = - yasm_expr_get_intnum(&depcopy, yasm_common_calc_bc_dist); - if (intn) - span->new_val = yasm_intnum_get_int(intn); - else { - /* absolute, external, or too complex; force to longer form */ - span->new_val = LONG_MAX; - span->active = 0; - } - yasm_expr_destroy(depcopy); - } else - span->new_val = 0; - - /* Handle relative portion */ - if (span->depval->rel && span->new_val != LONG_MAX) { - span->new_val += + if (!span->active) + continue; + yasm_value_init_copy(&val, span->depval); + num = yasm_value_get_intnum(&val, span->bc, 1); + if (num) { + span->new_val = yasm_intnum_get_int(num); + yasm_intnum_destroy(num); + } else { + /* external or too complex; force to longer form */ + span->new_val = LONG_MAX; + span->active = 0; } - - if (span->new_val < span->neg_thres - || span->new_val > span->pos_thres) { - int retval = yasm_bc_expand(span->bc, span->id, span->cur_val, - span->new_val, &neg_thres, &pos_thres); + yasm_value_delete(&val); + + if ((span->id == 0 && span->new_val != span->cur_val) || + (span->new_val < span->neg_thres + || span->new_val > span->pos_thres)) { + retval = yasm_bc_expand(span->bc, span->id, span->cur_val, + span->new_val, &neg_thres, &pos_thres); + yasm_errwarn_propagate(errwarns, span->bc->line); if (retval < 0) saw_error = 1; else if (retval > 0) { - span->neg_thres = neg_thres; - span->pos_thres = pos_thres; + if (!span->active) { + yasm_error_set(YASM_ERROR_VALUE, + N_("secondary expansion of an external/complex value")); + yasm_errwarn_propagate(errwarns, span->bc->line); + saw_error = 1; + } else { + span->neg_thres = neg_thres; + span->pos_thres = pos_thres; + } } else span->active = 0; } span->cur_val = span->new_val; } -#endif + if (saw_error) return; diff --git a/libyasm/tests/Makefile.inc b/libyasm/tests/Makefile.inc index 83016245..062d1789 100644 --- a/libyasm/tests/Makefile.inc +++ b/libyasm/tests/Makefile.inc @@ -24,6 +24,11 @@ EXTRA_DIST += libyasm/tests/externdef.hex EXTRA_DIST += libyasm/tests/incbin.asm EXTRA_DIST += libyasm/tests/incbin.errwarn EXTRA_DIST += libyasm/tests/incbin.hex +EXTRA_DIST += libyasm/tests/jmpsize1.asm +EXTRA_DIST += libyasm/tests/jmpsize1.errwarn +EXTRA_DIST += libyasm/tests/jmpsize1.hex +EXTRA_DIST += libyasm/tests/jmpsize1-err.asm +EXTRA_DIST += libyasm/tests/jmpsize1-err.errwarn EXTRA_DIST += libyasm/tests/timesover-err.asm EXTRA_DIST += libyasm/tests/timesover-err.errwarn EXTRA_DIST += libyasm/tests/unary.asm diff --git a/libyasm/tests/jmpsize1-err.asm b/libyasm/tests/jmpsize1-err.asm new file mode 100644 index 00000000..a0df3e2b --- /dev/null +++ b/libyasm/tests/jmpsize1-err.asm @@ -0,0 +1,264 @@ +jmp x ; short +nop +w: +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +x: +jmp w ; short +jmp short y ; must be near; forcing short should error +nop +z: +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +y: +jmp short z ; must be near; forcing short should error + diff --git a/libyasm/tests/jmpsize1-err.errwarn b/libyasm/tests/jmpsize1-err.errwarn new file mode 100644 index 00000000..9b821acc --- /dev/null +++ b/libyasm/tests/jmpsize1-err.errwarn @@ -0,0 +1,2 @@ +-:132: short jump out of range +-:263: short jump out of range diff --git a/libyasm/tests/jmpsize1.asm b/libyasm/tests/jmpsize1.asm new file mode 100644 index 00000000..821b245f --- /dev/null +++ b/libyasm/tests/jmpsize1.asm @@ -0,0 +1,264 @@ +jmp x ; short +nop +w: +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +x: +jmp w ; short +jmp y ; near +nop +z: +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +nop +y: +jmp z ; near + diff --git a/libyasm/tests/jmpsize1.errwarn b/libyasm/tests/jmpsize1.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/libyasm/tests/jmpsize1.hex b/libyasm/tests/jmpsize1.hex new file mode 100644 index 00000000..d885f865 --- /dev/null +++ b/libyasm/tests/jmpsize1.hex @@ -0,0 +1,265 @@ +eb +7f +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +eb +80 +e9 +80 +00 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +90 +e9 +7e +ff diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c index b5e5cd83..3c1766fc 100644 --- a/modules/arch/x86/x86bc.c +++ b/modules/arch/x86/x86bc.c @@ -687,7 +687,7 @@ x86_bc_jmp_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, * The objfmt will error if not supported. */ if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { - if (jmp->nearop.len == 0) + if (jmp->op_sel == JMP_NONE) jmp->op_sel = JMP_SHORT; bc->len += jmp->shortop.len + 1; } else { @@ -699,9 +699,11 @@ 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; + if (jmp->op_sel == JMP_NONE) + jmp->op_sel = JMP_SHORT; bc->len += jmp->shortop.len + 1; - add_span(add_span_data, bc, 1, &jmp->target, -128, 127); + add_span(add_span_data, bc, 1, &jmp->target, -128+(long)bc->len, + 127+(long)bc->len); return 0; } @@ -719,7 +721,7 @@ x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val, long new_val, opersize = (jmp->common.opersize == 0) ? jmp->common.mode_bits : jmp->common.opersize; - if (jmp->nearop.len == 0) { + if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { yasm_error_set(YASM_ERROR_VALUE, N_("short jump out of range")); return -1; } -- 2.40.0