Add lea, l?s, and arithmetic instructions. Arithmetic instructions needed

two additional actions: signed immediate and spare+ea.

svn path=/trunk/yasm/; revision=676
0.3
Peter Johnson 23 years ago
parent e1eae9bae5
commit 0af7326e75
  1. 236
      modules/arch/x86/x86id.re
  2. 236
      src/arch/x86/x86id.re

@ -127,8 +127,11 @@ static unsigned long cpu_enabled = ~CPU_Any;
* 0 = does nothing (operand data is discarded) * 0 = does nothing (operand data is discarded)
* 1 = operand data goes into ea field * 1 = operand data goes into ea field
* 2 = operand data goes into imm field * 2 = operand data goes into imm field
* 3 = operand data goes into "spare" field * 3 = operand data goes into sign-extended imm field
* 4 = operand data is added to opcode byte 0 * 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_Imm 0x0
#define OPT_Reg 0x1 #define OPT_Reg 0x1
@ -168,8 +171,10 @@ static unsigned long cpu_enabled = ~CPU_Any;
#define OPA_None (0<<9) #define OPA_None (0<<9)
#define OPA_EA (1<<9) #define OPA_EA (1<<9)
#define OPA_Imm (2<<9) #define OPA_Imm (2<<9)
#define OPA_Spare (3<<9) #define OPA_SImm (3<<9)
#define OPA_Op0Add (4<<9) #define OPA_Spare (4<<9)
#define OPA_Op0Add (5<<9)
#define OPA_SpareEA (6<<9)
#define OPA_MASK 0x0E00 #define OPA_MASK 0x0E00
typedef struct x86_insn_info { 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} } {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 * bytecode *
x86_new_insn(const unsigned long data[4], int num_operands, x86_new_insn(const unsigned long data[4], int num_operands,
insn_operandhead *operands) insn_operandhead *operands)
@ -717,6 +879,15 @@ x86_new_insn(const unsigned long data[4], int num_operands,
} else } else
InternalError(_("invalid operand conversion")); InternalError(_("invalid operand conversion"));
break; 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: case OPA_Spare:
if (op->type == INSN_OPERAND_REG || if (op->type == INSN_OPERAND_REG ||
op->type == INSN_OPERAND_SEGREG) op->type == INSN_OPERAND_SEGREG)
@ -730,6 +901,13 @@ x86_new_insn(const unsigned long data[4], int num_operands,
else else
InternalError(_("invalid operand conversion")); InternalError(_("invalid operand conversion"));
break; 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: default:
InternalError(_("unknown operand action")); 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); } I N { RET_INSN(in, 0, CPU_Any); }
O U T { RET_INSN(out, 0, CPU_Any); } O U T { RET_INSN(out, 0, CPU_Any); }
/* Load effective address */ /* Load effective address */
/* L E A */ L E A { RET_INSN(lea, 0, CPU_Any); }
/* Load segment registers from memory */ /* Load segment registers from memory */
/* L D S */ L D S { RET_INSN(ldes, 0xC5, CPU_Any); }
/* L E S */ L E S { RET_INSN(ldes, 0xC4, CPU_Any); }
/* L F S */ L F S { RET_INSN(lfgss, 0xB4, CPU_386); }
/* L G S */ L G S { RET_INSN(lfgss, 0xB5, CPU_386); }
/* L S S */ L S S { RET_INSN(lfgss, 0xB6, CPU_386); }
/* Flags register instructions */ /* Flags register instructions */
C L C { RET_INSN(onebyte, 0x00F8, CPU_Any); } C L C { RET_INSN(onebyte, 0x00F8, CPU_Any); }
C L D { RET_INSN(onebyte, 0x00FC, 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 D { RET_INSN(onebyte, 0x00FD, CPU_Any); }
S T I { RET_INSN(onebyte, 0x00FB, CPU_Any); } S T I { RET_INSN(onebyte, 0x00FB, CPU_Any); }
/* Arithmetic */ /* Arithmetic */
/* A D D */ A D D { RET_INSN(arith, 0x0000, CPU_Any); }
/* I N C */ I N C { RET_INSN(incdec, 0x0040, CPU_Any); }
/* S U B */ S U B { RET_INSN(arith, 0x0528, CPU_Any); }
/* D E C */ D E C { RET_INSN(incdec, 0x0148, CPU_Any); }
/* S B B */ S B B { RET_INSN(arith, 0x0318, CPU_Any); }
/* C M P */ C M P { RET_INSN(arith, 0x0738, CPU_Any); }
/* T E S T */ T E S T { RET_INSN(test, 0, CPU_Any); }
/* A N D */ A N D { RET_INSN(arith, 0x0420, CPU_Any); }
/* O R */ O R { RET_INSN(arith, 0x0108, CPU_Any); }
/* X O R */ X O R { RET_INSN(arith, 0x0630, CPU_Any); }
/* A D C */ A D C { RET_INSN(arith, 0x0210, CPU_Any); }
/* N E G */ N E G { RET_INSN(f6, 0x03, CPU_Any); }
/* N O T */ N O T { RET_INSN(f6, 0x02, CPU_Any); }
A A A { RET_INSN(onebyte, 0x0037, CPU_Any); } A A A { RET_INSN(onebyte, 0x0037, CPU_Any); }
A A S { RET_INSN(onebyte, 0x003F, CPU_Any); } A A S { RET_INSN(onebyte, 0x003F, CPU_Any); }
D A A { RET_INSN(onebyte, 0x0027, CPU_Any); } D A A { RET_INSN(onebyte, 0x0027, CPU_Any); }
D A S { RET_INSN(onebyte, 0x002F, CPU_Any); } D A S { RET_INSN(onebyte, 0x002F, CPU_Any); }
/* A A D */ A A D { RET_INSN(aadm, 0x01, CPU_Any); }
/* A A M */ A A M { RET_INSN(aadm, 0x00, CPU_Any); }
/* Conversion instructions */ /* Conversion instructions */
C B W { RET_INSN(onebyte, 0x1098, CPU_Any); } C B W { RET_INSN(onebyte, 0x1098, CPU_Any); }
C W D E { RET_INSN(onebyte, 0x2098, CPU_386); } C W D E { RET_INSN(onebyte, 0x2098, CPU_386); }
C W D { RET_INSN(onebyte, 0x1099, CPU_Any); } C W D { RET_INSN(onebyte, 0x1099, CPU_Any); }
C D Q { RET_INSN(onebyte, 0x2099, CPU_386); } C D Q { RET_INSN(onebyte, 0x2099, CPU_386); }
/* Multiplication and division */ /* Multiplication and division */
/* M U L */ M U L { RET_INSN(f6, 0x04, CPU_Any); }
/* I M U L */ I M U L { RET_INSN(imul, 0, CPU_Any); }
/* D I V */ D I V { RET_INSN(f6, 0x06, CPU_Any); }
/* I D I V */ I D I V { RET_INSN(f6, 0x07, CPU_Any); }
/* Shifts */ /* Shifts */
/* R O L */ /* R O L */
/* R O R */ /* R O R */

@ -127,8 +127,11 @@ static unsigned long cpu_enabled = ~CPU_Any;
* 0 = does nothing (operand data is discarded) * 0 = does nothing (operand data is discarded)
* 1 = operand data goes into ea field * 1 = operand data goes into ea field
* 2 = operand data goes into imm field * 2 = operand data goes into imm field
* 3 = operand data goes into "spare" field * 3 = operand data goes into sign-extended imm field
* 4 = operand data is added to opcode byte 0 * 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_Imm 0x0
#define OPT_Reg 0x1 #define OPT_Reg 0x1
@ -168,8 +171,10 @@ static unsigned long cpu_enabled = ~CPU_Any;
#define OPA_None (0<<9) #define OPA_None (0<<9)
#define OPA_EA (1<<9) #define OPA_EA (1<<9)
#define OPA_Imm (2<<9) #define OPA_Imm (2<<9)
#define OPA_Spare (3<<9) #define OPA_SImm (3<<9)
#define OPA_Op0Add (4<<9) #define OPA_Spare (4<<9)
#define OPA_Op0Add (5<<9)
#define OPA_SpareEA (6<<9)
#define OPA_MASK 0x0E00 #define OPA_MASK 0x0E00
typedef struct x86_insn_info { 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} } {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 * bytecode *
x86_new_insn(const unsigned long data[4], int num_operands, x86_new_insn(const unsigned long data[4], int num_operands,
insn_operandhead *operands) insn_operandhead *operands)
@ -717,6 +879,15 @@ x86_new_insn(const unsigned long data[4], int num_operands,
} else } else
InternalError(_("invalid operand conversion")); InternalError(_("invalid operand conversion"));
break; 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: case OPA_Spare:
if (op->type == INSN_OPERAND_REG || if (op->type == INSN_OPERAND_REG ||
op->type == INSN_OPERAND_SEGREG) op->type == INSN_OPERAND_SEGREG)
@ -730,6 +901,13 @@ x86_new_insn(const unsigned long data[4], int num_operands,
else else
InternalError(_("invalid operand conversion")); InternalError(_("invalid operand conversion"));
break; 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: default:
InternalError(_("unknown operand action")); 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); } I N { RET_INSN(in, 0, CPU_Any); }
O U T { RET_INSN(out, 0, CPU_Any); } O U T { RET_INSN(out, 0, CPU_Any); }
/* Load effective address */ /* Load effective address */
/* L E A */ L E A { RET_INSN(lea, 0, CPU_Any); }
/* Load segment registers from memory */ /* Load segment registers from memory */
/* L D S */ L D S { RET_INSN(ldes, 0xC5, CPU_Any); }
/* L E S */ L E S { RET_INSN(ldes, 0xC4, CPU_Any); }
/* L F S */ L F S { RET_INSN(lfgss, 0xB4, CPU_386); }
/* L G S */ L G S { RET_INSN(lfgss, 0xB5, CPU_386); }
/* L S S */ L S S { RET_INSN(lfgss, 0xB6, CPU_386); }
/* Flags register instructions */ /* Flags register instructions */
C L C { RET_INSN(onebyte, 0x00F8, CPU_Any); } C L C { RET_INSN(onebyte, 0x00F8, CPU_Any); }
C L D { RET_INSN(onebyte, 0x00FC, 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 D { RET_INSN(onebyte, 0x00FD, CPU_Any); }
S T I { RET_INSN(onebyte, 0x00FB, CPU_Any); } S T I { RET_INSN(onebyte, 0x00FB, CPU_Any); }
/* Arithmetic */ /* Arithmetic */
/* A D D */ A D D { RET_INSN(arith, 0x0000, CPU_Any); }
/* I N C */ I N C { RET_INSN(incdec, 0x0040, CPU_Any); }
/* S U B */ S U B { RET_INSN(arith, 0x0528, CPU_Any); }
/* D E C */ D E C { RET_INSN(incdec, 0x0148, CPU_Any); }
/* S B B */ S B B { RET_INSN(arith, 0x0318, CPU_Any); }
/* C M P */ C M P { RET_INSN(arith, 0x0738, CPU_Any); }
/* T E S T */ T E S T { RET_INSN(test, 0, CPU_Any); }
/* A N D */ A N D { RET_INSN(arith, 0x0420, CPU_Any); }
/* O R */ O R { RET_INSN(arith, 0x0108, CPU_Any); }
/* X O R */ X O R { RET_INSN(arith, 0x0630, CPU_Any); }
/* A D C */ A D C { RET_INSN(arith, 0x0210, CPU_Any); }
/* N E G */ N E G { RET_INSN(f6, 0x03, CPU_Any); }
/* N O T */ N O T { RET_INSN(f6, 0x02, CPU_Any); }
A A A { RET_INSN(onebyte, 0x0037, CPU_Any); } A A A { RET_INSN(onebyte, 0x0037, CPU_Any); }
A A S { RET_INSN(onebyte, 0x003F, CPU_Any); } A A S { RET_INSN(onebyte, 0x003F, CPU_Any); }
D A A { RET_INSN(onebyte, 0x0027, CPU_Any); } D A A { RET_INSN(onebyte, 0x0027, CPU_Any); }
D A S { RET_INSN(onebyte, 0x002F, CPU_Any); } D A S { RET_INSN(onebyte, 0x002F, CPU_Any); }
/* A A D */ A A D { RET_INSN(aadm, 0x01, CPU_Any); }
/* A A M */ A A M { RET_INSN(aadm, 0x00, CPU_Any); }
/* Conversion instructions */ /* Conversion instructions */
C B W { RET_INSN(onebyte, 0x1098, CPU_Any); } C B W { RET_INSN(onebyte, 0x1098, CPU_Any); }
C W D E { RET_INSN(onebyte, 0x2098, CPU_386); } C W D E { RET_INSN(onebyte, 0x2098, CPU_386); }
C W D { RET_INSN(onebyte, 0x1099, CPU_Any); } C W D { RET_INSN(onebyte, 0x1099, CPU_Any); }
C D Q { RET_INSN(onebyte, 0x2099, CPU_386); } C D Q { RET_INSN(onebyte, 0x2099, CPU_386); }
/* Multiplication and division */ /* Multiplication and division */
/* M U L */ M U L { RET_INSN(f6, 0x04, CPU_Any); }
/* I M U L */ I M U L { RET_INSN(imul, 0, CPU_Any); }
/* D I V */ D I V { RET_INSN(f6, 0x06, CPU_Any); }
/* I D I V */ I D I V { RET_INSN(f6, 0x07, CPU_Any); }
/* Shifts */ /* Shifts */
/* R O L */ /* R O L */
/* R O R */ /* R O R */

Loading…
Cancel
Save