From ad1280030cb5e189600af3c02e436ab880673c0c Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Mon, 30 Nov 2009 03:43:10 +0000 Subject: [PATCH] Fix a bunch of GAS x86 instruction issues. - Fix #193: ljmp/lcall not implemented; add 2-operand far jump to jmp/call. - Add loop{,z,e} instruction suffixes - Fix a bunch of jmp/call minor issues. - Vastly improve suffix handling in general to make more consistent and make a greater variety of no-suffix instructions work in a way that matches GAS. svn path=/trunk/yasm/; revision=2238 --- modules/arch/x86/gen_x86_insn.py | 229 +++++++- modules/arch/x86/tests/gas32/Makefile.inc | 4 + modules/arch/x86/tests/gas32/gas-farjump.asm | 13 + modules/arch/x86/tests/gas32/gas-farjump.hex | 408 ++++++++++++++ modules/arch/x86/tests/gas32/gas-loop32.asm | 5 + modules/arch/x86/tests/gas32/gas-loop32.hex | 376 +++++++++++++ modules/arch/x86/tests/gas64/Makefile.inc | 2 + modules/arch/x86/tests/gas64/gas-loop64.asm | 5 + modules/arch/x86/tests/gas64/gas-loop64.hex | 528 +++++++++++++++++++ modules/arch/x86/x86id.c | 77 ++- 10 files changed, 1597 insertions(+), 50 deletions(-) create mode 100644 modules/arch/x86/tests/gas32/gas-farjump.asm create mode 100644 modules/arch/x86/tests/gas32/gas-farjump.hex create mode 100644 modules/arch/x86/tests/gas32/gas-loop32.asm create mode 100644 modules/arch/x86/tests/gas32/gas-loop32.hex create mode 100644 modules/arch/x86/tests/gas64/gas-loop64.asm create mode 100644 modules/arch/x86/tests/gas64/gas-loop64.hex diff --git a/modules/arch/x86/gen_x86_insn.py b/modules/arch/x86/gen_x86_insn.py index eb79cc28..eefd2ca8 100755 --- a/modules/arch/x86/gen_x86_insn.py +++ b/modules/arch/x86/gen_x86_insn.py @@ -178,6 +178,14 @@ class GroupForm(object): suffix = kwargs.pop("suffix", None) if suffix is not None: self.suffixes = [suffix] + + req_suffix = kwargs.pop("req_suffix", False) + if not req_suffix: + if self.suffixes is None: + self.suffixes = ["Z"] + else: + self.suffixes.append("Z") + if self.suffixes is not None: self.suffixes = set(x.upper() for x in self.suffixes) @@ -452,7 +460,7 @@ class Insn(object): def __str__(self): if self.suffix is None: - suffix_str = "NONE" + suffix_str = "SUF_Z" elif len(self.suffix) == 1: suffix_str = "SUF_" + self.suffix else: @@ -532,14 +540,6 @@ def finalize_insns(): parsers &= insn.parsers if "gas" in parsers: - keyword = name - if keyword in gas_insns: - raise ValueError("duplicate gas instruction %s" % keyword) - newinsn = insn.copy() - newinsn.auto_cpu("gas") - newinsn.auto_misc_flags("gas") - gas_insns[keyword] = newinsn - if insn.suffix is None: suffixes = set() for form in group: @@ -547,7 +547,10 @@ def finalize_insns(): suffixes |= form.suffixes for suffix in suffixes: - keyword = name+suffix + if suffix == "Z": + keyword = name + else: + keyword = name+suffix if keyword in gas_insns: raise ValueError("duplicate gas instruction %s" % keyword) @@ -556,6 +559,15 @@ def finalize_insns(): newinsn.auto_cpu("gas") newinsn.auto_misc_flags("gas") gas_insns[keyword] = newinsn + else: + keyword = name + if keyword in gas_insns: + raise ValueError("duplicate gas instruction %s" % + keyword) + newinsn = insn.copy() + newinsn.auto_cpu("gas") + newinsn.auto_misc_flags("gas") + gas_insns[keyword] = newinsn if "nasm" in parsers: keyword = name @@ -2206,15 +2218,18 @@ add_group("call", opcode=[], operands=[Operand(type="ImmNotSegOff", dest="JmpRel")]) add_group("call", + suffix="w", opersize=16, opcode=[], operands=[Operand(type="ImmNotSegOff", size=16, dest="JmpRel")]) add_group("call", + suffix="l", not64=True, opersize=32, opcode=[], operands=[Operand(type="ImmNotSegOff", size=32, dest="JmpRel")]) add_group("call", + suffixes=["l", "q"], only64=True, opersize=64, opcode=[], @@ -2242,59 +2257,77 @@ add_group("call", operands=[Operand(type="Imm", tmod="Near", dest="JmpRel")]) add_group("call", + suffix="w", + req_suffix=True, opersize=16, opcode=[0xFF], spare=2, operands=[Operand(type="RM", size=16, dest="EA")]) add_group("call", + suffix="l", + req_suffix=True, not64=True, opersize=32, opcode=[0xFF], spare=2, operands=[Operand(type="RM", size=32, dest="EA")]) add_group("call", + suffix="q", + req_suffix=True, opersize=64, def_opersize_64=64, opcode=[0xFF], spare=2, operands=[Operand(type="RM", size=64, dest="EA")]) +add_group("call", + parsers=["gas"], + def_opersize_64=64, + opcode=[0xFF], + spare=2, + operands=[Operand(type="Reg", size="BITS", dest="EA")]) add_group("call", def_opersize_64=64, opcode=[0xFF], spare=2, operands=[Operand(type="Mem", dest="EA")]) add_group("call", + parsers=["nasm"], opersize=16, def_opersize_64=64, opcode=[0xFF], spare=2, operands=[Operand(type="RM", size=16, tmod="Near", dest="EA")]) add_group("call", + parsers=["nasm"], not64=True, opersize=32, opcode=[0xFF], spare=2, operands=[Operand(type="RM", size=32, tmod="Near", dest="EA")]) add_group("call", + parsers=["nasm"], opersize=64, def_opersize_64=64, opcode=[0xFF], spare=2, operands=[Operand(type="RM", size=64, tmod="Near", dest="EA")]) add_group("call", + parsers=["nasm"], def_opersize_64=64, opcode=[0xFF], spare=2, operands=[Operand(type="Mem", tmod="Near", dest="EA")]) -# Far indirect (through memory). Needs explicit FAR override. +# Far indirect (through memory). Needs explicit FAR override (NASM only) for sz in [16, 32, 64]: add_group("call", + parsers=["nasm"], opersize=sz, opcode=[0xFF], spare=3, operands=[Operand(type="Mem", size=sz, tmod="Far", dest="EA")]) add_group("call", + parsers=["nasm"], opcode=[0xFF], spare=3, operands=[Operand(type="Mem", tmod="Far", dest="EA")]) @@ -2302,34 +2335,52 @@ add_group("call", # With explicit FAR override for sz in [16, 32]: add_group("call", + parsers=["nasm"], not64=True, opersize=sz, opcode=[0x9A], - spare=3, operands=[Operand(type="Imm", size=sz, tmod="Far", dest="JmpFar")]) add_group("call", + parsers=["nasm"], not64=True, opcode=[0x9A], - spare=3, operands=[Operand(type="Imm", tmod="Far", dest="JmpFar")]) -# Since not caught by first ImmNotSegOff group, implicitly FAR. +# Since not caught by first ImmNotSegOff group, implicitly FAR (in NASM). for sz in [16, 32]: add_group("call", + parsers=["nasm"], not64=True, opersize=sz, opcode=[0x9A], - spare=3, operands=[Operand(type="Imm", size=sz, dest="JmpFar")]) add_group("call", + parsers=["nasm"], not64=True, opcode=[0x9A], - spare=3, operands=[Operand(type="Imm", dest="JmpFar")]) +# Two-operand FAR (GAS only) +for sfx, sz in zip("wl", [16, 32]): + add_group("call", + suffix=sfx, + req_suffix=True, + parsers=["gas"], + not64=True, + gas_no_reverse=True, + opersize=sz, + opcode=[0x9A], + operands=[Operand(type="Imm", size=16, relaxed=True, dest="JmpFar"), + Operand(type="Imm", size=sz, relaxed=True, dest="JmpFar")]) +add_group("call", + parsers=["gas"], + not64=True, + gas_no_reverse=True, + opcode=[0x9A], + operands=[Operand(type="Imm", size=16, relaxed=True, dest="JmpFar"), + Operand(type="Imm", size="BITS", relaxed=True, dest="JmpFar")]) + add_insn("call", "call") -add_insn("calll", "call", parser="gas", not64=True) -add_insn("callq", "call", parser="gas", only64=True) # # jmp @@ -2338,15 +2389,18 @@ add_group("jmp", opcode=[], operands=[Operand(type="ImmNotSegOff", dest="JmpRel")]) add_group("jmp", + suffix="w", opersize=16, opcode=[], operands=[Operand(type="ImmNotSegOff", size=16, dest="JmpRel")]) add_group("jmp", + suffix="l", not64=True, opersize=32, opcode=[0x00], operands=[Operand(type="ImmNotSegOff", size=32, dest="JmpRel")]) add_group("jmp", + suffixes=["l", "q"], only64=True, opersize=64, opcode=[0x00], @@ -2379,35 +2433,49 @@ add_group("jmp", operands=[Operand(type="Imm", tmod="Near", dest="JmpRel")]) add_group("jmp", + suffix="w", + req_suffix=True, opersize=16, def_opersize_64=64, opcode=[0xFF], spare=4, operands=[Operand(type="RM", size=16, dest="EA")]) add_group("jmp", + suffix="l", + req_suffix=True, not64=True, opersize=32, opcode=[0xFF], spare=4, operands=[Operand(type="RM", size=32, dest="EA")]) add_group("jmp", + suffix="q", + req_suffix=True, opersize=64, def_opersize_64=64, opcode=[0xFF], spare=4, operands=[Operand(type="RM", size=64, dest="EA")]) +add_group("jmp", + parsers=["gas"], + def_opersize_64=64, + opcode=[0xFF], + spare=4, + operands=[Operand(type="Reg", size="BITS", dest="EA")]) add_group("jmp", def_opersize_64=64, opcode=[0xFF], spare=4, operands=[Operand(type="Mem", dest="EA")]) add_group("jmp", + parsers=["nasm"], opersize=16, def_opersize_64=64, opcode=[0xFF], spare=4, operands=[Operand(type="RM", size=16, tmod="Near", dest="EA")]) add_group("jmp", + parsers=["nasm"], not64=True, cpu=["386"], opersize=32, @@ -2415,12 +2483,14 @@ add_group("jmp", spare=4, operands=[Operand(type="RM", size=32, tmod="Near", dest="EA")]) add_group("jmp", + parsers=["nasm"], opersize=64, def_opersize_64=64, opcode=[0xFF], spare=4, operands=[Operand(type="RM", size=64, tmod="Near", dest="EA")]) add_group("jmp", + parsers=["nasm"], def_opersize_64=64, opcode=[0xFF], spare=4, @@ -2444,30 +2514,91 @@ for sz in [16, 32]: not64=True, opersize=sz, opcode=[0xEA], - spare=3, operands=[Operand(type="Imm", size=sz, tmod="Far", dest="JmpFar")]) add_group("jmp", not64=True, opcode=[0xEA], - spare=3, operands=[Operand(type="Imm", tmod="Far", dest="JmpFar")]) -# Since not caught by first ImmNotSegOff group, implicitly FAR. +# Since not caught by first ImmNotSegOff group, implicitly FAR (in NASM). for sz in [16, 32]: add_group("jmp", + parsers=["nasm"], not64=True, opersize=sz, opcode=[0xEA], - spare=3, operands=[Operand(type="Imm", size=sz, dest="JmpFar")]) add_group("jmp", + parsers=["nasm"], not64=True, opcode=[0xEA], - spare=3, operands=[Operand(type="Imm", dest="JmpFar")]) +# Two-operand FAR (GAS only) +for sfx, sz in zip("wl", [16, 32]): + add_group("jmp", + parsers=["gas"], + suffix=sfx, + req_suffix=True, + not64=True, + gas_no_reverse=True, + opersize=sz, + opcode=[0xEA], + operands=[Operand(type="Imm", size=16, relaxed=True, dest="JmpFar"), + Operand(type="Imm", size=sz, relaxed=True, dest="JmpFar")]) +add_group("jmp", + parsers=["gas"], + not64=True, + gas_no_reverse=True, + opcode=[0xEA], + operands=[Operand(type="Imm", size=16, relaxed=True, dest="JmpFar"), + Operand(type="Imm", size="BITS", relaxed=True, dest="JmpFar")]) + add_insn("jmp", "jmp") +# +# GAS far calls/jumps +# + +# Far indirect (through memory) +for sfx, sz in zip("wlq", [16, 32, 64]): + add_group("ljmpcall", + suffix=sfx, + req_suffix=True, + opersize=sz, + modifiers=["SpAdd"], + opcode=[0xFF], + spare=0, + operands=[Operand(type="Mem", size=sz, relaxed=True, dest="EA")]) +add_group("ljmpcall", + modifiers=["SpAdd"], + opcode=[0xFF], + spare=0, + operands=[Operand(type="Mem", size="BITS", relaxed=True, dest="EA")]) + +# Two-operand far +for sfx, sz in zip("wl", [16, 32]): + add_group("ljmpcall", + not64=True, + gas_no_reverse=True, + suffix=sfx, + req_suffix=True, + opersize=sz, + modifiers=["Gap", "Op0Add"], + opcode=[0x00], + operands=[Operand(type="Imm", size=16, relaxed=True, dest="JmpFar"), + Operand(type="Imm", size=sz, relaxed=True, dest="JmpFar")]) +add_group("ljmpcall", + not64=True, + gas_no_reverse=True, + modifiers=["Gap", "Op0Add"], + opcode=[0x00], + operands=[Operand(type="Imm", size=16, relaxed=True, dest="JmpFar"), + Operand(type="Imm", size="BITS", relaxed=True, dest="JmpFar")]) + +add_insn("ljmp", "ljmpcall", parser="gas", modifiers=[5, 0xEA]) +add_insn("lcall", "ljmpcall", parser="gas", modifiers=[3, 0x9A]) + # # ret # @@ -2511,10 +2642,11 @@ add_insn("retl", "retnf", parser="gas", modifiers=[0xC2], not64=True) add_insn("retq", "retnf", parser="gas", modifiers=[0xC2], only64=True) add_insn("retn", "retnf", parser="nasm", modifiers=[0xC2]) add_insn("retf", "retnf", parser="nasm", modifiers=[0xCA, 64]) -add_insn("lretw", "retnf", parser="gas", modifiers=[0xCA, 16], suffix="NONE") -add_insn("lretl", "retnf", parser="gas", modifiers=[0xCA], suffix="NONE") +add_insn("lret", "retnf", parser="gas", modifiers=[0xCA], suffix="z") +add_insn("lretw", "retnf", parser="gas", modifiers=[0xCA, 16], suffix="w") +add_insn("lretl", "retnf", parser="gas", modifiers=[0xCA], suffix="l") add_insn("lretq", "retnf", parser="gas", modifiers=[0xCA, 64], only64=True, - suffix="NONE") + suffix="q") # # enter @@ -2707,6 +2839,45 @@ add_insn("loope", "loop", modifiers=[1]) add_insn("loopnz", "loop", modifiers=[0]) add_insn("loopne", "loop", modifiers=[0]) +# GAS w/l/q suffixes have to set addrsize via modifiers +for sfx, sz in zip("wlq", [16, 32, 64]): + add_group("loop"+sfx, + not64=(sz == 16), + only64=(sz == 64), + modifiers=["Gap", "AdSizeR"], + def_opersize_64=64, + opcode=[], + operands=[Operand(type="Imm", dest="JmpRel")]) + add_group("loop"+sfx, + not64=(sz == 16), + only64=(sz == 64), + modifiers=["Op0Add", "AdSizeR"], + def_opersize_64=64, + opcode=[0xE0], + operands=[Operand(type="Imm", tmod="Short", dest="JmpRel")]) + + add_group("loop"+sfx, + not64=(sz == 16), + only64=(sz == 64), + def_opersize_64=64, + opcode=[], + operands=[Operand(type="Imm", dest="JmpRel"), + Operand(type="Creg", size=sz, dest="AdSizeR")]) + add_group("loop"+sfx, + not64=(sz == 16), + only64=(sz == 64), + modifiers=["Op0Add"], + def_opersize_64=64, + opcode=[0xE0], + operands=[Operand(type="Imm", tmod="Short", dest="JmpRel"), + Operand(type="Creg", size=sz, dest="AdSizeR")]) + + add_insn("loop"+sfx, "loop"+sfx, parser="gas", modifiers=[2, sz]) + add_insn("loopz"+sfx, "loop"+sfx, parser="gas", modifiers=[1, sz]) + add_insn("loope"+sfx, "loop"+sfx, parser="gas", modifiers=[1, sz]) + add_insn("loopnz"+sfx, "loop"+sfx, parser="gas", modifiers=[0, sz]) + add_insn("loopne"+sfx, "loop"+sfx, parser="gas", modifiers=[0, sz]) + ##################################################################### # Set byte on flag instructions ##################################################################### @@ -3091,10 +3262,10 @@ add_group("fldstpt", modifiers=["SpAdd"], opcode=[0xDB], spare=0, - operands=[Operand(type="Mem", size=80, dest="EA")]) + operands=[Operand(type="Mem", size=80, relaxed=True, dest="EA")]) -add_insn("fldt", "fldstpt", suffix="WEAK", modifiers=[5]) -add_insn("fstpt", "fldstpt", suffix="WEAK", modifiers=[7]) +add_insn("fldt", "fldstpt", modifiers=[5]) +add_insn("fstpt", "fldstpt", modifiers=[7]) add_group("fildstp", suffix="s", diff --git a/modules/arch/x86/tests/gas32/Makefile.inc b/modules/arch/x86/tests/gas32/Makefile.inc index 10329f1d..11fbe15c 100644 --- a/modules/arch/x86/tests/gas32/Makefile.inc +++ b/modules/arch/x86/tests/gas32/Makefile.inc @@ -7,8 +7,12 @@ EXTRA_DIST += modules/arch/x86/tests/gas32/align32.asm EXTRA_DIST += modules/arch/x86/tests/gas32/align32.hex EXTRA_DIST += modules/arch/x86/tests/gas32/gas-farithr.asm EXTRA_DIST += modules/arch/x86/tests/gas32/gas-farithr.hex +EXTRA_DIST += modules/arch/x86/tests/gas32/gas-farjump.asm +EXTRA_DIST += modules/arch/x86/tests/gas32/gas-farjump.hex EXTRA_DIST += modules/arch/x86/tests/gas32/gas-fpmem.asm EXTRA_DIST += modules/arch/x86/tests/gas32/gas-fpmem.hex +EXTRA_DIST += modules/arch/x86/tests/gas32/gas-loop32.asm +EXTRA_DIST += modules/arch/x86/tests/gas32/gas-loop32.hex EXTRA_DIST += modules/arch/x86/tests/gas32/gas-movdq32.asm EXTRA_DIST += modules/arch/x86/tests/gas32/gas-movdq32.hex EXTRA_DIST += modules/arch/x86/tests/gas32/gas-movsd.asm diff --git a/modules/arch/x86/tests/gas32/gas-farjump.asm b/modules/arch/x86/tests/gas32/gas-farjump.asm new file mode 100644 index 00000000..6d890da2 --- /dev/null +++ b/modules/arch/x86/tests/gas32/gas-farjump.asm @@ -0,0 +1,13 @@ +call $0x1234, $0x567890ab +lcall $0x1234, $0x567890ab +jmp $0x1234, $0x567890ab +ljmp $0x1234, $0x567890ab +ljmp *(%eax) +lcall *(%eax) +jmp *(%eax) +call *(%eax) +jmp *%eax +call *%eax +ret +lret +lret $0x100 diff --git a/modules/arch/x86/tests/gas32/gas-farjump.hex b/modules/arch/x86/tests/gas32/gas-farjump.hex new file mode 100644 index 00000000..839492d4 --- /dev/null +++ b/modules/arch/x86/tests/gas32/gas-farjump.hex @@ -0,0 +1,408 @@ +7f +45 +4c +46 +01 +01 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +03 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +d0 +00 +00 +00 +00 +00 +00 +00 +34 +00 +00 +00 +00 +00 +28 +00 +05 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +9a +ab +90 +78 +56 +34 +12 +9a +ab +90 +78 +56 +34 +12 +ea +ab +90 +78 +56 +34 +12 +ea +ab +90 +78 +56 +34 +12 +ff +28 +ff +18 +ff +20 +ff +10 +ff +e0 +ff +d0 +c3 +cb +ca +00 +01 +00 +00 +00 +00 +2e +74 +65 +78 +74 +00 +2e +73 +74 +72 +74 +61 +62 +00 +2e +73 +79 +6d +74 +61 +62 +00 +2e +73 +68 +73 +74 +72 +74 +61 +62 +00 +00 +00 +00 +00 +2d +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +f1 +ff +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +17 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +70 +00 +00 +00 +21 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +94 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0f +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +98 +00 +00 +00 +30 +00 +00 +00 +02 +00 +00 +00 +03 +00 +00 +00 +04 +00 +00 +00 +10 +00 +00 +00 +01 +00 +00 +00 +01 +00 +00 +00 +06 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +2d +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 diff --git a/modules/arch/x86/tests/gas32/gas-loop32.asm b/modules/arch/x86/tests/gas32/gas-loop32.asm new file mode 100644 index 00000000..3b5777de --- /dev/null +++ b/modules/arch/x86/tests/gas32/gas-loop32.asm @@ -0,0 +1,5 @@ +loop label +loopw label +loopl label +#loopq label +label: diff --git a/modules/arch/x86/tests/gas32/gas-loop32.hex b/modules/arch/x86/tests/gas32/gas-loop32.hex new file mode 100644 index 00000000..5bf161bc --- /dev/null +++ b/modules/arch/x86/tests/gas32/gas-loop32.hex @@ -0,0 +1,376 @@ +7f +45 +4c +46 +01 +01 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +03 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +b0 +00 +00 +00 +00 +00 +00 +00 +34 +00 +00 +00 +00 +00 +28 +00 +05 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +e2 +05 +67 +e2 +02 +e2 +00 +00 +00 +2e +74 +65 +78 +74 +00 +2e +73 +74 +72 +74 +61 +62 +00 +2e +73 +79 +6d +74 +61 +62 +00 +2e +73 +68 +73 +74 +72 +74 +61 +62 +00 +00 +00 +00 +00 +2d +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +f1 +ff +00 +00 +00 +00 +07 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +17 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +48 +00 +00 +00 +21 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +6c +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0f +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +70 +00 +00 +00 +40 +00 +00 +00 +02 +00 +00 +00 +04 +00 +00 +00 +04 +00 +00 +00 +10 +00 +00 +00 +01 +00 +00 +00 +01 +00 +00 +00 +06 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +07 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 diff --git a/modules/arch/x86/tests/gas64/Makefile.inc b/modules/arch/x86/tests/gas64/Makefile.inc index ab6589aa..cfda8a56 100644 --- a/modules/arch/x86/tests/gas64/Makefile.inc +++ b/modules/arch/x86/tests/gas64/Makefile.inc @@ -11,6 +11,8 @@ EXTRA_DIST += modules/arch/x86/tests/gas64/gas-fp.asm EXTRA_DIST += modules/arch/x86/tests/gas64/gas-fp.hex EXTRA_DIST += modules/arch/x86/tests/gas64/gas-inout.asm EXTRA_DIST += modules/arch/x86/tests/gas64/gas-inout.hex +EXTRA_DIST += modules/arch/x86/tests/gas64/gas-loop64.asm +EXTRA_DIST += modules/arch/x86/tests/gas64/gas-loop64.hex EXTRA_DIST += modules/arch/x86/tests/gas64/gas-moreinsn.asm EXTRA_DIST += modules/arch/x86/tests/gas64/gas-moreinsn.hex EXTRA_DIST += modules/arch/x86/tests/gas64/gas-movabs.asm diff --git a/modules/arch/x86/tests/gas64/gas-loop64.asm b/modules/arch/x86/tests/gas64/gas-loop64.asm new file mode 100644 index 00000000..d441ad69 --- /dev/null +++ b/modules/arch/x86/tests/gas64/gas-loop64.asm @@ -0,0 +1,5 @@ +loop label +#loopw label +loopl label +loopq label +label: diff --git a/modules/arch/x86/tests/gas64/gas-loop64.hex b/modules/arch/x86/tests/gas64/gas-loop64.hex new file mode 100644 index 00000000..7c1e9246 --- /dev/null +++ b/modules/arch/x86/tests/gas64/gas-loop64.hex @@ -0,0 +1,528 @@ +7f +45 +4c +46 +02 +01 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +3e +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +d0 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +40 +00 +05 +00 +01 +00 +e2 +05 +67 +e2 +02 +e2 +00 +00 +00 +2e +74 +65 +78 +74 +00 +2e +73 +74 +72 +74 +61 +62 +00 +2e +73 +79 +6d +74 +61 +62 +00 +2e +73 +68 +73 +74 +72 +74 +61 +62 +00 +00 +00 +00 +00 +2d +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +04 +00 +f1 +ff +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +07 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +17 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +48 +00 +00 +00 +00 +00 +00 +00 +21 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +6c +00 +00 +00 +00 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0f +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +70 +00 +00 +00 +00 +00 +00 +00 +60 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +04 +00 +00 +00 +08 +00 +00 +00 +00 +00 +00 +00 +18 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +01 +00 +00 +00 +06 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c index 902b8475..c446d462 100644 --- a/modules/arch/x86/x86id.c +++ b/modules/arch/x86/x86id.c @@ -53,21 +53,18 @@ static const char *cpu_find_reverse(unsigned int cpu0, unsigned int cpu1, /* GAS suffix flags for instructions */ enum x86_gas_suffix_flags { - NONE = 0, - SUF_B = 1<<0, - SUF_W = 1<<1, - SUF_L = 1<<2, - SUF_Q = 1<<3, - SUF_S = 1<<4, - SUF_MASK = SUF_B|SUF_W|SUF_L|SUF_Q|SUF_S, + SUF_Z = 1<<0, /* no suffix */ + SUF_B = 1<<1, + SUF_W = 1<<2, + SUF_L = 1<<3, + SUF_Q = 1<<4, + SUF_S = 1<<5, + SUF_MASK = SUF_Z|SUF_B|SUF_W|SUF_L|SUF_Q|SUF_S, /* Flags only used in x86_insn_info */ - GAS_ONLY = 1<<5, /* Only available in GAS mode */ - GAS_ILLEGAL = 1<<6, /* Illegal in GAS mode */ - GAS_NO_REV = 1<<7, /* Don't reverse operands in GAS mode */ - - /* Flags only used in insnprefix_parse_data */ - WEAK = 1<<5 /* Relaxed operand mode for GAS */ + GAS_ONLY = 1<<6, /* Only available in GAS mode */ + GAS_ILLEGAL = 1<<7, /* Illegal in GAS mode */ + GAS_NO_REV = 1<<8 /* Don't reverse operands in GAS mode */ }; /* Miscellaneous flag tests for instructions */ @@ -233,10 +230,10 @@ typedef struct x86_info_operand { typedef struct x86_insn_info { /* GAS suffix flags */ - unsigned int gas_flags:8; /* Enabled for these GAS suffixes */ + unsigned int gas_flags:9; /* Enabled for these GAS suffixes */ /* Tests against BITS==64, AVX, and XOP */ - unsigned int misc_flags:6; + unsigned int misc_flags:5; /* The CPU feature flags needed to execute this instruction. This is OR'ed * with arch-specific data[2]. This combined value is compared with @@ -318,10 +315,10 @@ typedef struct x86_id_insn { unsigned int mode_bits:8; /* Suffix flags */ - unsigned int suffix:8; + unsigned int suffix:9; /* Tests against BITS==64 and AVX */ - unsigned int misc_flags:6; + unsigned int misc_flags:5; /* Parser enabled at the time of parsing the instruction */ unsigned int parser:2; @@ -385,9 +382,11 @@ x86_finalize_jmpfar(yasm_bytecode *bc, yasm_bytecode *prev_bc, const x86_insn_info *info) { x86_id_insn *id_insn = (x86_id_insn *)bc->contents; + unsigned char *mod_data = id_insn->mod_data; unsigned int mode_bits = id_insn->mode_bits; x86_jmpfar *jmpfar; yasm_insn_operand *op; + unsigned int i; jmpfar = yasm_xmalloc(sizeof(x86_jmpfar)); x86_finalize_common(&jmpfar->common, info, mode_bits); @@ -413,9 +412,44 @@ x86_finalize_jmpfar(yasm_bytecode *bc, yasm_bytecode *prev_bc, || yasm_value_finalize_expr(&jmpfar->segment, e, prev_bc, 16)) yasm_error_set(YASM_ERROR_TOO_COMPLEX, N_("jump target expression too complex")); + } else if (yasm_insn_op_next(op)) { + /* Two operand form (gas) */ + yasm_insn_operand *op2 = yasm_insn_op_next(op); + if (yasm_value_finalize_expr(&jmpfar->segment, op->data.val, prev_bc, + 16)) + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("jump target segment too complex")); + if (yasm_value_finalize_expr(&jmpfar->offset, op2->data.val, prev_bc, + 0)) + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("jump target offset too complex")); + if (op2->size == OPS_BITS) + jmpfar->common.opersize = (unsigned char)mode_bits; } else yasm_internal_error(N_("didn't get FAR expression in jmpfar")); + /* Apply modifiers */ + for (i=0; imodifiers); i++) { + switch (info->modifiers[i]) { + case MOD_Gap: + break; + case MOD_Op0Add: + jmpfar->opcode.opcode[0] += mod_data[i]; + break; + case MOD_Op1Add: + jmpfar->opcode.opcode[1] += mod_data[i]; + break; + case MOD_Op2Add: + jmpfar->opcode.opcode[2] += mod_data[i]; + break; + case MOD_Op1AddSp: + jmpfar->opcode.opcode[1] += mod_data[i]<<3; + break; + default: + break; + } + } + yasm_x86__bc_apply_prefixes((x86_common *)jmpfar, NULL, info->def_opersize_64, id_insn->insn.num_prefixes, @@ -605,7 +639,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops, continue; /* Match suffix (if required) */ - if (suffix != 0 && suffix != WEAK + if (id_insn->parser == X86_PARSER_GAS && ((suffix & SUF_MASK) & (gas_flags & SUF_MASK)) == 0) continue; @@ -826,7 +860,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops, /* Check operand size */ size = size_lookup[info_ops[i].size]; - if (suffix != 0) { + if (id_insn->parser == X86_PARSER_GAS) { /* Require relaxed operands for GAS mode (don't allow * per-operand sizing). */ @@ -868,7 +902,8 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops, break; /* Check for 64-bit effective address size in NASM mode */ - if (suffix == 0 && op->type == YASM_INSN__OPERAND_MEMORY) { + if (id_insn->parser != X86_PARSER_GAS && + op->type == YASM_INSN__OPERAND_MEMORY) { if (info_ops[i].eas64) { if (op->data.ea->disp.size != 64) mismatch = 1; @@ -1850,7 +1885,7 @@ yasm_x86__create_empty_insn(yasm_arch *arch, unsigned long line) id_insn->mod_data[2] = 0; id_insn->num_info = NELEMS(empty_insn); id_insn->mode_bits = arch_x86->mode_bits; - id_insn->suffix = 0; + id_insn->suffix = (arch_x86->parser == X86_PARSER_GAS) ? SUF_Z : 0; id_insn->misc_flags = 0; id_insn->parser = arch_x86->parser; id_insn->force_strict = arch_x86->force_strict != 0; -- 2.40.0