From eb067621cf12238fcc8b17e83766064aff16cc2a Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 11 Aug 2002 01:07:20 +0000 Subject: [PATCH] Added rest of floating point instructions. Needed to add new action to add to opcode byte 1. svn path=/trunk/yasm/; revision=683 --- modules/arch/x86/x86id.re | 213 ++++++++++++++++++++++++++++++-------- src/arch/x86/x86id.re | 213 ++++++++++++++++++++++++++++++-------- 2 files changed, 334 insertions(+), 92 deletions(-) diff --git a/modules/arch/x86/x86id.re b/modules/arch/x86/x86id.re index 05006266..fd624fc4 100644 --- a/modules/arch/x86/x86id.re +++ b/modules/arch/x86/x86id.re @@ -136,7 +136,8 @@ static unsigned long cpu_enabled = ~CPU_Any; * 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 + * 6 = operand data is added to opcode byte 1 + * 7 = operand data goes into BOTH ea and spare * [special case for imul opcode] * The below describes postponed actions: actions which can't be completed at * parse-time due to things like EQU and complex expressions. For these, some @@ -196,7 +197,8 @@ static unsigned long cpu_enabled = ~CPU_Any; #define OPA_SImm (3<<12) #define OPA_Spare (4<<12) #define OPA_Op0Add (5<<12) -#define OPA_SpareEA (6<<12) +#define OPA_Op1Add (6<<12) +#define OPA_SpareEA (7<<12) #define OPA_MASK (7<<12) #define OPAP_None (0<<15) @@ -726,6 +728,119 @@ static const x86_insn_info sldtmsw_insn[] = { {OPT_Reg|OPS_32|OPA_EA, 0, 0} } }; +/* Floating point instructions - load/store with pop (integer and normal) */ +static const x86_insn_info fldstp_insn[] = { + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xD9, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xDD, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Gap1|MOD_SpAdd, 0, 1, {0xDB, 0, 0}, 0, 1, + {OPT_Mem|OPS_80|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xD9, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} } +}; +static const x86_insn_info fildstp_insn[] = { + { CPU_FPU, MOD_SpAdd, 0, 1, {0xDF, 0, 0}, 0, 1, + {OPT_Mem|OPS_16|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_SpAdd, 0, 1, {0xDB, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xDF, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} } +}; +static const x86_insn_info fbldstp_insn[] = { + { CPU_FPU, MOD_SpAdd, 0, 1, {0xDF, 0, 0}, 0, 1, + {OPT_Mem|OPS_80|OPS_Relaxed|OPA_EA, 0, 0} } +}; +/* Floating point instructions - store (normal) */ +static const x86_insn_info fst_insn[] = { + { CPU_FPU, 0, 0, 1, {0xD9, 0, 0}, 2, 1, {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 1, {0xDD, 0, 0}, 2, 1, {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 2, {0xDD, 0xD0, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} } +}; +/* Floating point instructions - exchange (with ST0) */ +static const x86_insn_info fxch_insn[] = { + { CPU_FPU, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} }, + { CPU_FPU, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 2, + {OPT_Reg|OPS_80|OPA_Op1Add, OPT_ST0|OPS_80|OPA_None, 0} }, + { CPU_FPU, 0, 0, 2, {0xD9, 0xC9, 0}, 0, 0, {0, 0, 0} } +}; +/* Floating point instructions - comparisons */ +static const x86_insn_info fcom_insn[] = { + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xD8, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xDC, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} } +}; +/* Floating point instructions - extended comparisons */ +static const x86_insn_info fcom2_insn[] = { + { CPU_286|CPU_FPU, MOD_Op0Add|MOD_Op1Add, 0, 2, {0x00, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_286|CPU_FPU, MOD_Op0Add|MOD_Op1Add, 0, 2, {0x00, 0x00, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} } +}; +/* Floating point instructions - arithmetic */ +static const x86_insn_info farith_insn[] = { + { CPU_FPU, MOD_Gap0|MOD_Gap1|MOD_SpAdd, 0, 1, {0xD8, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Gap1|MOD_SpAdd, 0, 1, {0xDC, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDC, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPTM_To|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDC, 0x00, 0}, 0, 2, + {OPT_Reg|OPS_80|OPA_Op1Add, OPT_ST0|OPS_80|OPA_None, 0} } +}; +static const x86_insn_info farithp_insn[] = { + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDE, 0x01, 0}, 0, 0, {0, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDE, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDE, 0x00, 0}, 0, 2, + {OPT_Reg|OPS_80|OPA_Op1Add, OPT_ST0|OPS_80|OPA_None, 0} } +}; +/* Floating point instructions - integer arith/store wo pop/compare */ +static const x86_insn_info fiarith_insn[] = { + { CPU_FPU, MOD_Op0Add|MOD_SpAdd, 0, 1, {0x04, 0, 0}, 0, 1, + {OPT_Mem|OPS_16|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Op0Add|MOD_SpAdd, 0, 1, {0x00, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} } +}; +/* Floating point instructions - processor control */ +static const x86_insn_info fldnstcw_insn[] = { + { CPU_FPU, MOD_SpAdd, 0, 1, {0xD9, 0, 0}, 0, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} } +}; +static const x86_insn_info fstcw_insn[] = { + { CPU_FPU, 0, 0, 2, {0x9B, 0xD9, 0}, 7, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} } +}; +static const x86_insn_info fnstsw_insn[] = { + { CPU_FPU, 0, 0, 1, {0xDD, 0, 0}, 7, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 2, {0xDF, 0xE0, 0}, 0, 1, + {OPT_Areg|OPS_16|OPA_None, 0, 0} } +}; +static const x86_insn_info fstsw_insn[] = { + { CPU_FPU, 0, 0, 2, {0x9B, 0xDD, 0}, 7, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 3, {0x9B, 0xDF, 0xE0}, 0, 1, + {OPT_Areg|OPS_16|OPA_None, 0, 0} } +}; +static const x86_insn_info ffree_insn[] = { + { CPU_FPU, MOD_Op0Add, 0, 2, {0x00, 0xC0, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} } +}; + bytecode * x86_new_insn(const unsigned long data[4], int num_operands, @@ -1074,6 +1189,12 @@ x86_new_insn(const unsigned long data[4], int num_operands, else InternalError(_("invalid operand conversion")); break; + case OPA_Op1Add: + if (op->type == INSN_OPERAND_REG) + d.op[1] += (unsigned char)(op->data.reg&7); + else + InternalError(_("invalid operand conversion")); + break; case OPA_SpareEA: if (op->type == INSN_OPERAND_REG) { d.spare = (unsigned char)(op->data.reg&7); @@ -1629,22 +1750,22 @@ x86_check_identifier(unsigned long data[4], const char *id) V E R R { RET_INSN(prot286, 0x0400, CPU_286|CPU_Prot); } V E R W { RET_INSN(prot286, 0x0500, CPU_286|CPU_Prot); } /* Floating point instructions */ - /* F L D */ - /* F I L D */ - /* F B L D */ - /* F S T */ - /* F I S T */ - /* F S T P */ - /* F I S T P */ - /* F B S T P */ - /* F X C H */ - /* F C O M */ - /* F I C O M */ - /* F C O M P */ - /* F I C O M P */ + F L D { RET_INSN(fldstp, 0x0500C0, CPU_FPU); } + F I L D { RET_INSN(fildstp, 0x0500, 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, 0x0703, 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 */ - /* F U C O M P */ + 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); } @@ -1655,24 +1776,24 @@ x86_check_identifier(unsigned long data[4], const char *id) 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 */ - /* F A D D P */ - /* F I A D D */ - /* F S U B */ - /* F I S U B */ - /* F S U B P */ - /* F S U B R */ - /* F I S U B R */ - /* F S U B R P */ - /* F M U L */ - /* F I M U L */ - /* F M U L P */ - /* F D I V */ - /* F I D I V */ - /* F D I V P */ - /* F D I V R */ - /* F I D I V R */ - /* F D I V R P */ + 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); } @@ -1693,11 +1814,11 @@ x86_check_identifier(unsigned long data[4], const char *id) 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, 0x98DBE3, CPU_FPU); } - /* F L D C W */ - /* F N S T C W */ - /* F S T C W */ - /* F N S T S W */ - /* F S T S W */ + 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, 0x98DBE2, CPU_FPU); } F N S T E N V { RET_INSN(onebytemem, 0x06D9, CPU_FPU); } @@ -1706,8 +1827,8 @@ x86_check_identifier(unsigned long data[4], const char *id) 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 */ - /* F F R E E P */ + 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); } /* Prefixes (should the others be here too? should wait be a prefix? */ @@ -1737,10 +1858,10 @@ x86_check_identifier(unsigned long data[4], const char *id) U D "1" { RET_INSN(twobyte, 0x0FB9, CPU_286|CPU_Undoc); } /* C M O V */ /* F C M O V */ - /* F C O M I */ - /* F U C O M I */ - /* F C O M I P */ - /* F U C O M I P */ + 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); } /* Pentium4 extensions */ /* M O V N T I */ /* C L F L U S H */ diff --git a/src/arch/x86/x86id.re b/src/arch/x86/x86id.re index 05006266..fd624fc4 100644 --- a/src/arch/x86/x86id.re +++ b/src/arch/x86/x86id.re @@ -136,7 +136,8 @@ static unsigned long cpu_enabled = ~CPU_Any; * 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 + * 6 = operand data is added to opcode byte 1 + * 7 = operand data goes into BOTH ea and spare * [special case for imul opcode] * The below describes postponed actions: actions which can't be completed at * parse-time due to things like EQU and complex expressions. For these, some @@ -196,7 +197,8 @@ static unsigned long cpu_enabled = ~CPU_Any; #define OPA_SImm (3<<12) #define OPA_Spare (4<<12) #define OPA_Op0Add (5<<12) -#define OPA_SpareEA (6<<12) +#define OPA_Op1Add (6<<12) +#define OPA_SpareEA (7<<12) #define OPA_MASK (7<<12) #define OPAP_None (0<<15) @@ -726,6 +728,119 @@ static const x86_insn_info sldtmsw_insn[] = { {OPT_Reg|OPS_32|OPA_EA, 0, 0} } }; +/* Floating point instructions - load/store with pop (integer and normal) */ +static const x86_insn_info fldstp_insn[] = { + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xD9, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xDD, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Gap1|MOD_SpAdd, 0, 1, {0xDB, 0, 0}, 0, 1, + {OPT_Mem|OPS_80|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xD9, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} } +}; +static const x86_insn_info fildstp_insn[] = { + { CPU_FPU, MOD_SpAdd, 0, 1, {0xDF, 0, 0}, 0, 1, + {OPT_Mem|OPS_16|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_SpAdd, 0, 1, {0xDB, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xDF, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} } +}; +static const x86_insn_info fbldstp_insn[] = { + { CPU_FPU, MOD_SpAdd, 0, 1, {0xDF, 0, 0}, 0, 1, + {OPT_Mem|OPS_80|OPS_Relaxed|OPA_EA, 0, 0} } +}; +/* Floating point instructions - store (normal) */ +static const x86_insn_info fst_insn[] = { + { CPU_FPU, 0, 0, 1, {0xD9, 0, 0}, 2, 1, {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 1, {0xDD, 0, 0}, 2, 1, {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 2, {0xDD, 0xD0, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} } +}; +/* Floating point instructions - exchange (with ST0) */ +static const x86_insn_info fxch_insn[] = { + { CPU_FPU, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} }, + { CPU_FPU, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 2, + {OPT_Reg|OPS_80|OPA_Op1Add, OPT_ST0|OPS_80|OPA_None, 0} }, + { CPU_FPU, 0, 0, 2, {0xD9, 0xC9, 0}, 0, 0, {0, 0, 0} } +}; +/* Floating point instructions - comparisons */ +static const x86_insn_info fcom_insn[] = { + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xD8, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_SpAdd, 0, 1, {0xDC, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} } +}; +/* Floating point instructions - extended comparisons */ +static const x86_insn_info fcom2_insn[] = { + { CPU_286|CPU_FPU, MOD_Op0Add|MOD_Op1Add, 0, 2, {0x00, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_286|CPU_FPU, MOD_Op0Add|MOD_Op1Add, 0, 2, {0x00, 0x00, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} } +}; +/* Floating point instructions - arithmetic */ +static const x86_insn_info farith_insn[] = { + { CPU_FPU, MOD_Gap0|MOD_Gap1|MOD_SpAdd, 0, 1, {0xD8, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Gap1|MOD_SpAdd, 0, 1, {0xDC, 0, 0}, 0, 1, + {OPT_Mem|OPS_64|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Gap0|MOD_Op1Add, 0, 2, {0xD8, 0x00, 0}, 0, 2, + {OPT_ST0|OPS_80|OPA_None, OPT_Reg|OPS_80|OPA_Op1Add, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDC, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPTM_To|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDC, 0x00, 0}, 0, 2, + {OPT_Reg|OPS_80|OPA_Op1Add, OPT_ST0|OPS_80|OPA_None, 0} } +}; +static const x86_insn_info farithp_insn[] = { + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDE, 0x01, 0}, 0, 0, {0, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDE, 0x00, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} }, + { CPU_FPU, MOD_Op1Add, 0, 2, {0xDE, 0x00, 0}, 0, 2, + {OPT_Reg|OPS_80|OPA_Op1Add, OPT_ST0|OPS_80|OPA_None, 0} } +}; +/* Floating point instructions - integer arith/store wo pop/compare */ +static const x86_insn_info fiarith_insn[] = { + { CPU_FPU, MOD_Op0Add|MOD_SpAdd, 0, 1, {0x04, 0, 0}, 0, 1, + {OPT_Mem|OPS_16|OPA_EA, 0, 0} }, + { CPU_FPU, MOD_Op0Add|MOD_SpAdd, 0, 1, {0x00, 0, 0}, 0, 1, + {OPT_Mem|OPS_32|OPA_EA, 0, 0} } +}; +/* Floating point instructions - processor control */ +static const x86_insn_info fldnstcw_insn[] = { + { CPU_FPU, MOD_SpAdd, 0, 1, {0xD9, 0, 0}, 0, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} } +}; +static const x86_insn_info fstcw_insn[] = { + { CPU_FPU, 0, 0, 2, {0x9B, 0xD9, 0}, 7, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} } +}; +static const x86_insn_info fnstsw_insn[] = { + { CPU_FPU, 0, 0, 1, {0xDD, 0, 0}, 7, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 2, {0xDF, 0xE0, 0}, 0, 1, + {OPT_Areg|OPS_16|OPA_None, 0, 0} } +}; +static const x86_insn_info fstsw_insn[] = { + { CPU_FPU, 0, 0, 2, {0x9B, 0xDD, 0}, 7, 1, + {OPT_Mem|OPS_16|OPS_Relaxed|OPA_EA, 0, 0} }, + { CPU_FPU, 0, 0, 3, {0x9B, 0xDF, 0xE0}, 0, 1, + {OPT_Areg|OPS_16|OPA_None, 0, 0} } +}; +static const x86_insn_info ffree_insn[] = { + { CPU_FPU, MOD_Op0Add, 0, 2, {0x00, 0xC0, 0}, 0, 1, + {OPT_Reg|OPS_80|OPA_Op1Add, 0, 0} } +}; + bytecode * x86_new_insn(const unsigned long data[4], int num_operands, @@ -1074,6 +1189,12 @@ x86_new_insn(const unsigned long data[4], int num_operands, else InternalError(_("invalid operand conversion")); break; + case OPA_Op1Add: + if (op->type == INSN_OPERAND_REG) + d.op[1] += (unsigned char)(op->data.reg&7); + else + InternalError(_("invalid operand conversion")); + break; case OPA_SpareEA: if (op->type == INSN_OPERAND_REG) { d.spare = (unsigned char)(op->data.reg&7); @@ -1629,22 +1750,22 @@ x86_check_identifier(unsigned long data[4], const char *id) V E R R { RET_INSN(prot286, 0x0400, CPU_286|CPU_Prot); } V E R W { RET_INSN(prot286, 0x0500, CPU_286|CPU_Prot); } /* Floating point instructions */ - /* F L D */ - /* F I L D */ - /* F B L D */ - /* F S T */ - /* F I S T */ - /* F S T P */ - /* F I S T P */ - /* F B S T P */ - /* F X C H */ - /* F C O M */ - /* F I C O M */ - /* F C O M P */ - /* F I C O M P */ + F L D { RET_INSN(fldstp, 0x0500C0, CPU_FPU); } + F I L D { RET_INSN(fildstp, 0x0500, 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, 0x0703, 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 */ - /* F U C O M P */ + 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); } @@ -1655,24 +1776,24 @@ x86_check_identifier(unsigned long data[4], const char *id) 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 */ - /* F A D D P */ - /* F I A D D */ - /* F S U B */ - /* F I S U B */ - /* F S U B P */ - /* F S U B R */ - /* F I S U B R */ - /* F S U B R P */ - /* F M U L */ - /* F I M U L */ - /* F M U L P */ - /* F D I V */ - /* F I D I V */ - /* F D I V P */ - /* F D I V R */ - /* F I D I V R */ - /* F D I V R P */ + 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); } @@ -1693,11 +1814,11 @@ x86_check_identifier(unsigned long data[4], const char *id) 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, 0x98DBE3, CPU_FPU); } - /* F L D C W */ - /* F N S T C W */ - /* F S T C W */ - /* F N S T S W */ - /* F S T S W */ + 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, 0x98DBE2, CPU_FPU); } F N S T E N V { RET_INSN(onebytemem, 0x06D9, CPU_FPU); } @@ -1706,8 +1827,8 @@ x86_check_identifier(unsigned long data[4], const char *id) 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 */ - /* F F R E E P */ + 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); } /* Prefixes (should the others be here too? should wait be a prefix? */ @@ -1737,10 +1858,10 @@ x86_check_identifier(unsigned long data[4], const char *id) U D "1" { RET_INSN(twobyte, 0x0FB9, CPU_286|CPU_Undoc); } /* C M O V */ /* F C M O V */ - /* F C O M I */ - /* F U C O M I */ - /* F C O M I P */ - /* F U C O M I P */ + 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); } /* Pentium4 extensions */ /* M O V N T I */ /* C L F L U S H */