summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assemble.c2
-rw-r--r--nasm.h2
-rw-r--r--parser.c8
-rw-r--r--test/convergence.asm39
4 files changed, 37 insertions, 14 deletions
diff --git a/assemble.c b/assemble.c
index 6fcb748..d4e7f25 100644
--- a/assemble.c
+++ b/assemble.c
@@ -263,7 +263,7 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits,
isize = calcsize(segment, offset, bits, ins, code);
- if (passn == 1 && ins->oprs[0].segment == NO_SEG)
+ if (ins->oprs[0].opflags & OPFLAG_UNKNOWN)
/* Be optimistic in pass 1 */
return true;
diff --git a/nasm.h b/nasm.h
index 77c6aa4..7add093 100644
--- a/nasm.h
+++ b/nasm.h
@@ -654,6 +654,8 @@ typedef struct operand { /* operand to an instruction */
#define OPFLAG_FORWARD 1 /* operand is a forward reference */
#define OPFLAG_EXTERN 2 /* operand is an external reference */
+#define OPFLAG_UNKNOWN 4 /* operand is an unknown reference */
+ /* (always a forward reference also) */
typedef struct extop { /* extended operand */
struct extop *next; /* linked list */
diff --git a/parser.c b/parser.c
index 91b7abf..0f64043 100644
--- a/parser.c
+++ b/parser.c
@@ -737,6 +737,7 @@ restart_parse:
return result;
} else {
if (e->type == EXPR_UNKNOWN) {
+ result->oprs[operand].opflags |= OPFLAG_UNKNOWN;
o = 0; /* doesn't matter what */
result->oprs[operand].wrt = NO_SEG; /* nor this */
result->oprs[operand].segment = NO_SEG; /* or this */
@@ -818,9 +819,16 @@ restart_parse:
if (is_just_unknown(value)) { /* it's immediate but unknown */
result->oprs[operand].type |= IMMEDIATE;
+ result->oprs[operand].opflags |= OPFLAG_UNKNOWN;
result->oprs[operand].offset = 0; /* don't care */
result->oprs[operand].segment = NO_SEG; /* don't care again */
result->oprs[operand].wrt = NO_SEG; /* still don't care */
+
+ if(optimizing >= 0 && !(result->oprs[operand].type & STRICT))
+ {
+ /* Be optimistic */
+ result->oprs[operand].type |= SBYTE16 | SBYTE32 | SBYTE64;
+ }
} else if (is_reloc(value)) { /* it's immediate */
result->oprs[operand].type |= IMMEDIATE;
result->oprs[operand].offset = reloc_value(value);
diff --git a/test/convergence.asm b/test/convergence.asm
index 02ef2e1..d037886 100644
--- a/test/convergence.asm
+++ b/test/convergence.asm
@@ -4,34 +4,47 @@
BITS 32
+; Simple
jmp foo
times 124 nop
foo:
-jmp bar
-times 125 nop
-bar:
-
-db 0
-
-jmp baz
-times 126 nop
-baz:
-
+; Must start short to converge optimally
jmp car
times 127 nop
car:
+; Always near
+jmp cdr
+times 128 nop
+cdr:
+
+
+; Simple
add eax, quux2 - quux1
quux1:
times 127 nop
quux2:
-; currently fails - short add possible but converges to long form
+; Must start short
corge1:
add eax, corge2 - corge1
-times 124 nop
+times 127 - 3 nop
corge2:
-; this needs to actually *work*...
+
+; Simple
+lea eax, [bolug2-bolug1]
+bolug1:
+times 127 nop
+bolug2:
+
+; Must start short
+calog1:
+lea eax, [calog2-calog1]
+times 127 - 3 nop
+calog2:
+
+
+; Do not confuse forward references and segmentless addresses!
jmp 12345