]> granicus.if.org Git - yasm/commitdiff
Support NASM's upcoming RIP-relative syntax, with a few differences.
authorPeter Johnson <peter@tortall.net>
Wed, 19 Sep 2007 07:47:10 +0000 (07:47 -0000)
committerPeter Johnson <peter@tortall.net>
Wed, 19 Sep 2007 07:47:10 +0000 (07:47 -0000)
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

17 files changed:
libyasm/insn.h
modules/arch/lc3b/lc3barch.c
modules/arch/x86/tests/Makefile.inc
modules/arch/x86/tests/riprel1.asm [new file with mode: 0644]
modules/arch/x86/tests/riprel1.hex [new file with mode: 0644]
modules/arch/x86/tests/riprel2.asm [new file with mode: 0644]
modules/arch/x86/tests/riprel2.errwarn [new file with mode: 0644]
modules/arch/x86/tests/riprel2.hex [new file with mode: 0644]
modules/arch/x86/x86arch.c
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
modules/arch/x86/x86id.c
modules/parsers/nasm/nasm-parse.c
modules/parsers/nasm/nasm-parser.h
modules/parsers/nasm/nasm-token.re
modules/preprocs/nasm/standard.mac

index 20977b2c2fb1a9b169d6b10cf36dc970e5bc81b3..ea3fe53919b24d30fad820f06132b2282acdfa66 100644 (file)
@@ -64,6 +64,12 @@ struct yasm_effaddr {
      * "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). */
index e1835d0a94dd319f7d92abca73224af7e76b459c..84f188a838d1cd4278d28cc985de14e6aed343eb 100644 (file)
@@ -158,6 +158,8 @@ lc3b_ea_create_expr(yasm_arch *arch, yasm_expr *e)
     ea->nosplit = 0;
     ea->strong = 0;
     ea->segreg = 0;
+    ea->pc_rel = 0;
+    ea->not_pc_rel = 0;
     return ea;
 }
 
index c513ad17bd948ba8eccc7412aa281460daad2905..67e8b5c68d8fd58506dbc555e0f78b37254f9817 100644 (file)
@@ -126,6 +126,11 @@ EXTRA_DIST += modules/arch/x86/tests/rep.asm
 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 (file)
index 0000000..b1fdbec
--- /dev/null
@@ -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 (file)
index 0000000..78f28bf
--- /dev/null
@@ -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 (file)
index 0000000..813d9e5
--- /dev/null
@@ -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 (file)
index 0000000..b219dc7
--- /dev/null
@@ -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 (file)
index 0000000..5d9a918
--- /dev/null
@@ -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 
index d410ac0e1986069453346f58add00feb83379a59..5b8ad70063ffe28aca064f493bd5b47b4fd81910 100644 (file)
@@ -67,6 +67,7 @@ x86_create(const char *machine, const char *parser,
     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 @@ x86_set_var(yasm_arch *arch, const char *var, unsigned long val)
         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;
 }
index 705933c09a48dbb0f1b652ea7b79e69df3a1cbcd..b5c0f0910ece8befe56cf89e132b01bb5582369c 100644 (file)
@@ -87,6 +87,7 @@ typedef struct yasm_arch_x86 {
     } 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.
index 4319318bad438f66d57496064ad602c779985d98..f3717bf7a4e22c2c280d24cfb720c8bf2b3d0d18 100644 (file)
@@ -190,6 +190,8 @@ ea_create(void)
     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;
index eb145e7aa4f5853c17c5bea4961cede83663da32..6358bff1dbd952f19b324f8c59b905976a94798d 100644 (file)
@@ -636,6 +636,12 @@ yasm_x86__expr_checkea(x86_effaddr *x86_ea, unsigned char *addrsize,
             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 @@ yasm_x86__expr_checkea(x86_effaddr *x86_ea, unsigned char *addrsize,
          * (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) {
index 739c86798fc3ab9a046eec578f4fb6fb5d528c39..59e74aed20b07488d5067446ad1f20e96d54f501 100644 (file)
@@ -301,6 +301,9 @@ typedef struct x86_id_insn {
 
     /* 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 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
                 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 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
                             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 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
              * 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 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
             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 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
         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 @@ yasm_x86__create_empty_insn(yasm_arch *arch, unsigned long line)
     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);
 }
index b449dd1c13648a62ef1f1f8bdfc2aa3f58897f87..b3927e036a8c351a612db2dc794206022fe6e434 100644 (file)
@@ -755,8 +755,11 @@ parse_memaddr(yasm_parser_nasm *parser_nasm)
             }
             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 @@ parse_memaddr(yasm_parser_nasm *parser_nasm)
             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 @@ nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
                                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 @@ nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
                            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);
index a267155989638a07a737fdb8939c569cf8daba14..4c8de4132fe27ac113b5e1c9c503c56d442e435f 100644 (file)
@@ -45,6 +45,8 @@ enum tokentype {
     TIMES,
     SEG,
     WRT,
+    ABS,
+    REL,
     NOSPLIT,
     STRICT,
     INSN,
index 2e0f30766981871809766ef255530b0e1c8bce49..cfaad6d57bf1fe80329fa157293c49917e5bc46d 100644 (file)
@@ -315,6 +315,9 @@ scan:
         'seg'           { RETURN(SEG); }
         'wrt'           { RETURN(WRT); }
 
+        'abs'           { RETURN(ABS); }
+        'rel'           { RETURN(REL); }
+
         'nosplit'       { RETURN(NOSPLIT); }
         'strict'        { RETURN(STRICT); }
 
index 6d285d9e259b1e18417b7871484cd1f22640114c..6efd3c84ffca0d7a7c61fd5d5d7d2c20475a5114 100644 (file)
@@ -114,6 +114,10 @@ __SECT__
 [cpu %1]
 %endmacro
 
+%imacro default 1+.nolist
+[default %1]
+%endmacro
+
 ; NASM compatibility shim
 %define __OUTPUT_FORMAT__ __YASM_OBJFMT__