From aa2571e22ba3103549db8289716cb55f61c394c4 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 25 Sep 2005 04:25:26 +0000 Subject: [PATCH] Preliminary GAS parser. Only a few instructions are supported at present. This work is being done under contract with a company that has requested to remain unnamed at the present time. * bc-int.h (yasm_effaddr): Add strong flag to indicate if the effective address is definitely an effective address; GAS does not use [] to designate effective addresses so it's otherwise impossible to tell the difference between "expr(,1)" and just "expr" (important for the relative jump instructions). * bytecode.h (yasm_ea_set_strong): New function to set the strong flag. * bytecode.c (yasm_ea_set_strong): Implementation. * x86bc.c (yasm_x86__ea_create_reg): Initialize strong flag. * arch.h (yasm_insn_operand): Add deref flag to indicate use of "*foo" in GAS syntax. * arch.c (yasm_operand_create_reg, yasm_operand_create_segreg) (yasm_operand_create_mem, yasm_operand_create_imm): Set deref flag to 0. * gas: GAS syntax lexer and parser. Not all directives are implemented yet (some will require additional core bytecodes). * elf-objfmt.c (elf_objfmt_section_switch): Add support for GAS-style section flags. * x86arch.h (yasm_arch_x86): Add parser setting. * x86arch.c (x86_create): Check for gas parser and initialize setting. * x86bc.c (yasm_x86__ea_create_expr): Transform val+RIP to val wrt RIP when using the GAS parser (this is how GAS interprets "expr(%rip)"). * x86id.re: Too many changes to enumerate in detail. Add new modifiers for GAS suffixes. Start using them in a couple instructions. Split check_id into subfunctions (still one entry point at present). (yasm_x86__finalize_insn): Support new modifiers, reverse operands, derefs. * yasm.c (main): Change all undef to extern when using GAS parser (this is default GAS behavior). svn path=/trunk/yasm/; revision=1239 --- frontends/yasm/yasm.c | 4 +- libyasm/arch.c | 4 + libyasm/arch.h | 10 + libyasm/bc-int.h | 4 + libyasm/bytecode.c | 9 + libyasm/bytecode.h | 10 + modules/arch/x86/x86arch.c | 6 +- modules/arch/x86/x86arch.h | 4 + modules/arch/x86/x86bc.c | 17 + modules/arch/x86/x86id.re | 2097 +++++++++-------- modules/objfmts/elf/elf-objfmt.c | 22 +- modules/parsers/Makefile.inc | 2 + modules/parsers/gas/Makefile.inc | 28 + modules/parsers/gas/gas-bison.y | 726 ++++++ modules/parsers/gas/gas-defs.h | 88 + modules/parsers/gas/gas-parser.c | 105 + modules/parsers/gas/gas-parser.h | 89 + modules/parsers/gas/gas-token.re | 535 +++++ modules/parsers/gas/tests/Makefile.inc | 23 + modules/parsers/gas/tests/amd64/Makefile.inc | 9 + .../parsers/gas/tests/amd64/gas_amd64_test.sh | 4 + modules/parsers/gas/tests/amd64/riprel.asm | 1 + .../parsers/gas/tests/amd64/riprel.errwarn | 0 modules/parsers/gas/tests/amd64/riprel.hex | 640 +++++ modules/parsers/gas/tests/datavis.asm | 39 + modules/parsers/gas/tests/datavis.errwarn | 1 + modules/parsers/gas/tests/datavis.hex | 920 ++++++++ modules/parsers/gas/tests/datavis2.asm | 13 + modules/parsers/gas/tests/datavis2.errwarn | 0 modules/parsers/gas/tests/datavis2.hex | 712 ++++++ modules/parsers/gas/tests/gas_test.sh | 4 + modules/parsers/gas/tests/jmpcall.asm | 13 + modules/parsers/gas/tests/jmpcall.errwarn | 4 + modules/parsers/gas/tests/jmpcall.hex | 496 ++++ modules/parsers/gas/tests/reggroup-err.asm | 5 + .../parsers/gas/tests/reggroup-err.errwarn | 1 + modules/parsers/gas/tests/reggroup.asm | 5 + modules/parsers/gas/tests/reggroup.errwarn | 0 modules/parsers/gas/tests/reggroup.hex | 360 +++ 39 files changed, 6032 insertions(+), 978 deletions(-) create mode 100644 modules/parsers/gas/Makefile.inc create mode 100644 modules/parsers/gas/gas-bison.y create mode 100644 modules/parsers/gas/gas-defs.h create mode 100644 modules/parsers/gas/gas-parser.c create mode 100644 modules/parsers/gas/gas-parser.h create mode 100644 modules/parsers/gas/gas-token.re create mode 100644 modules/parsers/gas/tests/Makefile.inc create mode 100644 modules/parsers/gas/tests/amd64/Makefile.inc create mode 100755 modules/parsers/gas/tests/amd64/gas_amd64_test.sh create mode 100644 modules/parsers/gas/tests/amd64/riprel.asm create mode 100644 modules/parsers/gas/tests/amd64/riprel.errwarn create mode 100644 modules/parsers/gas/tests/amd64/riprel.hex create mode 100644 modules/parsers/gas/tests/datavis.asm create mode 100644 modules/parsers/gas/tests/datavis.errwarn create mode 100644 modules/parsers/gas/tests/datavis.hex create mode 100644 modules/parsers/gas/tests/datavis2.asm create mode 100644 modules/parsers/gas/tests/datavis2.errwarn create mode 100644 modules/parsers/gas/tests/datavis2.hex create mode 100755 modules/parsers/gas/tests/gas_test.sh create mode 100644 modules/parsers/gas/tests/jmpcall.asm create mode 100644 modules/parsers/gas/tests/jmpcall.errwarn create mode 100644 modules/parsers/gas/tests/jmpcall.hex create mode 100644 modules/parsers/gas/tests/reggroup-err.asm create mode 100644 modules/parsers/gas/tests/reggroup-err.errwarn create mode 100644 modules/parsers/gas/tests/reggroup.asm create mode 100644 modules/parsers/gas/tests/reggroup.errwarn create mode 100644 modules/parsers/gas/tests/reggroup.hex diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index 10e39c8f..27eb8a21 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -611,7 +611,9 @@ main(int argc, char *argv[]) fclose(in); /* Check for undefined symbols */ - yasm_symtab_parser_finalize(yasm_object_get_symtab(object), 0, NULL); + yasm_symtab_parser_finalize(yasm_object_get_symtab(object), + strcmp(cur_parser_module->keyword, "gas")==0, + cur_objfmt); if (yasm_get_num_errors(warning_error) > 0) { yasm_errwarn_output_all(yasm_object_get_linemap(object), warning_error, diff --git a/libyasm/arch.c b/libyasm/arch.c index 140f259a..90f7a233 100644 --- a/libyasm/arch.c +++ b/libyasm/arch.c @@ -47,6 +47,7 @@ yasm_operand_create_reg(unsigned long reg) retval->data.reg = reg; retval->targetmod = 0; retval->size = 0; + retval->deref = 0; return retval; } @@ -60,6 +61,7 @@ yasm_operand_create_segreg(unsigned long segreg) retval->data.reg = segreg; retval->targetmod = 0; retval->size = 0; + retval->deref = 0; return retval; } @@ -73,6 +75,7 @@ yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea) retval->data.ea = ea; retval->targetmod = 0; retval->size = 0; + retval->deref = 0; return retval; } @@ -93,6 +96,7 @@ yasm_operand_create_imm(/*@only@*/ yasm_expr *val) retval->data.val = val; retval->targetmod = 0; retval->size = 0; + retval->deref = 0; } return retval; diff --git a/libyasm/arch.h b/libyasm/arch.h index 760c869f..f3e704f2 100644 --- a/libyasm/arch.h +++ b/libyasm/arch.h @@ -246,6 +246,16 @@ struct yasm_insn_operand { /** Specified size of the operand, in bytes. 0 if not user-specified. */ unsigned int size; + + /** Nonzero if dereference. Used for "*foo" in GAS. + * The reason for this is that by default in GAS, an unprefixed value + * is a memory address, except for jumps/calls, in which case it needs a + * "*" prefix to become a memory address (otherwise it's an immediate). + * This isn't knowable in the parser stage, so the parser sets this flag + * to indicate the "*" prefix has been used, and the arch needs to adjust + * the operand type appropriately depending on the instruction type. + */ + int deref; }; #endif diff --git a/libyasm/bc-int.h b/libyasm/bc-int.h index 251e53d0..fbf8fced 100644 --- a/libyasm/bc-int.h +++ b/libyasm/bc-int.h @@ -42,6 +42,10 @@ struct yasm_effaddr { */ unsigned char nosplit; /* 1 if reg*2 should not be split into reg+reg. (0 if not) */ + unsigned char strong; /* 1 if effective address is *definitely* + * an effective address, e.g. in GAS if + * expr(,1) form is used vs. just expr. + */ }; struct yasm_immval { diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index 05636a73..2c212b04 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -238,6 +238,15 @@ yasm_ea_set_nosplit(yasm_effaddr *ptr, unsigned int nosplit) ptr->nosplit = (unsigned char)nosplit; } +void +yasm_ea_set_strong(yasm_effaddr *ptr, unsigned int strong) +{ + if (!ptr) + return; + + ptr->strong = (unsigned char)strong; +} + void yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long segreg, unsigned long line) { diff --git a/libyasm/bytecode.h b/libyasm/bytecode.h index 1bd9bbfc..79d940b9 100644 --- a/libyasm/bytecode.h +++ b/libyasm/bytecode.h @@ -92,6 +92,16 @@ void yasm_ea_set_len(yasm_effaddr *ea, unsigned int len); */ void yasm_ea_set_nosplit(yasm_effaddr *ea, unsigned int nosplit); +/** Set/clear strong flag of an effective address. + * The strong flag indicates if an effective address is *definitely* an + * effective address. This is used in e.g. the GAS parser to differentiate + * between "expr" (which might or might not be an effective address) and + * "expr(,1)" (which is definitely an effective address). + * \param ea effective address + * \param strong strong flag setting (0=not strong, nonzero=strong) + */ +void yasm_ea_set_strong(yasm_effaddr *ea, unsigned int strong); + /** Set segment override for an effective address. * Some architectures (such as x86) support segment overrides on effective * addresses. A override of an override will result in a warning. diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c index eed01ce8..bdb23c8d 100644 --- a/modules/arch/x86/x86arch.c +++ b/modules/arch/x86/x86arch.c @@ -62,7 +62,11 @@ x86_create(const char *machine, const char *parser, arch_x86->amd64_machine = amd64_machine; arch_x86->mode_bits = 0; - if (yasm__strcasecmp(parser, "nasm") != 0) { + if (yasm__strcasecmp(parser, "nasm") == 0) + arch_x86->parser = X86_PARSER_NASM; + else if (yasm__strcasecmp(parser, "gas") == 0) + arch_x86->parser = X86_PARSER_GAS; + else { yasm_xfree(arch_x86); *error = YASM_ARCH_CREATE_BAD_PARSER; return NULL; diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index 84b43451..c3140e29 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -68,6 +68,10 @@ typedef struct yasm_arch_x86 { /* What instructions/features are enabled? */ unsigned long cpu_enabled; unsigned int amd64_machine; + enum { + X86_PARSER_NASM, + X86_PARSER_GAS + } parser; unsigned char mode_bits; } yasm_arch_x86; diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c index c35274e9..1d7114a5 100644 --- a/modules/arch/x86/x86bc.c +++ b/modules/arch/x86/x86bc.c @@ -206,6 +206,7 @@ yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex, x86_ea->ea.disp = (yasm_expr *)NULL; x86_ea->ea.len = 0; x86_ea->ea.nosplit = 0; + x86_ea->ea.strong = 0; x86_ea->ea.segreg = 0; x86_ea->modrm = 0xC0 | rm; /* Mod=11, R/M=Reg, Reg=0 */ x86_ea->valid_modrm = 1; @@ -221,11 +222,27 @@ yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex, yasm_effaddr * yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e) { + yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; x86_effaddr *x86_ea; x86_ea = yasm_xmalloc(sizeof(x86_effaddr)); x86_ea->ea.callback = &x86_ea_callback; + if (arch_x86->parser == X86_PARSER_GAS) { + /* Need to change foo+rip into foo wrt rip. + * Note this assumes a particular ordering coming from the parser + * to work (it's not very smart)! + */ + if (e->op == YASM_EXPR_ADD && e->terms[0].type == YASM_EXPR_REG + && e->terms[0].data.reg == X86_RIP) { + /* replace register with 0 */ + e->terms[0].type = YASM_EXPR_INT; + e->terms[0].data.intn = yasm_intnum_create_uint(0); + /* build new wrt expression */ + e = yasm_expr_create(YASM_EXPR_WRT, yasm_expr_expr(e), + yasm_expr_reg(X86_RIP), e->line); + } + } x86_ea->ea.disp = e; x86_ea->ea.len = 0; x86_ea->ea.nosplit = 0; diff --git a/modules/arch/x86/x86id.re b/modules/arch/x86/x86id.re index 5bf90e26..96b5d660 100644 --- a/modules/arch/x86/x86id.re +++ b/modules/arch/x86/x86id.re @@ -52,6 +52,17 @@ RCSID("$Id$"); #define MOD_AdSizeR (1UL<<10) /* Parameter replaces addrsize (jmp only) */ #define MOD_DOpS64R (1UL<<11) /* Parameter replaces default 64-bit opersize */ +/* Modifiers that aren't: these are used with the GAS parser to indicate + * special cases. + */ +#define MOD_GasNoRev (1UL<<15) /* Don't reverse operands */ +#define MOD_GasSufB (1UL<<16) /* GAS B suffix ok */ +#define MOD_GasSufW (1UL<<17) /* GAS W suffix ok */ +#define MOD_GasSufL (1UL<<18) /* GAS L suffix ok */ +#define MOD_GasSufQ (1UL<<19) /* GAS Q suffix ok */ +#define MOD_GasSuf_SHIFT 16 +#define MOD_GasSuf_MASK (0xFUL<<16) + /* Modifiers that aren't actually used as modifiers. Rather, if set, bits * 20-27 in the modifier are used as an index into an array. * Obviously, only one of these may be set at a time. @@ -255,7 +266,9 @@ typedef struct x86_insn_info { unsigned long operands[3]; } x86_insn_info; -/* Define lexer arch-specific data with 0-3 modifiers. */ +/* Define lexer arch-specific data with 0-3 modifiers. + * This assumes arch_x86 is locally defined. + */ #define DEF_INSN_DATA(group, mod, cpu) do { \ data[0] = (unsigned long)group##_insn; \ data[1] = ((mod)<<8) | \ @@ -264,11 +277,6 @@ typedef struct x86_insn_info { data[3] = arch_x86->mode_bits; \ } while (0) -#define RET_INSN(group, mod, cpu) do { \ - DEF_INSN_DATA(group, mod, cpu); \ - return YASM_ARCH_CHECK_ID_INSN; \ - } while (0) - /* * General instruction groupings */ @@ -338,21 +346,21 @@ static const x86_insn_info vmxthreebytemem_insn[] = { /* Move instructions */ static const x86_insn_info mov_insn[] = { /* Absolute forms for non-64-bit mode */ - { CPU_Not64, 0, 0, 0, 0, 1, {0xA0, 0, 0}, 0, 2, + { CPU_Not64, MOD_GasSufB, 0, 0, 0, 1, {0xA0, 0, 0}, 0, 2, {OPT_Areg|OPS_8|OPA_None, OPT_MemOffs|OPS_8|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Not64, 0, 16, 0, 0, 1, {0xA1, 0, 0}, 0, 2, + { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0xA1, 0, 0}, 0, 2, {OPT_Areg|OPS_16|OPA_None, OPT_MemOffs|OPS_16|OPS_Relaxed|OPA_EA, 0} }, - { CPU_386|CPU_Not64, 0, 32, 0, 0, 1, {0xA1, 0, 0}, 0, 2, + { CPU_386|CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0xA1, 0, 0}, 0, 2, {OPT_Areg|OPS_32|OPA_None, OPT_MemOffs|OPS_32|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Not64, 0, 0, 0, 0, 1, {0xA2, 0, 0}, 0, 2, + { CPU_Not64, MOD_GasSufB, 0, 0, 0, 1, {0xA2, 0, 0}, 0, 2, {OPT_MemOffs|OPS_8|OPS_Relaxed|OPA_EA, OPT_Areg|OPS_8|OPA_None, 0} }, - { CPU_Not64, 0, 16, 0, 0, 1, {0xA3, 0, 0}, 0, 2, + { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0xA3, 0, 0}, 0, 2, {OPT_MemOffs|OPS_16|OPS_Relaxed|OPA_EA, OPT_Areg|OPS_16|OPA_None, 0} }, - { CPU_386|CPU_Not64, 0, 32, 0, 0, 1, {0xA3, 0, 0}, 0, 2, + { CPU_386|CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0xA3, 0, 0}, 0, 2, {OPT_MemOffs|OPS_32|OPS_Relaxed|OPA_EA, OPT_Areg|OPS_32|OPA_None, 0} }, - /* 64-bit absolute forms for 64-bit mode */ + /* 64-bit absolute forms for 64-bit mode. Disabled for GAS, see movabs */ { CPU_Hammer|CPU_64, 0, 0, 0, 0, 1, {0xA0, 0, 0}, 0, 2, {OPT_Areg|OPS_8|OPA_None, OPT_MemOffs|OPS_8|OPS_Relaxed|OPEAS_64|OPA_EA, 0} }, @@ -380,121 +388,156 @@ static const x86_insn_info mov_insn[] = { OPT_Areg|OPS_64|OPA_None, 0} }, /* General 32-bit forms using Areg / short absolute option */ - { CPU_Any, 0, 0, 0, 0, 1, {0x88, 0xA2, 0}, 0, 2, + { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0x88, 0xA2, 0}, 0, 2, {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA|OPAP_ShortMov, OPT_Areg|OPS_8|OPA_Spare, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA|OPAP_ShortMov, OPT_Areg|OPS_16|OPA_Spare, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA|OPAP_ShortMov, OPT_Areg|OPS_32|OPA_Spare, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA|OPAP_ShortMov, OPT_Areg|OPS_64|OPA_Spare, 0} }, /* General 32-bit forms */ - { CPU_Any, 0, 0, 0, 0, 1, {0x88, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0x88, 0, 0}, 0, 2, {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_8|OPA_Spare, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0x89, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x89, 0, 0}, 0, 2, {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0x89, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x89, 0, 0}, 0, 2, {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x89, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x89, 0, 0}, 0, 2, {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare, 0} }, /* General 32-bit forms using Areg / short absolute option */ - { CPU_Any, 0, 0, 0, 0, 1, {0x8A, 0xA0, 0}, 0, 2, + { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0x8A, 0xA0, 0}, 0, 2, {OPT_Areg|OPS_8|OPA_Spare, OPT_RM|OPS_8|OPS_Relaxed|OPA_EA|OPAP_ShortMov, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, {OPT_Areg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA|OPAP_ShortMov, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, {OPT_Areg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA|OPAP_ShortMov, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, {OPT_Areg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA|OPAP_ShortMov, 0} }, /* General 32-bit forms */ - { CPU_Any, 0, 0, 0, 0, 1, {0x8A, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0x8A, 0, 0}, 0, 2, {OPT_Reg|OPS_8|OPA_Spare, OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0x8B, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x8B, 0, 0}, 0, 2, {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0x8B, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x8B, 0, 0}, 0, 2, {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x8B, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x8B, 0, 0}, 0, 2, {OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, 0} }, /* Segment register forms */ - { CPU_Any, 0, 0, 0, 0, 1, {0x8C, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 0, 0, 0, 1, {0x8C, 0, 0}, 0, 2, {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, OPT_SegReg|OPS_16|OPS_Relaxed|OPA_Spare, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0x8C, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x8C, 0, 0}, 0, 2, {OPT_Reg|OPS_16|OPA_EA, OPT_SegReg|OPS_16|OPS_Relaxed|OPA_Spare, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0x8C, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x8C, 0, 0}, 0, 2, {OPT_Reg|OPS_32|OPA_EA, OPT_SegReg|OPS_16|OPS_Relaxed|OPA_Spare, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x8C, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x8C, 0, 0}, 0, 2, {OPT_Reg|OPS_64|OPA_EA, OPT_SegReg|OPS_16|OPS_Relaxed|OPA_Spare, 0} }, - { CPU_Any, 0, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, {OPT_SegReg|OPS_16|OPS_Relaxed|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, - { CPU_386, 0, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, {OPT_SegReg|OPS_16|OPS_Relaxed|OPA_Spare, OPT_Reg|OPS_32|OPA_EA, 0} }, - { CPU_Hammer|CPU_64, 0, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, {OPT_SegReg|OPS_16|OPS_Relaxed|OPA_Spare, OPT_Reg|OPS_64|OPA_EA, 0} }, /* Immediate forms */ - { CPU_Any, 0, 0, 0, 0, 1, {0xB0, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0xB0, 0, 0}, 0, 2, {OPT_Reg|OPS_8|OPA_Op0Add, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0xB8, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0xB8, 0, 0}, 0, 2, {OPT_Reg|OPS_16|OPA_Op0Add, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0xB8, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0xB8, 0, 0}, 0, 2, {OPT_Reg|OPS_32|OPA_Op0Add, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0xB8, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0xB8, 0, 0}, 0, 2, {OPT_Reg|OPS_64|OPA_Op0Add, OPT_Imm|OPS_64|OPS_Relaxed|OPA_Imm, 0} }, /* Need two sets here, one for strictness on left side, one for right. */ - { CPU_Any, 0, 0, 0, 0, 1, {0xC6, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0xC6, 0, 0}, 0, 2, {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_8|OPA_Imm, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0xC7, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0xC7, 0, 0}, 0, 2, {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_16|OPA_Imm, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0xC7, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0xC7, 0, 0}, 0, 2, {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0xC7, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0xC7, 0, 0}, 0, 2, {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, - { CPU_Any, 0, 0, 0, 0, 1, {0xC6, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0xC6, 0, 0}, 0, 2, {OPT_RM|OPS_8|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Any, 0, 16, 0, 0, 1, {0xC7, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0xC7, 0, 0}, 0, 2, {OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0xC7, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0xC7, 0, 0}, 0, 2, {OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0xC7, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0xC7, 0, 0}, 0, 2, {OPT_RM|OPS_64|OPA_EA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, /* CR/DR forms */ - { CPU_586|CPU_Priv|CPU_Not64, 0, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, 2, - {OPT_CR4|OPS_32|OPA_Spare, OPT_Reg|OPS_32|OPA_EA, 0} }, - { CPU_386|CPU_Priv|CPU_Not64, 0, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, 2, - {OPT_CRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_32|OPA_EA, 0} }, - { CPU_Hammer|CPU_Priv|CPU_64, 0, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, 2, - {OPT_CRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_64|OPA_EA, 0} }, - { CPU_586|CPU_Priv|CPU_Not64, 0, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, 2, - {OPT_Reg|OPS_32|OPA_EA, OPT_CR4|OPS_32|OPA_Spare, 0} }, - { CPU_386|CPU_Priv|CPU_Not64, 0, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, 2, - {OPT_Reg|OPS_32|OPA_EA, OPT_CRReg|OPS_32|OPA_Spare, 0} }, - { CPU_Hammer|CPU_Priv|CPU_64, 0, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, 2, - {OPT_Reg|OPS_64|OPA_EA, OPT_CRReg|OPS_32|OPA_Spare, 0} }, - - { CPU_386|CPU_Priv|CPU_Not64, 0, 0, 0, 0, 2, {0x0F, 0x23, 0}, 0, 2, - {OPT_DRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_32|OPA_EA, 0} }, - { CPU_Hammer|CPU_Priv|CPU_64, 0, 0, 0, 0, 2, {0x0F, 0x23, 0}, 0, 2, - {OPT_DRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_64|OPA_EA, 0} }, - { CPU_386|CPU_Priv|CPU_Not64, 0, 0, 0, 0, 2, {0x0F, 0x21, 0}, 0, 2, - {OPT_Reg|OPS_32|OPA_EA, OPT_DRReg|OPS_32|OPA_Spare, 0} }, - { CPU_Hammer|CPU_Priv|CPU_64, 0, 0, 0, 0, 2, {0x0F, 0x21, 0}, 0, 2, - {OPT_Reg|OPS_64|OPA_EA, OPT_DRReg|OPS_32|OPA_Spare, 0} } + { CPU_586|CPU_Priv|CPU_Not64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, + 2, {OPT_CR4|OPS_32|OPA_Spare, OPT_Reg|OPS_32|OPA_EA, 0} }, + { CPU_386|CPU_Priv|CPU_Not64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, + 2, {OPT_CRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_32|OPA_EA, 0} }, + { CPU_Hammer|CPU_Priv|CPU_64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, + 2, {OPT_CRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_64|OPA_EA, 0} }, + { CPU_586|CPU_Priv|CPU_Not64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, + 2, {OPT_Reg|OPS_32|OPA_EA, OPT_CR4|OPS_32|OPA_Spare, 0} }, + { CPU_386|CPU_Priv|CPU_Not64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, + 2, {OPT_Reg|OPS_32|OPA_EA, OPT_CRReg|OPS_32|OPA_Spare, 0} }, + { CPU_Hammer|CPU_Priv|CPU_64, MOD_GasSufQ, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, + 2, {OPT_Reg|OPS_64|OPA_EA, OPT_CRReg|OPS_32|OPA_Spare, 0} }, + + { CPU_386|CPU_Priv|CPU_Not64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x23, 0}, 0, + 2, {OPT_DRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_32|OPA_EA, 0} }, + { CPU_Hammer|CPU_Priv|CPU_64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x23, 0}, 0, + 2, {OPT_DRReg|OPS_32|OPA_Spare, OPT_Reg|OPS_64|OPA_EA, 0} }, + { CPU_386|CPU_Priv|CPU_Not64, MOD_GasSufL, 0, 0, 0, 2, {0x0F, 0x21, 0}, 0, + 2, {OPT_Reg|OPS_32|OPA_EA, OPT_DRReg|OPS_32|OPA_Spare, 0} }, + { CPU_Hammer|CPU_Priv|CPU_64, MOD_GasSufQ, 0, 0, 0, 2, {0x0F, 0x21, 0}, 0, + 2, {OPT_Reg|OPS_64|OPA_EA, OPT_DRReg|OPS_32|OPA_Spare, 0} } +}; + +/* 64-bit absolute move (for GAS). + * These are disabled for GAS for normal mov above. + */ +static const x86_insn_info movabs_insn[] = { + { CPU_Hammer|CPU_64, MOD_GasSufB, 0, 0, 0, 1, {0xA0, 0, 0}, 0, 2, + {OPT_Areg|OPS_8|OPA_None, + OPT_MemOffs|OPS_8|OPS_Relaxed|OPEAS_64|OPA_EA, 0} }, + { CPU_Hammer|CPU_64, MOD_GasSufW, 16, 0, 0, 1, {0xA1, 0, 0}, 0, 2, + {OPT_Areg|OPS_16|OPA_None, + OPT_MemOffs|OPS_16|OPS_Relaxed|OPEAS_64|OPA_EA, 0} }, + { CPU_Hammer|CPU_64, MOD_GasSufL, 32, 0, 0, 1, {0xA1, 0, 0}, 0, 2, + {OPT_Areg|OPS_32|OPA_None, + OPT_MemOffs|OPS_32|OPS_Relaxed|OPEAS_64|OPA_EA, 0} }, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0xA1, 0, 0}, 0, 2, + {OPT_Areg|OPS_64|OPA_None, + OPT_MemOffs|OPS_64|OPS_Relaxed|OPEAS_64|OPA_EA, 0} }, + + { CPU_Hammer|CPU_64, MOD_GasSufB, 0, 0, 0, 1, {0xA2, 0, 0}, 0, 2, + {OPT_MemOffs|OPS_8|OPS_Relaxed|OPEAS_64|OPA_EA, + OPT_Areg|OPS_8|OPA_None, 0} }, + { CPU_Hammer|CPU_64, MOD_GasSufW, 16, 0, 0, 1, {0xA3, 0, 0}, 0, 2, + {OPT_MemOffs|OPS_16|OPS_Relaxed|OPEAS_64|OPA_EA, + OPT_Areg|OPS_16|OPA_None, 0} }, + { CPU_Hammer|CPU_64, MOD_GasSufL, 32, 0, 0, 1, {0xA3, 0, 0}, 0, 2, + {OPT_MemOffs|OPS_32|OPS_Relaxed|OPEAS_64|OPA_EA, + OPT_Areg|OPS_32|OPA_None, 0} }, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0xA3, 0, 0}, 0, 2, + {OPT_MemOffs|OPS_64|OPS_Relaxed|OPEAS_64|OPA_EA, + OPT_Areg|OPS_64|OPA_None, 0} }, + + /* 64-bit immediate form */ + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0xB8, 0, 0}, 0, 2, + {OPT_Reg|OPS_64|OPA_Op0Add, OPT_Imm|OPS_64|OPS_Relaxed|OPA_Imm, 0} }, }; /* Move with sign/zero extend */ @@ -519,61 +562,61 @@ static const x86_insn_info movsxd_insn[] = { /* Push instructions */ static const x86_insn_info push_insn[] = { - { CPU_Any, 0, 16, 64, 0, 1, {0x50, 0, 0}, 0, 1, + { CPU_Any, MOD_GasSufW, 16, 64, 0, 1, {0x50, 0, 0}, 0, 1, {OPT_Reg|OPS_16|OPA_Op0Add, 0, 0} }, - { CPU_386|CPU_Not64, 0, 32, 0, 0, 1, {0x50, 0, 0}, 0, 1, + { CPU_386|CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0x50, 0, 0}, 0, 1, {OPT_Reg|OPS_32|OPA_Op0Add, 0, 0} }, - { CPU_Hammer|CPU_64, 0, 0, 64, 0, 1, {0x50, 0, 0}, 0, 1, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 0, 64, 0, 1, {0x50, 0, 0}, 0, 1, {OPT_Reg|OPS_64|OPA_Op0Add, 0, 0} }, - { CPU_Any, 0, 16, 64, 0, 1, {0xFF, 0, 0}, 6, 1, + { CPU_Any, MOD_GasSufW, 16, 64, 0, 1, {0xFF, 0, 0}, 6, 1, {OPT_RM|OPS_16|OPA_EA, 0, 0} }, - { CPU_386|CPU_Not64, 0, 32, 0, 0, 1, {0xFF, 0, 0}, 6, 1, + { CPU_386|CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0xFF, 0, 0}, 6, 1, {OPT_RM|OPS_32|OPA_EA, 0, 0} }, - { CPU_Hammer|CPU_64, 0, 0, 64, 0, 1, {0xFF, 0, 0}, 6, 1, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 0, 64, 0, 1, {0xFF, 0, 0}, 6, 1, {OPT_RM|OPS_64|OPA_EA, 0, 0} }, - { CPU_Any, 0, 0, 64, 0, 1, {0x6A, 0, 0}, 0, 1, + { CPU_Any, MOD_GasSufQ, 0, 64, 0, 1, {0x6A, 0, 0}, 0, 1, {OPT_Imm|OPS_8|OPA_SImm, 0, 0} }, - { CPU_Any, 0, 16, 64, 0, 1, {0x68, 0, 0}, 0, 1, + { CPU_Any, MOD_GasSufW, 16, 64, 0, 1, {0x68, 0, 0}, 0, 1, {OPT_Imm|OPS_16|OPA_Imm, 0, 0} }, - { CPU_386|CPU_Not64, 0, 32, 0, 0, 1, {0x68, 0, 0}, 0, 1, + { CPU_386|CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0x68, 0, 0}, 0, 1, {OPT_Imm|OPS_32|OPA_Imm, 0, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 64, 0, 1, {0x68, 0, 0}, 0, 1, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 64, 0, 1, {0x68, 0, 0}, 0, 1, {OPT_Imm|OPS_32|OPA_SImm, 0, 0} }, { CPU_Not64, 0, 0, 0, 0, 1, {0x0E, 0, 0}, 0, 1, {OPT_CS|OPS_Any|OPA_None, 0, 0} }, - { CPU_Not64, 0, 16, 0, 0, 1, {0x0E, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0x0E, 0, 0}, 0, 1, {OPT_CS|OPS_16|OPA_None, 0, 0} }, - { CPU_Not64, 0, 32, 0, 0, 1, {0x0E, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0x0E, 0, 0}, 0, 1, {OPT_CS|OPS_32|OPA_None, 0, 0} }, { CPU_Not64, 0, 0, 0, 0, 1, {0x16, 0, 0}, 0, 1, {OPT_SS|OPS_Any|OPA_None, 0, 0} }, - { CPU_Not64, 0, 16, 0, 0, 1, {0x16, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0x16, 0, 0}, 0, 1, {OPT_SS|OPS_16|OPA_None, 0, 0} }, - { CPU_Not64, 0, 32, 0, 0, 1, {0x16, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0x16, 0, 0}, 0, 1, {OPT_SS|OPS_32|OPA_None, 0, 0} }, { CPU_Not64, 0, 0, 0, 0, 1, {0x1E, 0, 0}, 0, 1, {OPT_DS|OPS_Any|OPA_None, 0, 0} }, - { CPU_Not64, 0, 16, 0, 0, 1, {0x1E, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0x1E, 0, 0}, 0, 1, {OPT_DS|OPS_16|OPA_None, 0, 0} }, - { CPU_Not64, 0, 32, 0, 0, 1, {0x1E, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0x1E, 0, 0}, 0, 1, {OPT_DS|OPS_32|OPA_None, 0, 0} }, { CPU_Not64, 0, 0, 0, 0, 1, {0x06, 0, 0}, 0, 1, {OPT_ES|OPS_Any|OPA_None, 0, 0} }, - { CPU_Not64, 0, 16, 0, 0, 1, {0x06, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0x06, 0, 0}, 0, 1, {OPT_ES|OPS_16|OPA_None, 0, 0} }, - { CPU_Not64, 0, 32, 0, 0, 1, {0x06, 0, 0}, 0, 1, + { CPU_Not64, MOD_GasSufL, 32, 0, 0, 1, {0x06, 0, 0}, 0, 1, {OPT_ES|OPS_32|OPA_None, 0, 0} }, { CPU_386, 0, 0, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, {OPT_FS|OPS_Any|OPA_None, 0, 0} }, - { CPU_386, 0, 16, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, + { CPU_386, MOD_GasSufW, 16, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, {OPT_FS|OPS_16|OPA_None, 0, 0} }, - { CPU_386, 0, 32, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, + { CPU_386, MOD_GasSufL, 32, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, {OPT_FS|OPS_32|OPA_None, 0, 0} }, { CPU_386, 0, 0, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, {OPT_GS|OPS_Any|OPA_None, 0, 0} }, - { CPU_386, 0, 16, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, + { CPU_386, MOD_GasSufW, 16, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, {OPT_GS|OPS_16|OPA_None, 0, 0} }, - { CPU_386, 0, 32, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, + { CPU_386, MOD_GasSufL, 32, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, {OPT_GS|OPS_32|OPA_None, 0, 0} } }; @@ -693,11 +736,11 @@ static const x86_insn_info out_insn[] = { /* Load effective address */ static const x86_insn_info lea_insn[] = { - { CPU_Any, 0, 16, 0, 0, 1, {0x8D, 0, 0}, 0, 2, + { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x8D, 0, 0}, 0, 2, {OPT_Reg|OPS_16|OPA_Spare, OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0} }, - { CPU_386, 0, 32, 0, 0, 1, {0x8D, 0, 0}, 0, 2, + { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x8D, 0, 0}, 0, 2, {OPT_Reg|OPS_32|OPA_Spare, OPT_Mem|OPS_32|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Hammer|CPU_64, 0, 64, 0, 0, 1, {0x8D, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x8D, 0, 0}, 0, 2, {OPT_Reg|OPS_64|OPA_Spare, OPT_Mem|OPS_64|OPS_Relaxed|OPA_EA, 0} } }; @@ -717,57 +760,60 @@ static const x86_insn_info lfgss_insn[] = { /* Arithmetic - general */ static const x86_insn_info arith_insn[] = { - { CPU_Any, MOD_Op0Add, 0, 0, 0, 1, {0x04, 0, 0}, 0, 2, + { CPU_Any, MOD_Op0Add|MOD_GasSufB, 0, 0, 0, 1, {0x04, 0, 0}, 0, 2, {OPT_Areg|OPS_8|OPA_None, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Any, MOD_Op0Add, 16, 0, 0, 1, {0x05, 0, 0}, 0, 2, + { CPU_Any, MOD_Op0Add|MOD_GasSufW, 16, 0, 0, 1, {0x05, 0, 0}, 0, 2, {OPT_Areg|OPS_16|OPA_None, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_386, MOD_Op0Add, 32, 0, 0, 1, {0x05, 0, 0}, 0, 2, + { CPU_386, MOD_Op0Add|MOD_GasSufL, 32, 0, 0, 1, {0x05, 0, 0}, 0, 2, {OPT_Areg|OPS_32|OPA_None, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Hammer|CPU_64, MOD_Op0Add, 64, 0, 0, 1, {0x05, 0, 0}, 0, 2, - {OPT_Areg|OPS_64|OPA_None, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Hammer|CPU_64, MOD_Op0Add|MOD_GasSufQ, 64, 0, 0, 1, {0x05, 0, 0}, 0, + 2, {OPT_Areg|OPS_64|OPA_None, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Any, MOD_Gap0|MOD_SpAdd, 0, 0, 0, 1, {0x80, 0, 0}, 0, 2, + { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0x80, 0, 0}, 0, 2, {OPT_RM|OPS_8|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, - { CPU_Any, MOD_Gap0|MOD_SpAdd, 0, 0, 0, 1, {0x80, 0, 0}, 0, 2, + { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufB, 0, 0, 0, 1, {0x80, 0, 0}, 0, 2, {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_8|OPA_Imm, 0} }, - { CPU_Any, MOD_Gap0|MOD_SpAdd, 16, 0, 0, 1, {0x83, 0, 0}, 0, 2, + { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0x83, 0, 0}, 0, 2, {OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_8|OPA_SImm, 0} }, - { CPU_Any, MOD_Gap0|MOD_SpAdd, 16, 0, 0, 1, {0x81, 0x83, 0}, 0, 2, - {OPT_RM|OPS_16|OPA_EA, - OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} }, - { CPU_Any, MOD_Gap0|MOD_SpAdd, 16, 0, 0, 1, {0x81, 0, 0}, 0, 2, + { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0x81, 0x83, 0}, 0, + 2, {OPT_RM|OPS_16|OPA_EA, + OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} }, + { CPU_Any, MOD_Gap0|MOD_SpAdd|MOD_GasSufW, 16, 0, 0, 1, {0x81, 0, 0}, 0, 2, {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_16|OPA_Imm, 0} }, - { CPU_386, MOD_Gap0|MOD_SpAdd, 32, 0, 0, 1, {0x83, 0, 0}, 0, 2, + { CPU_386, MOD_Gap0|MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0x83, 0, 0}, 0, 2, {OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_8|OPA_SImm, 0} }, - { CPU_386, MOD_Gap0|MOD_SpAdd, 32, 0, 0, 1, {0x81, 0x83, 0}, 0, 2, - {OPT_RM|OPS_32|OPA_EA, - OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} }, - { CPU_386, MOD_Gap0|MOD_SpAdd, 32, 0, 0, 1, {0x81, 0, 0}, 0, 2, + { CPU_386, MOD_Gap0|MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0x81, 0x83, 0}, 0, + 2, {OPT_RM|OPS_32|OPA_EA, + OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} }, + { CPU_386, MOD_Gap0|MOD_SpAdd|MOD_GasSufL, 32, 0, 0, 1, {0x81, 0, 0}, 0, 2, {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, - { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd, 64, 0, 0, 1, {0x83, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, + {0x83, 0, 0}, 0, 2, {OPT_RM|OPS_64|OPA_EA, OPT_Imm|OPS_8|OPA_SImm, 0} }, - { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd, 64, 0, 0, 1, {0x81, 0x83, 0}, - 0, 2, {OPT_RM|OPS_64|OPA_EA, - OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} }, - { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd, 64, 0, 0, 1, {0x81, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, + {0x81, 0x83, 0}, 0, 2, + {OPT_RM|OPS_64|OPA_EA, + OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0} }, + { CPU_Hammer|CPU_64, MOD_Gap0|MOD_SpAdd|MOD_GasSufQ, 64, 0, 0, 1, + {0x81, 0, 0}, 0, 2, {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, - { CPU_Any, MOD_Op0Add, 0, 0, 0, 1, {0x00, 0, 0}, 0, 2, + { CPU_Any, MOD_Op0Add|MOD_GasSufB, 0, 0, 0, 1, {0x00, 0, 0}, 0, 2, {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_8|OPA_Spare, 0} }, - { CPU_Any, MOD_Op0Add, 16, 0, 0, 1, {0x01, 0, 0}, 0, 2, + { CPU_Any, MOD_Op0Add|MOD_GasSufW, 16, 0, 0, 1, {0x01, 0, 0}, 0, 2, {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare, 0} }, - { CPU_386, MOD_Op0Add, 32, 0, 0, 1, {0x01, 0, 0}, 0, 2, + { CPU_386, MOD_Op0Add|MOD_GasSufL, 32, 0, 0, 1, {0x01, 0, 0}, 0, 2, {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} }, - { CPU_Hammer|CPU_64, MOD_Op0Add, 64, 0, 0, 1, {0x01, 0, 0}, 0, 2, - {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare, 0} }, - { CPU_Any, MOD_Op0Add, 0, 0, 0, 1, {0x02, 0, 0}, 0, 2, + { CPU_Hammer|CPU_64, MOD_Op0Add|MOD_GasSufQ, 64, 0, 0, 1, {0x01, 0, 0}, 0, + 2, {OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_64|OPA_Spare, 0} }, + { CPU_Any, MOD_Op0Add|MOD_GasSufB, 0, 0, 0, 1, {0x02, 0, 0}, 0, 2, {OPT_Reg|OPS_8|OPA_Spare, OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Any, MOD_Op0Add, 16, 0, 0, 1, {0x03, 0, 0}, 0, 2, + { CPU_Any, MOD_Op0Add|MOD_GasSufW, 16, 0, 0, 1, {0x03, 0, 0}, 0, 2, {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, - { CPU_386, MOD_Op0Add, 32, 0, 0, 1, {0x03, 0, 0}, 0, 2, + { CPU_386, MOD_Op0Add|MOD_GasSufL, 32, 0, 0, 1, {0x03, 0, 0}, 0, 2, {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Hammer|CPU_64, MOD_Op0Add, 64, 0, 0, 1, {0x03, 0, 0}, 0, 2, - {OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, 0} } + { CPU_Hammer|CPU_64, MOD_Op0Add|MOD_GasSufQ, 64, 0, 0, 1, {0x03, 0, 0}, 0, + 2, {OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, 0} } }; /* Arithmetic - inc/dec */ @@ -1820,7 +1866,8 @@ x86_finalize_jmp(yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc, int num_info = (int)(data[1]&0xFF); x86_insn_info *info = (x86_insn_info *)data[0]; unsigned long mod_data = data[1] >> 8; - unsigned char mode_bits = (unsigned char)data[3]; + unsigned char mode_bits = (unsigned char)(data[3] & 0xFF); + /*unsigned char suffix = (unsigned char)((data[3]>>8) & 0xFF);*/ yasm_insn_operand *op; static const unsigned char size_lookup[] = {0, 8, 16, 32, 64, 80, 128, 0}; @@ -1926,9 +1973,10 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc, int num_info = (int)(data[1]&0xFF); x86_insn_info *info = (x86_insn_info *)data[0]; unsigned long mod_data = data[1] >> 8; - unsigned char mode_bits = (unsigned char)data[3]; + unsigned char mode_bits = (unsigned char)(data[3] & 0xFF); + unsigned long suffix = (data[3]>>8) & 0xFF; int found = 0; - yasm_insn_operand *op; + yasm_insn_operand *op, *ops[4], *rev_ops[4], **use_ops; /*@null@*/ yasm_symrec *origin; /*@null@*/ yasm_expr *imm; unsigned char im_len; @@ -1937,9 +1985,60 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc, int i; static const unsigned int size_lookup[] = {0, 1, 2, 4, 8, 10, 16, 0}; - /* First look for SEG:OFF operands and apply X86_FAR_SEGOFF targetmod. */ - for (i = 0, op = yasm_ops_first(operands); op && inum_operands; - op = yasm_operand_next(op), i++) { + /* Build local array of operands from list, since we know we have a max + * of 3 operands. + */ + if (num_operands > 3) { + yasm__error(bc->line, N_("too many operands")); + return; + } + ops[0] = ops[1] = ops[2] = ops[3] = NULL; + for (i = 0, op = yasm_ops_first(operands); op && i < num_operands; + op = yasm_operand_next(op), i++) + ops[i] = op; + use_ops = ops; + + /* If we're running in GAS mode, build a reverse array of the operands + * as most GAS instructions have reversed operands from Intel style. + */ + if (arch_x86->parser == X86_PARSER_GAS) { + rev_ops[0] = rev_ops[1] = rev_ops[2] = rev_ops[3] = NULL; + for (i = num_operands-1, op = yasm_ops_first(operands); op && i >= 0; + op = yasm_operand_next(op), i--) + rev_ops[i] = op; + use_ops = rev_ops; + } + + /* If we're running in GAS mode, look at the first insn_info to see + * if this is a relative jump (OPA_JmpRel). If so, run through the + * operands and adjust for dereferences / lack thereof. + */ + if (arch_x86->parser == X86_PARSER_GAS + && (info->operands[0] & OPA_MASK) == OPA_JmpRel) { + for (i = 0, op = ops[0]; op; op = ops[++i]) { + if (!op->deref && (op->type == YASM_INSN__OPERAND_REG + || (op->type == YASM_INSN__OPERAND_MEMORY + && op->data.ea->strong))) + yasm__warning(YASM_WARN_GENERAL, bc->line, + N_("indirect call without `*'")); + if (!op->deref && op->type == YASM_INSN__OPERAND_MEMORY + && !op->data.ea->strong) { + /* Memory that is not dereferenced, and not strong, is + * actually an immediate for the purposes of relative jumps. + */ + if (op->data.ea->segreg != 0) + yasm__warning(YASM_WARN_GENERAL, bc->line, + N_("skipping prefixes on this instruction")); + imm = yasm_expr_copy(op->data.ea->disp); + yasm_ea_destroy(op->data.ea); + op->type = YASM_INSN__OPERAND_IMM; + op->data.val = imm; + } + } + } + + /* Look for SEG:OFF operands and apply X86_FAR_SEGOFF targetmod. */ + for (i = 0, op = ops[0]; op; op = ops[++i]) { if (op->type == YASM_INSN__OPERAND_IMM && op->targetmod == 0 && yasm_expr_is_op(op->data.val, YASM_EXPR_SEGOFF)) op->targetmod = X86_FAR_SEGOFF; @@ -1969,14 +2068,18 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc, if (num_operands != info->num_operands) continue; + /* Match suffix (if required) */ + if (suffix != 0 && ((suffix<modifiers) == 0) + continue; + if (!operands) { found = 1; /* no operands -> must have a match here. */ break; } /* Match each operand type and size */ - for(i = 0, op = yasm_ops_first(operands); op && inum_operands && - !mismatch; op = yasm_operand_next(op), i++) { + for (i = 0, op = use_ops[0]; op && inum_operands && !mismatch; + op = use_ops[++i]) { /* Check operand type */ switch ((int)(info->operands[i] & OPT_MASK)) { case OPT_Imm: @@ -2140,19 +2243,28 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc, /* Check operand size */ size = size_lookup[(info->operands[i] & OPS_MASK)>>OPS_SHIFT]; - if (op->type == YASM_INSN__OPERAND_REG && op->size == 0) { - /* Register size must exactly match */ - if (yasm_x86__get_reg_size(arch, op->data.reg) != size) + if (suffix != 0) { + /* Require relaxed operands for suffix mode (don't allow + * per-operand sizing). + */ + if ((info->operands[i] & OPT_MASK) == OPT_Imm + && (info->operands[i] & OPS_RMASK) != OPS_Relaxed) mismatch = 1; } else { - if ((info->operands[i] & OPS_RMASK) == OPS_Relaxed) { - /* Relaxed checking */ - if (size != 0 && op->size != size && op->size != 0) + if (op->type == YASM_INSN__OPERAND_REG && op->size == 0) { + /* Register size must exactly match */ + if (yasm_x86__get_reg_size(arch, op->data.reg) != size) mismatch = 1; } else { - /* Strict checking */ - if (op->size != size) - mismatch = 1; + if ((info->operands[i] & OPS_RMASK) == OPS_Relaxed) { + /* Relaxed checking */ + if (size != 0 && op->size != size && op->size != 0) + mismatch = 1; + } else { + /* Strict checking */ + if (op->size != size) + mismatch = 1; + } } } @@ -2318,8 +2430,8 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc, /* Go through operands and assign */ if (operands) { - for(i = 0, op = yasm_ops_first(operands); op && inum_operands; - op = yasm_operand_next(op), i++) { + for (i = 0, op = use_ops[0]; op && inum_operands; + op = use_ops[++i]) { switch ((int)(info->operands[i] & OPA_MASK)) { case OPA_None: /* Throw away the operand contents */ @@ -2674,13 +2786,10 @@ yasm_x86__parse_cpu(yasm_arch *arch, const char *id, unsigned long line) */ } -yasm_arch_check_id_retval -yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], - const char *id, unsigned long line) +static yasm_arch_check_id_retval +yasm_x86__parse_check_targetmod(yasm_arch *arch, unsigned long data[4], + const char *id, unsigned long line) { - yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; - const char *oid = id; - /*const char *marker;*/ /*!re2c /* target modifiers */ N E A R { @@ -2700,6 +2809,24 @@ yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], return YASM_ARCH_CHECK_ID_TARGETMOD; } + /* catchalls */ + [\001-\377]+ { + return YASM_ARCH_CHECK_ID_NONE; + } + [\000] { + return YASM_ARCH_CHECK_ID_NONE; + } + */ + return YASM_ARCH_CHECK_ID_NONE; +} + +static yasm_arch_check_id_retval +yasm_x86__parse_check_prefix(yasm_arch *arch, unsigned long data[4], + const char *id, unsigned long line) +{ + yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; + const char *oid = id; + /*!re2c /* operand size overrides */ O "16" { data[0] = X86_OPERSIZE; @@ -2780,6 +2907,24 @@ yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], return YASM_ARCH_CHECK_ID_PREFIX; } + /* catchalls */ + [\001-\377]+ { + return YASM_ARCH_CHECK_ID_NONE; + } + [\000] { + return YASM_ARCH_CHECK_ID_NONE; + } + */ + return YASM_ARCH_CHECK_ID_NONE; +} + +static yasm_arch_check_id_retval +yasm_x86__parse_check_reg(yasm_arch *arch, unsigned long data[4], + const char *id, unsigned long line) +{ + yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; + const char *oid = id; + /*!re2c /* control, debug, and test registers */ C R [02-48] { if (arch_x86->mode_bits != 64 && oid[2] == '8') { @@ -2804,10 +2949,24 @@ yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], data[0] = X86_FPUREG | (oid[2]-'0'); return YASM_ARCH_CHECK_ID_REG; } + S T { + if (arch_x86->parser == X86_PARSER_GAS) { + data[0] = X86_FPUREG; + return YASM_ARCH_CHECK_ID_REGGROUP; + } else + return YASM_ARCH_CHECK_ID_NONE; + } M M [0-7] { data[0] = X86_MMXREG | (oid[2]-'0'); return YASM_ARCH_CHECK_ID_REG; } + M M { + if (arch_x86->parser == X86_PARSER_GAS) { + data[0] = X86_MMXREG; + return YASM_ARCH_CHECK_ID_REGGROUP; + } else + return YASM_ARCH_CHECK_ID_NONE; + } X M M [0-9] { if (arch_x86->mode_bits != 64 && (oid[3] == '8' || oid[3] == '9')) { @@ -2827,6 +2986,13 @@ yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], data[0] = X86_XMMREG | (10+oid[4]-'0'); return YASM_ARCH_CHECK_ID_REG; } + X M M { + if (arch_x86->parser == X86_PARSER_GAS) { + data[0] = X86_XMMREG; + return YASM_ARCH_CHECK_ID_REGGROUP; + } else + return YASM_ARCH_CHECK_ID_NONE; + } /* integer registers */ R A X { @@ -3074,941 +3240,859 @@ yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], return YASM_ARCH_CHECK_ID_REG; } + /* catchalls */ + [\001-\377]+ { + return YASM_ARCH_CHECK_ID_NONE; + } + [\000] { + return YASM_ARCH_CHECK_ID_NONE; + } + */ + return YASM_ARCH_CHECK_ID_NONE; +} + +#define RET_INSN(nosuffixsize, group, mod, cpu) do { \ + suffix = (id-oid) > nosuffixsize; \ + DEF_INSN_DATA(group, mod, cpu); \ + goto done; \ + } while (0) + +/* No suffix version of RET_INSN */ +#define RET_INSN_NS(group, mod, cpu) do { \ + DEF_INSN_DATA(group, mod, cpu); \ + goto done; \ + } while (0) + +#define RET_INSN_GAS(nosuffixsize, group, mod, cpu) do { \ + if (arch_x86->parser != X86_PARSER_GAS) \ + return YASM_ARCH_CHECK_ID_NONE; \ + RET_INSN(nosuffixsize, group, mod, cpu); \ + } while (0) + +#define RET_INSN_NONGAS(nosuffixsize, group, mod, cpu) do { \ + if (arch_x86->parser == X86_PARSER_GAS) \ + return YASM_ARCH_CHECK_ID_NONE; \ + RET_INSN(nosuffixsize, group, mod, cpu); \ + } while (0) + +static yasm_arch_check_id_retval +yasm_x86__parse_check_insn(yasm_arch *arch, unsigned long data[4], + const char *id, unsigned long line) +{ + yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; + const char *oid = id; + /*const char *marker;*/ + int suffix = 0; + int not64 = 0; + int warn64 = 0; + + /*!re2c /* instructions */ /* Move */ - M O V { RET_INSN(mov, 0, CPU_Any); } + M O V [bBwWlLqQ]? { RET_INSN(3, mov, 0, CPU_Any); } + M O V A B S [bBwWlLqQ]? { RET_INSN_GAS(6, movabs, 0, CPU_Hammer|CPU_64); } /* Move with sign/zero extend */ - M O V S X { RET_INSN(movszx, 0xBE, CPU_386); } + M O V S X [bBwWlL]? { RET_INSN(5, movszx, 0xBE, CPU_386); } M O V S X D { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(movsxd, 0, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(6, movsxd, 0, CPU_Hammer|CPU_64); } - M O V Z X { RET_INSN(movszx, 0xB6, CPU_386); } + M O V Z X { RET_INSN(5, movszx, 0xB6, CPU_386); } /* Push instructions */ - P U S H { RET_INSN(push, 0, CPU_Any); } + P U S H [wWlLqQ]? { RET_INSN(4, push, 0, CPU_Any); } P U S H A { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x0060, CPU_186); + not64 = 1; + RET_INSN(5, onebyte, 0x0060, CPU_186); } P U S H A D { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x2060, CPU_386); + not64 = 1; + RET_INSN(6, onebyte, 0x2060, CPU_386); } P U S H A W { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x1060, CPU_186); + not64 = 1; + RET_INSN(6, onebyte, 0x1060, CPU_186); } /* Pop instructions */ - P O P { RET_INSN(pop, 0, CPU_Any); } + P O P [wWlLqQ]? { RET_INSN(3, pop, 0, CPU_Any); } P O P A { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x0061, CPU_186); + not64 = 1; + RET_INSN(4, onebyte, 0x0061, CPU_186); } P O P A D { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x2061, CPU_386); + not64 = 1; + RET_INSN(5, onebyte, 0x2061, CPU_386); + } + P O P A L { + not64 = 1; + RET_INSN_GAS(5, onebyte, 0x2061, CPU_386); } P O P A W { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x1061, CPU_186); + not64 = 1; + RET_INSN(5, onebyte, 0x1061, CPU_186); } /* Exchange */ - X C H G { RET_INSN(xchg, 0, CPU_Any); } + X C H G { RET_INSN(4, xchg, 0, CPU_Any); } /* In/out from ports */ - I N { RET_INSN(in, 0, CPU_Any); } - O U T { RET_INSN(out, 0, CPU_Any); } + I N { RET_INSN(2, in, 0, CPU_Any); } + O U T { RET_INSN(3, out, 0, CPU_Any); } /* Load effective address */ - L E A { RET_INSN(lea, 0, CPU_Any); } + L E A [wWlLqQ]? { RET_INSN(3, lea, 0, CPU_Any); } /* Load segment registers from memory */ L D S { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(ldes, 0xC5, CPU_Any); + not64 = 1; + RET_INSN(3, ldes, 0xC5, CPU_Any); } L E S { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(ldes, 0xC4, CPU_Any); + not64 = 1; + RET_INSN(3, ldes, 0xC4, CPU_Any); } - L F S { RET_INSN(lfgss, 0xB4, CPU_386); } - L G S { RET_INSN(lfgss, 0xB5, CPU_386); } - L S S { RET_INSN(lfgss, 0xB2, CPU_386); } + L F S { RET_INSN(3, lfgss, 0xB4, CPU_386); } + L G S { RET_INSN(3, lfgss, 0xB5, CPU_386); } + L S S { RET_INSN(3, lfgss, 0xB2, CPU_386); } /* Flags register instructions */ - C L C { RET_INSN(onebyte, 0x00F8, CPU_Any); } - C L D { RET_INSN(onebyte, 0x00FC, CPU_Any); } - C L I { RET_INSN(onebyte, 0x00FA, CPU_Any); } - C L T S { RET_INSN(twobyte, 0x0F06, CPU_286|CPU_Priv); } - C M C { RET_INSN(onebyte, 0x00F5, CPU_Any); } + C L C { RET_INSN(3, onebyte, 0x00F8, CPU_Any); } + C L D { RET_INSN(3, onebyte, 0x00FC, CPU_Any); } + C L I { RET_INSN(3, onebyte, 0x00FA, CPU_Any); } + C L T S { RET_INSN(4, twobyte, 0x0F06, CPU_286|CPU_Priv); } + C M C { RET_INSN(3, onebyte, 0x00F5, CPU_Any); } L A H F { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x009F, CPU_Any); + not64 = 1; + RET_INSN(4, onebyte, 0x009F, CPU_Any); } S A H F { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x009E, CPU_Any); + not64 = 1; + RET_INSN(4, onebyte, 0x009E, CPU_Any); } - P U S H F { RET_INSN(onebyte, 0x009C, CPU_Any); } - P U S H F D { RET_INSN(onebyte, 0x209C, CPU_386); } - P U S H F W { RET_INSN(onebyte, 0x109C, CPU_Any); } + P U S H F { RET_INSN(5, onebyte, 0x009C, CPU_Any); } + P U S H F D { RET_INSN_NONGAS(6, onebyte, 0x209C, CPU_386); } + P U S H F W { RET_INSN(6, onebyte, 0x109C, CPU_Any); } P U S H F Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x409C, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(6, onebyte, 0x409C, CPU_Hammer|CPU_64); } - P O P F { RET_INSN(onebyte, 0x40009D, CPU_Any); } + P O P F { RET_INSN(4, onebyte, 0x40009D, CPU_Any); } P O P F D { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x00209D, CPU_386); + not64 = 1; + RET_INSN(5, onebyte, 0x00209D, CPU_386); } - P O P F W { RET_INSN(onebyte, 0x40109D, CPU_Any); } + P O P F W { RET_INSN(5, onebyte, 0x40109D, CPU_Any); } P O P F Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x40409D, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(5, onebyte, 0x40409D, CPU_Hammer|CPU_64); } - S T C { RET_INSN(onebyte, 0x00F9, CPU_Any); } - S T D { RET_INSN(onebyte, 0x00FD, CPU_Any); } - S T I { RET_INSN(onebyte, 0x00FB, CPU_Any); } + S T C { RET_INSN(3, onebyte, 0x00F9, CPU_Any); } + S T D { RET_INSN(3, onebyte, 0x00FD, CPU_Any); } + S T I { RET_INSN(3, onebyte, 0x00FB, CPU_Any); } /* Arithmetic */ - A D D { RET_INSN(arith, 0x0000, CPU_Any); } - I N C { RET_INSN(incdec, 0x0040, CPU_Any); } - S U B { RET_INSN(arith, 0x0528, CPU_Any); } - D E C { RET_INSN(incdec, 0x0148, CPU_Any); } - S B B { RET_INSN(arith, 0x0318, CPU_Any); } - C M P { RET_INSN(arith, 0x0738, CPU_Any); } - T E S T { RET_INSN(test, 0, CPU_Any); } - A N D { RET_INSN(arith, 0x0420, CPU_Any); } - O R { RET_INSN(arith, 0x0108, CPU_Any); } - X O R { RET_INSN(arith, 0x0630, CPU_Any); } - A D C { RET_INSN(arith, 0x0210, CPU_Any); } - N E G { RET_INSN(f6, 0x03, CPU_Any); } - N O T { RET_INSN(f6, 0x02, CPU_Any); } + A D D [bBwWlLqQ]? { RET_INSN(3, arith, 0x0000, CPU_Any); } + I N C [bBwWlLqQ]? { RET_INSN(3, incdec, 0x0040, CPU_Any); } + S U B [bBwWlLqQ]? { RET_INSN(3, arith, 0x0528, CPU_Any); } + D E C [bBwWlLqQ]? { RET_INSN(3, incdec, 0x0148, CPU_Any); } + S B B [bBwWlLqQ]? { RET_INSN(3, arith, 0x0318, CPU_Any); } + C M P [bBwWlLqQ]? { RET_INSN(3, arith, 0x0738, CPU_Any); } + T E S T [bBwWlLqQ]? { RET_INSN(4, test, 0, CPU_Any); } + A N D [bBwWlLqQ]? { RET_INSN(3, arith, 0x0420, CPU_Any); } + O R [bBwWlLqQ]? { RET_INSN(2, arith, 0x0108, CPU_Any); } + X O R [bBwWlLqQ]? { RET_INSN(3, arith, 0x0630, CPU_Any); } + A D C [bBwWlLqQ]? { RET_INSN(3, arith, 0x0210, CPU_Any); } + N E G [bBwWlLqQ]? { RET_INSN(3, f6, 0x03, CPU_Any); } + N O T [bBwWlLqQ]? { RET_INSN(3, f6, 0x02, CPU_Any); } A A A { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x0037, CPU_Any); + not64 = 1; + RET_INSN(3, onebyte, 0x0037, CPU_Any); } A A S { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x003F, CPU_Any); + not64 = 1; + RET_INSN(3, onebyte, 0x003F, CPU_Any); } D A A { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x0027, CPU_Any); + not64 = 1; + RET_INSN(3, onebyte, 0x0027, CPU_Any); } D A S { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x002F, CPU_Any); + not64 = 1; + RET_INSN(3, onebyte, 0x002F, CPU_Any); } A A D { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(aadm, 0x01, CPU_Any); + not64 = 1; + RET_INSN(3, aadm, 0x01, CPU_Any); } A A M { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(aadm, 0x00, CPU_Any); + not64 = 1; + RET_INSN(3, aadm, 0x00, CPU_Any); } /* Conversion instructions */ - C B W { RET_INSN(onebyte, 0x1098, CPU_Any); } - C W D E { RET_INSN(onebyte, 0x2098, CPU_386); } + C B W { RET_INSN(3, onebyte, 0x1098, CPU_Any); } + C W D E { RET_INSN(4, onebyte, 0x2098, CPU_386); } C D Q E { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x4098, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(4, onebyte, 0x4098, CPU_Hammer|CPU_64); } - C W D { RET_INSN(onebyte, 0x1099, CPU_Any); } - C D Q { RET_INSN(onebyte, 0x2099, CPU_386); } + C W D { RET_INSN(3, onebyte, 0x1099, CPU_Any); } + C D Q { RET_INSN(3, onebyte, 0x2099, CPU_386); } C D O { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x4099, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(3, onebyte, 0x4099, CPU_Hammer|CPU_64); } /* Multiplication and division */ - M U L { RET_INSN(f6, 0x04, CPU_Any); } - I M U L { RET_INSN(imul, 0, CPU_Any); } - D I V { RET_INSN(f6, 0x06, CPU_Any); } - I D I V { RET_INSN(f6, 0x07, CPU_Any); } + M U L { RET_INSN(3, f6, 0x04, CPU_Any); } + I M U L { RET_INSN(4, imul, 0, CPU_Any); } + D I V { RET_INSN(3, f6, 0x06, CPU_Any); } + I D I V { RET_INSN(4, f6, 0x07, CPU_Any); } /* Shifts */ - R O L { RET_INSN(shift, 0x00, CPU_Any); } - R O R { RET_INSN(shift, 0x01, CPU_Any); } - R C L { RET_INSN(shift, 0x02, CPU_Any); } - R C R { RET_INSN(shift, 0x03, CPU_Any); } - S A L { RET_INSN(shift, 0x04, CPU_Any); } - S H L { RET_INSN(shift, 0x04, CPU_Any); } - S H R { RET_INSN(shift, 0x05, CPU_Any); } - S A R { RET_INSN(shift, 0x07, CPU_Any); } - S H L D { RET_INSN(shlrd, 0xA4, CPU_386); } - S H R D { RET_INSN(shlrd, 0xAC, CPU_386); } + R O L { RET_INSN(3, shift, 0x00, CPU_Any); } + R O R { RET_INSN(3, shift, 0x01, CPU_Any); } + R C L { RET_INSN(3, shift, 0x02, CPU_Any); } + R C R { RET_INSN(3, shift, 0x03, CPU_Any); } + S A L { RET_INSN(3, shift, 0x04, CPU_Any); } + S H L { RET_INSN(3, shift, 0x04, CPU_Any); } + S H R { RET_INSN(3, shift, 0x05, CPU_Any); } + S A R { RET_INSN(3, shift, 0x07, CPU_Any); } + S H L D { RET_INSN(4, shlrd, 0xA4, CPU_386); } + S H R D { RET_INSN(4, shlrd, 0xAC, CPU_386); } /* Control transfer instructions (unconditional) */ - C A L L { RET_INSN(call, 0, CPU_Any); } - J M P { RET_INSN(jmp, 0, CPU_Any); } - R E T { RET_INSN(retnf, 0xC2, CPU_Any); } - R E T N { RET_INSN(retnf, 0xC2, CPU_Any); } - R E T F { RET_INSN(retnf, 0xCA, CPU_Any); } - E N T E R { RET_INSN(enter, 0, CPU_186); } - L E A V E { RET_INSN(onebyte, 0x4000C9, CPU_186); } + C A L L { RET_INSN(4, call, 0, CPU_Any); } + J M P { RET_INSN(3, jmp, 0, CPU_Any); } + R E T { RET_INSN(3, retnf, 0xC2, CPU_Any); } + R E T N { RET_INSN(4, retnf, 0xC2, CPU_Any); } + R E T F { RET_INSN(4, retnf, 0xCA, CPU_Any); } + E N T E R { RET_INSN(5, enter, 0, CPU_186); } + L E A V E { RET_INSN(5, onebyte, 0x4000C9, CPU_186); } /* Conditional jumps */ - J O { RET_INSN(jcc, 0x00, CPU_Any); } - J N O { RET_INSN(jcc, 0x01, CPU_Any); } - J B { RET_INSN(jcc, 0x02, CPU_Any); } - J C { RET_INSN(jcc, 0x02, CPU_Any); } - J N A E { RET_INSN(jcc, 0x02, CPU_Any); } - J N B { RET_INSN(jcc, 0x03, CPU_Any); } - J N C { RET_INSN(jcc, 0x03, CPU_Any); } - J A E { RET_INSN(jcc, 0x03, CPU_Any); } - J E { RET_INSN(jcc, 0x04, CPU_Any); } - J Z { RET_INSN(jcc, 0x04, CPU_Any); } - J N E { RET_INSN(jcc, 0x05, CPU_Any); } - J N Z { RET_INSN(jcc, 0x05, CPU_Any); } - J B E { RET_INSN(jcc, 0x06, CPU_Any); } - J N A { RET_INSN(jcc, 0x06, CPU_Any); } - J N B E { RET_INSN(jcc, 0x07, CPU_Any); } - J A { RET_INSN(jcc, 0x07, CPU_Any); } - J S { RET_INSN(jcc, 0x08, CPU_Any); } - J N S { RET_INSN(jcc, 0x09, CPU_Any); } - J P { RET_INSN(jcc, 0x0A, CPU_Any); } - J P E { RET_INSN(jcc, 0x0A, CPU_Any); } - J N P { RET_INSN(jcc, 0x0B, CPU_Any); } - J P O { RET_INSN(jcc, 0x0B, CPU_Any); } - J L { RET_INSN(jcc, 0x0C, CPU_Any); } - J N G E { RET_INSN(jcc, 0x0C, CPU_Any); } - J N L { RET_INSN(jcc, 0x0D, CPU_Any); } - J G E { RET_INSN(jcc, 0x0D, CPU_Any); } - J L E { RET_INSN(jcc, 0x0E, CPU_Any); } - J N G { RET_INSN(jcc, 0x0E, CPU_Any); } - J N L E { RET_INSN(jcc, 0x0F, CPU_Any); } - J G { RET_INSN(jcc, 0x0F, CPU_Any); } - J C X Z { RET_INSN(jcxz, 16, CPU_Any); } - J E C X Z { RET_INSN(jcxz, 32, CPU_386); } + J O { RET_INSN(2, jcc, 0x00, CPU_Any); } + J N O { RET_INSN(3, jcc, 0x01, CPU_Any); } + J B { RET_INSN(2, jcc, 0x02, CPU_Any); } + J C { RET_INSN(2, jcc, 0x02, CPU_Any); } + J N A E { RET_INSN(4, jcc, 0x02, CPU_Any); } + J N B { RET_INSN(3, jcc, 0x03, CPU_Any); } + J N C { RET_INSN(3, jcc, 0x03, CPU_Any); } + J A E { RET_INSN(3, jcc, 0x03, CPU_Any); } + J E { RET_INSN(2, jcc, 0x04, CPU_Any); } + J Z { RET_INSN(2, jcc, 0x04, CPU_Any); } + J N E { RET_INSN(3, jcc, 0x05, CPU_Any); } + J N Z { RET_INSN(3, jcc, 0x05, CPU_Any); } + J B E { RET_INSN(3, jcc, 0x06, CPU_Any); } + J N A { RET_INSN(3, jcc, 0x06, CPU_Any); } + J N B E { RET_INSN(4, jcc, 0x07, CPU_Any); } + J A { RET_INSN(2, jcc, 0x07, CPU_Any); } + J S { RET_INSN(2, jcc, 0x08, CPU_Any); } + J N S { RET_INSN(3, jcc, 0x09, CPU_Any); } + J P { RET_INSN(2, jcc, 0x0A, CPU_Any); } + J P E { RET_INSN(3, jcc, 0x0A, CPU_Any); } + J N P { RET_INSN(3, jcc, 0x0B, CPU_Any); } + J P O { RET_INSN(3, jcc, 0x0B, CPU_Any); } + J L { RET_INSN(2, jcc, 0x0C, CPU_Any); } + J N G E { RET_INSN(4, jcc, 0x0C, CPU_Any); } + J N L { RET_INSN(3, jcc, 0x0D, CPU_Any); } + J G E { RET_INSN(3, jcc, 0x0D, CPU_Any); } + J L E { RET_INSN(3, jcc, 0x0E, CPU_Any); } + J N G { RET_INSN(3, jcc, 0x0E, CPU_Any); } + J N L E { RET_INSN(3, jcc, 0x0F, CPU_Any); } + J G { RET_INSN(2, jcc, 0x0F, CPU_Any); } + J C X Z { RET_INSN(4, jcxz, 16, CPU_Any); } + J E C X Z { RET_INSN(5, jcxz, 32, CPU_386); } J R C X Z { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(jcxz, 64, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(5, jcxz, 64, CPU_Hammer|CPU_64); } /* Loop instructions */ - L O O P { RET_INSN(loop, 0x02, CPU_Any); } - L O O P Z { RET_INSN(loop, 0x01, CPU_Any); } - L O O P E { RET_INSN(loop, 0x01, CPU_Any); } - L O O P N Z { RET_INSN(loop, 0x00, CPU_Any); } - L O O P N E { RET_INSN(loop, 0x00, CPU_Any); } + L O O P { RET_INSN(4, loop, 0x02, CPU_Any); } + L O O P Z { RET_INSN(5, loop, 0x01, CPU_Any); } + L O O P E { RET_INSN(5, loop, 0x01, CPU_Any); } + L O O P N Z { RET_INSN(6, loop, 0x00, CPU_Any); } + L O O P N E { RET_INSN(6, loop, 0x00, CPU_Any); } /* Set byte on flag instructions */ - S E T O { RET_INSN(setcc, 0x00, CPU_386); } - S E T N O { RET_INSN(setcc, 0x01, CPU_386); } - S E T B { RET_INSN(setcc, 0x02, CPU_386); } - S E T C { RET_INSN(setcc, 0x02, CPU_386); } - S E T N A E { RET_INSN(setcc, 0x02, CPU_386); } - S E T N B { RET_INSN(setcc, 0x03, CPU_386); } - S E T N C { RET_INSN(setcc, 0x03, CPU_386); } - S E T A E { RET_INSN(setcc, 0x03, CPU_386); } - S E T E { RET_INSN(setcc, 0x04, CPU_386); } - S E T Z { RET_INSN(setcc, 0x04, CPU_386); } - S E T N E { RET_INSN(setcc, 0x05, CPU_386); } - S E T N Z { RET_INSN(setcc, 0x05, CPU_386); } - S E T B E { RET_INSN(setcc, 0x06, CPU_386); } - S E T N A { RET_INSN(setcc, 0x06, CPU_386); } - S E T N B E { RET_INSN(setcc, 0x07, CPU_386); } - S E T A { RET_INSN(setcc, 0x07, CPU_386); } - S E T S { RET_INSN(setcc, 0x08, CPU_386); } - S E T N S { RET_INSN(setcc, 0x09, CPU_386); } - S E T P { RET_INSN(setcc, 0x0A, CPU_386); } - S E T P E { RET_INSN(setcc, 0x0A, CPU_386); } - S E T N P { RET_INSN(setcc, 0x0B, CPU_386); } - S E T P O { RET_INSN(setcc, 0x0B, CPU_386); } - S E T L { RET_INSN(setcc, 0x0C, CPU_386); } - S E T N G E { RET_INSN(setcc, 0x0C, CPU_386); } - S E T N L { RET_INSN(setcc, 0x0D, CPU_386); } - S E T G E { RET_INSN(setcc, 0x0D, CPU_386); } - S E T L E { RET_INSN(setcc, 0x0E, CPU_386); } - S E T N G { RET_INSN(setcc, 0x0E, CPU_386); } - S E T N L E { RET_INSN(setcc, 0x0F, CPU_386); } - S E T G { RET_INSN(setcc, 0x0F, CPU_386); } + S E T O { RET_INSN(4, setcc, 0x00, CPU_386); } + S E T N O { RET_INSN(5, setcc, 0x01, CPU_386); } + S E T B { RET_INSN(4, setcc, 0x02, CPU_386); } + S E T C { RET_INSN(4, setcc, 0x02, CPU_386); } + S E T N A E { RET_INSN(6, setcc, 0x02, CPU_386); } + S E T N B { RET_INSN(5, setcc, 0x03, CPU_386); } + S E T N C { RET_INSN(5, setcc, 0x03, CPU_386); } + S E T A E { RET_INSN(5, setcc, 0x03, CPU_386); } + S E T E { RET_INSN(4, setcc, 0x04, CPU_386); } + S E T Z { RET_INSN(4, setcc, 0x04, CPU_386); } + S E T N E { RET_INSN(5, setcc, 0x05, CPU_386); } + S E T N Z { RET_INSN(5, setcc, 0x05, CPU_386); } + S E T B E { RET_INSN(5, setcc, 0x06, CPU_386); } + S E T N A { RET_INSN(5, setcc, 0x06, CPU_386); } + S E T N B E { RET_INSN(6, setcc, 0x07, CPU_386); } + S E T A { RET_INSN(4, setcc, 0x07, CPU_386); } + S E T S { RET_INSN(4, setcc, 0x08, CPU_386); } + S E T N S { RET_INSN(5, setcc, 0x09, CPU_386); } + S E T P { RET_INSN(4, setcc, 0x0A, CPU_386); } + S E T P E { RET_INSN(5, setcc, 0x0A, CPU_386); } + S E T N P { RET_INSN(5, setcc, 0x0B, CPU_386); } + S E T P O { RET_INSN(5, setcc, 0x0B, CPU_386); } + S E T L { RET_INSN(4, setcc, 0x0C, CPU_386); } + S E T N G E { RET_INSN(6, setcc, 0x0C, CPU_386); } + S E T N L { RET_INSN(5, setcc, 0x0D, CPU_386); } + S E T G E { RET_INSN(5, setcc, 0x0D, CPU_386); } + S E T L E { RET_INSN(5, setcc, 0x0E, CPU_386); } + S E T N G { RET_INSN(5, setcc, 0x0E, CPU_386); } + S E T N L E { RET_INSN(6, setcc, 0x0F, CPU_386); } + S E T G { RET_INSN(4, setcc, 0x0F, CPU_386); } /* String instructions. */ - C M P S B { RET_INSN(onebyte, 0x00A6, CPU_Any); } - C M P S W { RET_INSN(onebyte, 0x10A7, CPU_Any); } - C M P S D { RET_INSN(cmpsd, 0, CPU_Any); } + C M P S B { RET_INSN(5, onebyte, 0x00A6, CPU_Any); } + C M P S W { RET_INSN(5, onebyte, 0x10A7, CPU_Any); } + C M P S D { RET_INSN(5, cmpsd, 0, CPU_Any); } C M P S Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x40A7, CPU_Hammer|CPU_64); - } - I N S B { RET_INSN(onebyte, 0x006C, CPU_Any); } - I N S W { RET_INSN(onebyte, 0x106D, CPU_Any); } - I N S D { RET_INSN(onebyte, 0x206D, CPU_386); } - O U T S B { RET_INSN(onebyte, 0x006E, CPU_Any); } - O U T S W { RET_INSN(onebyte, 0x106F, CPU_Any); } - O U T S D { RET_INSN(onebyte, 0x206F, CPU_386); } - L O D S B { RET_INSN(onebyte, 0x00AC, CPU_Any); } - L O D S W { RET_INSN(onebyte, 0x10AD, CPU_Any); } - L O D S D { RET_INSN(onebyte, 0x20AD, CPU_386); } + warn64 = 1; + RET_INSN(5, onebyte, 0x40A7, CPU_Hammer|CPU_64); + } + I N S B { RET_INSN(4, onebyte, 0x006C, CPU_Any); } + I N S W { RET_INSN(4, onebyte, 0x106D, CPU_Any); } + I N S D { RET_INSN(4, onebyte, 0x206D, CPU_386); } + O U T S B { RET_INSN(5, onebyte, 0x006E, CPU_Any); } + O U T S W { RET_INSN(5, onebyte, 0x106F, CPU_Any); } + O U T S D { RET_INSN(5, onebyte, 0x206F, CPU_386); } + L O D S B { RET_INSN(5, onebyte, 0x00AC, CPU_Any); } + L O D S W { RET_INSN(5, onebyte, 0x10AD, CPU_Any); } + L O D S D { RET_INSN(5, onebyte, 0x20AD, CPU_386); } L O D S Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x40AD, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(5, onebyte, 0x40AD, CPU_Hammer|CPU_64); } - M O V S B { RET_INSN(onebyte, 0x00A4, CPU_Any); } - M O V S W { RET_INSN(onebyte, 0x10A5, CPU_Any); } - M O V S D { RET_INSN(movsd, 0, CPU_Any); } + M O V S B { RET_INSN(5, onebyte, 0x00A4, CPU_Any); } + M O V S W { RET_INSN(5, onebyte, 0x10A5, CPU_Any); } + M O V S D { RET_INSN(5, movsd, 0, CPU_Any); } M O V S Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x40A5, CPU_Any); + warn64 = 1; + RET_INSN(5, onebyte, 0x40A5, CPU_Any); } - S C A S B { RET_INSN(onebyte, 0x00AE, CPU_Any); } - S C A S W { RET_INSN(onebyte, 0x10AF, CPU_Any); } - S C A S D { RET_INSN(onebyte, 0x20AF, CPU_386); } + S C A S B { RET_INSN(5, onebyte, 0x00AE, CPU_Any); } + S C A S W { RET_INSN(5, onebyte, 0x10AF, CPU_Any); } + S C A S D { RET_INSN(5, onebyte, 0x20AF, CPU_386); } S C A S Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x40AF, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(5, onebyte, 0x40AF, CPU_Hammer|CPU_64); } - S T O S B { RET_INSN(onebyte, 0x00AA, CPU_Any); } - S T O S W { RET_INSN(onebyte, 0x10AB, CPU_Any); } - S T O S D { RET_INSN(onebyte, 0x20AB, CPU_386); } + S T O S B { RET_INSN(5, onebyte, 0x00AA, CPU_Any); } + S T O S W { RET_INSN(5, onebyte, 0x10AB, CPU_Any); } + S T O S D { RET_INSN(5, onebyte, 0x20AB, CPU_386); } S T O S Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x40AB, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(5, onebyte, 0x40AB, CPU_Hammer|CPU_64); } - X L A T B? { RET_INSN(onebyte, 0x00D7, CPU_Any); } + X L A T B? { RET_INSN(5, onebyte, 0x00D7, CPU_Any); } /* Bit manipulation */ - B S F { RET_INSN(bsfr, 0xBC, CPU_386); } - B S R { RET_INSN(bsfr, 0xBD, CPU_386); } - B T { RET_INSN(bittest, 0x04A3, CPU_386); } - B T C { RET_INSN(bittest, 0x07BB, CPU_386); } - B T R { RET_INSN(bittest, 0x06B3, CPU_386); } - B T S { RET_INSN(bittest, 0x05AB, CPU_386); } + B S F { RET_INSN(3, bsfr, 0xBC, CPU_386); } + B S R { RET_INSN(3, bsfr, 0xBD, CPU_386); } + B T { RET_INSN(2, bittest, 0x04A3, CPU_386); } + B T C { RET_INSN(3, bittest, 0x07BB, CPU_386); } + B T R { RET_INSN(3, bittest, 0x06B3, CPU_386); } + B T S { RET_INSN(3, bittest, 0x05AB, CPU_386); } /* Interrupts and operating system instructions */ - I N T { RET_INSN(int, 0, CPU_Any); } - I N T "3" { RET_INSN(onebyte, 0x00CC, CPU_Any); } - I N T "03" { RET_INSN(onebyte, 0x00CC, CPU_Any); } + I N T { RET_INSN(3, int, 0, CPU_Any); } + I N T "3" { RET_INSN(4, onebyte, 0x00CC, CPU_Any); } + I N T "03" { RET_INSN(5, onebyte, 0x00CC, CPU_Any); } I N T O { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x00CE, CPU_Any); + not64 = 1; + RET_INSN(4, onebyte, 0x00CE, CPU_Any); } - I R E T { RET_INSN(onebyte, 0x00CF, CPU_Any); } - I R E T W { RET_INSN(onebyte, 0x10CF, CPU_Any); } - I R E T D { RET_INSN(onebyte, 0x20CF, CPU_386); } + I R E T { RET_INSN(4, onebyte, 0x00CF, CPU_Any); } + I R E T W { RET_INSN(5, onebyte, 0x10CF, CPU_Any); } + I R E T D { RET_INSN(5, onebyte, 0x20CF, CPU_386); } I R E T Q { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(onebyte, 0x40CF, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(5, onebyte, 0x40CF, CPU_Hammer|CPU_64); } - R S M { RET_INSN(twobyte, 0x0FAA, CPU_586|CPU_SMM); } + R S M { RET_INSN(3, twobyte, 0x0FAA, CPU_586|CPU_SMM); } B O U N D { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(bound, 0, CPU_186); + not64 = 1; + RET_INSN(5, bound, 0, CPU_186); } - H L T { RET_INSN(onebyte, 0x00F4, CPU_Priv); } - N O P { RET_INSN(onebyte, 0x0090, CPU_Any); } + H L T { RET_INSN(3, onebyte, 0x00F4, CPU_Priv); } + N O P { RET_INSN(3, onebyte, 0x0090, CPU_Any); } /* Protection control */ A R P L { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(arpl, 0, CPU_286|CPU_Prot); - } - L A R { RET_INSN(bsfr, 0x02, CPU_286|CPU_Prot); } - L G D T { RET_INSN(twobytemem, 0x020F01, CPU_286|CPU_Priv); } - L I D T { RET_INSN(twobytemem, 0x030F01, CPU_286|CPU_Priv); } - L L D T { RET_INSN(prot286, 0x0200, CPU_286|CPU_Prot|CPU_Priv); } - L M S W { RET_INSN(prot286, 0x0601, CPU_286|CPU_Priv); } - L S L { RET_INSN(bsfr, 0x03, CPU_286|CPU_Prot); } - L T R { RET_INSN(prot286, 0x0300, CPU_286|CPU_Prot|CPU_Priv); } - S G D T { RET_INSN(twobytemem, 0x000F01, CPU_286|CPU_Priv); } - S I D T { RET_INSN(twobytemem, 0x010F01, CPU_286|CPU_Priv); } - S L D T { RET_INSN(sldtmsw, 0x0000, CPU_286); } - S M S W { RET_INSN(sldtmsw, 0x0401, CPU_286); } - S T R { RET_INSN(str, 0, CPU_286|CPU_Prot); } - V E R R { RET_INSN(prot286, 0x0400, CPU_286|CPU_Prot); } - V E R W { RET_INSN(prot286, 0x0500, CPU_286|CPU_Prot); } + not64 = 1; + RET_INSN(4, arpl, 0, CPU_286|CPU_Prot); + } + L A R { RET_INSN(3, bsfr, 0x02, CPU_286|CPU_Prot); } + L G D T { RET_INSN(4, twobytemem, 0x020F01, CPU_286|CPU_Priv); } + L I D T { RET_INSN(4, twobytemem, 0x030F01, CPU_286|CPU_Priv); } + L L D T { RET_INSN(4, prot286, 0x0200, CPU_286|CPU_Prot|CPU_Priv); } + L M S W { RET_INSN(4, prot286, 0x0601, CPU_286|CPU_Priv); } + L S L { RET_INSN(3, bsfr, 0x03, CPU_286|CPU_Prot); } + L T R { RET_INSN(3, prot286, 0x0300, CPU_286|CPU_Prot|CPU_Priv); } + S G D T { RET_INSN(4, twobytemem, 0x000F01, CPU_286|CPU_Priv); } + S I D T { RET_INSN(4, twobytemem, 0x010F01, CPU_286|CPU_Priv); } + S L D T { RET_INSN(4, sldtmsw, 0x0000, CPU_286); } + S M S W { RET_INSN(4, sldtmsw, 0x0401, CPU_286); } + S T R { RET_INSN(3, str, 0, CPU_286|CPU_Prot); } + V E R R { RET_INSN(4, prot286, 0x0400, CPU_286|CPU_Prot); } + V E R W { RET_INSN(4, prot286, 0x0500, CPU_286|CPU_Prot); } /* Floating point instructions */ - F L D { RET_INSN(fldstp, 0x0500C0, CPU_FPU); } - F I L D { RET_INSN(fildstp, 0x050200, CPU_FPU); } - F B L D { RET_INSN(fbldstp, 0x04, CPU_FPU); } - F S T { RET_INSN(fst, 0, CPU_FPU); } - F I S T { RET_INSN(fiarith, 0x02DB, CPU_FPU); } - F S T P { RET_INSN(fldstp, 0x0703D8, CPU_FPU); } - F I S T P { RET_INSN(fildstp, 0x070203, CPU_FPU); } - F B S T P { RET_INSN(fbldstp, 0x06, CPU_FPU); } - F X C H { RET_INSN(fxch, 0, CPU_FPU); } - F C O M { RET_INSN(fcom, 0x02D0, CPU_FPU); } - F I C O M { RET_INSN(fiarith, 0x02DA, CPU_FPU); } - F C O M P { RET_INSN(fcom, 0x03D8, CPU_FPU); } - F I C O M P { RET_INSN(fiarith, 0x03DA, CPU_FPU); } - F C O M P P { RET_INSN(twobyte, 0xDED9, CPU_FPU); } - F U C O M { RET_INSN(fcom2, 0xDDE0, CPU_286|CPU_FPU); } - F U C O M P { RET_INSN(fcom2, 0xDDE8, CPU_286|CPU_FPU); } - F U C O M P P { RET_INSN(twobyte, 0xDAE9, CPU_286|CPU_FPU); } - F T S T { RET_INSN(twobyte, 0xD9E4, CPU_FPU); } - F X A M { RET_INSN(twobyte, 0xD9E5, CPU_FPU); } - F L D "1" { RET_INSN(twobyte, 0xD9E8, CPU_FPU); } - F L D L "2" T { RET_INSN(twobyte, 0xD9E9, CPU_FPU); } - F L D L "2" E { RET_INSN(twobyte, 0xD9EA, CPU_FPU); } - F L D P I { RET_INSN(twobyte, 0xD9EB, CPU_FPU); } - F L D L G "2" { RET_INSN(twobyte, 0xD9EC, CPU_FPU); } - F L D L N "2" { RET_INSN(twobyte, 0xD9ED, CPU_FPU); } - F L D Z { RET_INSN(twobyte, 0xD9EE, CPU_FPU); } - F A D D { RET_INSN(farith, 0x00C0C0, CPU_FPU); } - F A D D P { RET_INSN(farithp, 0xC0, CPU_FPU); } - F I A D D { RET_INSN(fiarith, 0x00DA, CPU_FPU); } - F S U B { RET_INSN(farith, 0x04E0E8, CPU_FPU); } - F I S U B { RET_INSN(fiarith, 0x04DA, CPU_FPU); } - F S U B P { RET_INSN(farithp, 0xE8, CPU_FPU); } - F S U B R { RET_INSN(farith, 0x05E8E0, CPU_FPU); } - F I S U B R { RET_INSN(fiarith, 0x05DA, CPU_FPU); } - F S U B R P { RET_INSN(farithp, 0xE0, CPU_FPU); } - F M U L { RET_INSN(farith, 0x01C8C8, CPU_FPU); } - F I M U L { RET_INSN(fiarith, 0x01DA, CPU_FPU); } - F M U L P { RET_INSN(farithp, 0xC8, CPU_FPU); } - F D I V { RET_INSN(farith, 0x06F0F8, CPU_FPU); } - F I D I V { RET_INSN(fiarith, 0x06DA, CPU_FPU); } - F D I V P { RET_INSN(farithp, 0xF8, CPU_FPU); } - F D I V R { RET_INSN(farith, 0x07F8F0, CPU_FPU); } - F I D I V R { RET_INSN(fiarith, 0x07DA, CPU_FPU); } - F D I V R P { RET_INSN(farithp, 0xF0, CPU_FPU); } - F "2" X M "1" { RET_INSN(twobyte, 0xD9F0, CPU_FPU); } - F Y L "2" X { RET_INSN(twobyte, 0xD9F1, CPU_FPU); } - F P T A N { RET_INSN(twobyte, 0xD9F2, CPU_FPU); } - F P A T A N { RET_INSN(twobyte, 0xD9F3, CPU_FPU); } - F X T R A C T { RET_INSN(twobyte, 0xD9F4, CPU_FPU); } - F P R E M "1" { RET_INSN(twobyte, 0xD9F5, CPU_286|CPU_FPU); } - F D E C S T P { RET_INSN(twobyte, 0xD9F6, CPU_FPU); } - F I N C S T P { RET_INSN(twobyte, 0xD9F7, CPU_FPU); } - F P R E M { RET_INSN(twobyte, 0xD9F8, CPU_FPU); } - F Y L "2" X P "1" { RET_INSN(twobyte, 0xD9F9, CPU_FPU); } - F S Q R T { RET_INSN(twobyte, 0xD9FA, CPU_FPU); } - F S I N C O S { RET_INSN(twobyte, 0xD9FB, CPU_286|CPU_FPU); } - F R N D I N T { RET_INSN(twobyte, 0xD9FC, CPU_FPU); } - F S C A L E { RET_INSN(twobyte, 0xD9FD, CPU_FPU); } - F S I N { RET_INSN(twobyte, 0xD9FE, CPU_286|CPU_FPU); } - F C O S { RET_INSN(twobyte, 0xD9FF, CPU_286|CPU_FPU); } - F C H S { RET_INSN(twobyte, 0xD9E0, CPU_FPU); } - F A B S { RET_INSN(twobyte, 0xD9E1, CPU_FPU); } - F N I N I T { RET_INSN(twobyte, 0xDBE3, CPU_FPU); } - F I N I T { RET_INSN(threebyte, 0x9BDBE3UL, CPU_FPU); } - F L D C W { RET_INSN(fldnstcw, 0x05, CPU_FPU); } - F N S T C W { RET_INSN(fldnstcw, 0x07, CPU_FPU); } - F S T C W { RET_INSN(fstcw, 0, CPU_FPU); } - F N S T S W { RET_INSN(fnstsw, 0, CPU_FPU); } - F S T S W { RET_INSN(fstsw, 0, CPU_FPU); } - F N C L E X { RET_INSN(twobyte, 0xDBE2, CPU_FPU); } - F C L E X { RET_INSN(threebyte, 0x9BDBE2UL, CPU_FPU); } - F N S T E N V { RET_INSN(onebytemem, 0x06D9, CPU_FPU); } - F S T E N V { RET_INSN(twobytemem, 0x069BD9, CPU_FPU); } - F L D E N V { RET_INSN(onebytemem, 0x04D9, CPU_FPU); } - F N S A V E { RET_INSN(onebytemem, 0x06DD, CPU_FPU); } - F S A V E { RET_INSN(twobytemem, 0x069BDD, CPU_FPU); } - F R S T O R { RET_INSN(onebytemem, 0x04DD, CPU_FPU); } - F F R E E { RET_INSN(ffree, 0xDD, CPU_FPU); } - F F R E E P { RET_INSN(ffree, 0xDF, CPU_686|CPU_FPU|CPU_Undoc); } - F N O P { RET_INSN(twobyte, 0xD9D0, CPU_FPU); } - F W A I T { RET_INSN(onebyte, 0x009B, CPU_FPU); } + F L D { RET_INSN(3, fldstp, 0x0500C0, CPU_FPU); } + F I L D { RET_INSN(4, fildstp, 0x050200, CPU_FPU); } + F B L D { RET_INSN(4, fbldstp, 0x04, CPU_FPU); } + F S T { RET_INSN(3, fst, 0, CPU_FPU); } + F I S T { RET_INSN(4, fiarith, 0x02DB, CPU_FPU); } + F S T P { RET_INSN(4, fldstp, 0x0703D8, CPU_FPU); } + F I S T P { RET_INSN(5, fildstp, 0x070203, CPU_FPU); } + F B S T P { RET_INSN(5, fbldstp, 0x06, CPU_FPU); } + F X C H { RET_INSN(4, fxch, 0, CPU_FPU); } + F C O M { RET_INSN(4, fcom, 0x02D0, CPU_FPU); } + F I C O M { RET_INSN(5, fiarith, 0x02DA, CPU_FPU); } + F C O M P { RET_INSN(5, fcom, 0x03D8, CPU_FPU); } + F I C O M P { RET_INSN(6, fiarith, 0x03DA, CPU_FPU); } + F C O M P P { RET_INSN(6, twobyte, 0xDED9, CPU_FPU); } + F U C O M { RET_INSN(5, fcom2, 0xDDE0, CPU_286|CPU_FPU); } + F U C O M P { RET_INSN(6, fcom2, 0xDDE8, CPU_286|CPU_FPU); } + F U C O M P P { RET_INSN(7, twobyte, 0xDAE9, CPU_286|CPU_FPU); } + F T S T { RET_INSN(4, twobyte, 0xD9E4, CPU_FPU); } + F X A M { RET_INSN(4, twobyte, 0xD9E5, CPU_FPU); } + F L D "1" { RET_INSN(4, twobyte, 0xD9E8, CPU_FPU); } + F L D L "2" T { RET_INSN(6, twobyte, 0xD9E9, CPU_FPU); } + F L D L "2" E { RET_INSN(6, twobyte, 0xD9EA, CPU_FPU); } + F L D P I { RET_INSN(5, twobyte, 0xD9EB, CPU_FPU); } + F L D L G "2" { RET_INSN(6, twobyte, 0xD9EC, CPU_FPU); } + F L D L N "2" { RET_INSN(6, twobyte, 0xD9ED, CPU_FPU); } + F L D Z { RET_INSN(4, twobyte, 0xD9EE, CPU_FPU); } + F A D D { RET_INSN(4, farith, 0x00C0C0, CPU_FPU); } + F A D D P { RET_INSN(5, farithp, 0xC0, CPU_FPU); } + F I A D D { RET_INSN(5, fiarith, 0x00DA, CPU_FPU); } + F S U B { RET_INSN(4, farith, 0x04E0E8, CPU_FPU); } + F I S U B { RET_INSN(5, fiarith, 0x04DA, CPU_FPU); } + F S U B P { RET_INSN(5, farithp, 0xE8, CPU_FPU); } + F S U B R { RET_INSN(5, farith, 0x05E8E0, CPU_FPU); } + F I S U B R { RET_INSN(6, fiarith, 0x05DA, CPU_FPU); } + F S U B R P { RET_INSN(6, farithp, 0xE0, CPU_FPU); } + F M U L { RET_INSN(4, farith, 0x01C8C8, CPU_FPU); } + F I M U L { RET_INSN(5, fiarith, 0x01DA, CPU_FPU); } + F M U L P { RET_INSN(5, farithp, 0xC8, CPU_FPU); } + F D I V { RET_INSN(4, farith, 0x06F0F8, CPU_FPU); } + F I D I V { RET_INSN(5, fiarith, 0x06DA, CPU_FPU); } + F D I V P { RET_INSN(5, farithp, 0xF8, CPU_FPU); } + F D I V R { RET_INSN(5, farith, 0x07F8F0, CPU_FPU); } + F I D I V R { RET_INSN(6, fiarith, 0x07DA, CPU_FPU); } + F D I V R P { RET_INSN(6, farithp, 0xF0, CPU_FPU); } + F "2" X M "1" { RET_INSN(5, twobyte, 0xD9F0, CPU_FPU); } + F Y L "2" X { RET_INSN(5, twobyte, 0xD9F1, CPU_FPU); } + F P T A N { RET_INSN(5, twobyte, 0xD9F2, CPU_FPU); } + F P A T A N { RET_INSN(6, twobyte, 0xD9F3, CPU_FPU); } + F X T R A C T { RET_INSN(7, twobyte, 0xD9F4, CPU_FPU); } + F P R E M "1" { RET_INSN(6, twobyte, 0xD9F5, CPU_286|CPU_FPU); } + F D E C S T P { RET_INSN(7, twobyte, 0xD9F6, CPU_FPU); } + F I N C S T P { RET_INSN(7, twobyte, 0xD9F7, CPU_FPU); } + F P R E M { RET_INSN(5, twobyte, 0xD9F8, CPU_FPU); } + F Y L "2" X P "1" { RET_INSN(7, twobyte, 0xD9F9, CPU_FPU); } + F S Q R T { RET_INSN(5, twobyte, 0xD9FA, CPU_FPU); } + F S I N C O S { RET_INSN(7, twobyte, 0xD9FB, CPU_286|CPU_FPU); } + F R N D I N T { RET_INSN(7, twobyte, 0xD9FC, CPU_FPU); } + F S C A L E { RET_INSN(6, twobyte, 0xD9FD, CPU_FPU); } + F S I N { RET_INSN(4, twobyte, 0xD9FE, CPU_286|CPU_FPU); } + F C O S { RET_INSN(4, twobyte, 0xD9FF, CPU_286|CPU_FPU); } + F C H S { RET_INSN(4, twobyte, 0xD9E0, CPU_FPU); } + F A B S { RET_INSN(4, twobyte, 0xD9E1, CPU_FPU); } + F N I N I T { RET_INSN(6, twobyte, 0xDBE3, CPU_FPU); } + F I N I T { RET_INSN(5, threebyte, 0x9BDBE3UL, CPU_FPU); } + F L D C W { RET_INSN(5, fldnstcw, 0x05, CPU_FPU); } + F N S T C W { RET_INSN(6, fldnstcw, 0x07, CPU_FPU); } + F S T C W { RET_INSN(5, fstcw, 0, CPU_FPU); } + F N S T S W { RET_INSN(6, fnstsw, 0, CPU_FPU); } + F S T S W { RET_INSN(5, fstsw, 0, CPU_FPU); } + F N C L E X { RET_INSN(6, twobyte, 0xDBE2, CPU_FPU); } + F C L E X { RET_INSN(5, threebyte, 0x9BDBE2UL, CPU_FPU); } + F N S T E N V { RET_INSN(7, onebytemem, 0x06D9, CPU_FPU); } + F S T E N V { RET_INSN(6, twobytemem, 0x069BD9, CPU_FPU); } + F L D E N V { RET_INSN(6, onebytemem, 0x04D9, CPU_FPU); } + F N S A V E { RET_INSN(6, onebytemem, 0x06DD, CPU_FPU); } + F S A V E { RET_INSN(5, twobytemem, 0x069BDD, CPU_FPU); } + F R S T O R { RET_INSN(6, onebytemem, 0x04DD, CPU_FPU); } + F F R E E { RET_INSN(5, ffree, 0xDD, CPU_FPU); } + F F R E E P { RET_INSN(6, ffree, 0xDF, CPU_686|CPU_FPU|CPU_Undoc); } + F N O P { RET_INSN(4, twobyte, 0xD9D0, CPU_FPU); } + F W A I T { RET_INSN(5, onebyte, 0x009B, CPU_FPU); } /* Prefixes (should the others be here too? should wait be a prefix? */ - W A I T { RET_INSN(onebyte, 0x009B, CPU_Any); } + W A I T { RET_INSN(4, onebyte, 0x009B, CPU_Any); } /* 486 extensions */ - B S W A P { RET_INSN(bswap, 0, CPU_486); } - X A D D { RET_INSN(cmpxchgxadd, 0xC0, CPU_486); } - C M P X C H G { RET_INSN(cmpxchgxadd, 0xB0, CPU_486); } - C M P X C H G "486" { RET_INSN(cmpxchgxadd, 0xA6, CPU_486|CPU_Undoc); } - I N V D { RET_INSN(twobyte, 0x0F08, CPU_486|CPU_Priv); } - W B I N V D { RET_INSN(twobyte, 0x0F09, CPU_486|CPU_Priv); } - I N V L P G { RET_INSN(twobytemem, 0x070F01, CPU_486|CPU_Priv); } + B S W A P { RET_INSN(5, bswap, 0, CPU_486); } + X A D D { RET_INSN(4, cmpxchgxadd, 0xC0, CPU_486); } + C M P X C H G { RET_INSN(7, cmpxchgxadd, 0xB0, CPU_486); } + C M P X C H G "486" { RET_INSN(10, cmpxchgxadd, 0xA6, CPU_486|CPU_Undoc); } + I N V D { RET_INSN(4, twobyte, 0x0F08, CPU_486|CPU_Priv); } + W B I N V D { RET_INSN(6, twobyte, 0x0F09, CPU_486|CPU_Priv); } + I N V L P G { RET_INSN(6, twobytemem, 0x070F01, CPU_486|CPU_Priv); } /* 586+ and late 486 extensions */ - C P U I D { RET_INSN(twobyte, 0x0FA2, CPU_486); } + C P U I D { RET_INSN(5, twobyte, 0x0FA2, CPU_486); } /* Pentium extensions */ - W R M S R { RET_INSN(twobyte, 0x0F30, CPU_586|CPU_Priv); } - R D T S C { RET_INSN(twobyte, 0x0F31, CPU_586); } - R D M S R { RET_INSN(twobyte, 0x0F32, CPU_586|CPU_Priv); } - C M P X C H G "8" B { RET_INSN(cmpxchg8b, 0, CPU_586); } + W R M S R { RET_INSN(5, twobyte, 0x0F30, CPU_586|CPU_Priv); } + R D T S C { RET_INSN(5, twobyte, 0x0F31, CPU_586); } + R D M S R { RET_INSN(5, twobyte, 0x0F32, CPU_586|CPU_Priv); } + C M P X C H G "8" B { RET_INSN(9, cmpxchg8b, 0, CPU_586); } /* Pentium II/Pentium Pro extensions */ S Y S E N T E R { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(twobyte, 0x0F34, CPU_686); + not64 = 1; + RET_INSN(8, twobyte, 0x0F34, CPU_686); } S Y S E X I T { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(twobyte, 0x0F35, CPU_686|CPU_Priv); - } - F X S A V E { RET_INSN(twobytemem, 0x000FAE, CPU_686|CPU_FPU); } - F X R S T O R { RET_INSN(twobytemem, 0x010FAE, CPU_686|CPU_FPU); } - R D P M C { RET_INSN(twobyte, 0x0F33, CPU_686); } - U D "2" { RET_INSN(twobyte, 0x0F0B, CPU_286); } - U D "1" { RET_INSN(twobyte, 0x0FB9, CPU_286|CPU_Undoc); } - C M O V O { RET_INSN(cmovcc, 0x00, CPU_686); } - C M O V N O { RET_INSN(cmovcc, 0x01, CPU_686); } - C M O V B { RET_INSN(cmovcc, 0x02, CPU_686); } - C M O V C { RET_INSN(cmovcc, 0x02, CPU_686); } - C M O V N A E { RET_INSN(cmovcc, 0x02, CPU_686); } - C M O V N B { RET_INSN(cmovcc, 0x03, CPU_686); } - C M O V N C { RET_INSN(cmovcc, 0x03, CPU_686); } - C M O V A E { RET_INSN(cmovcc, 0x03, CPU_686); } - C M O V E { RET_INSN(cmovcc, 0x04, CPU_686); } - C M O V Z { RET_INSN(cmovcc, 0x04, CPU_686); } - C M O V N E { RET_INSN(cmovcc, 0x05, CPU_686); } - C M O V N Z { RET_INSN(cmovcc, 0x05, CPU_686); } - C M O V B E { RET_INSN(cmovcc, 0x06, CPU_686); } - C M O V N A { RET_INSN(cmovcc, 0x06, CPU_686); } - C M O V N B E { RET_INSN(cmovcc, 0x07, CPU_686); } - C M O V A { RET_INSN(cmovcc, 0x07, CPU_686); } - C M O V S { RET_INSN(cmovcc, 0x08, CPU_686); } - C M O V N S { RET_INSN(cmovcc, 0x09, CPU_686); } - C M O V P { RET_INSN(cmovcc, 0x0A, CPU_686); } - C M O V P E { RET_INSN(cmovcc, 0x0A, CPU_686); } - C M O V N P { RET_INSN(cmovcc, 0x0B, CPU_686); } - C M O V P O { RET_INSN(cmovcc, 0x0B, CPU_686); } - C M O V L { RET_INSN(cmovcc, 0x0C, CPU_686); } - C M O V N G E { RET_INSN(cmovcc, 0x0C, CPU_686); } - C M O V N L { RET_INSN(cmovcc, 0x0D, CPU_686); } - C M O V G E { RET_INSN(cmovcc, 0x0D, CPU_686); } - C M O V L E { RET_INSN(cmovcc, 0x0E, CPU_686); } - C M O V N G { RET_INSN(cmovcc, 0x0E, CPU_686); } - C M O V N L E { RET_INSN(cmovcc, 0x0F, CPU_686); } - C M O V G { RET_INSN(cmovcc, 0x0F, CPU_686); } - F C M O V B { RET_INSN(fcmovcc, 0xDAC0, CPU_686|CPU_FPU); } - F C M O V E { RET_INSN(fcmovcc, 0xDAC8, CPU_686|CPU_FPU); } - F C M O V B E { RET_INSN(fcmovcc, 0xDAD0, CPU_686|CPU_FPU); } - F C M O V U { RET_INSN(fcmovcc, 0xDAD8, CPU_686|CPU_FPU); } - F C M O V N B { RET_INSN(fcmovcc, 0xDBC0, CPU_686|CPU_FPU); } - F C M O V N E { RET_INSN(fcmovcc, 0xDBC8, CPU_686|CPU_FPU); } - F C M O V N B E { RET_INSN(fcmovcc, 0xDBD0, CPU_686|CPU_FPU); } - F C M O V U { RET_INSN(fcmovcc, 0xDBD8, CPU_686|CPU_FPU); } - F C O M I { RET_INSN(fcom2, 0xDBF0, CPU_686|CPU_FPU); } - F U C O M I { RET_INSN(fcom2, 0xDBE8, CPU_686|CPU_FPU); } - F C O M I P { RET_INSN(fcom2, 0xDFF0, CPU_686|CPU_FPU); } - F U C O M I P { RET_INSN(fcom2, 0xDFE8, CPU_686|CPU_FPU); } + not64 = 1; + RET_INSN(7, twobyte, 0x0F35, CPU_686|CPU_Priv); + } + F X S A V E { RET_INSN(6, twobytemem, 0x000FAE, CPU_686|CPU_FPU); } + F X R S T O R { RET_INSN(7, twobytemem, 0x010FAE, CPU_686|CPU_FPU); } + R D P M C { RET_INSN(5, twobyte, 0x0F33, CPU_686); } + U D "2" { RET_INSN(3, twobyte, 0x0F0B, CPU_286); } + U D "1" { RET_INSN(3, twobyte, 0x0FB9, CPU_286|CPU_Undoc); } + C M O V O { RET_INSN(5, cmovcc, 0x00, CPU_686); } + C M O V N O { RET_INSN(6, cmovcc, 0x01, CPU_686); } + C M O V B { RET_INSN(5, cmovcc, 0x02, CPU_686); } + C M O V C { RET_INSN(5, cmovcc, 0x02, CPU_686); } + C M O V N A E { RET_INSN(7, cmovcc, 0x02, CPU_686); } + C M O V N B { RET_INSN(6, cmovcc, 0x03, CPU_686); } + C M O V N C { RET_INSN(6, cmovcc, 0x03, CPU_686); } + C M O V A E { RET_INSN(6, cmovcc, 0x03, CPU_686); } + C M O V E { RET_INSN(5, cmovcc, 0x04, CPU_686); } + C M O V Z { RET_INSN(5, cmovcc, 0x04, CPU_686); } + C M O V N E { RET_INSN(6, cmovcc, 0x05, CPU_686); } + C M O V N Z { RET_INSN(6, cmovcc, 0x05, CPU_686); } + C M O V B E { RET_INSN(6, cmovcc, 0x06, CPU_686); } + C M O V N A { RET_INSN(6, cmovcc, 0x06, CPU_686); } + C M O V N B E { RET_INSN(7, cmovcc, 0x07, CPU_686); } + C M O V A { RET_INSN(5, cmovcc, 0x07, CPU_686); } + C M O V S { RET_INSN(5, cmovcc, 0x08, CPU_686); } + C M O V N S { RET_INSN(6, cmovcc, 0x09, CPU_686); } + C M O V P { RET_INSN(5, cmovcc, 0x0A, CPU_686); } + C M O V P E { RET_INSN(6, cmovcc, 0x0A, CPU_686); } + C M O V N P { RET_INSN(6, cmovcc, 0x0B, CPU_686); } + C M O V P O { RET_INSN(6, cmovcc, 0x0B, CPU_686); } + C M O V L { RET_INSN(5, cmovcc, 0x0C, CPU_686); } + C M O V N G E { RET_INSN(7, cmovcc, 0x0C, CPU_686); } + C M O V N L { RET_INSN(6, cmovcc, 0x0D, CPU_686); } + C M O V G E { RET_INSN(6, cmovcc, 0x0D, CPU_686); } + C M O V L E { RET_INSN(6, cmovcc, 0x0E, CPU_686); } + C M O V N G { RET_INSN(6, cmovcc, 0x0E, CPU_686); } + C M O V N L E { RET_INSN(7, cmovcc, 0x0F, CPU_686); } + C M O V G { RET_INSN(5, cmovcc, 0x0F, CPU_686); } + F C M O V B { RET_INSN(6, fcmovcc, 0xDAC0, CPU_686|CPU_FPU); } + F C M O V E { RET_INSN(6, fcmovcc, 0xDAC8, CPU_686|CPU_FPU); } + F C M O V B E { RET_INSN(7, fcmovcc, 0xDAD0, CPU_686|CPU_FPU); } + F C M O V U { RET_INSN(6, fcmovcc, 0xDAD8, CPU_686|CPU_FPU); } + F C M O V N B { RET_INSN(7, fcmovcc, 0xDBC0, CPU_686|CPU_FPU); } + F C M O V N E { RET_INSN(7, fcmovcc, 0xDBC8, CPU_686|CPU_FPU); } + F C M O V N B E { RET_INSN(8, fcmovcc, 0xDBD0, CPU_686|CPU_FPU); } + F C M O V U { RET_INSN(6, fcmovcc, 0xDBD8, CPU_686|CPU_FPU); } + F C O M I { RET_INSN(5, fcom2, 0xDBF0, CPU_686|CPU_FPU); } + F U C O M I { RET_INSN(6, fcom2, 0xDBE8, CPU_686|CPU_FPU); } + F C O M I P { RET_INSN(6, fcom2, 0xDFF0, CPU_686|CPU_FPU); } + F U C O M I P { RET_INSN(7, fcom2, 0xDFE8, CPU_686|CPU_FPU); } /* Pentium4 extensions */ - M O V N T I { RET_INSN(movnti, 0, CPU_P4); } - C L F L U S H { RET_INSN(clflush, 0, CPU_P3); } - L F E N C E { RET_INSN(threebyte, 0x0FAEE8, CPU_P3); } - M F E N C E { RET_INSN(threebyte, 0x0FAEF0, CPU_P3); } - P A U S E { RET_INSN(onebyte_prefix, 0xF390, CPU_P4); } + M O V N T I { RET_INSN(6, movnti, 0, CPU_P4); } + C L F L U S H { RET_INSN(7, clflush, 0, CPU_P3); } + L F E N C E { RET_INSN(6, threebyte, 0x0FAEE8, CPU_P3); } + M F E N C E { RET_INSN(6, threebyte, 0x0FAEF0, CPU_P3); } + P A U S E { RET_INSN(5, onebyte_prefix, 0xF390, CPU_P4); } /* MMX/SSE2 instructions */ - E M M S { RET_INSN(twobyte, 0x0F77, CPU_MMX); } - M O V D { RET_INSN(movd, 0, CPU_MMX); } - M O V Q { RET_INSN(movq, 0, CPU_MMX); } - P A C K S S D W { RET_INSN(mmxsse2, 0x6B, CPU_MMX); } - P A C K S S W B { RET_INSN(mmxsse2, 0x63, CPU_MMX); } - P A C K U S W B { RET_INSN(mmxsse2, 0x67, CPU_MMX); } - P A D D B { RET_INSN(mmxsse2, 0xFC, CPU_MMX); } - P A D D W { RET_INSN(mmxsse2, 0xFD, CPU_MMX); } - P A D D D { RET_INSN(mmxsse2, 0xFE, CPU_MMX); } - P A D D Q { RET_INSN(mmxsse2, 0xD4, CPU_MMX); } - P A D D S B { RET_INSN(mmxsse2, 0xEC, CPU_MMX); } - P A D D S W { RET_INSN(mmxsse2, 0xED, CPU_MMX); } - P A D D U S B { RET_INSN(mmxsse2, 0xDC, CPU_MMX); } - P A D D U S W { RET_INSN(mmxsse2, 0xDD, CPU_MMX); } - P A N D { RET_INSN(mmxsse2, 0xDB, CPU_MMX); } - P A N D N { RET_INSN(mmxsse2, 0xDF, CPU_MMX); } - P C M P E Q B { RET_INSN(mmxsse2, 0x74, CPU_MMX); } - P C M P E Q W { RET_INSN(mmxsse2, 0x75, CPU_MMX); } - P C M P E Q D { RET_INSN(mmxsse2, 0x76, CPU_MMX); } - P C M P G T B { RET_INSN(mmxsse2, 0x64, CPU_MMX); } - P C M P G T W { RET_INSN(mmxsse2, 0x65, CPU_MMX); } - P C M P G T D { RET_INSN(mmxsse2, 0x66, CPU_MMX); } - P M A D D W D { RET_INSN(mmxsse2, 0xF5, CPU_MMX); } - P M U L H W { RET_INSN(mmxsse2, 0xE5, CPU_MMX); } - P M U L L W { RET_INSN(mmxsse2, 0xD5, CPU_MMX); } - P O R { RET_INSN(mmxsse2, 0xEB, CPU_MMX); } - P S L L W { RET_INSN(pshift, 0x0671F1, CPU_MMX); } - P S L L D { RET_INSN(pshift, 0x0672F2, CPU_MMX); } - P S L L Q { RET_INSN(pshift, 0x0673F3, CPU_MMX); } - P S R A W { RET_INSN(pshift, 0x0471E1, CPU_MMX); } - P S R A D { RET_INSN(pshift, 0x0472E2, CPU_MMX); } - P S R L W { RET_INSN(pshift, 0x0271D1, CPU_MMX); } - P S R L D { RET_INSN(pshift, 0x0272D2, CPU_MMX); } - P S R L Q { RET_INSN(pshift, 0x0273D3, CPU_MMX); } - P S U B B { RET_INSN(mmxsse2, 0xF8, CPU_MMX); } - P S U B W { RET_INSN(mmxsse2, 0xF9, CPU_MMX); } - P S U B D { RET_INSN(mmxsse2, 0xFA, CPU_MMX); } - P S U B Q { RET_INSN(mmxsse2, 0xFB, CPU_MMX); } - P S U B S B { RET_INSN(mmxsse2, 0xE8, CPU_MMX); } - P S U B S W { RET_INSN(mmxsse2, 0xE9, CPU_MMX); } - P S U B U S B { RET_INSN(mmxsse2, 0xD8, CPU_MMX); } - P S U B U S W { RET_INSN(mmxsse2, 0xD9, CPU_MMX); } - P U N P C K H B W { RET_INSN(mmxsse2, 0x68, CPU_MMX); } - P U N P C K H W D { RET_INSN(mmxsse2, 0x69, CPU_MMX); } - P U N P C K H D Q { RET_INSN(mmxsse2, 0x6A, CPU_MMX); } - P U N P C K L B W { RET_INSN(mmxsse2, 0x60, CPU_MMX); } - P U N P C K L W D { RET_INSN(mmxsse2, 0x61, CPU_MMX); } - P U N P C K L D Q { RET_INSN(mmxsse2, 0x62, CPU_MMX); } - P X O R { RET_INSN(mmxsse2, 0xEF, CPU_MMX); } + E M M S { RET_INSN(4, twobyte, 0x0F77, CPU_MMX); } + M O V D { RET_INSN(4, movd, 0, CPU_MMX); } + M O V Q { RET_INSN(4, movq, 0, CPU_MMX); } + P A C K S S D W { RET_INSN(8, mmxsse2, 0x6B, CPU_MMX); } + P A C K S S W B { RET_INSN(8, mmxsse2, 0x63, CPU_MMX); } + P A C K U S W B { RET_INSN(8, mmxsse2, 0x67, CPU_MMX); } + P A D D B { RET_INSN(5, mmxsse2, 0xFC, CPU_MMX); } + P A D D W { RET_INSN(5, mmxsse2, 0xFD, CPU_MMX); } + P A D D D { RET_INSN(5, mmxsse2, 0xFE, CPU_MMX); } + P A D D Q { RET_INSN(5, mmxsse2, 0xD4, CPU_MMX); } + P A D D S B { RET_INSN(6, mmxsse2, 0xEC, CPU_MMX); } + P A D D S W { RET_INSN(6, mmxsse2, 0xED, CPU_MMX); } + P A D D U S B { RET_INSN(7, mmxsse2, 0xDC, CPU_MMX); } + P A D D U S W { RET_INSN(7, mmxsse2, 0xDD, CPU_MMX); } + P A N D { RET_INSN(4, mmxsse2, 0xDB, CPU_MMX); } + P A N D N { RET_INSN(5, mmxsse2, 0xDF, CPU_MMX); } + P C M P E Q B { RET_INSN(7, mmxsse2, 0x74, CPU_MMX); } + P C M P E Q W { RET_INSN(7, mmxsse2, 0x75, CPU_MMX); } + P C M P E Q D { RET_INSN(7, mmxsse2, 0x76, CPU_MMX); } + P C M P G T B { RET_INSN(7, mmxsse2, 0x64, CPU_MMX); } + P C M P G T W { RET_INSN(7, mmxsse2, 0x65, CPU_MMX); } + P C M P G T D { RET_INSN(7, mmxsse2, 0x66, CPU_MMX); } + P M A D D W D { RET_INSN(7, mmxsse2, 0xF5, CPU_MMX); } + P M U L H W { RET_INSN(6, mmxsse2, 0xE5, CPU_MMX); } + P M U L L W { RET_INSN(6, mmxsse2, 0xD5, CPU_MMX); } + P O R { RET_INSN(3, mmxsse2, 0xEB, CPU_MMX); } + P S L L W { RET_INSN(5, pshift, 0x0671F1, CPU_MMX); } + P S L L D { RET_INSN(5, pshift, 0x0672F2, CPU_MMX); } + P S L L Q { RET_INSN(5, pshift, 0x0673F3, CPU_MMX); } + P S R A W { RET_INSN(5, pshift, 0x0471E1, CPU_MMX); } + P S R A D { RET_INSN(5, pshift, 0x0472E2, CPU_MMX); } + P S R L W { RET_INSN(5, pshift, 0x0271D1, CPU_MMX); } + P S R L D { RET_INSN(5, pshift, 0x0272D2, CPU_MMX); } + P S R L Q { RET_INSN(5, pshift, 0x0273D3, CPU_MMX); } + P S U B B { RET_INSN(5, mmxsse2, 0xF8, CPU_MMX); } + P S U B W { RET_INSN(5, mmxsse2, 0xF9, CPU_MMX); } + P S U B D { RET_INSN(5, mmxsse2, 0xFA, CPU_MMX); } + P S U B Q { RET_INSN(5, mmxsse2, 0xFB, CPU_MMX); } + P S U B S B { RET_INSN(6, mmxsse2, 0xE8, CPU_MMX); } + P S U B S W { RET_INSN(6, mmxsse2, 0xE9, CPU_MMX); } + P S U B U S B { RET_INSN(7, mmxsse2, 0xD8, CPU_MMX); } + P S U B U S W { RET_INSN(7, mmxsse2, 0xD9, CPU_MMX); } + P U N P C K H B W { RET_INSN(9, mmxsse2, 0x68, CPU_MMX); } + P U N P C K H W D { RET_INSN(9, mmxsse2, 0x69, CPU_MMX); } + P U N P C K H D Q { RET_INSN(9, mmxsse2, 0x6A, CPU_MMX); } + P U N P C K L B W { RET_INSN(9, mmxsse2, 0x60, CPU_MMX); } + P U N P C K L W D { RET_INSN(9, mmxsse2, 0x61, CPU_MMX); } + P U N P C K L D Q { RET_INSN(9, mmxsse2, 0x62, CPU_MMX); } + P X O R { RET_INSN(4, mmxsse2, 0xEF, CPU_MMX); } /* PIII (Katmai) new instructions / SIMD instructions */ - A D D P S { RET_INSN(sseps, 0x58, CPU_SSE); } - A D D S S { RET_INSN(ssess, 0xF358, CPU_SSE); } - A N D N P S { RET_INSN(sseps, 0x55, CPU_SSE); } - A N D P S { RET_INSN(sseps, 0x54, CPU_SSE); } - C M P E Q P S { RET_INSN(ssecmpps, 0x00, CPU_SSE); } - C M P E Q S S { RET_INSN(ssecmpss, 0x00F3, CPU_SSE); } - C M P L E P S { RET_INSN(ssecmpps, 0x02, CPU_SSE); } - C M P L E S S { RET_INSN(ssecmpss, 0x02F3, CPU_SSE); } - C M P L T P S { RET_INSN(ssecmpps, 0x01, CPU_SSE); } - C M P L T S S { RET_INSN(ssecmpss, 0x01F3, CPU_SSE); } - C M P N E Q P S { RET_INSN(ssecmpps, 0x04, CPU_SSE); } - C M P N E Q S S { RET_INSN(ssecmpss, 0x04F3, CPU_SSE); } - C M P N L E P S { RET_INSN(ssecmpps, 0x06, CPU_SSE); } - C M P N L E S S { RET_INSN(ssecmpss, 0x06F3, CPU_SSE); } - C M P N L T P S { RET_INSN(ssecmpps, 0x05, CPU_SSE); } - C M P N L T S S { RET_INSN(ssecmpss, 0x05F3, CPU_SSE); } - C M P O R D P S { RET_INSN(ssecmpps, 0x07, CPU_SSE); } - C M P O R D S S { RET_INSN(ssecmpss, 0x07F3, CPU_SSE); } - C M P U N O R D P S { RET_INSN(ssecmpps, 0x03, CPU_SSE); } - C M P U N O R D S S { RET_INSN(ssecmpss, 0x03F3, CPU_SSE); } - C M P P S { RET_INSN(ssepsimm, 0xC2, CPU_SSE); } - C M P S S { RET_INSN(ssessimm, 0xF3C2, CPU_SSE); } - C O M I S S { RET_INSN(sseps, 0x2F, CPU_SSE); } - C V T P I "2" P S { RET_INSN(cvt_xmm_mm_ps, 0x2A, CPU_SSE); } - C V T P S "2" P I { RET_INSN(cvt_mm_xmm64, 0x2D, CPU_SSE); } - C V T S I "2" S S { RET_INSN(cvt_xmm_rmx, 0xF32A, CPU_SSE); } - C V T S S "2" S I { RET_INSN(cvt_rx_xmm32, 0xF32D, CPU_SSE); } - C V T T P S "2" P I { RET_INSN(cvt_mm_xmm64, 0x2C, CPU_SSE); } - C V T T S S "2" S I { RET_INSN(cvt_rx_xmm32, 0xF32C, CPU_SSE); } - D I V P S { RET_INSN(sseps, 0x5E, CPU_SSE); } - D I V S S { RET_INSN(ssess, 0xF35E, CPU_SSE); } - L D M X C S R { RET_INSN(ldstmxcsr, 0x02, CPU_SSE); } - M A S K M O V Q { RET_INSN(maskmovq, 0, CPU_P3|CPU_MMX); } - M A X P S { RET_INSN(sseps, 0x5F, CPU_SSE); } - M A X S S { RET_INSN(ssess, 0xF35F, CPU_SSE); } - M I N P S { RET_INSN(sseps, 0x5D, CPU_SSE); } - M I N S S { RET_INSN(ssess, 0xF35D, CPU_SSE); } - M O V A P S { RET_INSN(movaups, 0x28, CPU_SSE); } - M O V H L P S { RET_INSN(movhllhps, 0x12, CPU_SSE); } - M O V H P S { RET_INSN(movhlps, 0x16, CPU_SSE); } - M O V L H P S { RET_INSN(movhllhps, 0x16, CPU_SSE); } - M O V L P S { RET_INSN(movhlps, 0x12, CPU_SSE); } - M O V M S K P S { RET_INSN(movmskps, 0, CPU_SSE); } - M O V N T P S { RET_INSN(movntps, 0, CPU_SSE); } - M O V N T Q { RET_INSN(movntq, 0, CPU_SSE); } - M O V S S { RET_INSN(movss, 0, CPU_SSE); } - M O V U P S { RET_INSN(movaups, 0x10, CPU_SSE); } - M U L P S { RET_INSN(sseps, 0x59, CPU_SSE); } - M U L S S { RET_INSN(ssess, 0xF359, CPU_SSE); } - O R P S { RET_INSN(sseps, 0x56, CPU_SSE); } - P A V G B { RET_INSN(mmxsse2, 0xE0, CPU_P3|CPU_MMX); } - P A V G W { RET_INSN(mmxsse2, 0xE3, CPU_P3|CPU_MMX); } - P E X T R W { RET_INSN(pextrw, 0, CPU_P3|CPU_MMX); } - P I N S R W { RET_INSN(pinsrw, 0, CPU_P3|CPU_MMX); } - P M A X S W { RET_INSN(mmxsse2, 0xEE, CPU_P3|CPU_MMX); } - P M A X U B { RET_INSN(mmxsse2, 0xDE, CPU_P3|CPU_MMX); } - P M I N S W { RET_INSN(mmxsse2, 0xEA, CPU_P3|CPU_MMX); } - P M I N U B { RET_INSN(mmxsse2, 0xDA, CPU_P3|CPU_MMX); } - P M O V M S K B { RET_INSN(pmovmskb, 0, CPU_SSE); } - P M U L H U W { RET_INSN(mmxsse2, 0xE4, CPU_P3|CPU_MMX); } - P R E F E T C H N T A { RET_INSN(twobytemem, 0x000F18, CPU_P3); } - P R E F E T C H T "0" { RET_INSN(twobytemem, 0x010F18, CPU_P3); } - P R E F E T C H T "1" { RET_INSN(twobytemem, 0x020F18, CPU_P3); } - P R E F E T C H T "2" { RET_INSN(twobytemem, 0x030F18, CPU_P3); } - P S A D B W { RET_INSN(mmxsse2, 0xF6, CPU_P3|CPU_MMX); } - P S H U F W { RET_INSN(pshufw, 0, CPU_P3|CPU_MMX); } - R C P P S { RET_INSN(sseps, 0x53, CPU_SSE); } - R C P S S { RET_INSN(ssess, 0xF353, CPU_SSE); } - R S Q R T P S { RET_INSN(sseps, 0x52, CPU_SSE); } - R S Q R T S S { RET_INSN(ssess, 0xF352, CPU_SSE); } - S F E N C E { RET_INSN(threebyte, 0x0FAEF8, CPU_P3); } - S H U F P S { RET_INSN(ssepsimm, 0xC6, CPU_SSE); } - S Q R T P S { RET_INSN(sseps, 0x51, CPU_SSE); } - S Q R T S S { RET_INSN(ssess, 0xF351, CPU_SSE); } - S T M X C S R { RET_INSN(ldstmxcsr, 0x03, CPU_SSE); } - S U B P S { RET_INSN(sseps, 0x5C, CPU_SSE); } - S U B S S { RET_INSN(ssess, 0xF35C, CPU_SSE); } - U C O M I S S { RET_INSN(ssess, 0x2E, CPU_SSE); } - U N P C K H P S { RET_INSN(sseps, 0x15, CPU_SSE); } - U N P C K L P S { RET_INSN(sseps, 0x14, CPU_SSE); } - X O R P S { RET_INSN(sseps, 0x57, CPU_SSE); } + A D D P S { RET_INSN(5, sseps, 0x58, CPU_SSE); } + A D D S S { RET_INSN(5, ssess, 0xF358, CPU_SSE); } + A N D N P S { RET_INSN(6, sseps, 0x55, CPU_SSE); } + A N D P S { RET_INSN(5, sseps, 0x54, CPU_SSE); } + C M P E Q P S { RET_INSN(7, ssecmpps, 0x00, CPU_SSE); } + C M P E Q S S { RET_INSN(7, ssecmpss, 0x00F3, CPU_SSE); } + C M P L E P S { RET_INSN(7, ssecmpps, 0x02, CPU_SSE); } + C M P L E S S { RET_INSN(7, ssecmpss, 0x02F3, CPU_SSE); } + C M P L T P S { RET_INSN(7, ssecmpps, 0x01, CPU_SSE); } + C M P L T S S { RET_INSN(7, ssecmpss, 0x01F3, CPU_SSE); } + C M P N E Q P S { RET_INSN(8, ssecmpps, 0x04, CPU_SSE); } + C M P N E Q S S { RET_INSN(8, ssecmpss, 0x04F3, CPU_SSE); } + C M P N L E P S { RET_INSN(8, ssecmpps, 0x06, CPU_SSE); } + C M P N L E S S { RET_INSN(8, ssecmpss, 0x06F3, CPU_SSE); } + C M P N L T P S { RET_INSN(8, ssecmpps, 0x05, CPU_SSE); } + C M P N L T S S { RET_INSN(8, ssecmpss, 0x05F3, CPU_SSE); } + C M P O R D P S { RET_INSN(8, ssecmpps, 0x07, CPU_SSE); } + C M P O R D S S { RET_INSN(8, ssecmpss, 0x07F3, CPU_SSE); } + C M P U N O R D P S { RET_INSN(10, ssecmpps, 0x03, CPU_SSE); } + C M P U N O R D S S { RET_INSN(10, ssecmpss, 0x03F3, CPU_SSE); } + C M P P S { RET_INSN(5, ssepsimm, 0xC2, CPU_SSE); } + C M P S S { RET_INSN(5, ssessimm, 0xF3C2, CPU_SSE); } + C O M I S S { RET_INSN(6, sseps, 0x2F, CPU_SSE); } + C V T P I "2" P S { RET_INSN(8, cvt_xmm_mm_ps, 0x2A, CPU_SSE); } + C V T P S "2" P I { RET_INSN(8, cvt_mm_xmm64, 0x2D, CPU_SSE); } + C V T S I "2" S S { RET_INSN(8, cvt_xmm_rmx, 0xF32A, CPU_SSE); } + C V T S S "2" S I { RET_INSN(8, cvt_rx_xmm32, 0xF32D, CPU_SSE); } + C V T T P S "2" P I { RET_INSN(9, cvt_mm_xmm64, 0x2C, CPU_SSE); } + C V T T S S "2" S I { RET_INSN(9, cvt_rx_xmm32, 0xF32C, CPU_SSE); } + D I V P S { RET_INSN(5, sseps, 0x5E, CPU_SSE); } + D I V S S { RET_INSN(5, ssess, 0xF35E, CPU_SSE); } + L D M X C S R { RET_INSN(7, ldstmxcsr, 0x02, CPU_SSE); } + M A S K M O V Q { RET_INSN(8, maskmovq, 0, CPU_P3|CPU_MMX); } + M A X P S { RET_INSN(5, sseps, 0x5F, CPU_SSE); } + M A X S S { RET_INSN_NS(ssess, 0xF35F, CPU_SSE); } + M I N P S { RET_INSN_NS(sseps, 0x5D, CPU_SSE); } + M I N S S { RET_INSN_NS(ssess, 0xF35D, CPU_SSE); } + M O V A P S { RET_INSN_NS(movaups, 0x28, CPU_SSE); } + M O V H L P S { RET_INSN_NS(movhllhps, 0x12, CPU_SSE); } + M O V H P S { RET_INSN_NS(movhlps, 0x16, CPU_SSE); } + M O V L H P S { RET_INSN_NS(movhllhps, 0x16, CPU_SSE); } + M O V L P S { RET_INSN_NS(movhlps, 0x12, CPU_SSE); } + M O V M S K P S { RET_INSN_NS(movmskps, 0, CPU_SSE); } + M O V N T P S { RET_INSN_NS(movntps, 0, CPU_SSE); } + M O V N T Q { RET_INSN_NS(movntq, 0, CPU_SSE); } + M O V S S { RET_INSN_NS(movss, 0, CPU_SSE); } + M O V U P S { RET_INSN_NS(movaups, 0x10, CPU_SSE); } + M U L P S { RET_INSN_NS(sseps, 0x59, CPU_SSE); } + M U L S S { RET_INSN_NS(ssess, 0xF359, CPU_SSE); } + O R P S { RET_INSN_NS(sseps, 0x56, CPU_SSE); } + P A V G B { RET_INSN_NS(mmxsse2, 0xE0, CPU_P3|CPU_MMX); } + P A V G W { RET_INSN_NS(mmxsse2, 0xE3, CPU_P3|CPU_MMX); } + P E X T R W { RET_INSN_NS(pextrw, 0, CPU_P3|CPU_MMX); } + P I N S R W { RET_INSN_NS(pinsrw, 0, CPU_P3|CPU_MMX); } + P M A X S W { RET_INSN_NS(mmxsse2, 0xEE, CPU_P3|CPU_MMX); } + P M A X U B { RET_INSN_NS(mmxsse2, 0xDE, CPU_P3|CPU_MMX); } + P M I N S W { RET_INSN_NS(mmxsse2, 0xEA, CPU_P3|CPU_MMX); } + P M I N U B { RET_INSN_NS(mmxsse2, 0xDA, CPU_P3|CPU_MMX); } + P M O V M S K B { RET_INSN_NS(pmovmskb, 0, CPU_SSE); } + P M U L H U W { RET_INSN_NS(mmxsse2, 0xE4, CPU_P3|CPU_MMX); } + P R E F E T C H N T A { RET_INSN_NS(twobytemem, 0x000F18, CPU_P3); } + P R E F E T C H T "0" { RET_INSN_NS(twobytemem, 0x010F18, CPU_P3); } + P R E F E T C H T "1" { RET_INSN_NS(twobytemem, 0x020F18, CPU_P3); } + P R E F E T C H T "2" { RET_INSN_NS(twobytemem, 0x030F18, CPU_P3); } + P S A D B W { RET_INSN_NS(mmxsse2, 0xF6, CPU_P3|CPU_MMX); } + P S H U F W { RET_INSN_NS(pshufw, 0, CPU_P3|CPU_MMX); } + R C P P S { RET_INSN_NS(sseps, 0x53, CPU_SSE); } + R C P S S { RET_INSN_NS(ssess, 0xF353, CPU_SSE); } + R S Q R T P S { RET_INSN_NS(sseps, 0x52, CPU_SSE); } + R S Q R T S S { RET_INSN_NS(ssess, 0xF352, CPU_SSE); } + S F E N C E { RET_INSN_NS(threebyte, 0x0FAEF8, CPU_P3); } + S H U F P S { RET_INSN_NS(ssepsimm, 0xC6, CPU_SSE); } + S Q R T P S { RET_INSN_NS(sseps, 0x51, CPU_SSE); } + S Q R T S S { RET_INSN_NS(ssess, 0xF351, CPU_SSE); } + S T M X C S R { RET_INSN_NS(ldstmxcsr, 0x03, CPU_SSE); } + S U B P S { RET_INSN_NS(sseps, 0x5C, CPU_SSE); } + S U B S S { RET_INSN_NS(ssess, 0xF35C, CPU_SSE); } + U C O M I S S { RET_INSN_NS(ssess, 0x2E, CPU_SSE); } + U N P C K H P S { RET_INSN_NS(sseps, 0x15, CPU_SSE); } + U N P C K L P S { RET_INSN_NS(sseps, 0x14, CPU_SSE); } + X O R P S { RET_INSN_NS(sseps, 0x57, CPU_SSE); } /* SSE2 instructions */ - A D D P D { RET_INSN(ssess, 0x6658, CPU_SSE2); } - A D D S D { RET_INSN(ssess, 0xF258, CPU_SSE2); } - A N D N P D { RET_INSN(ssess, 0x6655, CPU_SSE2); } - A N D P D { RET_INSN(ssess, 0x6654, CPU_SSE2); } - C M P E Q P D { RET_INSN(ssecmpss, 0x0066, CPU_SSE2); } - C M P E Q S D { RET_INSN(ssecmpss, 0x00F2, CPU_SSE2); } - C M P L E P D { RET_INSN(ssecmpss, 0x0266, CPU_SSE2); } - C M P L E S D { RET_INSN(ssecmpss, 0x02F2, CPU_SSE2); } - C M P L T P D { RET_INSN(ssecmpss, 0x0166, CPU_SSE2); } - C M P L T S D { RET_INSN(ssecmpss, 0x01F2, CPU_SSE2); } - C M P N E Q P D { RET_INSN(ssecmpss, 0x0466, CPU_SSE2); } - C M P N E Q S D { RET_INSN(ssecmpss, 0x04F2, CPU_SSE2); } - C M P N L E P D { RET_INSN(ssecmpss, 0x0666, CPU_SSE2); } - C M P N L E S D { RET_INSN(ssecmpss, 0x06F2, CPU_SSE2); } - C M P N L T P D { RET_INSN(ssecmpss, 0x0566, CPU_SSE2); } - C M P N L T S D { RET_INSN(ssecmpss, 0x05F2, CPU_SSE2); } - C M P O R D P D { RET_INSN(ssecmpss, 0x0766, CPU_SSE2); } - C M P O R D S D { RET_INSN(ssecmpss, 0x07F2, CPU_SSE2); } - C M P U N O R D P D { RET_INSN(ssecmpss, 0x0366, CPU_SSE2); } - C M P U N O R D S D { RET_INSN(ssecmpss, 0x03F2, CPU_SSE2); } - C M P P D { RET_INSN(ssessimm, 0x66C2, CPU_SSE2); } + A D D P D { RET_INSN_NS(ssess, 0x6658, CPU_SSE2); } + A D D S D { RET_INSN_NS(ssess, 0xF258, CPU_SSE2); } + A N D N P D { RET_INSN_NS(ssess, 0x6655, CPU_SSE2); } + A N D P D { RET_INSN_NS(ssess, 0x6654, CPU_SSE2); } + C M P E Q P D { RET_INSN_NS(ssecmpss, 0x0066, CPU_SSE2); } + C M P E Q S D { RET_INSN_NS(ssecmpss, 0x00F2, CPU_SSE2); } + C M P L E P D { RET_INSN_NS(ssecmpss, 0x0266, CPU_SSE2); } + C M P L E S D { RET_INSN_NS(ssecmpss, 0x02F2, CPU_SSE2); } + C M P L T P D { RET_INSN_NS(ssecmpss, 0x0166, CPU_SSE2); } + C M P L T S D { RET_INSN_NS(ssecmpss, 0x01F2, CPU_SSE2); } + C M P N E Q P D { RET_INSN_NS(ssecmpss, 0x0466, CPU_SSE2); } + C M P N E Q S D { RET_INSN_NS(ssecmpss, 0x04F2, CPU_SSE2); } + C M P N L E P D { RET_INSN_NS(ssecmpss, 0x0666, CPU_SSE2); } + C M P N L E S D { RET_INSN_NS(ssecmpss, 0x06F2, CPU_SSE2); } + C M P N L T P D { RET_INSN_NS(ssecmpss, 0x0566, CPU_SSE2); } + C M P N L T S D { RET_INSN_NS(ssecmpss, 0x05F2, CPU_SSE2); } + C M P O R D P D { RET_INSN_NS(ssecmpss, 0x0766, CPU_SSE2); } + C M P O R D S D { RET_INSN_NS(ssecmpss, 0x07F2, CPU_SSE2); } + C M P U N O R D P D { RET_INSN_NS(ssecmpss, 0x0366, CPU_SSE2); } + C M P U N O R D S D { RET_INSN_NS(ssecmpss, 0x03F2, CPU_SSE2); } + C M P P D { RET_INSN_NS(ssessimm, 0x66C2, CPU_SSE2); } /* C M P S D is in string instructions above */ - C O M I S D { RET_INSN(ssess, 0x662F, CPU_SSE2); } - C V T P I "2" P D { RET_INSN(cvt_xmm_mm_ss, 0x662A, CPU_SSE2); } - C V T S I "2" S D { RET_INSN(cvt_xmm_rmx, 0xF22A, CPU_SSE2); } - D I V P D { RET_INSN(ssess, 0x665E, CPU_SSE2); } - D I V S D { RET_INSN(ssess, 0xF25E, CPU_SSE2); } - M A X P D { RET_INSN(ssess, 0x665F, CPU_SSE2); } - M A X S D { RET_INSN(ssess, 0xF25F, CPU_SSE2); } - M I N P D { RET_INSN(ssess, 0x665D, CPU_SSE2); } - M I N S D { RET_INSN(ssess, 0xF25D, CPU_SSE2); } - M O V A P D { RET_INSN(movaupd, 0x28, CPU_SSE2); } - M O V H P D { RET_INSN(movhlpd, 0x16, CPU_SSE2); } - M O V L P D { RET_INSN(movhlpd, 0x12, CPU_SSE2); } - M O V M S K P D { RET_INSN(movmskpd, 0, CPU_SSE2); } - M O V N T P D { RET_INSN(movntpddq, 0x2B, CPU_SSE2); } - M O V N T D Q { RET_INSN(movntpddq, 0xE7, CPU_SSE2); } + C O M I S D { RET_INSN_NS(ssess, 0x662F, CPU_SSE2); } + C V T P I "2" P D { RET_INSN_NS(cvt_xmm_mm_ss, 0x662A, CPU_SSE2); } + C V T S I "2" S D { RET_INSN_NS(cvt_xmm_rmx, 0xF22A, CPU_SSE2); } + D I V P D { RET_INSN_NS(ssess, 0x665E, CPU_SSE2); } + D I V S D { RET_INSN_NS(ssess, 0xF25E, CPU_SSE2); } + M A X P D { RET_INSN_NS(ssess, 0x665F, CPU_SSE2); } + M A X S D { RET_INSN_NS(ssess, 0xF25F, CPU_SSE2); } + M I N P D { RET_INSN_NS(ssess, 0x665D, CPU_SSE2); } + M I N S D { RET_INSN_NS(ssess, 0xF25D, CPU_SSE2); } + M O V A P D { RET_INSN_NS(movaupd, 0x28, CPU_SSE2); } + M O V H P D { RET_INSN_NS(movhlpd, 0x16, CPU_SSE2); } + M O V L P D { RET_INSN_NS(movhlpd, 0x12, CPU_SSE2); } + M O V M S K P D { RET_INSN_NS(movmskpd, 0, CPU_SSE2); } + M O V N T P D { RET_INSN_NS(movntpddq, 0x2B, CPU_SSE2); } + M O V N T D Q { RET_INSN_NS(movntpddq, 0xE7, CPU_SSE2); } /* M O V S D is in string instructions above */ - M O V U P D { RET_INSN(movaupd, 0x10, CPU_SSE2); } - M U L P D { RET_INSN(ssess, 0x6659, CPU_SSE2); } - M U L S D { RET_INSN(ssess, 0xF259, CPU_SSE2); } - O R P D { RET_INSN(ssess, 0x6656, CPU_SSE2); } - S H U F P D { RET_INSN(ssessimm, 0x66C6, CPU_SSE2); } - S Q R T P D { RET_INSN(ssess, 0x6651, CPU_SSE2); } - S Q R T S D { RET_INSN(ssess, 0xF251, CPU_SSE2); } - S U B P D { RET_INSN(ssess, 0x665C, CPU_SSE2); } - S U B S D { RET_INSN(ssess, 0xF25C, CPU_SSE2); } - U C O M I S D { RET_INSN(ssess, 0x662E, CPU_SSE2); } - U N P C K H P D { RET_INSN(ssess, 0x6615, CPU_SSE2); } - U N P C K L P D { RET_INSN(ssess, 0x6614, CPU_SSE2); } - X O R P D { RET_INSN(ssess, 0x6657, CPU_SSE2); } - C V T D Q "2" P D { RET_INSN(cvt_xmm_xmm64_ss, 0xF3E6, CPU_SSE2); } - C V T P D "2" D Q { RET_INSN(ssess, 0xF2E6, CPU_SSE2); } - C V T D Q "2" P S { RET_INSN(sseps, 0x5B, CPU_SSE2); } - C V T P D "2" P I { RET_INSN(cvt_mm_xmm, 0x662D, CPU_SSE2); } - C V T P D "2" P S { RET_INSN(ssess, 0x665A, CPU_SSE2); } - C V T P S "2" P D { RET_INSN(cvt_xmm_xmm64_ps, 0x5A, CPU_SSE2); } - C V T P S "2" D Q { RET_INSN(ssess, 0x665B, CPU_SSE2); } - C V T S D "2" S I { RET_INSN(cvt_rx_xmm64, 0xF22D, CPU_SSE2); } - C V T S D "2" S S { RET_INSN(cvt_xmm_xmm64_ss, 0xF25A, CPU_SSE2); } + M O V U P D { RET_INSN_NS(movaupd, 0x10, CPU_SSE2); } + M U L P D { RET_INSN_NS(ssess, 0x6659, CPU_SSE2); } + M U L S D { RET_INSN_NS(ssess, 0xF259, CPU_SSE2); } + O R P D { RET_INSN_NS(ssess, 0x6656, CPU_SSE2); } + S H U F P D { RET_INSN_NS(ssessimm, 0x66C6, CPU_SSE2); } + S Q R T P D { RET_INSN_NS(ssess, 0x6651, CPU_SSE2); } + S Q R T S D { RET_INSN_NS(ssess, 0xF251, CPU_SSE2); } + S U B P D { RET_INSN_NS(ssess, 0x665C, CPU_SSE2); } + S U B S D { RET_INSN_NS(ssess, 0xF25C, CPU_SSE2); } + U C O M I S D { RET_INSN_NS(ssess, 0x662E, CPU_SSE2); } + U N P C K H P D { RET_INSN_NS(ssess, 0x6615, CPU_SSE2); } + U N P C K L P D { RET_INSN_NS(ssess, 0x6614, CPU_SSE2); } + X O R P D { RET_INSN_NS(ssess, 0x6657, CPU_SSE2); } + C V T D Q "2" P D { RET_INSN_NS(cvt_xmm_xmm64_ss, 0xF3E6, CPU_SSE2); } + C V T P D "2" D Q { RET_INSN_NS(ssess, 0xF2E6, CPU_SSE2); } + C V T D Q "2" P S { RET_INSN_NS(sseps, 0x5B, CPU_SSE2); } + C V T P D "2" P I { RET_INSN_NS(cvt_mm_xmm, 0x662D, CPU_SSE2); } + C V T P D "2" P S { RET_INSN_NS(ssess, 0x665A, CPU_SSE2); } + C V T P S "2" P D { RET_INSN_NS(cvt_xmm_xmm64_ps, 0x5A, CPU_SSE2); } + C V T P S "2" D Q { RET_INSN_NS(ssess, 0x665B, CPU_SSE2); } + C V T S D "2" S I { RET_INSN_NS(cvt_rx_xmm64, 0xF22D, CPU_SSE2); } + C V T S D "2" S S { RET_INSN_NS(cvt_xmm_xmm64_ss, 0xF25A, CPU_SSE2); } /* P4 VMX Instructions */ - V M C A L L { RET_INSN(threebyte, 0x0F01C1, CPU_P4); } - V M L A U N C H { RET_INSN(threebyte, 0x0F01C2, CPU_P4); } - V M R E S U M E { RET_INSN(threebyte, 0x0F01C3, CPU_P4); } - V M X O F F { RET_INSN(threebyte, 0x0F01C4, CPU_P4); } - V M R E A D { RET_INSN(vmxmemrd, 0x0F78, CPU_P4); } - V M W R I T E { RET_INSN(vmxmemwr, 0x0F79, CPU_P4); } - V M P T R L D { RET_INSN(vmxtwobytemem, 0x06C7, CPU_P4); } - V M P T R S T { RET_INSN(vmxtwobytemem, 0x07C7, CPU_P4); } - V M C L E A R { RET_INSN(vmxthreebytemem, 0x0666C7, CPU_P4); } - V M X O N { RET_INSN(vmxthreebytemem, 0x06F3C7, CPU_P4); } - C V T S S "2" S D { RET_INSN(cvt_xmm_xmm32, 0xF35A, CPU_SSE2); } - C V T T P D "2" P I { RET_INSN(cvt_mm_xmm, 0x662C, CPU_SSE2); } - C V T T S D "2" S I { RET_INSN(cvt_rx_xmm64, 0xF22C, CPU_SSE2); } - C V T T P D "2" D Q { RET_INSN(ssess, 0x66E6, CPU_SSE2); } - C V T T P S "2" D Q { RET_INSN(ssess, 0xF35B, CPU_SSE2); } - M A S K M O V D Q U { RET_INSN(maskmovdqu, 0, CPU_SSE2); } - M O V D Q A { RET_INSN(movdqau, 0x66, CPU_SSE2); } - M O V D Q U { RET_INSN(movdqau, 0xF3, CPU_SSE2); } - M O V D Q "2" Q { RET_INSN(movdq2q, 0, CPU_SSE2); } - M O V Q "2" D Q { RET_INSN(movq2dq, 0, CPU_SSE2); } - P M U L U D Q { RET_INSN(mmxsse2, 0xF4, CPU_SSE2); } - P S H U F D { RET_INSN(ssessimm, 0x6670, CPU_SSE2); } - P S H U F H W { RET_INSN(ssessimm, 0xF370, CPU_SSE2); } - P S H U F L W { RET_INSN(ssessimm, 0xF270, CPU_SSE2); } - P S L L D Q { RET_INSN(pslrldq, 0x07, CPU_SSE2); } - P S R L D Q { RET_INSN(pslrldq, 0x03, CPU_SSE2); } - P U N P C K H Q D Q { RET_INSN(ssess, 0x666D, CPU_SSE2); } - P U N P C K L Q D Q { RET_INSN(ssess, 0x666C, CPU_SSE2); } + V M C A L L { RET_INSN_NS(threebyte, 0x0F01C1, CPU_P4); } + V M L A U N C H { RET_INSN_NS(threebyte, 0x0F01C2, CPU_P4); } + V M R E S U M E { RET_INSN_NS(threebyte, 0x0F01C3, CPU_P4); } + V M X O F F { RET_INSN_NS(threebyte, 0x0F01C4, CPU_P4); } + V M R E A D { RET_INSN_NS(vmxmemrd, 0x0F78, CPU_P4); } + V M W R I T E { RET_INSN_NS(vmxmemwr, 0x0F79, CPU_P4); } + V M P T R L D { RET_INSN_NS(vmxtwobytemem, 0x06C7, CPU_P4); } + V M P T R S T { RET_INSN_NS(vmxtwobytemem, 0x07C7, CPU_P4); } + V M C L E A R { RET_INSN_NS(vmxthreebytemem, 0x0666C7, CPU_P4); } + V M X O N { RET_INSN_NS(vmxthreebytemem, 0x06F3C7, CPU_P4); } + C V T S S "2" S D { RET_INSN_NS(cvt_xmm_xmm32, 0xF35A, CPU_SSE2); } + C V T T P D "2" P I { RET_INSN_NS(cvt_mm_xmm, 0x662C, CPU_SSE2); } + C V T T S D "2" S I { RET_INSN_NS(cvt_rx_xmm64, 0xF22C, CPU_SSE2); } + C V T T P D "2" D Q { RET_INSN_NS(ssess, 0x66E6, CPU_SSE2); } + C V T T P S "2" D Q { RET_INSN_NS(ssess, 0xF35B, CPU_SSE2); } + M A S K M O V D Q U { RET_INSN_NS(maskmovdqu, 0, CPU_SSE2); } + M O V D Q A { RET_INSN_NS(movdqau, 0x66, CPU_SSE2); } + M O V D Q U { RET_INSN_NS(movdqau, 0xF3, CPU_SSE2); } + M O V D Q "2" Q { RET_INSN_NS(movdq2q, 0, CPU_SSE2); } + M O V Q "2" D Q { RET_INSN_NS(movq2dq, 0, CPU_SSE2); } + P M U L U D Q { RET_INSN_NS(mmxsse2, 0xF4, CPU_SSE2); } + P S H U F D { RET_INSN_NS(ssessimm, 0x6670, CPU_SSE2); } + P S H U F H W { RET_INSN_NS(ssessimm, 0xF370, CPU_SSE2); } + P S H U F L W { RET_INSN_NS(ssessimm, 0xF270, CPU_SSE2); } + P S L L D Q { RET_INSN_NS(pslrldq, 0x07, CPU_SSE2); } + P S R L D Q { RET_INSN_NS(pslrldq, 0x03, CPU_SSE2); } + P U N P C K H Q D Q { RET_INSN_NS(ssess, 0x666D, CPU_SSE2); } + P U N P C K L Q D Q { RET_INSN_NS(ssess, 0x666C, CPU_SSE2); } /* SSE3 / PNI (Prescott New Instructions) instructions */ - A D D S U B P D { RET_INSN(ssess, 0x66D0, CPU_SSE3); } - A D D S U B P S { RET_INSN(ssess, 0xF2D0, CPU_SSE3); } - F I S T T P { RET_INSN(fildstp, 0x010001, CPU_SSE3); } - H A D D P D { RET_INSN(ssess, 0x667C, CPU_SSE3); } - H A D D P S { RET_INSN(ssess, 0xF27C, CPU_SSE3); } - H S U B P D { RET_INSN(ssess, 0x667D, CPU_SSE3); } - H S U B P S { RET_INSN(ssess, 0xF27D, CPU_SSE3); } - L D D Q U { RET_INSN(lddqu, 0, CPU_SSE3); } - M O N I T O R { RET_INSN(threebyte, 0x0F01C8, CPU_SSE3); } - M O V D D U P { RET_INSN(cvt_xmm_xmm64_ss, 0xF212, CPU_SSE3); } - M O V S H D U P { RET_INSN(ssess, 0xF316, CPU_SSE3); } - M O V S L D U P { RET_INSN(ssess, 0xF312, CPU_SSE3); } - M W A I T { RET_INSN(threebyte, 0x0F01C9, CPU_SSE3); } + A D D S U B P D { RET_INSN_NS(ssess, 0x66D0, CPU_SSE3); } + A D D S U B P S { RET_INSN_NS(ssess, 0xF2D0, CPU_SSE3); } + F I S T T P { RET_INSN_NS(fildstp, 0x010001, CPU_SSE3); } + H A D D P D { RET_INSN_NS(ssess, 0x667C, CPU_SSE3); } + H A D D P S { RET_INSN_NS(ssess, 0xF27C, CPU_SSE3); } + H S U B P D { RET_INSN_NS(ssess, 0x667D, CPU_SSE3); } + H S U B P S { RET_INSN_NS(ssess, 0xF27D, CPU_SSE3); } + L D D Q U { RET_INSN_NS(lddqu, 0, CPU_SSE3); } + M O N I T O R { RET_INSN_NS(threebyte, 0x0F01C8, CPU_SSE3); } + M O V D D U P { RET_INSN_NS(cvt_xmm_xmm64_ss, 0xF212, CPU_SSE3); } + M O V S H D U P { RET_INSN_NS(ssess, 0xF316, CPU_SSE3); } + M O V S L D U P { RET_INSN_NS(ssess, 0xF312, CPU_SSE3); } + M W A I T { RET_INSN_NS(threebyte, 0x0F01C9, CPU_SSE3); } /* AMD 3DNow! instructions */ - P R E F E T C H { RET_INSN(twobytemem, 0x000F0D, CPU_3DNow); } - P R E F E T C H W { RET_INSN(twobytemem, 0x010F0D, CPU_3DNow); } - F E M M S { RET_INSN(twobyte, 0x0F0E, CPU_3DNow); } - P A V G U S B { RET_INSN(now3d, 0xBF, CPU_3DNow); } - P F "2" I D { RET_INSN(now3d, 0x1D, CPU_3DNow); } - P F "2" I W { RET_INSN(now3d, 0x1C, CPU_Athlon|CPU_3DNow); } - P F A C C { RET_INSN(now3d, 0xAE, CPU_3DNow); } - P F A D D { RET_INSN(now3d, 0x9E, CPU_3DNow); } - P F C M P E Q { RET_INSN(now3d, 0xB0, CPU_3DNow); } - P F C M P G E { RET_INSN(now3d, 0x90, CPU_3DNow); } - P F C M P G T { RET_INSN(now3d, 0xA0, CPU_3DNow); } - P F M A X { RET_INSN(now3d, 0xA4, CPU_3DNow); } - P F M I N { RET_INSN(now3d, 0x94, CPU_3DNow); } - P F M U L { RET_INSN(now3d, 0xB4, CPU_3DNow); } - P F N A C C { RET_INSN(now3d, 0x8A, CPU_Athlon|CPU_3DNow); } - P F P N A C C { RET_INSN(now3d, 0x8E, CPU_Athlon|CPU_3DNow); } - P F R C P { RET_INSN(now3d, 0x96, CPU_3DNow); } - P F R C P I T "1" { RET_INSN(now3d, 0xA6, CPU_3DNow); } - P F R C P I T "2" { RET_INSN(now3d, 0xB6, CPU_3DNow); } - P F R S Q I T "1" { RET_INSN(now3d, 0xA7, CPU_3DNow); } - P F R S Q R T { RET_INSN(now3d, 0x97, CPU_3DNow); } - P F S U B { RET_INSN(now3d, 0x9A, CPU_3DNow); } - P F S U B R { RET_INSN(now3d, 0xAA, CPU_3DNow); } - P I "2" F D { RET_INSN(now3d, 0x0D, CPU_3DNow); } - P I "2" F W { RET_INSN(now3d, 0x0C, CPU_Athlon|CPU_3DNow); } - P M U L H R W A { RET_INSN(now3d, 0xB7, CPU_3DNow); } - P S W A P D { RET_INSN(now3d, 0xBB, CPU_Athlon|CPU_3DNow); } + P R E F E T C H { RET_INSN_NS(twobytemem, 0x000F0D, CPU_3DNow); } + P R E F E T C H W { RET_INSN_NS(twobytemem, 0x010F0D, CPU_3DNow); } + F E M M S { RET_INSN_NS(twobyte, 0x0F0E, CPU_3DNow); } + P A V G U S B { RET_INSN_NS(now3d, 0xBF, CPU_3DNow); } + P F "2" I D { RET_INSN_NS(now3d, 0x1D, CPU_3DNow); } + P F "2" I W { RET_INSN_NS(now3d, 0x1C, CPU_Athlon|CPU_3DNow); } + P F A C C { RET_INSN_NS(now3d, 0xAE, CPU_3DNow); } + P F A D D { RET_INSN_NS(now3d, 0x9E, CPU_3DNow); } + P F C M P E Q { RET_INSN_NS(now3d, 0xB0, CPU_3DNow); } + P F C M P G E { RET_INSN_NS(now3d, 0x90, CPU_3DNow); } + P F C M P G T { RET_INSN_NS(now3d, 0xA0, CPU_3DNow); } + P F M A X { RET_INSN_NS(now3d, 0xA4, CPU_3DNow); } + P F M I N { RET_INSN_NS(now3d, 0x94, CPU_3DNow); } + P F M U L { RET_INSN_NS(now3d, 0xB4, CPU_3DNow); } + P F N A C C { RET_INSN_NS(now3d, 0x8A, CPU_Athlon|CPU_3DNow); } + P F P N A C C { RET_INSN_NS(now3d, 0x8E, CPU_Athlon|CPU_3DNow); } + P F R C P { RET_INSN_NS(now3d, 0x96, CPU_3DNow); } + P F R C P I T "1" { RET_INSN_NS(now3d, 0xA6, CPU_3DNow); } + P F R C P I T "2" { RET_INSN_NS(now3d, 0xB6, CPU_3DNow); } + P F R S Q I T "1" { RET_INSN_NS(now3d, 0xA7, CPU_3DNow); } + P F R S Q R T { RET_INSN_NS(now3d, 0x97, CPU_3DNow); } + P F S U B { RET_INSN(5, now3d, 0x9A, CPU_3DNow); } + P F S U B R { RET_INSN(6, now3d, 0xAA, CPU_3DNow); } + P I "2" F D { RET_INSN(5, now3d, 0x0D, CPU_3DNow); } + P I "2" F W { RET_INSN(5, now3d, 0x0C, CPU_Athlon|CPU_3DNow); } + P M U L H R W A { RET_INSN(8, now3d, 0xB7, CPU_3DNow); } + P S W A P D { RET_INSN(6, now3d, 0xBB, CPU_Athlon|CPU_3DNow); } /* AMD extensions */ - S Y S C A L L { RET_INSN(twobyte, 0x0F05, CPU_686|CPU_AMD); } - S Y S R E T { RET_INSN(twobyte, 0x0F07, CPU_686|CPU_AMD|CPU_Priv); } + S Y S C A L L { RET_INSN(7, twobyte, 0x0F05, CPU_686|CPU_AMD); } + S Y S R E T { RET_INSN(6, twobyte, 0x0F07, CPU_686|CPU_AMD|CPU_Priv); } /* AMD x86-64 extensions */ S W A P G S { - if (arch_x86->mode_bits != 64) { - yasm__warning(YASM_WARN_GENERAL, line, - N_("`%s' is an instruction in 64-bit mode"), - oid); - return YASM_ARCH_CHECK_ID_NONE; - } - RET_INSN(threebyte, 0x0F01F8, CPU_Hammer|CPU_64); + warn64 = 1; + RET_INSN(6, threebyte, 0x0F01F8, CPU_Hammer|CPU_64); } /* Cyrix MMX instructions */ - P A D D S I W { RET_INSN(cyrixmmx, 0x51, CPU_Cyrix|CPU_MMX); } - P A V E B { RET_INSN(cyrixmmx, 0x50, CPU_Cyrix|CPU_MMX); } - P D I S T I B { RET_INSN(cyrixmmx, 0x54, CPU_Cyrix|CPU_MMX); } - P M A C H R I W { RET_INSN(pmachriw, 0, CPU_Cyrix|CPU_MMX); } - P M A G W { RET_INSN(cyrixmmx, 0x52, CPU_Cyrix|CPU_MMX); } - P M U L H R I W { RET_INSN(cyrixmmx, 0x5D, CPU_Cyrix|CPU_MMX); } - P M U L H R W C { RET_INSN(cyrixmmx, 0x59, CPU_Cyrix|CPU_MMX); } - P M V G E Z B { RET_INSN(cyrixmmx, 0x5C, CPU_Cyrix|CPU_MMX); } - P M V L Z B { RET_INSN(cyrixmmx, 0x5B, CPU_Cyrix|CPU_MMX); } - P M V N Z B { RET_INSN(cyrixmmx, 0x5A, CPU_Cyrix|CPU_MMX); } - P M V Z B { RET_INSN(cyrixmmx, 0x58, CPU_Cyrix|CPU_MMX); } - P S U B S I W { RET_INSN(cyrixmmx, 0x55, CPU_Cyrix|CPU_MMX); } + P A D D S I W { RET_INSN(7, cyrixmmx, 0x51, CPU_Cyrix|CPU_MMX); } + P A V E B { RET_INSN(5, cyrixmmx, 0x50, CPU_Cyrix|CPU_MMX); } + P D I S T I B { RET_INSN(7, cyrixmmx, 0x54, CPU_Cyrix|CPU_MMX); } + P M A C H R I W { RET_INSN(8, pmachriw, 0, CPU_Cyrix|CPU_MMX); } + P M A G W { RET_INSN(5, cyrixmmx, 0x52, CPU_Cyrix|CPU_MMX); } + P M U L H R I W { RET_INSN(8, cyrixmmx, 0x5D, CPU_Cyrix|CPU_MMX); } + P M U L H R W C { RET_INSN(8, cyrixmmx, 0x59, CPU_Cyrix|CPU_MMX); } + P M V G E Z B { RET_INSN(7, cyrixmmx, 0x5C, CPU_Cyrix|CPU_MMX); } + P M V L Z B { RET_INSN(6, cyrixmmx, 0x5B, CPU_Cyrix|CPU_MMX); } + P M V N Z B { RET_INSN(6, cyrixmmx, 0x5A, CPU_Cyrix|CPU_MMX); } + P M V Z B { RET_INSN(5, cyrixmmx, 0x58, CPU_Cyrix|CPU_MMX); } + P S U B S I W { RET_INSN(7, cyrixmmx, 0x55, CPU_Cyrix|CPU_MMX); } /* Cyrix extensions */ - R D S H R { RET_INSN(twobyte, 0x0F36, CPU_686|CPU_Cyrix|CPU_SMM); } - R S D C { RET_INSN(rsdc, 0, CPU_486|CPU_Cyrix|CPU_SMM); } - R S L D T { RET_INSN(cyrixsmm, 0x7B, CPU_486|CPU_Cyrix|CPU_SMM); } - R S T S { RET_INSN(cyrixsmm, 0x7D, CPU_486|CPU_Cyrix|CPU_SMM); } - S V D C { RET_INSN(svdc, 0, CPU_486|CPU_Cyrix|CPU_SMM); } - S V L D T { RET_INSN(cyrixsmm, 0x7A, CPU_486|CPU_Cyrix|CPU_SMM); } - S V T S { RET_INSN(cyrixsmm, 0x7C, CPU_486|CPU_Cyrix|CPU_SMM); } - S M I N T { RET_INSN(twobyte, 0x0F38, CPU_686|CPU_Cyrix); } - S M I N T O L D { RET_INSN(twobyte, 0x0F7E, CPU_486|CPU_Cyrix|CPU_Obs); } - W R S H R { RET_INSN(twobyte, 0x0F37, CPU_686|CPU_Cyrix|CPU_SMM); } + R D S H R { RET_INSN(5, twobyte, 0x0F36, CPU_686|CPU_Cyrix|CPU_SMM); } + R S D C { RET_INSN(4, rsdc, 0, CPU_486|CPU_Cyrix|CPU_SMM); } + R S L D T { RET_INSN(5, cyrixsmm, 0x7B, CPU_486|CPU_Cyrix|CPU_SMM); } + R S T S { RET_INSN(4, cyrixsmm, 0x7D, CPU_486|CPU_Cyrix|CPU_SMM); } + S V D C { RET_INSN(4, svdc, 0, CPU_486|CPU_Cyrix|CPU_SMM); } + S V L D T { RET_INSN(5, cyrixsmm, 0x7A, CPU_486|CPU_Cyrix|CPU_SMM); } + S V T S { RET_INSN(4, cyrixsmm, 0x7C, CPU_486|CPU_Cyrix|CPU_SMM); } + S M I N T { RET_INSN(5, twobyte, 0x0F38, CPU_686|CPU_Cyrix); } + S M I N T O L D { RET_INSN(8, twobyte, 0x0F7E, CPU_486|CPU_Cyrix|CPU_Obs); } + W R S H R { RET_INSN(5, twobyte, 0x0F37, CPU_686|CPU_Cyrix|CPU_SMM); } /* Obsolete/undocumented instructions */ - F S E T P M { RET_INSN(twobyte, 0xDBE4, CPU_286|CPU_FPU|CPU_Obs); } - I B T S { RET_INSN(ibts, 0, CPU_386|CPU_Undoc|CPU_Obs); } - L O A D A L L { RET_INSN(twobyte, 0x0F07, CPU_386|CPU_Undoc); } - L O A D A L L "286" { RET_INSN(twobyte, 0x0F05, CPU_286|CPU_Undoc); } + F S E T P M { RET_INSN(6, twobyte, 0xDBE4, CPU_286|CPU_FPU|CPU_Obs); } + I B T S { RET_INSN(4, ibts, 0, CPU_386|CPU_Undoc|CPU_Obs); } + L O A D A L L { RET_INSN(7, twobyte, 0x0F07, CPU_386|CPU_Undoc); } + L O A D A L L "286" { RET_INSN(10, twobyte, 0x0F05, CPU_286|CPU_Undoc); } S A L C { - if (arch_x86->mode_bits == 64) { - yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); - RET_INSN(not64, 0, CPU_Not64); - } - RET_INSN(onebyte, 0x00D6, CPU_Undoc); + not64 = 1; + RET_INSN(4, onebyte, 0x00D6, CPU_Undoc); } - S M I { RET_INSN(onebyte, 0x00F1, CPU_386|CPU_Undoc); } - U M O V { RET_INSN(umov, 0, CPU_386|CPU_Undoc); } - X B T S { RET_INSN(xbts, 0, CPU_386|CPU_Undoc|CPU_Obs); } + S M I { RET_INSN(3, onebyte, 0x00F1, CPU_386|CPU_Undoc); } + U M O V { RET_INSN(4, umov, 0, CPU_386|CPU_Undoc); } + X B T S { RET_INSN(4, xbts, 0, CPU_386|CPU_Undoc|CPU_Obs); } /* catchalls */ @@ -4019,4 +4103,69 @@ yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], return YASM_ARCH_CHECK_ID_NONE; } */ +done: + if (suffix) { + /* If not using the GAS parser, no instructions have suffixes. */ + if (arch_x86->parser != X86_PARSER_GAS) + return YASM_ARCH_CHECK_ID_NONE; + + /* Match suffixes */ + switch (id[-1]) { + case 'b': + case 'B': + data[3] |= (MOD_GasSufB >> MOD_GasSuf_SHIFT) << 8; + break; + case 'w': + case 'W': + data[3] |= (MOD_GasSufW >> MOD_GasSuf_SHIFT) << 8; + break; + case 'l': + case 'L': + data[3] |= (MOD_GasSufL >> MOD_GasSuf_SHIFT) << 8; + break; + case 'q': + case 'Q': + data[3] |= (MOD_GasSufQ >> MOD_GasSuf_SHIFT) << 8; + break; + default: + yasm_internal_error(N_("unrecognized suffix")); + } + } + if (warn64 && arch_x86->mode_bits != 64) { + yasm__warning(YASM_WARN_GENERAL, line, + N_("`%s' is an instruction in 64-bit mode"), + oid); + return YASM_ARCH_CHECK_ID_NONE; + } + if (not64 && arch_x86->mode_bits == 64) { + yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid); + DEF_INSN_DATA(not64, 0, CPU_Not64); + return YASM_ARCH_CHECK_ID_INSN; + } + return YASM_ARCH_CHECK_ID_INSN; +} + +yasm_arch_check_id_retval +yasm_x86__parse_check_id(yasm_arch *arch, unsigned long data[4], + const char *id, unsigned long line) +{ + yasm_arch_check_id_retval rv; + + rv = yasm_x86__parse_check_reg(arch, data, id, line); + if (rv != YASM_ARCH_CHECK_ID_NONE) + return rv; + + rv = yasm_x86__parse_check_insn(arch, data, id, line); + if (rv != YASM_ARCH_CHECK_ID_NONE) + return rv; + + rv = yasm_x86__parse_check_prefix(arch, data, id, line); + if (rv != YASM_ARCH_CHECK_ID_NONE) + return rv; + + rv = yasm_x86__parse_check_targetmod(arch, data, id, line); + if (rv != YASM_ARCH_CHECK_ID_NONE) + return rv; + + return YASM_ARCH_CHECK_ID_NONE; } diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index 1e63ae2b..af0622a2 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -742,11 +742,29 @@ elf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams, if (match) ; - else if (yasm__strcasecmp(vp->val, "progbits") == 0) { + else if (yasm__strncasecmp(vp->val, "gas_", 4) == 0) { + /* GAS-style flags */ + flags = 0; + for (i=4; ival); i++) { + switch (vp->val[i]) { + case 'a': + flags |= SHF_ALLOC; + break; + case 'w': + flags |= SHF_WRITE; + break; + case 'x': + flags |= SHF_EXECINSTR; + break; + } + } + } else if (yasm__strcasecmp(vp->val, "progbits") == 0) { type |= SHT_PROGBITS; } - else if (yasm__strcasecmp(vp->val, "noprogbits") == 0) { + else if (yasm__strcasecmp(vp->val, "noprogbits") == 0 || + yasm__strcasecmp(vp->val, "nobits") == 0) { type &= ~SHT_PROGBITS; + type |= SHT_NOBITS; } else if (yasm__strcasecmp(vp->val, "align") == 0 && vp->param) { /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; diff --git a/modules/parsers/Makefile.inc b/modules/parsers/Makefile.inc index 64eab57f..eabd5f60 100644 --- a/modules/parsers/Makefile.inc +++ b/modules/parsers/Makefile.inc @@ -1,5 +1,7 @@ # $Id$ +EXTRA_DIST += modules/parsers/gas/Makefile.inc EXTRA_DIST += modules/parsers/nasm/Makefile.inc +include modules/parsers/gas/Makefile.inc include modules/parsers/nasm/Makefile.inc diff --git a/modules/parsers/gas/Makefile.inc b/modules/parsers/gas/Makefile.inc new file mode 100644 index 00000000..5b6e2f70 --- /dev/null +++ b/modules/parsers/gas/Makefile.inc @@ -0,0 +1,28 @@ +# $Id$ + +libyasm_a_SOURCES += modules/parsers/gas/gas-parser.c +libyasm_a_SOURCES += modules/parsers/gas/gas-parser.h +libyasm_a_SOURCES += modules/parsers/gas/gas-defs.h +libyasm_a_SOURCES += modules/parsers/gas/gas-bison.y +libyasm_a_SOURCES += gas-bison.h +libyasm_a_SOURCES += gas-token.c + +YASM_MODULES += parser_gas + +gas-token.c: $(srcdir)/modules/parsers/gas/gas-token.re re2c$(EXEEXT) cleanup$(EXEEXT) + $(top_builddir)/re2c$(EXEEXT) -b $(srcdir)/modules/parsers/gas/gas-token.re \ + | $(top_builddir)/cleanup$(EXEEXT) \ + | sed "/^#l/ s,re2c-out\.c,$@," > $@ + +BUILT_SOURCES += gas-bison.c +BUILT_SOURCES += gas-bison.h +BUILT_SOURCES += gas-token.c + +CLEANFILES += gas-bison.c +CLEANFILES += gas-bison.h +CLEANFILES += gas-token.c + +EXTRA_DIST += modules/parsers/gas/tests/Makefile.inc +EXTRA_DIST += modules/parsers/gas/gas-token.re + +include modules/parsers/gas/tests/Makefile.inc diff --git a/modules/parsers/gas/gas-bison.y b/modules/parsers/gas/gas-bison.y new file mode 100644 index 00000000..1e3b0203 --- /dev/null +++ b/modules/parsers/gas/gas-bison.y @@ -0,0 +1,726 @@ +/* + * GAS-compatible bison parser + * + * Copyright (C) 2005 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +%{ +#include +RCSID("$Id$"); + +#define YASM_LIB_INTERNAL +#define YASM_EXPR_INTERNAL +#include + +#ifdef STDC_HEADERS +# include +#endif + +#include "modules/parsers/gas/gas-parser.h" +#include "modules/parsers/gas/gas-defs.h" + +static void define_label(yasm_parser_gas *parser_gas, char *name, int local); +static yasm_section *gas_get_section(yasm_parser_gas *parser_gas, char *name, + /*@null@*/ char *flags, + /*@null@*/ char *type); +static void gas_switch_section(yasm_parser_gas *parser_gas, char *name, + /*@null@*/ char *flags, /*@null@*/ char *type); +static yasm_bytecode *gas_define_strings(yasm_parser_gas *parser_gas, + yasm_valparamhead *vps, int withzero); +static yasm_bytecode *gas_define_data(yasm_parser_gas *parser_gas, + yasm_valparamhead *vps, + unsigned int size); +static void gas_parser_directive + (yasm_parser_gas *parser_gas, const char *name, + yasm_valparamhead *valparams, + /*@null@*/ yasm_valparamhead *objext_valparams); + +#define gas_parser_error(s) yasm__parser_error(cur_line, s) +#define YYPARSE_PARAM parser_gas_arg +#define YYLEX_PARAM parser_gas_arg +#define parser_gas ((yasm_parser_gas *)parser_gas_arg) +#define gas_parser_debug (parser_gas->debug) + +/*@-usedef -nullassign -memtrans -usereleased -compdef -mustfree@*/ +%} + +%pure_parser + +%union { + unsigned int int_info; + char *str_val; + yasm_intnum *intn; + yasm_floatnum *flt; + yasm_symrec *sym; + unsigned long arch_data[4]; + yasm_effaddr *ea; + yasm_expr *exp; + yasm_bytecode *bc; + yasm_valparamhead valparams; + struct { + yasm_insn_operands operands; + int num_operands; + } insn_operands; + yasm_insn_operand *insn_operand; +} + +%token INTNUM +%token FLTNUM +%token STRING +%token SIZE_OVERRIDE +%token DECLARE_DATA +%token RESERVE_SPACE +%token INSN PREFIX REG REGGROUP SEGREG TARGETMOD +%token LEFT_OP RIGHT_OP +%token ID DIR_ID +%token LINE +%token DIR_2BYTE DIR_4BYTE DIR_ALIGN DIR_ASCII DIR_ASCIZ DIR_BALIGN +%token DIR_BSS DIR_BYTE DIR_COMM DIR_DATA DIR_DOUBLE DIR_ENDR DIR_EXTERN +%token DIR_EQU DIR_FILE DIR_FLOAT DIR_GLOBAL DIR_IDENT DIR_INT DIR_LOC +%token DIR_LCOMM DIR_OCTA DIR_ORG DIR_P2ALIGN DIR_REPT DIR_SECTION +%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_STRING +%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_WORD + +%type line lineexp instr + +%type label_id +%type memaddr +%type expr regmemexpr +%type explabel +%type strvals datavals strvals2 datavals2 +%type operands +%type operand + +%left '-' '+' +%left '|' '&' '^' '!' +%left '*' '/' '%' LEFT_OP RIGHT_OP +%nonassoc UNARYOP + +%% +input: /* empty */ + | input line { + parser_gas->temp_bc = + yasm_section_bcs_append(parser_gas->cur_section, $2); + if (parser_gas->temp_bc) + parser_gas->prev_bc = parser_gas->temp_bc; + if (parser_gas->save_input) + yasm_linemap_add_source(parser_gas->linemap, + parser_gas->temp_bc, + parser_gas->save_line[parser_gas->save_last ^ 1]); + yasm_linemap_goto_next(parser_gas->linemap); + } +; + +line: '\n' { $$ = (yasm_bytecode *)NULL; } + | lineexp '\n' + | error '\n' { + yasm__error(cur_line, + N_("label or instruction expected at start of line")); + $$ = (yasm_bytecode *)NULL; + yyerrok; + } +; + +lineexp: instr + | label_id ':' { + $$ = (yasm_bytecode *)NULL; + define_label(parser_gas, $1, 0); + } + | label_id ':' instr { + $$ = $3; + define_label(parser_gas, $1, 0); + } + /* Alignment directives */ + | DIR_ALIGN datavals2 { + /* FIXME: Whether this is power-of-two or not depends on arch */ + /*@dependent@*/ yasm_valparam *bound, *fill = NULL, *maxskip = NULL; + bound = yasm_vps_first(&$2); + if (bound) + fill = yasm_vps_next(bound); + else + yasm__error(cur_line, + N_("align directive must specify alignment")); + if (fill) + maxskip = yasm_vps_next(fill); + $$ = (yasm_bytecode *)NULL; + } + | DIR_P2ALIGN datavals2 { + $$ = (yasm_bytecode *)NULL; + } + | DIR_BALIGN datavals2 { + $$ = (yasm_bytecode *)NULL; + } + | DIR_ORG expr { + $$ = (yasm_bytecode *)NULL; + } + /* Data visibility directives */ + | DIR_GLOBAL label_id { + yasm_objfmt_global_declare(parser_gas->objfmt, $2, NULL, cur_line); + yasm_xfree($2); + $$ = NULL; + } + | DIR_COMM label_id ',' expr { + yasm_objfmt_common_declare(parser_gas->objfmt, $2, $4, NULL, cur_line); + yasm_xfree($2); + $$ = NULL; + } + | DIR_COMM label_id ',' expr ',' expr { + /* Give third parameter as objext valparam for use as alignment */ + yasm_valparamhead vps; + yasm_valparam *vp; + + yasm_vps_initialize(&vps); + vp = yasm_vp_create(NULL, $6); + yasm_vps_append(&vps, vp); + + yasm_objfmt_common_declare(parser_gas->objfmt, $2, $4, &vps, cur_line); + + yasm_vps_delete(&vps); + yasm_xfree($2); + $$ = NULL; + } + | DIR_EXTERN label_id { + /* Go ahead and do it, even though all undef become extern */ + yasm_objfmt_extern_declare(parser_gas->objfmt, $2, NULL, cur_line); + yasm_xfree($2); + $$ = NULL; + } + | DIR_LCOMM label_id ',' expr { + /* Put into .bss section. */ + /*@dependent@*/ yasm_section *bss = + gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL); + /* TODO: default alignment */ + yasm_symtab_define_label(p_symtab, $2, yasm_section_bcs_last(bss), 1, + cur_line); + yasm_section_bcs_append(bss, yasm_bc_create_reserve($4, 1, cur_line)); + yasm_xfree($2); + $$ = NULL; + } + | DIR_LCOMM label_id ',' expr ',' expr { + /* Put into .bss section. */ + /*@dependent@*/ yasm_section *bss = + gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL); + /* TODO: force alignment */ + yasm_symtab_define_label(p_symtab, $2, yasm_section_bcs_last(bss), 1, + cur_line); + yasm_section_bcs_append(bss, yasm_bc_create_reserve($4, 1, cur_line)); + yasm_xfree($2); + $$ = NULL; + } + /* Integer data definition directives */ + | DIR_ASCII strvals { + $$ = gas_define_strings(parser_gas, &$2, 0); + yasm_vps_delete(&$2); + } + | DIR_ASCIZ strvals { + $$ = gas_define_strings(parser_gas, &$2, 1); + yasm_vps_delete(&$2); + } + | DIR_BYTE datavals { + $$ = gas_define_data(parser_gas, &$2, 1); + yasm_vps_delete(&$2); + } + | DIR_SHORT datavals { + /* TODO: This should depend on arch */ + $$ = gas_define_data(parser_gas, &$2, 2); + yasm_vps_delete(&$2); + } + | DIR_WORD datavals { + $$ = gas_define_data(parser_gas, &$2, + yasm_arch_wordsize(parser_gas->arch)); + yasm_vps_delete(&$2); + } + | DIR_INT datavals { + /* TODO: This should depend on arch */ + $$ = gas_define_data(parser_gas, &$2, 4); + yasm_vps_delete(&$2); + } + | DIR_2BYTE datavals { + $$ = gas_define_data(parser_gas, &$2, 2); + yasm_vps_delete(&$2); + } + | DIR_4BYTE datavals { + $$ = gas_define_data(parser_gas, &$2, 4); + yasm_vps_delete(&$2); + } + | DIR_QUAD datavals { + $$ = gas_define_data(parser_gas, &$2, 8); + yasm_vps_delete(&$2); + } + | DIR_OCTA datavals { + $$ = gas_define_data(parser_gas, &$2, 16); + yasm_vps_delete(&$2); + } + /* Floating point data definition directives */ + | DIR_FLOAT datavals { + $$ = gas_define_data(parser_gas, &$2, 4); + yasm_vps_delete(&$2); + } + | DIR_DOUBLE datavals { + $$ = gas_define_data(parser_gas, &$2, 8); + yasm_vps_delete(&$2); + } + | DIR_TFLOAT datavals { + $$ = gas_define_data(parser_gas, &$2, 10); + yasm_vps_delete(&$2); + } + /* Empty space / fill data definition directives */ + | DIR_SKIP expr { + $$ = yasm_bc_create_reserve($2, 1, cur_line); + } + | DIR_SKIP expr ',' expr { + yasm_datavalhead dvs; + + yasm_dvs_initialize(&dvs); + yasm_dvs_append(&dvs, yasm_dv_create_expr($4)); + $$ = yasm_bc_create_data(&dvs, 1, cur_line); + + yasm_bc_set_multiple($$, $2); + } + /* Section directives */ + | DIR_TEXT { + gas_switch_section(parser_gas, yasm__xstrdup(".text"), NULL, NULL); + $$ = NULL; + } + | DIR_DATA { + gas_switch_section(parser_gas, yasm__xstrdup(".data"), NULL, NULL); + $$ = NULL; + } + | DIR_BSS { + gas_switch_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL); + $$ = NULL; + } + | DIR_SECTION label_id { + gas_switch_section(parser_gas, $2, NULL, NULL); + $$ = NULL; + } + | DIR_SECTION label_id ',' STRING { + gas_switch_section(parser_gas, $2, $4, NULL); + $$ = NULL; + } + | DIR_SECTION label_id ',' STRING ',' '@' label_id { + gas_switch_section(parser_gas, $2, $4, $7); + $$ = NULL; + } + /* Other directives */ + | DIR_IDENT strvals { + /* Put text into .comment section. */ + /*@dependent@*/ yasm_section *comment = + gas_get_section(parser_gas, yasm__xstrdup(".comment"), NULL, NULL); + /* To match GAS output, if the comment section is empty, put an + * initial 0 byte in the section. + */ + if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) { + yasm_datavalhead dvs; + + yasm_dvs_initialize(&dvs); + yasm_dvs_append(&dvs, yasm_dv_create_expr( + p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0))))); + yasm_section_bcs_append(comment, + yasm_bc_create_data(&dvs, 1, cur_line)); + } + yasm_section_bcs_append(comment, + gas_define_strings(parser_gas, &$2, 1)); + yasm_vps_delete(&$2); + $$ = NULL; + } + | DIR_FILE INTNUM STRING { + /* TODO */ + $$ = NULL; + } + | DIR_LOC INTNUM INTNUM INTNUM { + /* TODO */ + $$ = NULL; + } + | DIR_TYPE label_id ',' '@' label_id { + /* TODO */ + $$ = NULL; + } + | DIR_SIZE label_id ',' expr { + /* TODO */ + $$ = NULL; + } + | DIR_ID datavals { + yasm__warning(YASM_WARN_GENERAL, cur_line, + N_("directive `%s' not recognized"), $1); + $$ = (yasm_bytecode *)NULL; + yasm_xfree($1); + yasm_vps_delete(&$2); + } + | DIR_ID error { + yasm__warning(YASM_WARN_GENERAL, cur_line, + N_("directive `%s' not recognized"), $1); + $$ = (yasm_bytecode *)NULL; + yasm_xfree($1); + } + | label_id '=' expr { + $$ = (yasm_bytecode *)NULL; + yasm_symtab_define_equ(p_symtab, $1, $3, cur_line); + yasm_xfree($1); + } +; + +instr: INSN { + $$ = yasm_bc_create_insn(parser_gas->arch, $1, 0, NULL, cur_line); + } + | INSN operands { + $$ = yasm_bc_create_insn(parser_gas->arch, $1, $2.num_operands, + &$2.operands, cur_line); + } + | INSN error { + yasm__error(cur_line, N_("expression syntax error")); + $$ = NULL; + } + | PREFIX instr { + $$ = $2; + yasm_bc_insn_add_prefix($$, $1); + } + | ID { + yasm__error(cur_line, N_("instruction not recognized: `%s'"), $1); + $$ = NULL; + } + | ID operands { + yasm__error(cur_line, N_("instruction not recognized: `%s'"), $1); + $$ = NULL; + } + | ID error { + yasm__error(cur_line, N_("instruction not recognized: `%s'"), $1); + $$ = NULL; + } +; + +strvals: /* empty */ { yasm_vps_initialize(&$$); } + | strvals2 +; + +strvals2: STRING { + yasm_valparam *vp = yasm_vp_create($1, NULL); + yasm_vps_initialize(&$$); + yasm_vps_append(&$$, vp); + } + | strvals2 ',' STRING { + yasm_valparam *vp = yasm_vp_create($3, NULL); + yasm_vps_append(&$1, vp); + $$ = $1; + } + | strvals2 ',' ',' STRING { + yasm_valparam *vp = yasm_vp_create(NULL, NULL); + yasm_vps_append(&$1, vp); + vp = yasm_vp_create($4, NULL); + yasm_vps_append(&$1, vp); + $$ = $1; + } +; + +datavals: /* empty */ { yasm_vps_initialize(&$$); } + | datavals2 +; + +datavals2: expr { + yasm_valparam *vp = yasm_vp_create(NULL, $1); + yasm_vps_initialize(&$$); + yasm_vps_append(&$$, vp); + } + | datavals2 ',' expr { + yasm_valparam *vp = yasm_vp_create(NULL, $3); + yasm_vps_append(&$1, vp); + $$ = $1; + } + | datavals2 ',' ',' expr { + yasm_valparam *vp = yasm_vp_create(NULL, NULL); + yasm_vps_append(&$1, vp); + vp = yasm_vp_create(NULL, $4); + yasm_vps_append(&$1, vp); + $$ = $1; + } +; + +/* instruction operands */ +operands: operand { + yasm_ops_initialize(&$$.operands); + yasm_ops_append(&$$.operands, $1); + $$.num_operands = 1; + } + | operands ',' operand { + yasm_ops_append(&$1.operands, $3); + $$.operands = $1.operands; + $$.num_operands = $1.num_operands+1; + } +; + +regmemexpr: '(' REG ')' { + $$ = p_expr_new_ident(yasm_expr_reg($2[0])); + } + | '(' ',' REG ')' { + $$ = p_expr_new(yasm_expr_reg($3[0]), YASM_EXPR_MUL, + yasm_expr_int(yasm_intnum_create_uint(1))); + } + | '(' ',' INTNUM ')' { + if (yasm_intnum_get_uint($3) != 1) + yasm__warning(YASM_WARN_GENERAL, cur_line, + N_("scale factor of %u without an index register"), + yasm_intnum_get_uint($3)); + $$ = p_expr_new(yasm_expr_int(yasm_intnum_create_uint(0)), + YASM_EXPR_MUL, yasm_expr_int($3)); + } + | '(' REG ',' REG ')' { + $$ = p_expr_new(yasm_expr_reg($2[0]), YASM_EXPR_ADD, + yasm_expr_expr(p_expr_new(yasm_expr_reg($4[0]), YASM_EXPR_MUL, + yasm_expr_int(yasm_intnum_create_uint(1))))); + } + | '(' ',' REG ',' INTNUM ')' { + $$ = p_expr_new(yasm_expr_reg($3[0]), YASM_EXPR_MUL, + yasm_expr_int($5)); + } + | '(' REG ',' REG ',' INTNUM ')' { + $$ = p_expr_new(yasm_expr_reg($2[0]), YASM_EXPR_ADD, + yasm_expr_expr(p_expr_new(yasm_expr_reg($4[0]), YASM_EXPR_MUL, + yasm_expr_int($6)))); + } +; + +/* memory addresses */ +memaddr: expr { + $$ = yasm_arch_ea_create(parser_gas->arch, $1); + } + | regmemexpr { + $$ = yasm_arch_ea_create(parser_gas->arch, $1); + yasm_ea_set_strong($$, 1); + } + | expr regmemexpr { + $$ = yasm_arch_ea_create(parser_gas->arch, + p_expr_new_tree($2, YASM_EXPR_ADD, $1)); + yasm_ea_set_strong($$, 1); + } + | SEGREG ':' memaddr { + $$ = $3; + yasm_ea_set_segreg($$, $1[0], cur_line); + } +; + +operand: memaddr { $$ = yasm_operand_create_mem($1); } + | REG { $$ = yasm_operand_create_reg($1[0]); } + | REGGROUP { $$ = yasm_operand_create_reg($1[0]); } + | REGGROUP '(' INTNUM ')' { + unsigned long reg = + yasm_arch_reggroup_get_reg(parser_gas->arch, $1[0], + yasm_intnum_get_uint($3)); + yasm_intnum_destroy($3); + if (reg == 0) { + yasm__error(cur_line, N_("bad register index `%u'"), + yasm_intnum_get_uint($3)); + $$ = yasm_operand_create_reg($1[0]); + } else + $$ = yasm_operand_create_reg(reg); + } + | '$' expr { $$ = yasm_operand_create_imm($2); } + | '*' REG { + $$ = yasm_operand_create_reg($2[0]); + $$->deref = 1; + } + | '*' memaddr { + $$ = yasm_operand_create_mem($2); + $$->deref = 1; + } +; + +/* Expressions */ +expr: INTNUM { $$ = p_expr_new_ident(yasm_expr_int($1)); } + | FLTNUM { $$ = p_expr_new_ident(yasm_expr_float($1)); } + | explabel { $$ = p_expr_new_ident(yasm_expr_sym($1)); } + | expr '|' expr { $$ = p_expr_new_tree($1, YASM_EXPR_OR, $3); } + | expr '^' expr { $$ = p_expr_new_tree($1, YASM_EXPR_XOR, $3); } + | expr '&' expr { $$ = p_expr_new_tree($1, YASM_EXPR_AND, $3); } + | expr '!' expr { $$ = p_expr_new_tree($1, YASM_EXPR_NOR, $3); } + | expr LEFT_OP expr { $$ = p_expr_new_tree($1, YASM_EXPR_SHL, $3); } + | expr RIGHT_OP expr { $$ = p_expr_new_tree($1, YASM_EXPR_SHR, $3); } + | expr '+' expr { $$ = p_expr_new_tree($1, YASM_EXPR_ADD, $3); } + | expr '-' expr { $$ = p_expr_new_tree($1, YASM_EXPR_SUB, $3); } + | expr '*' expr { $$ = p_expr_new_tree($1, YASM_EXPR_MUL, $3); } + | expr '/' expr { $$ = p_expr_new_tree($1, YASM_EXPR_DIV, $3); } + | expr '%' expr { $$ = p_expr_new_tree($1, YASM_EXPR_MOD, $3); } + | '+' expr %prec UNARYOP { $$ = $2; } + | '-' expr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NEG, $2); } + | '~' expr %prec UNARYOP { $$ = p_expr_new_branch(YASM_EXPR_NOT, $2); } + | '(' expr ')' { $$ = $2; } +; + +explabel: label_id { + /* "." references the current assembly position */ + if ($1[1] == '\0' && $1[0] == '.') + $$ = yasm_symtab_define_label(p_symtab, ".", parser_gas->prev_bc, + 0, cur_line); + else + $$ = yasm_symtab_use(p_symtab, $1, cur_line); + yasm_xfree($1); + } + | label_id '@' label_id { + /* TODO: this is needed for shared objects, e.g. sym@PLT */ + $$ = yasm_symtab_use(p_symtab, $1, cur_line); + yasm_xfree($1); + yasm_xfree($3); + } +; + +label_id: ID | DIR_ID; + +%% +/*@=usedef =nullassign =memtrans =usereleased =compdef =mustfree@*/ + +#undef parser_gas + +static void +define_label(yasm_parser_gas *parser_gas, char *name, int local) +{ + if (!local) { + if (parser_gas->locallabel_base) + yasm_xfree(parser_gas->locallabel_base); + parser_gas->locallabel_base_len = strlen(name); + parser_gas->locallabel_base = + yasm_xmalloc(parser_gas->locallabel_base_len+1); + strcpy(parser_gas->locallabel_base, name); + } + + yasm_symtab_define_label(p_symtab, name, parser_gas->prev_bc, 1, + cur_line); + yasm_xfree(name); +} + +static yasm_section * +gas_get_section(yasm_parser_gas *parser_gas, char *name, + /*@null@*/ char *flags, /*@null@*/ char *type) +{ + yasm_valparamhead vps; + yasm_valparam *vp; + char *gasflags; + yasm_section *new_section; + + yasm_vps_initialize(&vps); + vp = yasm_vp_create(name, NULL); + yasm_vps_append(&vps, vp); + + if (flags) { + gasflags = yasm_xmalloc(5+strlen(flags)); + strcpy(gasflags, "gas_"); + strcat(gasflags, flags); + } else + gasflags = yasm__xstrdup("gas_"); + vp = yasm_vp_create(gasflags, NULL); + yasm_vps_append(&vps, vp); + + if (type) { + vp = yasm_vp_create(type, NULL); + yasm_vps_append(&vps, vp); + } + + new_section = yasm_objfmt_section_switch(parser_gas->objfmt, &vps, NULL, + cur_line); + + yasm_vps_delete(&vps); + return new_section; +} + +static void +gas_switch_section(yasm_parser_gas *parser_gas, char *name, + /*@null@*/ char *flags, /*@null@*/ char *type) +{ + yasm_section *new_section; + + new_section = gas_get_section(parser_gas, name, flags, type); + if (new_section) { + parser_gas->cur_section = new_section; + parser_gas->prev_bc = yasm_section_bcs_last(new_section); + } else + yasm__error(cur_line, N_("invalid section name `%s'"), name); +} + +static yasm_bytecode * +gas_define_strings(yasm_parser_gas *parser_gas, yasm_valparamhead *vps, + int withzero) +{ + if (yasm_vps_first(vps)) { + yasm_datavalhead dvs; + yasm_valparam *cur; + + yasm_dvs_initialize(&dvs); + yasm_vps_foreach(cur, vps) { + if (!cur->val) + yasm__error(cur_line, N_("missing string value")); + else { + yasm_dvs_append(&dvs, yasm_dv_create_string(cur->val)); + cur->val = NULL; + if (withzero) + yasm_dvs_append(&dvs, yasm_dv_create_expr( + p_expr_new_ident(yasm_expr_int( + yasm_intnum_create_uint(0))))); + } + } + return yasm_bc_create_data(&dvs, 1, cur_line); + } else + return NULL; +} + +static yasm_bytecode * +gas_define_data(yasm_parser_gas *parser_gas, yasm_valparamhead *vps, + unsigned int size) +{ + if (yasm_vps_first(vps)) { + yasm_datavalhead dvs; + yasm_valparam *cur; + + yasm_dvs_initialize(&dvs); + yasm_vps_foreach(cur, vps) { + if (!cur->param) + yasm__error(cur_line, N_("missing data value")); + else + yasm_dvs_append(&dvs, yasm_dv_create_expr(cur->param)); + cur->param = NULL; + } + return yasm_bc_create_data(&dvs, size, cur_line); + } else + return NULL; +} + +static void +gas_parser_directive(yasm_parser_gas *parser_gas, const char *name, + yasm_valparamhead *valparams, + yasm_valparamhead *objext_valparams) +{ + unsigned long line = cur_line; + + /* Handle (mostly) output-format independent directives here */ + if (!yasm_arch_parse_directive(parser_gas->arch, name, valparams, + objext_valparams, parser_gas->object, line)) { + ; + } else if (yasm_objfmt_directive(parser_gas->objfmt, name, valparams, + objext_valparams, line)) { + yasm__error(line, N_("unrecognized directive [%s]"), name); + } + + yasm_vps_delete(valparams); + if (objext_valparams) + yasm_vps_delete(objext_valparams); +} diff --git a/modules/parsers/gas/gas-defs.h b/modules/parsers/gas/gas-defs.h new file mode 100644 index 00000000..5991a5fd --- /dev/null +++ b/modules/parsers/gas/gas-defs.h @@ -0,0 +1,88 @@ +/* $Id$ + * Variable name redefinitions for GAS-compatible parser + * + * Copyright (C) 2005 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define yy_create_buffer gas_parser__create_buffer +#define yy_delete_buffer gas_parser__delete_buffer +#define yy_init_buffer gas_parser__init_buffer +#define yy_load_buffer_state gas_parser__load_buffer_state +#define yy_switch_to_buffer gas_parser__switch_to_buffer +#define yyact gas_parser_act +#define yyback gas_parser_back +#define yybgin gas_parser_bgin +#define yychar gas_parser_char +#define yychk gas_parser_chk +#define yycrank gas_parser_crank +#define yydebug gas_parser_debug +#define yydef gas_parser_def +#define yyerrflag gas_parser_errflag +#define yyerror gas_parser_error +#define yyestate gas_parser_estate +#define yyexca gas_parser_exca +#define yyextra gas_parser_extra +#define yyfnd gas_parser_fnd +#define yyin gas_parser_in +#define yyinput gas_parser_input +#define yyleng gas_parser_leng +#define yylex gas_parser_lex +#define yylineno gas_parser_lineno +#define yylook gas_parser_look +#define yylsp gas_parser_lsp +#define yylstate gas_parser_lstate +#define yylval gas_parser_lval +#define yymatch gas_parser_match +#define yymorfg gas_parser_morfg +#define yynerrs gas_parser_nerrs +#define yyolsp gas_parser_olsp +#define yyout gas_parser_out +#define yyoutput gas_parser_output +#define yypact gas_parser_pact +#define yyparse gas_parser_parse +#define yypgo gas_parser_pgo +#define yyprevious gas_parser_previous +#define yyps gas_parser_ps +#define yypv gas_parser_pv +#define yyr1 gas_parser_r1 +#define yyr2 gas_parser_r2 +#define yyreds gas_parser_reds +#define yyrestart gas_parser_restart +#define yys gas_parser_s +#define yysbuf gas_parser_sbuf +#define yysptr gas_parser_sptr +#define yystate gas_parser_state +#define yysvec gas_parser_svec +#define yytchar gas_parser_tchar +#define yytext gas_parser_text +#define yytmp gas_parser_tmp +#define yytoks gas_parser_toks +#define yytop gas_parser_top +#define yyunput gas_parser_unput +#define yyv gas_parser_v +#define yyval gas_parser_val +#define yyvstop gas_parser_vstop +/*#define yywrap gas_parser_wrap*/ diff --git a/modules/parsers/gas/gas-parser.c b/modules/parsers/gas/gas-parser.c new file mode 100644 index 00000000..31bf78a7 --- /dev/null +++ b/modules/parsers/gas/gas-parser.c @@ -0,0 +1,105 @@ +/* + * GAS-compatible parser + * + * Copyright (C) 2005 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +/*@unused@*/ RCSID("$Id$"); + +#define YASM_LIB_INTERNAL +#include + +#include "gas-parser.h" + + +static void +gas_parser_do_parse(yasm_object *object, yasm_preproc *pp, yasm_arch *a, + yasm_objfmt *of, FILE *f, const char *in_filename, + int save_input, yasm_section *def_sect) +{ + yasm_parser_gas parser_gas; + + parser_gas.object = object; + parser_gas.linemap = yasm_object_get_linemap(parser_gas.object); + parser_gas.symtab = yasm_object_get_symtab(parser_gas.object); + + parser_gas.in = f; + + parser_gas.locallabel_base = (char *)NULL; + parser_gas.locallabel_base_len = 0; + + parser_gas.preproc = pp; + parser_gas.arch = a; + parser_gas.objfmt = of; + + parser_gas.cur_section = def_sect; + parser_gas.prev_bc = yasm_section_bcs_first(def_sect); + + parser_gas.save_input = save_input; + parser_gas.save_last = 0; + + /* initialize scanner structure */ + parser_gas.s.bot = NULL; + parser_gas.s.tok = NULL; + parser_gas.s.ptr = NULL; + parser_gas.s.cur = NULL; + parser_gas.s.pos = NULL; + parser_gas.s.lim = NULL; + parser_gas.s.top = NULL; + parser_gas.s.eof = NULL; + parser_gas.s.tchar = 0; + parser_gas.s.tline = 0; + parser_gas.s.cline = 1; + + parser_gas.state = INITIAL; + + /* yacc debugging, needs YYDEBUG set in bison.y.in to work */ + parser_gas.debug = 1; + + gas_parser_parse(&parser_gas); + + gas_parser_cleanup(&parser_gas); + + /* Free locallabel base if necessary */ + if (parser_gas.locallabel_base) + yasm_xfree(parser_gas.locallabel_base); +} + +/* Define valid preprocessors to use with this parser */ +static const char *gas_parser_preproc_keywords[] = { + "raw", + NULL +}; + +/* Define parser structure -- see parser.h for details */ +yasm_parser_module yasm_gas_LTX_parser = { + "GNU AS (GAS)-compatible parser", + "gas", + gas_parser_preproc_keywords, + "raw", + gas_parser_do_parse +}; diff --git a/modules/parsers/gas/gas-parser.h b/modules/parsers/gas/gas-parser.h new file mode 100644 index 00000000..50137960 --- /dev/null +++ b/modules/parsers/gas/gas-parser.h @@ -0,0 +1,89 @@ +/* $Id$ + * GAS-compatible parser header file + * + * Copyright (C) 2005 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef YASM_NASM_PARSER_H +#define YASM_NASM_PARSER_H + +#include "gas-bison.h" + +#define YYCTYPE char +typedef struct Scanner { + YYCTYPE *bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof; + unsigned int tchar, tline, cline; +} Scanner; + +#define MAX_SAVED_LINE_LEN 80 + +typedef struct yasm_parser_gas { + FILE *in; + int debug; + + /*@only@*/ yasm_object *object; + /*@dependent@*/ yasm_section *cur_section; + + /* last "base" label for local (.) labels */ + /*@null@*/ char *locallabel_base; + size_t locallabel_base_len; + + /*@dependent@*/ yasm_preproc *preproc; + /*@dependent@*/ yasm_arch *arch; + /*@dependent@*/ yasm_objfmt *objfmt; + + /*@dependent@*/ yasm_linemap *linemap; + /*@dependent@*/ yasm_symtab *symtab; + + /*@null@*/ yasm_bytecode *prev_bc; + yasm_bytecode *temp_bc; + + int save_input; + YYCTYPE save_line[2][MAX_SAVED_LINE_LEN]; + int save_last; + + Scanner s; + enum { + INITIAL, + SECTION_DIRECTIVE + } state; +} yasm_parser_gas; + +/* shorter access names to commonly used parser_gas fields */ +#define p_symtab (parser_gas->symtab) + +#define cur_line (yasm_linemap_get_current(parser_gas->linemap)) + +#define p_expr_new(l,o,r) yasm_expr_create(o,l,r,cur_line) +#define p_expr_new_tree(l,o,r) yasm_expr_create_tree(l,o,r,cur_line) +#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line) +#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line) + +int gas_parser_parse(void *parser_gas_arg); +void gas_parser_cleanup(yasm_parser_gas *parser_gas); +int gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas); + +#endif diff --git a/modules/parsers/gas/gas-token.re b/modules/parsers/gas/gas-token.re new file mode 100644 index 00000000..84542d04 --- /dev/null +++ b/modules/parsers/gas/gas-token.re @@ -0,0 +1,535 @@ +/* + * GAS-compatible re2c lexer + * + * Copyright (C) 2005 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +RCSID("$Id$"); + +#define YASM_LIB_INTERNAL +#include + +#include "modules/parsers/gas/gas-parser.h" +#include "modules/parsers/gas/gas-defs.h" + + +#define BSIZE 8192 + +#define YYCURSOR cursor +#define YYLIMIT (s->lim) +#define YYMARKER (s->ptr) +#define YYFILL(n) {cursor = fill(parser_gas, cursor);} + +#define RETURN(i) {s->cur = cursor; return i;} + +#define SCANINIT() { \ + s->tchar = cursor - s->pos; \ + s->tline = s->cline; \ + s->tok = cursor; \ + } + +#define TOKLEN (size_t)(cursor-s->tok) + + +static YYCTYPE * +fill(yasm_parser_gas *parser_gas, YYCTYPE *cursor) +{ + Scanner *s = &parser_gas->s; + int first = 0; + if(!s->eof){ + size_t cnt = s->tok - s->bot; + if(cnt){ + memcpy(s->bot, s->tok, (size_t)(s->lim - s->tok)); + s->tok = s->bot; + s->ptr -= cnt; + cursor -= cnt; + s->pos -= cnt; + s->lim -= cnt; + } + if (!s->bot) + first = 1; + if((s->top - s->lim) < BSIZE){ + char *buf = yasm_xmalloc((size_t)(s->lim - s->bot) + BSIZE); + memcpy(buf, s->tok, (size_t)(s->lim - s->tok)); + s->tok = buf; + s->ptr = &buf[s->ptr - s->bot]; + cursor = &buf[cursor - s->bot]; + s->pos = &buf[s->pos - s->bot]; + s->lim = &buf[s->lim - s->bot]; + s->top = &s->lim[BSIZE]; + if (s->bot) + yasm_xfree(s->bot); + s->bot = buf; + } + if((cnt = yasm_preproc_input(parser_gas->preproc, s->lim, + BSIZE)) == 0) { + s->eof = &s->lim[cnt]; *s->eof++ = '\n'; + } + s->lim += cnt; + if (first && parser_gas->save_input) { + int i; + char *saveline; + parser_gas->save_last ^= 1; + saveline = parser_gas->save_line[parser_gas->save_last]; + /* save next line into cur_line */ + for (i=0; i<79 && &s->tok[i] < s->lim && s->tok[i] != '\n'; i++) + saveline[i] = s->tok[i]; + saveline[i] = '\0'; + } + } + return cursor; +} + +static YYCTYPE * +save_line(yasm_parser_gas *parser_gas, YYCTYPE *cursor) +{ + Scanner *s = &parser_gas->s; + int i = 0; + char *saveline; + + parser_gas->save_last ^= 1; + saveline = parser_gas->save_line[parser_gas->save_last]; + + /* save next line into cur_line */ + if ((YYLIMIT - YYCURSOR) < 80) + YYFILL(80); + for (i=0; i<79 && &cursor[i] < s->lim && cursor[i] != '\n'; i++) + saveline[i] = cursor[i]; + saveline[i] = '\0'; + return cursor; +} + +void +gas_parser_cleanup(yasm_parser_gas *parser_gas) +{ + if (parser_gas->s.bot) + yasm_xfree(parser_gas->s.bot); +} + +/* starting size of string buffer */ +#define STRBUF_ALLOC_SIZE 128 + +/* string buffer used when parsing strings/character constants */ +static char *strbuf = (char *)NULL; + +/* length of strbuf (including terminating NULL character) */ +static size_t strbuf_size = 0; + +static void +strbuf_append(size_t count, YYCTYPE *cursor, Scanner *s, unsigned long line, + int ch) +{ + if (cursor == s->eof) + yasm__error(line, N_("unexpected end of file in string")); + strbuf[count] = ch; + + if (count >= strbuf_size) { + strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE); + strbuf_size += STRBUF_ALLOC_SIZE; + } +} + +/*!re2c + any = [\000-\377]; + digit = [0-9]; + iletter = [a-zA-Z]; + bindigit = [01]; + octdigit = [0-7]; + hexdigit = [0-9a-fA-F]; + ws = [ \t\r]; + dquot = ["]; + A = [aA]; + B = [bB]; + C = [cC]; + D = [dD]; + E = [eE]; + F = [fF]; + G = [gG]; + H = [hH]; + I = [iI]; + J = [jJ]; + K = [kK]; + L = [lL]; + M = [mM]; + N = [nN]; + O = [oO]; + P = [pP]; + Q = [qQ]; + R = [rR]; + S = [sS]; + T = [tT]; + U = [uU]; + V = [vV]; + W = [wW]; + X = [xX]; + Y = [yY]; + Z = [zZ]; +*/ + + +int +gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas) +{ + Scanner *s = &parser_gas->s; + YYCTYPE *cursor = s->cur; + size_t count; + YYCTYPE savech; + yasm_arch_check_id_retval check_id_ret; + + /* Catch EOF */ + if (s->eof && cursor == s->eof) + return 0; + + /* Jump to proper "exclusive" states */ + switch (parser_gas->state) { + case SECTION_DIRECTIVE: + goto section_directive; + default: + break; + } + +scan: + SCANINIT(); + + /*!re2c + /* standard decimal integer */ + ([1-9] digit*) | "0" { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + lvalp->intn = yasm_intnum_create_dec(s->tok, cur_line); + s->tok[TOKLEN] = savech; + RETURN(INTNUM); + } + + /* 0b10010011 - binary number */ + "0" B bindigit+ { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + lvalp->intn = yasm_intnum_create_bin(s->tok+2, cur_line); + s->tok[TOKLEN] = savech; + RETURN(INTNUM); + } + + /* 0777 - octal number */ + "0" octdigit+ { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + lvalp->intn = yasm_intnum_create_oct(s->tok, cur_line); + s->tok[TOKLEN] = savech; + RETURN(INTNUM); + } + + /* 0xAA - hexidecimal number */ + "0x" hexdigit+ { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + /* skip 0 and x */ + lvalp->intn = yasm_intnum_create_hex(s->tok+2, cur_line); + s->tok[TOKLEN] = savech; + RETURN(INTNUM); + } + + /* floating point value */ + "0" [DdEeFfTt] [-+]? (digit+)? ("." digit*)? (E [-+]? digit+)? { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + lvalp->flt = yasm_floatnum_create(s->tok+2); + s->tok[TOKLEN] = savech; + RETURN(FLTNUM); + } + + /* character constant values */ + ['] { + goto charconst; + } + + /* string constant values */ + dquot { + goto stringconst; + } + + /* operators */ + "<<" { RETURN(LEFT_OP); } + ">>" { RETURN(RIGHT_OP); } + "<" { RETURN(LEFT_OP); } + ">" { RETURN(RIGHT_OP); } + [-+|^!*&/~$():@=,] { RETURN(s->tok[0]); } + + /* arch-independent directives */ + ".2byte" { RETURN(DIR_2BYTE); } + ".4byte" { RETURN(DIR_4BYTE); } + ".8byte" { RETURN(DIR_QUAD); } + ".align" { RETURN(DIR_ALIGN); } + ".ascii" { RETURN(DIR_ASCII); } + ".asciz" { RETURN(DIR_ASCIZ); } + ".balign" { RETURN(DIR_BALIGN); } + ".bss" { RETURN(DIR_BSS); } + ".byte" { RETURN(DIR_BYTE); } + ".comm" { RETURN(DIR_COMM); } + ".data" { RETURN(DIR_DATA); } + ".double" { RETURN(DIR_DOUBLE); } + ".endr" { RETURN(DIR_ENDR); } + ".equ" { RETURN(DIR_EQU); } + ".extern" { RETURN(DIR_EXTERN); } + ".file" { RETURN(DIR_FILE); } + ".float" { RETURN(DIR_FLOAT); } + ".global" { RETURN(DIR_GLOBAL); } + ".globl" { RETURN(DIR_GLOBAL); } + ".hword" { RETURN(DIR_SHORT); } + ".ident" { RETURN(DIR_IDENT); } + ".int" { RETURN(DIR_INT); } + ".lcomm" { RETURN(DIR_LCOMM); } + ".loc" { RETURN(DIR_LOC); } + ".long" { RETURN(DIR_INT); } + ".octa" { RETURN(DIR_OCTA); } + ".org" { RETURN(DIR_ORG); } + ".p2align" { RETURN(DIR_P2ALIGN); } + ".rept" { RETURN(DIR_REPT); } + ".section" { + parser_gas->state = SECTION_DIRECTIVE; + RETURN(DIR_SECTION); + } + ".set" { RETURN(DIR_EQU); } + ".short" { RETURN(DIR_SHORT); } + ".single" { RETURN(DIR_FLOAT); } + ".size" { RETURN(DIR_SIZE); } + ".skip" { RETURN(DIR_SKIP); } + ".space" { RETURN(DIR_SKIP); } + ".string" { RETURN(DIR_ASCIZ); } + ".text" { RETURN(DIR_TEXT); } + ".tfloat" { RETURN(DIR_TFLOAT); } + ".type" { RETURN(DIR_TYPE); } + ".quad" { RETURN(DIR_QUAD); } + ".word" { RETURN(DIR_WORD); } + + /* label or maybe directive */ + [.][a-zA-Z0-9_$.]* { + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + RETURN(DIR_ID); + } + + /* label */ + [_][a-zA-Z0-9_$.]* { + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + RETURN(ID); + } + + /* register or segment register */ + [%][a-z0-9]+ { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + check_id_ret = yasm_arch_parse_check_id(parser_gas->arch, + lvalp->arch_data, s->tok+1, + cur_line); + s->tok[TOKLEN] = savech; + switch (check_id_ret) { + case YASM_ARCH_CHECK_ID_REG: + RETURN(REG); + case YASM_ARCH_CHECK_ID_REGGROUP: + RETURN(REGGROUP); + case YASM_ARCH_CHECK_ID_SEGREG: + RETURN(SEGREG); + default: + s->tok[TOKLEN] = '\0'; + yasm__error(cur_line, + N_("Unrecognized register name `%s'"), s->tok); + s->tok[TOKLEN] = savech; + lvalp->arch_data[0] = 0; + lvalp->arch_data[1] = 0; + lvalp->arch_data[2] = 0; + lvalp->arch_data[3] = 0; + RETURN(REG); + } + } + + /* identifier that may be an instruction, etc. */ + [a-zA-Z][a-zA-Z0-9_$.]* { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + check_id_ret = yasm_arch_parse_check_id(parser_gas->arch, + lvalp->arch_data, s->tok, + cur_line); + s->tok[TOKLEN] = savech; + switch (check_id_ret) { + case YASM_ARCH_CHECK_ID_NONE: + /* Just an identifier, return as such. */ + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + RETURN(ID); + case YASM_ARCH_CHECK_ID_INSN: + RETURN(INSN); + case YASM_ARCH_CHECK_ID_PREFIX: + RETURN(PREFIX); + case YASM_ARCH_CHECK_ID_TARGETMOD: + RETURN(TARGETMOD); + case YASM_ARCH_CHECK_ID_REG: + case YASM_ARCH_CHECK_ID_SEGREG: + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + RETURN(ID); + default: + yasm__warning(YASM_WARN_GENERAL, cur_line, + N_("Arch feature not supported, treating as identifier")); + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + RETURN(ID); + } + } + + "#" (any \ [\n])* { goto scan; } + + ws+ { goto scan; } + + "\n" { + if (parser_gas->save_input && cursor != s->eof) + cursor = save_line(parser_gas, cursor); + parser_gas->state = INITIAL; + RETURN(s->tok[0]); + } + + any { + yasm__warning(YASM_WARN_UNREC_CHAR, cur_line, + N_("ignoring unrecognized character `%s'"), + yasm__conv_unprint(s->tok[0])); + goto scan; + } + */ + + /* .section directive (the section name portion thereof) */ +section_directive: + SCANINIT(); + + /*!re2c + [a-zA-Z0-9_$.-]+ { + lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN); + parser_gas->state = INITIAL; + RETURN(ID); + } + + dquot { goto stringconst; } + + ws+ { goto section_directive; } + + "," { + parser_gas->state = INITIAL; + RETURN(s->tok[0]); + } + + "\n" { + if (parser_gas->save_input && cursor != s->eof) + cursor = save_line(parser_gas, cursor); + parser_gas->state = INITIAL; + RETURN(s->tok[0]); + } + + any { + yasm__warning(YASM_WARN_UNREC_CHAR, cur_line, + N_("ignoring unrecognized character `%s'"), + yasm__conv_unprint(s->tok[0])); + goto section_directive; + } + */ + + /* character constant values */ +charconst: + /*TODO*/ + + /* string constant values */ +stringconst: + strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE); + strbuf_size = STRBUF_ALLOC_SIZE; + count = 0; + +stringconst_scan: + SCANINIT(); + + /*!re2c + /* Escaped constants */ + "\\b" { + strbuf_append(count++, cursor, s, cur_line, '\b'); + goto stringconst_scan; + } + "\\f" { + strbuf_append(count++, cursor, s, cur_line, '\f'); + goto stringconst_scan; + } + "\\n" { + strbuf_append(count++, cursor, s, cur_line, '\n'); + goto stringconst_scan; + } + "\\r" { + strbuf_append(count++, cursor, s, cur_line, '\r'); + goto stringconst_scan; + } + "\\t" { + strbuf_append(count++, cursor, s, cur_line, '\t'); + goto stringconst_scan; + } + "\\" digit digit digit { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + lvalp->intn = yasm_intnum_create_oct(s->tok+1, cur_line); + s->tok[TOKLEN] = savech; + + strbuf_append(count++, cursor, s, cur_line, + yasm_intnum_get_int(lvalp->intn)); + yasm_intnum_destroy(lvalp->intn); + goto stringconst_scan; + } + "\\" X hexdigit+ { + savech = s->tok[TOKLEN]; + s->tok[TOKLEN] = '\0'; + lvalp->intn = yasm_intnum_create_hex(s->tok+2, cur_line); + s->tok[TOKLEN] = savech; + + strbuf_append(count++, cursor, s, cur_line, + yasm_intnum_get_int(lvalp->intn)); + yasm_intnum_destroy(lvalp->intn); + goto stringconst_scan; + } + "\\\\" { + strbuf_append(count++, cursor, s, cur_line, '\\'); + goto stringconst_scan; + } + "\\\"" { + strbuf_append(count++, cursor, s, cur_line, '"'); + goto stringconst_scan; + } + /*"\\" any { + strbuf_append(count++, cursor, s, cur_line, s->tok[0]); + goto stringconst_scan; + }*/ + + dquot { + strbuf_append(count, cursor, s, cur_line, '\0'); + lvalp->str_val = strbuf; + RETURN(STRING); + } + + any { + strbuf_append(count++, cursor, s, cur_line, s->tok[0]); + goto stringconst_scan; + } + */ +} diff --git a/modules/parsers/gas/tests/Makefile.inc b/modules/parsers/gas/tests/Makefile.inc new file mode 100644 index 00000000..dbe3323c --- /dev/null +++ b/modules/parsers/gas/tests/Makefile.inc @@ -0,0 +1,23 @@ +# $Id$ + +TESTS += modules/parsers/gas/tests/gas_test.sh + +EXTRA_DIST += modules/parsers/gas/tests/gas_test.sh +EXTRA_DIST += modules/parsers/gas/tests/datavis.asm +EXTRA_DIST += modules/parsers/gas/tests/datavis.errwarn +EXTRA_DIST += modules/parsers/gas/tests/datavis.hex +EXTRA_DIST += modules/parsers/gas/tests/datavis2.asm +EXTRA_DIST += modules/parsers/gas/tests/datavis2.errwarn +EXTRA_DIST += modules/parsers/gas/tests/datavis2.hex +EXTRA_DIST += modules/parsers/gas/tests/jmpcall.asm +EXTRA_DIST += modules/parsers/gas/tests/jmpcall.errwarn +EXTRA_DIST += modules/parsers/gas/tests/jmpcall.hex +EXTRA_DIST += modules/parsers/gas/tests/reggroup-err.asm +EXTRA_DIST += modules/parsers/gas/tests/reggroup-err.errwarn +EXTRA_DIST += modules/parsers/gas/tests/reggroup.asm +EXTRA_DIST += modules/parsers/gas/tests/reggroup.errwarn +EXTRA_DIST += modules/parsers/gas/tests/reggroup.hex + +EXTRA_DIST += modules/parsers/gas/tests/amd64/Makefile.inc + +include modules/parsers/gas/tests/amd64/Makefile.inc diff --git a/modules/parsers/gas/tests/amd64/Makefile.inc b/modules/parsers/gas/tests/amd64/Makefile.inc new file mode 100644 index 00000000..c9357602 --- /dev/null +++ b/modules/parsers/gas/tests/amd64/Makefile.inc @@ -0,0 +1,9 @@ +# $Id$ + +TESTS += modules/parsers/gas/tests/amd64/gas_amd64_test.sh + +EXTRA_DIST += modules/parsers/gas/tests/amd64/gas_amd64_test.sh +EXTRA_DIST += modules/parsers/gas/tests/amd64/riprel.asm +EXTRA_DIST += modules/parsers/gas/tests/amd64/riprel.errwarn +EXTRA_DIST += modules/parsers/gas/tests/amd64/riprel.hex + diff --git a/modules/parsers/gas/tests/amd64/gas_amd64_test.sh b/modules/parsers/gas/tests/amd64/gas_amd64_test.sh new file mode 100755 index 00000000..3e2226ae --- /dev/null +++ b/modules/parsers/gas/tests/amd64/gas_amd64_test.sh @@ -0,0 +1,4 @@ +#! /bin/sh +# $Id$ +${srcdir}/out_test.sh gas_amd64_test modules/parsers/gas/tests/amd64 "gas-compat parser" "-f elf -m amd64 -p gas" ".o" +exit $? diff --git a/modules/parsers/gas/tests/amd64/riprel.asm b/modules/parsers/gas/tests/amd64/riprel.asm new file mode 100644 index 00000000..3cd84250 --- /dev/null +++ b/modules/parsers/gas/tests/amd64/riprel.asm @@ -0,0 +1 @@ +mov %rax,foo(%rip) diff --git a/modules/parsers/gas/tests/amd64/riprel.errwarn b/modules/parsers/gas/tests/amd64/riprel.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/modules/parsers/gas/tests/amd64/riprel.hex b/modules/parsers/gas/tests/amd64/riprel.hex new file mode 100644 index 00000000..437b6569 --- /dev/null +++ b/modules/parsers/gas/tests/amd64/riprel.hex @@ -0,0 +1,640 @@ +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 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +40 +00 +06 +00 +01 +00 +48 +89 +05 +00 +00 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +03 +00 +00 +00 +fc +ff +ff +ff +ff +ff +ff +ff +00 +2e +74 +65 +78 +74 +00 +2e +72 +65 +6c +61 +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 +2d +00 +66 +6f +6f +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 +03 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +00 +00 +10 +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 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +22 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +60 +00 +00 +00 +00 +00 +00 +00 +2c +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 +12 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +8c +00 +00 +00 +00 +00 +00 +00 +07 +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 +1a +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +94 +00 +00 +00 +00 +00 +00 +00 +60 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +03 +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 +07 +00 +00 +00 +04 +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 +18 +00 +00 +00 +00 +00 +00 +00 +03 +00 +00 +00 +04 +00 +00 +00 +08 +00 +00 +00 +00 +00 +00 +00 +18 +00 +00 +00 +00 +00 +00 +00 diff --git a/modules/parsers/gas/tests/datavis.asm b/modules/parsers/gas/tests/datavis.asm new file mode 100644 index 00000000..1bae755e --- /dev/null +++ b/modules/parsers/gas/tests/datavis.asm @@ -0,0 +1,39 @@ +#.file "string" +.extern extsym2 +.global label1 +.globl label2 +.text + call extsym + call extsym2 +.data +label1: +.ascii "baz" +.asciz "foo" +.string "bar", "str2" +.byte 1, 2, 070, 0x12 +.byte + +.section .xx, "", @ progbits +.hword 0 +.short 5 +.word 10 +.long 15 +.int 30 +.quad 20 +.octa 40 + +.section .yy, "w", @nobits +.skip 4 +.skip 4, 1 + +.bss +label2: +.skip 4 +.skip 4, 1 + +.section .data2 +.float 0E1e10 +.double 0E-1.11 +.skip 4 +.skip 4, 1 +.tfloat 0E+3.14e2 diff --git a/modules/parsers/gas/tests/datavis.errwarn b/modules/parsers/gas/tests/datavis.errwarn new file mode 100644 index 00000000..3f7b1fe6 --- /dev/null +++ b/modules/parsers/gas/tests/datavis.errwarn @@ -0,0 +1 @@ +-:37: warning: uninitialized space declared in code/data section: zeroing diff --git a/modules/parsers/gas/tests/datavis.hex b/modules/parsers/gas/tests/datavis.hex new file mode 100644 index 00000000..b5a76fb8 --- /dev/null +++ b/modules/parsers/gas/tests/datavis.hex @@ -0,0 +1,920 @@ +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 +e0 +01 +00 +00 +00 +00 +00 +00 +34 +00 +00 +00 +00 +00 +28 +00 +0b +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +e8 +fc +ff +ff +ff +e8 +fc +ff +ff +ff +00 +00 +01 +00 +00 +00 +02 +0b +00 +00 +06 +00 +00 +00 +02 +08 +00 +00 +62 +61 +7a +66 +6f +6f +00 +62 +61 +72 +00 +73 +74 +72 +32 +00 +01 +02 +38 +12 +00 +00 +05 +00 +0a +00 +0f +00 +00 +00 +1e +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +28 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +f9 +02 +15 +50 +c3 +f5 +28 +5c +8f +c2 +f1 +bf +00 +00 +00 +00 +01 +01 +01 +01 +00 +00 +00 +00 +00 +00 +00 +9d +07 +40 +00 +2e +74 +65 +78 +74 +00 +2e +64 +61 +74 +61 +00 +2e +78 +78 +00 +2e +79 +79 +00 +2e +62 +73 +73 +00 +2e +64 +61 +74 +61 +32 +00 +2e +72 +65 +6c +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 +65 +78 +74 +73 +79 +6d +32 +00 +6c +61 +62 +65 +6c +31 +00 +6c +61 +62 +65 +6c +32 +00 +65 +78 +74 +73 +79 +6d +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 +0a +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +09 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +07 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +06 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +04 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +0b +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +06 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +09 +00 +19 +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 +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 +3b +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +b4 +00 +00 +00 +45 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +2b +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +fc +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +33 +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +1c +01 +00 +00 +c0 +00 +00 +00 +02 +00 +00 +00 +08 +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 +0a +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 +21 +00 +00 +00 +09 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +4c +00 +00 +00 +10 +00 +00 +00 +03 +00 +00 +00 +04 +00 +00 +00 +04 +00 +00 +00 +08 +00 +00 +00 +07 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5c +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +0d +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +70 +00 +00 +00 +26 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +11 +00 +00 +00 +08 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +15 +00 +00 +00 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +1a +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +96 +00 +00 +00 +1e +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 diff --git a/modules/parsers/gas/tests/datavis2.asm b/modules/parsers/gas/tests/datavis2.asm new file mode 100644 index 00000000..9d0d5155 --- /dev/null +++ b/modules/parsers/gas/tests/datavis2.asm @@ -0,0 +1,13 @@ + .section .eh_frame, "",@progbits +.EHCIE: + .4byte 0x10 + .4byte 0x0 + .2byte 1 + .8byte 4 + .byte 0x01, 0x00, 0x01, 0x78, 0x10, 0x00, 0x0c, 0x07 + .byte 0x08, 0x90, 0x01, 0x00 + + .section .debug_line, "" + .section .note.GNU-stack,"",@progbits + .ident "# : compiled with : " + .ident "second ident" diff --git a/modules/parsers/gas/tests/datavis2.errwarn b/modules/parsers/gas/tests/datavis2.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/modules/parsers/gas/tests/datavis2.hex b/modules/parsers/gas/tests/datavis2.hex new file mode 100644 index 00000000..3526b01c --- /dev/null +++ b/modules/parsers/gas/tests/datavis2.hex @@ -0,0 +1,712 @@ +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 +60 +01 +00 +00 +00 +00 +00 +00 +34 +00 +00 +00 +00 +00 +28 +00 +09 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 +01 +00 +04 +00 +00 +00 +00 +00 +00 +00 +01 +00 +01 +78 +10 +00 +0c +07 +08 +90 +01 +00 +00 +23 +20 +3a +20 +63 +6f +6d +70 +69 +6c +65 +64 +20 +77 +69 +74 +68 +20 +3a +20 +00 +73 +65 +63 +6f +6e +64 +20 +69 +64 +65 +6e +74 +00 +00 +00 +00 +00 +2e +74 +65 +78 +74 +00 +2e +65 +68 +5f +66 +72 +61 +6d +65 +00 +2e +64 +65 +62 +75 +67 +5f +6c +69 +6e +65 +00 +2e +6e +6f +74 +65 +2e +47 +4e +55 +2d +73 +74 +61 +63 +6b +00 +2e +63 +6f +6d +6d +65 +6e +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 +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 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +07 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +06 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +05 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +05 +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 +46 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +84 +00 +00 +00 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +36 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +d4 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +3e +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +d8 +00 +00 +00 +80 +00 +00 +00 +02 +00 +00 +00 +08 +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 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +1e +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +11 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5e +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +1d +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5e +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +2d +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +5e +00 +00 +00 +23 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 diff --git a/modules/parsers/gas/tests/gas_test.sh b/modules/parsers/gas/tests/gas_test.sh new file mode 100755 index 00000000..bce85d3c --- /dev/null +++ b/modules/parsers/gas/tests/gas_test.sh @@ -0,0 +1,4 @@ +#! /bin/sh +# $Id$ +${srcdir}/out_test.sh gas_test modules/parsers/gas/tests "gas-compat parser" "-f elf -p gas" ".o" +exit $? diff --git a/modules/parsers/gas/tests/jmpcall.asm b/modules/parsers/gas/tests/jmpcall.asm new file mode 100644 index 00000000..269ff226 --- /dev/null +++ b/modules/parsers/gas/tests/jmpcall.asm @@ -0,0 +1,13 @@ +#.text +label: + call *%eax + call %eax + call *(%eax) + call (%eax) + call label(,1) + call label + call label+5 + call *label + call *label(%eax) + jmp %fs:label + jmp *%fs:label diff --git a/modules/parsers/gas/tests/jmpcall.errwarn b/modules/parsers/gas/tests/jmpcall.errwarn new file mode 100644 index 00000000..6c9ed600 --- /dev/null +++ b/modules/parsers/gas/tests/jmpcall.errwarn @@ -0,0 +1,4 @@ +-:4: warning: indirect call without `*' +-:6: warning: indirect call without `*' +-:7: warning: indirect call without `*' +-:12: warning: skipping prefixes on this instruction diff --git a/modules/parsers/gas/tests/jmpcall.hex b/modules/parsers/gas/tests/jmpcall.hex new file mode 100644 index 00000000..6677cf92 --- /dev/null +++ b/modules/parsers/gas/tests/jmpcall.hex @@ -0,0 +1,496 @@ +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 +00 +01 +00 +00 +00 +00 +00 +00 +34 +00 +00 +00 +00 +00 +28 +00 +06 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ff +d0 +ff +d0 +ff +10 +ff +10 +ff +15 +00 +00 +00 +00 +e8 +ed +ff +ff +ff +e8 +ed +ff +ff +ff +ff +15 +00 +00 +00 +00 +ff +90 +00 +00 +00 +00 +eb +da +64 +ff +25 +00 +00 +00 +00 +00 +00 +00 +0a +00 +00 +00 +01 +03 +00 +00 +1a +00 +00 +00 +01 +03 +00 +00 +20 +00 +00 +00 +01 +03 +00 +00 +29 +00 +00 +00 +01 +03 +00 +00 +00 +2e +74 +65 +78 +74 +00 +2e +72 +65 +6c +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 +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 +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 +21 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +90 +00 +00 +00 +2b +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +11 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +bc +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +19 +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +c0 +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 +2d +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +09 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +70 +00 +00 +00 +20 +00 +00 +00 +03 +00 +00 +00 +04 +00 +00 +00 +04 +00 +00 +00 +08 +00 +00 +00 diff --git a/modules/parsers/gas/tests/reggroup-err.asm b/modules/parsers/gas/tests/reggroup-err.asm new file mode 100644 index 00000000..fc6ca798 --- /dev/null +++ b/modules/parsers/gas/tests/reggroup-err.asm @@ -0,0 +1,5 @@ + fadd %st (2) + fadd %st (2), %st(0) + fadd %st (2), %st + fadd %st, %st + fadd %st (8) diff --git a/modules/parsers/gas/tests/reggroup-err.errwarn b/modules/parsers/gas/tests/reggroup-err.errwarn new file mode 100644 index 00000000..1b6d02b7 --- /dev/null +++ b/modules/parsers/gas/tests/reggroup-err.errwarn @@ -0,0 +1 @@ +-:5: bad register index `8' diff --git a/modules/parsers/gas/tests/reggroup.asm b/modules/parsers/gas/tests/reggroup.asm new file mode 100644 index 00000000..5c0d0bf2 --- /dev/null +++ b/modules/parsers/gas/tests/reggroup.asm @@ -0,0 +1,5 @@ + fadd %st (2) + fadd %st (2), %st(0) + fadd %st (2), %st + fadd %st, %st +# fadd %st (8) diff --git a/modules/parsers/gas/tests/reggroup.errwarn b/modules/parsers/gas/tests/reggroup.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/modules/parsers/gas/tests/reggroup.hex b/modules/parsers/gas/tests/reggroup.hex new file mode 100644 index 00000000..e265ffb1 --- /dev/null +++ b/modules/parsers/gas/tests/reggroup.hex @@ -0,0 +1,360 @@ +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 +a0 +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 +d8 +c2 +d8 +c2 +d8 +c2 +d8 +c0 +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 +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 +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 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 -- 2.40.0