]> granicus.if.org Git - yasm/commitdiff
Reimplement optimizer pass 1b and fix x86 so that jumps handle one pass of
authorPeter Johnson <peter@tortall.net>
Sat, 10 Jun 2006 20:34:32 +0000 (20:34 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 10 Jun 2006 20:34:32 +0000 (20:34 -0000)
expansion.

svn path=/branches/new-optimizer/; revision=1566

libyasm/section.c
libyasm/tests/Makefile.inc
libyasm/tests/jmpsize1-err.asm [new file with mode: 0644]
libyasm/tests/jmpsize1-err.errwarn [new file with mode: 0644]
libyasm/tests/jmpsize1.asm [new file with mode: 0644]
libyasm/tests/jmpsize1.errwarn [new file with mode: 0644]
libyasm/tests/jmpsize1.hex [new file with mode: 0644]
modules/arch/x86/x86bc.c

index b7552857d49bb31092f3e281d734badf07ff878f..e0402c1d0d0a29e3cf28c7bcf65f3736d4771010 100644 (file)
@@ -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;
 
index 830162452fa29fb3910d1d657c840e12791d79d6..062d17892e1d9622136a554e6b6c29b2565d6301 100644 (file)
@@ -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 (file)
index 0000000..a0df3e2
--- /dev/null
@@ -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 (file)
index 0000000..9b821ac
--- /dev/null
@@ -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 (file)
index 0000000..821b245
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/libyasm/tests/jmpsize1.hex b/libyasm/tests/jmpsize1.hex
new file mode 100644 (file)
index 0000000..d885f86
--- /dev/null
@@ -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 
index b5e5cd83f2dd9b9df99cf5ba1b77e4ef66933b48..3c1766fcb9eb8b3feec419650e588fa24fc8eabd 100644 (file)
@@ -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;
     }