Support NASM's upcoming RIP-relative syntax, with a few differences.

This adds a "default" directive that takes either "rel" or "abs".  This
sets whether the default mode for simple displacements is RIP-relative (rel)
or not (abs).  The default without a directive is "abs".

Also added is corresponding "rel" and "abs" effective address modifiers
to override whatever default is set:
[rel label] is RIP-relative
[abs label] is not.

In default rel mode, [label] defaults to the former, in default abs mode,
the latter.  Also, segment overrides (note difference from NASM below) are
abs regardless of mode, unless explicitly overridden with rel:
[fs:label] is always abs
[rel fs:label] is always rel

However, we have a number of differences from NASM in this handling due to
what I feel to be yasm's more sane handling of [dword ...] and [qword ...].
In yasm, these set the displacement size, rather than the address size; the
latter is set using a a32/a64 prefix.  I feel this is more sane as in 64-bit
mode the two can be different in the MovOffs (A0/A1 mov *ax) case.

Also, yasm disables default-rel mode if any segment register is used, not
just FS or GS as NASM currently does.

See modules/arch/x86/tests/riprel1.asm and
modules/arch/x86/tests/riprel2.asm for examples, as well as my recent
posting to the nasm-devel mailing list on SF.

svn path=/trunk/yasm/; revision=1963
diff --git a/libyasm/insn.h b/libyasm/insn.h
index 20977b2..ea3fe53 100644
--- a/libyasm/insn.h
+++ b/libyasm/insn.h
@@ -64,6 +64,12 @@
      * "expr(,1)" (which is definitely an effective address).
      */
     unsigned int strong:1;
+
+    /** 1 if effective address is forced PC-relative. */
+    unsigned int pc_rel:1;
+
+    /** 1 if effective address is forced non-PC-relative. */
+    unsigned int not_pc_rel:1;
 };
 
 /** An instruction operand (opaque type). */
diff --git a/modules/arch/lc3b/lc3barch.c b/modules/arch/lc3b/lc3barch.c
index e1835d0..84f188a 100644
--- a/modules/arch/lc3b/lc3barch.c
+++ b/modules/arch/lc3b/lc3barch.c
@@ -158,6 +158,8 @@
     ea->nosplit = 0;
     ea->strong = 0;
     ea->segreg = 0;
+    ea->pc_rel = 0;
+    ea->not_pc_rel = 0;
     return ea;
 }
 
diff --git a/modules/arch/x86/tests/Makefile.inc b/modules/arch/x86/tests/Makefile.inc
index c513ad1..67e8b5c 100644
--- a/modules/arch/x86/tests/Makefile.inc
+++ b/modules/arch/x86/tests/Makefile.inc
@@ -126,6 +126,11 @@
 EXTRA_DIST += modules/arch/x86/tests/rep.hex
 EXTRA_DIST += modules/arch/x86/tests/ret.asm
 EXTRA_DIST += modules/arch/x86/tests/ret.hex
+EXTRA_DIST += modules/arch/x86/tests/riprel1.asm
+EXTRA_DIST += modules/arch/x86/tests/riprel1.hex
+EXTRA_DIST += modules/arch/x86/tests/riprel2.asm
+EXTRA_DIST += modules/arch/x86/tests/riprel2.errwarn
+EXTRA_DIST += modules/arch/x86/tests/riprel2.hex
 EXTRA_DIST += modules/arch/x86/tests/segmov.asm
 EXTRA_DIST += modules/arch/x86/tests/segmov.hex
 EXTRA_DIST += modules/arch/x86/tests/shift.asm
