From 0af7326e75b9d4617eb63d63948cc32a9a928078 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 10 Aug 2002 08:26:02 +0000 Subject: [PATCH] Add lea, l?s, and arithmetic instructions. Arithmetic instructions needed two additional actions: signed immediate and spare+ea. svn path=/trunk/yasm/; revision=676 --- modules/arch/x86/x86id.re | 236 +++++++++++++++++++++++++++++++++----- src/arch/x86/x86id.re | 236 +++++++++++++++++++++++++++++++++----- 2 files changed, 414 insertions(+), 58 deletions(-) diff --git a/modules/arch/x86/x86id.re b/modules/arch/x86/x86id.re index 27892c94..c0c3814a 100644 --- a/modules/arch/x86/x86id.re +++ b/modules/arch/x86/x86id.re @@ -127,8 +127,11 @@ static unsigned long cpu_enabled = ~CPU_Any; * 0 = does nothing (operand data is discarded) * 1 = operand data goes into ea field * 2 = operand data goes into imm field - * 3 = operand data goes into "spare" field - * 4 = operand data is added to opcode byte 0 + * 3 = operand data goes into sign-extended imm field + * 4 = operand data goes into "spare" field + * 5 = operand data is added to opcode byte 0 + * 6 = operand data goes into BOTH ea and spare + * [special case for imul opcode] */ #define OPT_Imm 0x0 #define OPT_Reg 0x1 @@ -168,8 +171,10 @@ static unsigned long cpu_enabled = ~CPU_Any; #define OPA_None (0<<9) #define OPA_EA (1<<9) #define OPA_Imm (2<<9) -#define OPA_Spare (3<<9) -#define OPA_Op0Add (4<<9) +#define OPA_SImm (3<<9) +#define OPA_Spare (4<<9) +#define OPA_Op0Add (5<<9) +#define OPA_SpareEA (6<<9) #define OPA_MASK 0x0E00 typedef struct x86_insn_info { @@ -420,6 +425,163 @@ static const x86_insn_info out_insn[] = { {OPT_Dreg|OPS_16|OPA_None, OPT_Areg|OPS_32|OPA_None, 0} } }; +/* Load effective address */ +static const x86_insn_info lea_insn[] = { + { CPU_Any, 0, 16, 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, 1, {0x8D, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_Mem|OPS_32|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Load segment registers from memory */ +static const x86_insn_info ldes_insn[] = { + { CPU_Any, MOD_Op0Add, 16, 1, {0, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, MOD_Op0Add, 32, 1, {0, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} } +}; +static const x86_insn_info lfgss_insn[] = { + { CPU_386, MOD_Op1Add, 16, 1, {0x0F, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, MOD_Op1Add, 32, 1, {0x0F, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Arithmetic - general */ +static const x86_insn_info arith_insn[] = { + { CPU_Any, MOD_Op0Add, 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, 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, 1, {0x05, 0, 0}, 0, 2, + {OPT_Areg|OPS_32|OPA_None, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, MOD_Gap0|MOD_SpAdd, 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, 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, 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, 1, {0x81, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, MOD_Gap0|MOD_SpAdd, 16, 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, 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, 1, {0x81, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_386, MOD_Gap0|MOD_SpAdd, 32, 1, {0x81, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, + { CPU_Any, MOD_Op0Add, 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, 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, 1, {0x01, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} }, + { CPU_Any, MOD_Op0Add, 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, 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, 1, {0x03, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Arithmetic - inc/dec */ +static const x86_insn_info incdec_insn[] = { + { CPU_Any, MOD_Gap0|MOD_SpAdd, 0, 1, {0xFE, 0, 0}, 0, 1, + {OPT_RM|OPS_8|OPA_EA, 0, 0} }, + { CPU_Any, MOD_Op0Add, 16, 1, {0, 0, 0}, 0, 1, + {OPT_Reg|OPS_16|OPA_Op0Add, 0, 0} }, + { CPU_Any, MOD_Gap0|MOD_SpAdd, 16, 1, {0xFF, 0, 0}, 0, 1, + {OPT_RM|OPS_16|OPA_EA, 0, 0} }, + { CPU_386, MOD_Op0Add, 32, 1, {0, 0, 0}, 0, 1, + {OPT_Reg|OPS_32|OPA_Op0Add, 0, 0} }, + { CPU_386, MOD_Gap0|MOD_SpAdd, 32, 1, {0xFF, 0, 0}, 0, 1, + {OPT_RM|OPS_32|OPA_EA, 0, 0} }, +}; + +/* Arithmetic - "F6" opcodes (div/idiv/mul/neg/not) */ +static const x86_insn_info f6_insn[] = { + { CPU_Any, MOD_SpAdd, 0, 1, {0xF6, 0, 0}, 0, 1, + {OPT_RM|OPS_8|OPA_EA, 0, 0} }, + { CPU_Any, MOD_SpAdd, 16, 1, {0xF7, 0, 0}, 0, 1, + {OPT_RM|OPS_16|OPA_EA, 0, 0} }, + { CPU_386, MOD_SpAdd, 32, 1, {0xF7, 0, 0}, 0, 1, + {OPT_RM|OPS_32|OPA_EA, 0, 0} }, +}; + +/* Arithmetic - test instruction */ +static const x86_insn_info test_insn[] = { + { CPU_Any, 0, 0, 1, {0xA8, 0, 0}, 0, 2, + {OPT_Areg|OPS_8|OPA_None, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 16, 1, {0xA9, 0, 0}, 0, 2, + {OPT_Areg|OPS_16|OPA_None, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_386, 0, 32, 1, {0xA9, 0, 0}, 0, 2, + {OPT_Areg|OPS_32|OPA_None, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 0, 1, {0xF6, 0, 0}, 0, 2, + {OPT_RM|OPS_8|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 0, 1, {0xF6, 0, 0}, 0, 2, + {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_8|OPA_Imm, 0} }, + { CPU_Any, 0, 16, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 16, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_16|OPA_Imm, 0} }, + { CPU_386, 0, 32, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_386, 0, 32, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, + { CPU_Any, 0, 0, 1, {0x84, 0, 0}, 0, 2, + {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_8|OPA_Spare, 0} }, + { CPU_Any, 0, 16, 1, {0x85, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare, 0} }, + { CPU_386, 0, 32, 1, {0x85, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} }, + { CPU_Any, 0, 0, 1, {0x84, 0, 0}, 0, 2, + {OPT_Reg|OPS_8|OPA_Spare, OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, 0} }, + { CPU_Any, 0, 16, 1, {0x85, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, 0, 32, 1, {0x85, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Arithmetic - aad/aam */ +static const x86_insn_info aadm_insn[] = { + { CPU_Any, MOD_Op0Add, 0, 2, {0xD4, 0x0A, 0}, 0, 0, {0, 0, 0} }, + { CPU_Any, MOD_Op0Add, 0, 1, {0xD4, 0, 0}, 0, 1, + {OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0, 0} } +}; + +/* Arithmetic - imul */ +static const x86_insn_info imul_insn[] = { + { CPU_Any, 0, 0, 1, {0xF6, 0, 0}, 5, 1, {OPT_RM|OPS_8|OPA_EA, 0, 0} }, + { CPU_Any, 0, 16, 1, {0xF7, 0, 0}, 5, 1, {OPT_RM|OPS_16|OPA_EA, 0, 0} }, + { CPU_386, 0, 32, 1, {0xF7, 0, 0}, 5, 1, {OPT_RM|OPS_32|OPA_EA, 0, 0} }, + { CPU_386, 0, 16, 2, {0x0F, 0xAF, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, 0, 32, 2, {0x0F, 0xAF, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} }, + { CPU_186, 0, 16, 1, {0x6B, 0, 0}, 0, 3, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_8|OPA_SImm} }, + { CPU_386, 0, 32, 1, {0x6B, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_8|OPA_SImm} }, + { CPU_186, 0, 16, 1, {0x6B, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} }, + { CPU_386, 0, 32, 1, {0x6B, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} }, + { CPU_186, 0, 16, 1, {0x69, 0, 0}, 0, 3, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm} }, + { CPU_386, 0, 32, 1, {0x69, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm} }, + { CPU_186, 0, 16, 1, {0x69, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_SpareEA, OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm, 0} }, + { CPU_386, 0, 32, 1, {0x69, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_SpareEA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm, 0} } +}; + + bytecode * x86_new_insn(const unsigned long data[4], int num_operands, insn_operandhead *operands) @@ -717,6 +879,15 @@ x86_new_insn(const unsigned long data[4], int num_operands, } else InternalError(_("invalid operand conversion")); break; + case OPA_SImm: + if (op->type == INSN_OPERAND_IMM) { + d.imm = op->data.val; + d.im_len = size_lookup[(info->operands[i] & + OPS_MASK)>>OPS_SHIFT]; + d.im_sign = 1; + } else + InternalError(_("invalid operand conversion")); + break; case OPA_Spare: if (op->type == INSN_OPERAND_REG || op->type == INSN_OPERAND_SEGREG) @@ -730,6 +901,13 @@ x86_new_insn(const unsigned long data[4], int num_operands, else InternalError(_("invalid operand conversion")); break; + case OPA_SpareEA: + if (op->type == INSN_OPERAND_REG) { + d.spare = (unsigned char)(op->data.reg&7); + d.ea = x86_ea_new_reg((unsigned char)op->data.reg); + } else + InternalError(_("invalid operand conversion")); + break; default: InternalError(_("unknown operand action")); } @@ -1059,13 +1237,13 @@ x86_check_identifier(unsigned long data[4], const char *id) I N { RET_INSN(in, 0, CPU_Any); } O U T { RET_INSN(out, 0, CPU_Any); } /* Load effective address */ - /* L E A */ + L E A { RET_INSN(lea, 0, CPU_Any); } /* Load segment registers from memory */ - /* L D S */ - /* L E S */ - /* L F S */ - /* L G S */ - /* L S S */ + L D S { RET_INSN(ldes, 0xC5, CPU_Any); } + L E S { RET_INSN(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, 0xB6, CPU_386); } /* Flags register instructions */ C L C { RET_INSN(onebyte, 0x00F8, CPU_Any); } C L D { RET_INSN(onebyte, 0x00FC, CPU_Any); } @@ -1084,35 +1262,35 @@ x86_check_identifier(unsigned long data[4], const char *id) S T D { RET_INSN(onebyte, 0x00FD, CPU_Any); } S T I { RET_INSN(onebyte, 0x00FB, CPU_Any); } /* Arithmetic */ - /* A D D */ - /* I N C */ - /* S U B */ - /* D E C */ - /* S B B */ - /* C M P */ - /* T E S T */ - /* A N D */ - /* O R */ - /* X O R */ - /* A D C */ - /* N E G */ - /* N O T */ + 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 A A { RET_INSN(onebyte, 0x0037, CPU_Any); } A A S { RET_INSN(onebyte, 0x003F, CPU_Any); } D A A { RET_INSN(onebyte, 0x0027, CPU_Any); } D A S { RET_INSN(onebyte, 0x002F, CPU_Any); } - /* A A D */ - /* A A M */ + A A D { RET_INSN(aadm, 0x01, CPU_Any); } + A A M { RET_INSN(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 W D { RET_INSN(onebyte, 0x1099, CPU_Any); } C D Q { RET_INSN(onebyte, 0x2099, CPU_386); } /* Multiplication and division */ - /* M U L */ - /* I M U L */ - /* D I V */ - /* I D I V */ + 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); } /* Shifts */ /* R O L */ /* R O R */ diff --git a/src/arch/x86/x86id.re b/src/arch/x86/x86id.re index 27892c94..c0c3814a 100644 --- a/src/arch/x86/x86id.re +++ b/src/arch/x86/x86id.re @@ -127,8 +127,11 @@ static unsigned long cpu_enabled = ~CPU_Any; * 0 = does nothing (operand data is discarded) * 1 = operand data goes into ea field * 2 = operand data goes into imm field - * 3 = operand data goes into "spare" field - * 4 = operand data is added to opcode byte 0 + * 3 = operand data goes into sign-extended imm field + * 4 = operand data goes into "spare" field + * 5 = operand data is added to opcode byte 0 + * 6 = operand data goes into BOTH ea and spare + * [special case for imul opcode] */ #define OPT_Imm 0x0 #define OPT_Reg 0x1 @@ -168,8 +171,10 @@ static unsigned long cpu_enabled = ~CPU_Any; #define OPA_None (0<<9) #define OPA_EA (1<<9) #define OPA_Imm (2<<9) -#define OPA_Spare (3<<9) -#define OPA_Op0Add (4<<9) +#define OPA_SImm (3<<9) +#define OPA_Spare (4<<9) +#define OPA_Op0Add (5<<9) +#define OPA_SpareEA (6<<9) #define OPA_MASK 0x0E00 typedef struct x86_insn_info { @@ -420,6 +425,163 @@ static const x86_insn_info out_insn[] = { {OPT_Dreg|OPS_16|OPA_None, OPT_Areg|OPS_32|OPA_None, 0} } }; +/* Load effective address */ +static const x86_insn_info lea_insn[] = { + { CPU_Any, 0, 16, 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, 1, {0x8D, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_Mem|OPS_32|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Load segment registers from memory */ +static const x86_insn_info ldes_insn[] = { + { CPU_Any, MOD_Op0Add, 16, 1, {0, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, MOD_Op0Add, 32, 1, {0, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} } +}; +static const x86_insn_info lfgss_insn[] = { + { CPU_386, MOD_Op1Add, 16, 1, {0x0F, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, MOD_Op1Add, 32, 1, {0x0F, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_Mem|OPS_Any|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Arithmetic - general */ +static const x86_insn_info arith_insn[] = { + { CPU_Any, MOD_Op0Add, 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, 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, 1, {0x05, 0, 0}, 0, 2, + {OPT_Areg|OPS_32|OPA_None, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, MOD_Gap0|MOD_SpAdd, 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, 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, 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, 1, {0x81, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, MOD_Gap0|MOD_SpAdd, 16, 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, 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, 1, {0x81, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_386, MOD_Gap0|MOD_SpAdd, 32, 1, {0x81, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, + { CPU_Any, MOD_Op0Add, 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, 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, 1, {0x01, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} }, + { CPU_Any, MOD_Op0Add, 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, 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, 1, {0x03, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Arithmetic - inc/dec */ +static const x86_insn_info incdec_insn[] = { + { CPU_Any, MOD_Gap0|MOD_SpAdd, 0, 1, {0xFE, 0, 0}, 0, 1, + {OPT_RM|OPS_8|OPA_EA, 0, 0} }, + { CPU_Any, MOD_Op0Add, 16, 1, {0, 0, 0}, 0, 1, + {OPT_Reg|OPS_16|OPA_Op0Add, 0, 0} }, + { CPU_Any, MOD_Gap0|MOD_SpAdd, 16, 1, {0xFF, 0, 0}, 0, 1, + {OPT_RM|OPS_16|OPA_EA, 0, 0} }, + { CPU_386, MOD_Op0Add, 32, 1, {0, 0, 0}, 0, 1, + {OPT_Reg|OPS_32|OPA_Op0Add, 0, 0} }, + { CPU_386, MOD_Gap0|MOD_SpAdd, 32, 1, {0xFF, 0, 0}, 0, 1, + {OPT_RM|OPS_32|OPA_EA, 0, 0} }, +}; + +/* Arithmetic - "F6" opcodes (div/idiv/mul/neg/not) */ +static const x86_insn_info f6_insn[] = { + { CPU_Any, MOD_SpAdd, 0, 1, {0xF6, 0, 0}, 0, 1, + {OPT_RM|OPS_8|OPA_EA, 0, 0} }, + { CPU_Any, MOD_SpAdd, 16, 1, {0xF7, 0, 0}, 0, 1, + {OPT_RM|OPS_16|OPA_EA, 0, 0} }, + { CPU_386, MOD_SpAdd, 32, 1, {0xF7, 0, 0}, 0, 1, + {OPT_RM|OPS_32|OPA_EA, 0, 0} }, +}; + +/* Arithmetic - test instruction */ +static const x86_insn_info test_insn[] = { + { CPU_Any, 0, 0, 1, {0xA8, 0, 0}, 0, 2, + {OPT_Areg|OPS_8|OPA_None, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 16, 1, {0xA9, 0, 0}, 0, 2, + {OPT_Areg|OPS_16|OPA_None, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_386, 0, 32, 1, {0xA9, 0, 0}, 0, 2, + {OPT_Areg|OPS_32|OPA_None, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 0, 1, {0xF6, 0, 0}, 0, 2, + {OPT_RM|OPS_8|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 0, 1, {0xF6, 0, 0}, 0, 2, + {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_8|OPA_Imm, 0} }, + { CPU_Any, 0, 16, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPA_EA, OPT_Imm|OPS_16|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_Any, 0, 16, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_16|OPA_Imm, 0} }, + { CPU_386, 0, 32, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPA_EA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm, 0} }, + { CPU_386, 0, 32, 1, {0xF7, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_32|OPA_Imm, 0} }, + { CPU_Any, 0, 0, 1, {0x84, 0, 0}, 0, 2, + {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_8|OPA_Spare, 0} }, + { CPU_Any, 0, 16, 1, {0x85, 0, 0}, 0, 2, + {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare, 0} }, + { CPU_386, 0, 32, 1, {0x85, 0, 0}, 0, 2, + {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} }, + { CPU_Any, 0, 0, 1, {0x84, 0, 0}, 0, 2, + {OPT_Reg|OPS_8|OPA_Spare, OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, 0} }, + { CPU_Any, 0, 16, 1, {0x85, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, 0, 32, 1, {0x85, 0, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} } +}; + +/* Arithmetic - aad/aam */ +static const x86_insn_info aadm_insn[] = { + { CPU_Any, MOD_Op0Add, 0, 2, {0xD4, 0x0A, 0}, 0, 0, {0, 0, 0} }, + { CPU_Any, MOD_Op0Add, 0, 1, {0xD4, 0, 0}, 0, 1, + {OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm, 0, 0} } +}; + +/* Arithmetic - imul */ +static const x86_insn_info imul_insn[] = { + { CPU_Any, 0, 0, 1, {0xF6, 0, 0}, 5, 1, {OPT_RM|OPS_8|OPA_EA, 0, 0} }, + { CPU_Any, 0, 16, 1, {0xF7, 0, 0}, 5, 1, {OPT_RM|OPS_16|OPA_EA, 0, 0} }, + { CPU_386, 0, 32, 1, {0xF7, 0, 0}, 5, 1, {OPT_RM|OPS_32|OPA_EA, 0, 0} }, + { CPU_386, 0, 16, 2, {0x0F, 0xAF, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, + { CPU_386, 0, 32, 2, {0x0F, 0xAF, 0}, 0, 2, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} }, + { CPU_186, 0, 16, 1, {0x6B, 0, 0}, 0, 3, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_8|OPA_SImm} }, + { CPU_386, 0, 32, 1, {0x6B, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_8|OPA_SImm} }, + { CPU_186, 0, 16, 1, {0x6B, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} }, + { CPU_386, 0, 32, 1, {0x6B, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_SpareEA, OPT_Imm|OPS_8|OPA_SImm, 0} }, + { CPU_186, 0, 16, 1, {0x69, 0, 0}, 0, 3, + {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm} }, + { CPU_386, 0, 32, 1, {0x69, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, + OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm} }, + { CPU_186, 0, 16, 1, {0x69, 0, 0}, 0, 2, + {OPT_Reg|OPS_16|OPA_SpareEA, OPT_Imm|OPS_16|OPS_Relaxed|OPA_SImm, 0} }, + { CPU_386, 0, 32, 1, {0x69, 0, 0}, 0, 3, + {OPT_Reg|OPS_32|OPA_SpareEA, OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm, 0} } +}; + + bytecode * x86_new_insn(const unsigned long data[4], int num_operands, insn_operandhead *operands) @@ -717,6 +879,15 @@ x86_new_insn(const unsigned long data[4], int num_operands, } else InternalError(_("invalid operand conversion")); break; + case OPA_SImm: + if (op->type == INSN_OPERAND_IMM) { + d.imm = op->data.val; + d.im_len = size_lookup[(info->operands[i] & + OPS_MASK)>>OPS_SHIFT]; + d.im_sign = 1; + } else + InternalError(_("invalid operand conversion")); + break; case OPA_Spare: if (op->type == INSN_OPERAND_REG || op->type == INSN_OPERAND_SEGREG) @@ -730,6 +901,13 @@ x86_new_insn(const unsigned long data[4], int num_operands, else InternalError(_("invalid operand conversion")); break; + case OPA_SpareEA: + if (op->type == INSN_OPERAND_REG) { + d.spare = (unsigned char)(op->data.reg&7); + d.ea = x86_ea_new_reg((unsigned char)op->data.reg); + } else + InternalError(_("invalid operand conversion")); + break; default: InternalError(_("unknown operand action")); } @@ -1059,13 +1237,13 @@ x86_check_identifier(unsigned long data[4], const char *id) I N { RET_INSN(in, 0, CPU_Any); } O U T { RET_INSN(out, 0, CPU_Any); } /* Load effective address */ - /* L E A */ + L E A { RET_INSN(lea, 0, CPU_Any); } /* Load segment registers from memory */ - /* L D S */ - /* L E S */ - /* L F S */ - /* L G S */ - /* L S S */ + L D S { RET_INSN(ldes, 0xC5, CPU_Any); } + L E S { RET_INSN(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, 0xB6, CPU_386); } /* Flags register instructions */ C L C { RET_INSN(onebyte, 0x00F8, CPU_Any); } C L D { RET_INSN(onebyte, 0x00FC, CPU_Any); } @@ -1084,35 +1262,35 @@ x86_check_identifier(unsigned long data[4], const char *id) S T D { RET_INSN(onebyte, 0x00FD, CPU_Any); } S T I { RET_INSN(onebyte, 0x00FB, CPU_Any); } /* Arithmetic */ - /* A D D */ - /* I N C */ - /* S U B */ - /* D E C */ - /* S B B */ - /* C M P */ - /* T E S T */ - /* A N D */ - /* O R */ - /* X O R */ - /* A D C */ - /* N E G */ - /* N O T */ + 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 A A { RET_INSN(onebyte, 0x0037, CPU_Any); } A A S { RET_INSN(onebyte, 0x003F, CPU_Any); } D A A { RET_INSN(onebyte, 0x0027, CPU_Any); } D A S { RET_INSN(onebyte, 0x002F, CPU_Any); } - /* A A D */ - /* A A M */ + A A D { RET_INSN(aadm, 0x01, CPU_Any); } + A A M { RET_INSN(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 W D { RET_INSN(onebyte, 0x1099, CPU_Any); } C D Q { RET_INSN(onebyte, 0x2099, CPU_386); } /* Multiplication and division */ - /* M U L */ - /* I M U L */ - /* D I V */ - /* I D I V */ + 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); } /* Shifts */ /* R O L */ /* R O R */ -- 2.40.0