summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Johnson <peter@tortall.net>2007-09-19 07:47:10 +0000
committerPeter Johnson <peter@tortall.net>2007-09-19 07:47:10 +0000
commit31ef2e7a52647e34a37a94e7892be52f321dedf9 (patch)
tree20e847f861e34569337f2697c95f62ba9e6b475d
parent6dfe4b13fd4c4f971774325870e79da7f057bbfc (diff)
downloadyasm-31ef2e7a52647e34a37a94e7892be52f321dedf9.tar.gz
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
-rw-r--r--libyasm/insn.h6
-rw-r--r--modules/arch/lc3b/lc3barch.c2
-rw-r--r--modules/arch/x86/tests/Makefile.inc5
-rw-r--r--modules/arch/x86/tests/riprel1.asm66
-rw-r--r--modules/arch/x86/tests/riprel1.hex334
-rw-r--r--modules/arch/x86/tests/riprel2.asm110
-rw-r--r--modules/arch/x86/tests/riprel2.errwarn26
-rw-r--r--modules/arch/x86/tests/riprel2.hex708
-rw-r--r--modules/arch/x86/x86arch.c9
-rw-r--r--modules/arch/x86/x86arch.h1
-rw-r--r--modules/arch/x86/x86bc.c2
-rw-r--r--modules/arch/x86/x86expr.c15
-rw-r--r--modules/arch/x86/x86id.c24
-rw-r--r--modules/parsers/nasm/nasm-parse.c66
-rw-r--r--modules/parsers/nasm/nasm-parser.h2
-rw-r--r--modules/parsers/nasm/nasm-token.re3
-rw-r--r--modules/preprocs/nasm/standard.mac4
17 files changed, 1370 insertions, 13 deletions
diff --git a/libyasm/insn.h b/libyasm/insn.h
index 20977b2c..ea3fe539 100644
--- a/libyasm/insn.h
+++ b/libyasm/insn.h
@@ -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). */
diff --git a/modules/arch/lc3b/lc3barch.c b/modules/arch/lc3b/lc3barch.c
index e1835d0a..84f188a8 100644
--- a/modules/arch/lc3b/lc3barch.c
+++ b/modules/arch/lc3b/lc3barch.c
@@ -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;
}
diff --git a/modules/arch/x86/tests/Makefile.inc b/modules/arch/x86/tests/Makefile.inc
index c513ad17..67e8b5c6 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.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
index 00000000..b1fdbecb
--- /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 00000000..78f28bff
--- /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 00000000..813d9e5a
--- /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 00000000..b219dc7e
--- /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 00000000..5d9a9183
--- /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 d410ac0e..5b8ad700 100644
--- a/modules/arch/x86/x86arch.c
+++ b/modules/arch/x86/x86arch.c
@@ -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;
}
diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h
index 705933c0..b5c0f091 100644
--- a/modules/arch/x86/x86arch.h
+++ b/modules/arch/x86/x86arch.h
@@ -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.
diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c
index 4319318b..f3717bf7 100644
--- a/modules/arch/x86/x86bc.c
+++ b/modules/arch/x86/x86bc.c
@@ -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;
diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c
index eb145e7a..6358bff1 100644
--- a/modules/arch/x86/x86expr.c
+++ b/modules/arch/x86/x86expr.c
@@ -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) {
diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c
index 739c8679..59e74aed 100644
--- a/modules/arch/x86/x86id.c
+++ b/modules/arch/x86/x86id.c
@@ -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);
}
diff --git a/modules/parsers/nasm/nasm-parse.c b/modules/parsers/nasm/nasm-parse.c
index b449dd1c..b3927e03 100644
--- a/modules/parsers/nasm/nasm-parse.c
+++ b/modules/parsers/nasm/nasm-parse.c
@@ -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);
diff --git a/modules/parsers/nasm/nasm-parser.h b/modules/parsers/nasm/nasm-parser.h
index a2671559..4c8de413 100644
--- a/modules/parsers/nasm/nasm-parser.h
+++ b/modules/parsers/nasm/nasm-parser.h
@@ -45,6 +45,8 @@ enum tokentype {
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 2e0f3076..cfaad6d5 100644
--- a/modules/parsers/nasm/nasm-token.re
+++ b/modules/parsers/nasm/nasm-token.re
@@ -315,6 +315,9 @@ scan:
'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 6d285d9e..6efd3c84 100644
--- a/modules/preprocs/nasm/standard.mac
+++ b/modules/preprocs/nasm/standard.mac
@@ -114,6 +114,10 @@ __SECT__
[cpu %1]
%endmacro
+%imacro default 1+.nolist
+[default %1]
+%endmacro
+
; NASM compatibility shim
%define __OUTPUT_FORMAT__ __YASM_OBJFMT__