diff --git a/modules/arch/x86/tests/riprel1.asm b/modules/arch/x86/tests/riprel1.asm
new file mode 100644
index 0000000..b1fdbec
--- /dev/null
+++ b/modules/arch/x86/tests/riprel1.asm
@@ -0,0 +1,66 @@
+bits 64
+val:
+default abs
+
+mov rax, val			; 32-bit imm
+mov rax, dword val		; 32-bit imm
+mov rax, qword val		; 64-bit imm
+
+mov rbx, val			; 32-bit imm
+mov rbx, dword val		; 32-bit imm
+mov rbx, qword val		; 64-bit imm
+
+mov rax, [val]			; 48 8b ... (32-bit disp)
+mov rax, [dword val]		; 48 8b ... (32-bit disp)
+mov rax, [qword val]		; 48 a1 ... (64-bit disp)
+a32 mov rax, [val]		; 67 48 a1 ... (32-bit disp)
+a32 mov rax, [dword val]	; 67 48 a1 ... (32-bit disp)
+a32 mov rax, [qword val]	; 67 48 a1 ... (32-bit disp)
+				; [this one is debatable on correctness,
+				; I chose in yasm to make a32 override]
+a64 mov rax, [val]		; 48 8b ... (32-bit disp)
+a64 mov rax, [dword val]	; 48 8b ... (32-bit disp)
+a64 mov rax, [qword val]	; 48 a1 ... (64-bit disp)
+
+mov rbx, [val]			; 48 8b ... (32-bit disp)
+mov rbx, [dword val]		; 48 8b ... (32-bit disp)
+;mov rbx, [qword val]		; illegal (can't have 64-bit disp)
+a32 mov rbx, [val]		; 67 48 8b ... (32-bit disp)
+a32 mov rbx, [dword val]	; 67 48 8b ... (32-bit disp)
+;a32 mov rbx, [qword val]	; illegal (can't have 64-bit disp)
+a64 mov rbx, [val]		; 48 8b ... (32-bit disp)
+a64 mov rbx, [dword val]	; 48 8b ... (32-bit disp)
+;a64 mov rbx, [qword val]	; illegal (can't have 64-bit disp)
+
+default rel
+
+mov rax, val			; 32-bit imm
+mov rax, dword val		; 32-bit imm
+mov rax, qword val		; 64-bit imm
+
+mov rbx, val			; 32-bit imm
+mov rbx, dword val		; 32-bit imm
+mov rbx, qword val		; 64-bit imm
+
+mov rax, [val]			; 48 8b ... (32-bit disp, RIP-rel)
+mov rax, [dword val]		; 48 8b ... (32-bit disp, RIP-rel)
+mov rax, [qword val]		; 48 a1 ... (64-bit disp, ABS)
+a32 mov rax, [val]		; 67 48 8b ... (32-bit disp, RIP-rel)
+a32 mov rax, [dword val]	; 67 48 8b ... (32-bit disp, RIP-rel)
+a32 mov rax, [qword val]	; 67 48 a1 ... (32-bit disp, ABS)
+				; [this one is debatable on correctness,
+				; I chose in yasm to make a32 override]
+a64 mov rax, [val]		; 48 8b ... (32-bit disp, RIP-rel)
+a64 mov rax, [dword val]	; 48 8b ... (32-bit disp, RIP-rel)
+a64 mov rax, [qword val]	; 48 a1 ... (64-bit disp, ABS)
+
+mov rbx, [val]			; 48 8b ... (32-bit disp, RIP-rel)
+mov rbx, [dword val]		; 48 8b ... (32-bit disp, RIP-rel)
+;mov rbx, [qword val]		; illegal (can't have 64-bit disp)
+a32 mov rbx, [val]		; 67 48 8b ... (32-bit disp, RIP-rel)
+a32 mov rbx, [dword val]	; 67 48 8b ... (32-bit disp, RIP-rel)
+;a32 mov rbx, [qword val]	; illegal (can't have 64-bit disp)
+a64 mov rbx, [val]		; 48 8b ... (32-bit disp, RIP-rel)
+a64 mov rbx, [dword val]	; 48 8b ... (32-bit disp, RIP-rel)
+;a64 mov rbx, [qword val]	; illegal (can't have 64-bit disp)
+
diff --git a/modules/arch/x86/tests/riprel1.hex b/modules/arch/x86/tests/riprel1.hex
new file mode 100644
index 0000000..78f28bf
--- /dev/null
+++ b/modules/arch/x86/tests/riprel1.hex
@@ -0,0 +1,334 @@
+48 
+c7 
+c0 
+00 
+00 
+00 
+00 
+48 
+c7 
+c0 
+00 
+00 
+00 
+00 
+48 
+b8 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+c7 
+c3 
+00 
+00 
+00 
+00 
+48 
+c7 
+c3 
+00 
+00 
+00 
+00 
+48 
+bb 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+04 
+25 
+00 
+00 
+00 
+00 
+48 
+8b 
+04 
+25 
+00 
+00 
+00 
+00 
+48 
+a1 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+67 
+48 
+a1 
+00 
+00 
+00 
+00 
+67 
+48 
+a1 
+00 
+00 
+00 
+00 
+67 
+48 
+a1 
+00 
+00 
+00 
+00 
+48 
+8b 
+04 
+25 
+00 
+00 
+00 
+00 
+48 
+8b 
+04 
+25 
+00 
+00 
+00 
+00 
+48 
+a1 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+1c 
+25 
+00 
+00 
+00 
+00 
+48 
+8b 
+1c 
+25 
+00 
+00 
+00 
+00 
+67 
+48 
+8b 
+1c 
+25 
+00 
+00 
+00 
+00 
+67 
+48 
+8b 
+1c 
+25 
+00 
+00 
+00 
+00 
+48 
+8b 
+1c 
+25 
+00 
+00 
+00 
+00 
+48 
+8b 
+1c 
+25 
+00 
+00 
+00 
+00 
+48 
+c7 
+c0 
+00 
+00 
+00 
+00 
+48 
+c7 
+c0 
+00 
+00 
+00 
+00 
+48 
+b8 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+c7 
+c3 
+00 
+00 
+00 
+00 
+48 
+c7 
+c3 
+00 
+00 
+00 
+00 
+48 
+bb 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+05 
+1e 
+ff 
+ff 
+ff 
+48 
+8b 
+05 
+17 
+ff 
+ff 
+ff 
+48 
+a1 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+67 
+48 
+8b 
+05 
+05 
+ff 
+ff 
+ff 
+67 
+48 
+8b 
+05 
+fd 
+fe 
+ff 
+ff 
+67 
+48 
+a1 
+00 
+00 
+00 
+00 
+48 
+8b 
+05 
+ef 
+fe 
+ff 
+ff 
+48 
+8b 
+05 
+e8 
+fe 
+ff 
+ff 
+48 
+a1 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+1d 
+d7 
+fe 
+ff 
+ff 
+48 
+8b 
+1d 
+d0 
+fe 
+ff 
+ff 
+67 
+48 
+8b 
+1d 
+c8 
+fe 
+ff 
+ff 
+67 
+48 
+8b 
+1d 
+c0 
+fe 
+ff 
+ff 
+48 
+8b 
+1d 
+b9 
+fe 
+ff 
+ff 
+48 
+8b 
+1d 
+b2 
+fe 
+ff 
+ff 
diff --git a/modules/arch/x86/tests/riprel2.asm b/modules/arch/x86/tests/riprel2.asm
new file mode 100644
index 0000000..813d9e5
--- /dev/null
+++ b/modules/arch/x86/tests/riprel2.asm
@@ -0,0 +1,110 @@
+	bits 64
+
+	default abs	; default abs, except for explicit rel
+
+	mov rax,[foo]
+	mov rax,[qword 123456789abcdef0h]
+	mov rbx,[foo]
+	mov rax,[dword foo]
+	mov rbx,[dword foo]
+	mov rax,[qword foo]
+	mov rax,[rel foo]		; rel
+	mov rbx,[rel foo]		; rel
+	mov rax,[rel dword foo]		; rel
+	;mov rax,[rel qword foo]	; illegal
+	mov rax,[abs foo]
+	mov rbx,[abs foo]
+	mov rax,[abs dword foo]
+	mov rax,[abs qword foo]
+
+	mov rax,[es:foo]
+	mov rax,[qword es:123456789abcdef0h]
+	mov rbx,[es:foo]
+	mov rax,[dword es:foo]
+	mov rbx,[dword es:foo]
+	mov rax,[qword es:foo]
+	mov rax,[rel es:foo]		; rel
+	mov rbx,[rel es:foo]		; rel
+	mov rax,[rel dword es:foo]	; rel
+	;mov rax,[rel qword es:foo]	; illegal
+	mov rax,[abs es:foo]
+	mov rbx,[abs es:foo]
+	mov rax,[abs dword es:foo]
+	mov rax,[abs qword es:foo]
+
+	mov rax,[fs:foo]
+	mov rax,[qword fs:123456789abcdef0h]
+	mov rbx,[fs:foo]
+	mov rax,[dword fs:foo]
+	mov rbx,[dword fs:foo]
+	mov rax,[qword fs:foo]
+	mov rax,[rel fs:foo]		; rel
+	mov rbx,[rel fs:foo]		; rel
+	mov rax,[rel dword fs:foo]	; rel
+	;mov rax,[rel qword fs:foo]	; illegal
+	mov rax,[abs fs:foo]
+	mov rbx,[abs fs:foo]
+	mov rax,[abs dword fs:foo]
+	mov rax,[abs qword fs:foo]
+
+	mov rax,[rbx]
+	mov rax,[rel rbx]
+	mov rax,[abs rbx]
+
+	default rel
+
+	; all of these are default rel, except for 64-bit displacements
+	mov rax,[foo]
+	mov rax,[qword 123456789abcdef0h]	; abs
+	mov rbx,[foo]
+	mov rax,[dword foo]
+	mov rbx,[dword foo]
+	mov rax,[qword foo]		; abs
+	mov rax,[rel foo]
+	mov rbx,[rel foo]
+	mov rax,[rel dword foo]
+	;mov rax,[rel qword foo]	; illegal
+	mov rax,[abs foo]
+	mov rbx,[abs foo]
+	mov rax,[abs dword foo]
+	mov rax,[abs qword foo]
+
+	; all of these are abs due to es:, except for explicit rel
+	mov rax,[es:foo]
+	mov rax,[qword es:123456789abcdef0h]
+	mov rbx,[es:foo]
+	mov rax,[dword es:foo]
+	mov rbx,[dword es:foo]
+	mov rax,[qword es:foo]
+	mov rax,[rel es:foo]		; rel
+	mov rbx,[rel es:foo]		; rel
+	mov rax,[rel dword es:foo]	; rel
+	;mov rax,[rel qword es:foo]	; illegal
+	mov rax,[abs es:foo]
+	mov rbx,[abs es:foo]
+	mov rax,[abs dword es:foo]
+	mov rax,[abs qword es:foo]
+
+	; all of these are abs due to fs:, except for explicit rel
+	mov rax,[fs:foo]
+	mov rax,[qword fs:123456789abcdef0h]
+	mov rbx,[fs:foo]
+	mov rax,[dword fs:foo]
+	mov rbx,[dword fs:foo]
+	mov rax,[qword fs:foo]
+	mov rax,[rel fs:foo]		; rel
+	mov rbx,[rel fs:foo]		; rel
+	mov rax,[rel dword fs:foo]	; rel
+	;mov rax,[rel qword fs:foo]	; illegal
+	mov rax,[abs fs:foo]
+	mov rbx,[abs fs:foo]
+	mov rax,[abs dword fs:foo]
+	mov rax,[abs qword fs:foo]
+
+	mov rax,[rbx]
+	mov rax,[rel rbx]
+	mov rax,[abs rbx]
+
+	section .data
+foo	equ $
+	
diff --git a/modules/arch/x86/tests/riprel2.errwarn b/modules/arch/x86/tests/riprel2.errwarn
new file mode 100644
index 0000000..b219dc7
--- /dev/null
+++ b/modules/arch/x86/tests/riprel2.errwarn
@@ -0,0 +1,26 @@
+-:20: warning: `es' segment register ignored in 64-bit mode
+-:21: warning: `es' segment register ignored in 64-bit mode
+-:22: warning: `es' segment register ignored in 64-bit mode
+-:23: warning: `es' segment register ignored in 64-bit mode
+-:24: warning: `es' segment register ignored in 64-bit mode
+-:25: warning: `es' segment register ignored in 64-bit mode
+-:26: warning: `es' segment register ignored in 64-bit mode
+-:27: warning: `es' segment register ignored in 64-bit mode
+-:28: warning: `es' segment register ignored in 64-bit mode
+-:30: warning: `es' segment register ignored in 64-bit mode
+-:31: warning: `es' segment register ignored in 64-bit mode
+-:32: warning: `es' segment register ignored in 64-bit mode
+-:33: warning: `es' segment register ignored in 64-bit mode
+-:73: warning: `es' segment register ignored in 64-bit mode
+-:74: warning: `es' segment register ignored in 64-bit mode
+-:75: warning: `es' segment register ignored in 64-bit mode
+-:76: warning: `es' segment register ignored in 64-bit mode
+-:77: warning: `es' segment register ignored in 64-bit mode
+-:78: warning: `es' segment register ignored in 64-bit mode
+-:79: warning: `es' segment register ignored in 64-bit mode
+-:80: warning: `es' segment register ignored in 64-bit mode
+-:81: warning: `es' segment register ignored in 64-bit mode
+-:83: warning: `es' segment register ignored in 64-bit mode
+-:84: warning: `es' segment register ignored in 64-bit mode
+-:85: warning: `es' segment register ignored in 64-bit mode
+-:86: warning: `es' segment register ignored in 64-bit mode
diff --git a/modules/arch/x86/tests/riprel2.hex b/modules/arch/x86/tests/riprel2.hex
new file mode 100644
index 0000000..5d9a918
--- /dev/null
+++ b/modules/arch/x86/tests/riprel2.hex
@@ -0,0 +1,708 @@
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+48 
+a1 
+f0 
+de 
+bc 
+9a 
+78 
+56 
+34 
+12 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+05 
+89 
+02 
+00 
+00 
+48 
+8b 
+1d 
+82 
+02 
+00 
+00 
+48 
+8b 
+05 
+7b 
+02 
+00 
+00 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+a1 
+f0 
+de 
+bc 
+9a 
+78 
+56 
+34 
+12 
+26 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+26 
+48 
+8b 
+05 
+17 
+02 
+00 
+00 
+26 
+48 
+8b 
+1d 
+0f 
+02 
+00 
+00 
+26 
+48 
+8b 
+05 
+07 
+02 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+a1 
+f0 
+de 
+bc 
+9a 
+78 
+56 
+34 
+12 
+64 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+64 
+48 
+8b 
+05 
+9f 
+01 
+00 
+00 
+64 
+48 
+8b 
+1d 
+97 
+01 
+00 
+00 
+64 
+48 
+8b 
+05 
+8f 
+01 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+03 
+48 
+8b 
+03 
+48 
+8b 
+03 
+48 
+8b 
+05 
+59 
+01 
+00 
+00 
+48 
+a1 
+f0 
+de 
+bc 
+9a 
+78 
+56 
+34 
+12 
+48 
+8b 
+1d 
+48 
+01 
+00 
+00 
+48 
+8b 
+05 
+41 
+01 
+00 
+00 
+48 
+8b 
+1d 
+3a 
+01 
+00 
+00 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+05 
+29 
+01 
+00 
+00 
+48 
+8b 
+1d 
+22 
+01 
+00 
+00 
+48 
+8b 
+05 
+1b 
+01 
+00 
+00 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+a1 
+f0 
+de 
+bc 
+9a 
+78 
+56 
+34 
+12 
+26 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+26 
+48 
+8b 
+05 
+b7 
+00 
+00 
+00 
+26 
+48 
+8b 
+1d 
+af 
+00 
+00 
+00 
+26 
+48 
+8b 
+05 
+a7 
+00 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+26 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+a1 
+f0 
+de 
+bc 
+9a 
+78 
+56 
+34 
+12 
+64 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+64 
+48 
+8b 
+05 
+3f 
+00 
+00 
+00 
+64 
+48 
+8b 
+1d 
+37 
+00 
+00 
+00 
+64 
+48 
+8b 
+05 
+2f 
+00 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+1c 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+8b 
+04 
+25 
+c4 
+02 
+00 
+00 
+64 
+48 
+a1 
+c4 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+48 
+8b 
+03 
+48 
+8b 
+03 
+48 
+8b 
+03 
diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c
index d410ac0..5b8ad70 100644
--- a/modules/arch/x86/x86arch.c
+++ b/modules/arch/x86/x86arch.c
@@ -67,6 +67,7 @@
     arch_x86->amd64_machine = amd64_machine;
     arch_x86->mode_bits = 0;
     arch_x86->force_strict = 0;
+    arch_x86->default_rel = 0;
 
     if (yasm__strcasecmp(parser, "nasm") == 0)
         arch_x86->parser = X86_PARSER_NASM;
@@ -123,7 +124,13 @@
         arch_x86->mode_bits = (unsigned int)val;
     else if (yasm__strcasecmp(var, "force_strict") == 0)
         arch_x86->force_strict = (unsigned int)val;
-    else
+    else if (yasm__strcasecmp(var, "default_rel") == 0) {
+        if (arch_x86->mode_bits != 64)
+            yasm_warn_set(YASM_WARN_GENERAL,
+                          N_("ignoring default rel in non-64-bit mode"));
+        else
+            arch_x86->default_rel = (unsigned int)val;
+    } else
         return 1;
     return 0;
 }
diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h
index 705933c..b5c0f09 100644
--- a/modules/arch/x86/x86arch.h
+++ b/modules/arch/x86/x86arch.h
@@ -87,6 +87,7 @@
     } parser;
     unsigned int mode_bits;
     unsigned int force_strict;
+    unsigned int default_rel;
 } yasm_arch_x86;
 
 /* 0-15 (low 4 bits) used for register number, stored in same data area.
diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c
index 4319318..f3717bf 100644
--- a/modules/arch/x86/x86bc.c
+++ b/modules/arch/x86/x86bc.c
@@ -190,6 +190,8 @@
     x86_ea->ea.nosplit = 0;
     x86_ea->ea.strong = 0;
     x86_ea->ea.segreg = 0;
+    x86_ea->ea.pc_rel = 0;
+    x86_ea->ea.not_pc_rel = 0;
     x86_ea->modrm = 0;
     x86_ea->valid_modrm = 0;
     x86_ea->need_modrm = 0;
diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c
index eb145e7..6358bff 100644
--- a/modules/arch/x86/x86expr.c
+++ b/modules/arch/x86/x86expr.c
@@ -636,6 +636,12 @@
             return 1;
         }
 
+        if (x86_ea->ea.pc_rel && bits != 64) {
+            yasm_warn_set(YASM_WARN_GENERAL,
+                N_("RIP-relative directive ignored in non-64-bit mode"));
+            x86_ea->ea.pc_rel = 0;
+        }
+
         reg3264_data.regs = reg3264mult;
         reg3264_data.bits = bits;
         reg3264_data.addrsize = *addrsize;
@@ -755,6 +761,15 @@
          * (optional) SIB bytes.
          */
 
+        /* If we're supposed to be RIP-relative and there's no register
+         * usage, change to RIP-relative.
+         */
+        if (basereg == REG3264_NONE && indexreg == REG3264_NONE &&
+            x86_ea->ea.pc_rel) {
+            basereg = REG64_RIP;
+            yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
+        }
+
         /* First determine R/M (Mod is later determined from disp size) */
         x86_ea->need_modrm = 1; /* we always need ModRM */
         if (basereg == REG3264_NONE && indexreg == REG3264_NONE) {
diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c
index 739c867..59e74ae 100644
--- a/modules/arch/x86/x86id.c
+++ b/modules/arch/x86/x86id.c
@@ -301,6 +301,9 @@
 
     /* Strict forced setting at the time of parsing the instruction */
     unsigned int force_strict:1;
+
+    /* Default rel setting at the time of parsing the instruction */
+    unsigned int default_rel:1;
 } x86_id_insn;
 
 static void x86_id_insn_destroy(void *contents);
@@ -764,7 +767,10 @@
                 case OPT_MemOffs:
                     if (op->type != YASM_INSN__OPERAND_MEMORY ||
                         yasm_expr__contains(op->data.ea->disp.abs,
-                                            YASM_EXPR_REG))
+                                            YASM_EXPR_REG) ||
+                        op->data.ea->pc_rel ||
+                        (!op->data.ea->not_pc_rel && id_insn->default_rel &&
+                         op->data.ea->disp.size != 64))
                         mismatch = 1;
                     break;
                 case OPT_Imm1:
@@ -1170,6 +1176,13 @@
                             if (info_ops[i].type == OPT_MemOffs)
                                 /* Special-case for MOV MemOffs instruction */
                                 yasm_x86__ea_set_disponly(insn->x86_ea);
+                            else if (id_insn->default_rel &&
+                                     !op->data.ea->not_pc_rel &&
+                                     op->data.ea->segreg == 0 &&
+                                     !yasm_expr__contains(
+                                        op->data.ea->disp.abs, YASM_EXPR_REG))
+                                /* Enable default PC-rel if no regs/segregs */
+                                insn->x86_ea->ea.pc_rel = 1;
                             break;
                         case YASM_INSN__OPERAND_IMM:
                             insn->x86_ea =
@@ -1351,8 +1364,12 @@
              * short mov instructions if a 32-bit address override is applied in
              * 64-bit mode to an EA of just an offset (no registers) and the
              * target register is al/ax/eax/rax.
+             *
+             * We don't want to do this if we're in default rel mode.
              */
-            if (insn->common.mode_bits == 64 && insn->common.addrsize == 32 &&
+            if (!id_insn->default_rel &&
+                insn->common.mode_bits == 64 &&
+                insn->common.addrsize == 32 &&
                 (!insn->x86_ea->ea.disp.abs ||
                  !yasm_expr__contains(insn->x86_ea->ea.disp.abs,
                                       YASM_EXPR_REG))) {
@@ -1577,6 +1594,7 @@
             id_insn->suffix = 0;
             id_insn->parser = arch_x86->parser;
             id_insn->force_strict = arch_x86->force_strict != 0;
+            id_insn->default_rel = arch_x86->default_rel != 0;
             *bc = yasm_bc_create_common(&x86_id_insn_callback, id_insn, line);
             return YASM_ARCH_INSN;
         }
@@ -1608,6 +1626,7 @@
         id_insn->suffix = pdata->flags;
         id_insn->parser = arch_x86->parser;
         id_insn->force_strict = arch_x86->force_strict != 0;
+        id_insn->default_rel = arch_x86->default_rel != 0;
         *bc = yasm_bc_create_common(&x86_id_insn_callback, id_insn, line);
         return YASM_ARCH_INSN;
     } else {
@@ -1670,6 +1689,7 @@
     id_insn->suffix = 0;
     id_insn->parser = arch_x86->parser;
     id_insn->force_strict = arch_x86->force_strict != 0;
+    id_insn->default_rel = arch_x86->default_rel != 0;
 
     return yasm_bc_create_common(&x86_id_insn_callback, id_insn, line);
 }
diff --git a/modules/parsers/nasm/nasm-parse.c b/modules/parsers/nasm/nasm-parse.c
index b449dd1..b3927e0 100644
--- a/modules/parsers/nasm/nasm-parse.c
+++ b/modules/parsers/nasm/nasm-parse.c
@@ -755,8 +755,11 @@
             }
             get_next_token();
             ea = parse_memaddr(parser_nasm);
-            if (ea)
+            if (ea) {
                 yasm_ea_set_segreg(ea, segreg);
+                ea->pc_rel = 0;
+                ea->not_pc_rel = 1;
+            }
             return ea;
         }
         case SIZE_OVERRIDE:
@@ -774,6 +777,22 @@
             if (ea)
                 ea->nosplit = 1;
             return ea;
+        case REL:
+            get_next_token();
+            ea = parse_memaddr(parser_nasm);
+            if (ea) {
+                ea->pc_rel = 1;
+                ea->not_pc_rel = 0;
+            }
+            return ea;
+        case ABS:
+            get_next_token();
+            ea = parse_memaddr(parser_nasm);
+            if (ea) {
+                ea->pc_rel = 0;
+                ea->not_pc_rel = 1;
+            }
+            return ea;
         default:
         {
             yasm_expr *e = parse_expr(parser_nasm, NORM_EXPR);
@@ -1131,15 +1150,21 @@
                                objext_valparams, line))
         ;
     else if (yasm__strcasecmp(name, "absolute") == 0) {
-        vp = yasm_vps_first(valparams);
-        if (parser_nasm->absstart)
-            yasm_expr_destroy(parser_nasm->absstart);
-        if (parser_nasm->abspos)
-            yasm_expr_destroy(parser_nasm->abspos);
-        parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line);
-        parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart);
-        cursect = NULL;
-        parser_nasm->prev_bc = NULL;
+        if (!valparams) {
+            yasm_error_set(YASM_ERROR_SYNTAX,
+                           N_("directive `%s' requires an argument"),
+                           "absolute");
+        } else {
+            vp = yasm_vps_first(valparams);
+            if (parser_nasm->absstart)
+                yasm_expr_destroy(parser_nasm->absstart);
+            if (parser_nasm->abspos)
+                yasm_expr_destroy(parser_nasm->abspos);
+            parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line);
+            parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart);
+            cursect = NULL;
+            parser_nasm->prev_bc = NULL;
+        }
     } else if (yasm__strcasecmp(name, "align") == 0) {
         /* Really, we shouldn't end up with an align directive in an absolute
          * section (as it's supposed to be only used for nop fill), but handle
@@ -1166,6 +1191,27 @@
                            N_("directive `%s' requires an argument"), "align");
         } else
             dir_align(p_object, valparams, objext_valparams, line);
+    } else if (yasm__strcasecmp(name, "default") == 0) {
+        if (!valparams)
+            ;
+        else {
+            vp = yasm_vps_first(valparams);
+            while (vp) {
+                const char *id = yasm_vp_id(vp);
+                if (id) {
+                    if (yasm__strcasecmp(id, "rel") == 0)
+                        yasm_arch_set_var(p_object->arch, "default_rel", 1);
+                    else if (yasm__strcasecmp(id, "abs") == 0)
+                        yasm_arch_set_var(p_object->arch, "default_rel", 0);
+                    else
+                        yasm_error_set(YASM_ERROR_SYNTAX,
+                                       N_("unrecognized default `%s'"), id);
+                } else
+                    yasm_error_set(YASM_ERROR_SYNTAX,
+                                   N_("unrecognized default value"));
+                vp = yasm_vps_next(vp);
+            }
+        }
     } else
         yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive `%s'"),
                        name);
diff --git a/modules/parsers/nasm/nasm-parser.h b/modules/parsers/nasm/nasm-parser.h
index a267155..4c8de41 100644
--- a/modules/parsers/nasm/nasm-parser.h
+++ b/modules/parsers/nasm/nasm-parser.h
@@ -45,6 +45,8 @@
     TIMES,
     SEG,
     WRT,
+    ABS,
+    REL,
     NOSPLIT,
     STRICT,
     INSN,
diff --git a/modules/parsers/nasm/nasm-token.re b/modules/parsers/nasm/nasm-token.re
index 2e0f307..cfaad6d 100644
--- a/modules/parsers/nasm/nasm-token.re
+++ b/modules/parsers/nasm/nasm-token.re
@@ -315,6 +315,9 @@
         'seg'           { RETURN(SEG); }
         'wrt'           { RETURN(WRT); }
 
+        'abs'           { RETURN(ABS); }
+        'rel'           { RETURN(REL); }
+
         'nosplit'       { RETURN(NOSPLIT); }
         'strict'        { RETURN(STRICT); }
 
diff --git a/modules/preprocs/nasm/standard.mac b/modules/preprocs/nasm/standard.mac
index 6d285d9..6efd3c8 100644
--- a/modules/preprocs/nasm/standard.mac
+++ b/modules/preprocs/nasm/standard.mac
@@ -114,6 +114,10 @@
 [cpu %1]
 %endmacro
 
+%imacro default 1+.nolist
+[default %1]
+%endmacro
+
 ; NASM compatibility shim
 %define __OUTPUT_FORMAT__ __YASM_OBJFMT__