#include "string.h"
#include "as.h"
#include "flonum.h"
#include "expr.h"
#include "fixes.h"
#include "relax.h"
#include "i386.h"
#include "i386-opcode.h"
const seg_entry *use_it2 = &cs;
const seg_entry *use_it3 = &es;
const seg_entry *use_it4 = &fs;
const seg_entry *use_it5 = &gs;
static
char *
get_suffix(
uint32_t type,
uint32_t opcode_modifier)
{
#define NoSuf (No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf|No_qSuf)
if((opcode_modifier & NoSuf) == NoSuf)
return("");
switch(type){
case Disp8:
if(opcode_modifier & No_bSuf)
return("");
return("b");
case Imm8:
case Imm8S:
return("b");
case Imm16:
case Disp16:
case InOutPortReg:
if(opcode_modifier & No_wSuf)
return("");
return("w");
case Disp32:
case Disp32S:
case BaseIndex:
if(opcode_modifier & No_lSuf)
return("");
return("l");
case Imm32:
case Imm32S:
case Imm1:
return("l");
default: return("");
}
}
static char *Reg8_table[] = { "%bl", NULL };
static char *Reg16_table[] = { "%bx", NULL };
static char *Reg32_table[] = { "%ecx", NULL };
static char *Reg64_table[] = { "%r13", NULL };
static char *Imm8_table[] = { "$0x7f", NULL };
static char *Imm8_aad_aam_table[] = { "$0x8", NULL };
static char *Imm8S_table[] = { "$0xfe", NULL };
static char *Imm16_table[] = { "$0x7ace", NULL };
static char *Imm16_8_table[] = { "$0x6e", NULL };
static char *Imm32_table[] = { "$0x7afebabe", NULL };
static char *Imm32_8table[] = { "$0xbe", NULL };
static char *Imm32_16table[] = { "$0xbabe", NULL };
static char *Imm32S_table[] = { "$0x13572468", NULL };
static char *Imm32S16_table[] = { "$0x2468", NULL };
static char *Imm32S8_table[] = { "$0x68", NULL };
static char *Imm64_table[] = { "$0xfeedfacecafebabe", NULL };
static char *Imm1_table[] = { "$0", "$1", NULL };
static char *Disp8_table[] = { "0x45", NULL };
static char *Disp16_table[] = { "0x7eed", NULL };
static char *Disp32_table[] = { "0xbabecafe", NULL };
static char *Disp32S_table[] = { "0x12345678", NULL };
static char *Disp64_table[] = { "0xfeedfacebabecafe", NULL };
#ifdef ARCH64
static char *BaseIndex_table[] = { "0xdeadbeef(%rbx,%rcx,8)", NULL };
#else
static char *BaseIndex_table[] = { "0xdeadbeef(%ebx,%ecx,8)", NULL };
#endif
static char *InOutPortReg_table[] = { "%dx", NULL };
static char *ShiftCount_table[] = { "%cl", NULL };
static char *Control_table[] = { "%cr0", NULL };
static char *Debug_table[] = { "%db0", NULL };
static char *Test_table[] = { "%tr3", NULL };
static char *FloatReg_table[] = { "%st(2)", NULL };
static char *FloatAcc_table[] = { "%st", NULL };
static char *SReg2_table[] = { "%ds", NULL };
static char *SReg3_table[] = { "%fs", NULL };
static char *Acc_table[] = { "%eax", NULL };
static char *Acc8_table[] = { "%al", NULL };
static char *Acc16_table[] = { "%ax", NULL };
static char *Acc64_table[] = { "%rax", NULL };
static char *JumpAbsolute_table[] = { "*0xbadeface", NULL };
static char *RegMMX_table[] = { "%mm3", NULL };
static char *RegXMM_table[] = { "%xmm5", NULL };
static char *hosed_table[] = { "hosed", NULL };
static
char **
get_operand(
uint32_t type0,
uint32_t type1)
{
switch(type0){
case Reg8: return(Reg8_table);
case Reg16: return(Reg16_table);
case Reg32: return(Reg32_table);
case Reg64: return(Reg64_table);
case Imm8: return(Imm8_table);
case Imm8S: return(Imm8S_table);
case Imm16:
switch(type1){
case Reg8:
return(Imm16_8_table);
default:
return(Imm16_table);
}
case Imm32:
switch(type1){
case Reg8:
return(Imm32_8table);
case Reg16:
return(Imm32_16table);
default:
return(Imm32_table);
}
case Imm32S:
switch(type1){
case Reg8:
return(Imm32S8_table);
case Reg16:
return(Imm32S16_table);
default:
return(Imm32S_table);
}
case Imm64: return(Imm64_table);
case Imm1: return(Imm1_table);
case Disp8: return(Disp8_table);
case Disp16: return(Disp16_table);
case Disp32: return(Disp32_table);
case Disp32S: return(Disp32S_table);
case Disp64: return(Disp64_table);
case BaseIndex: return(BaseIndex_table);
case InOutPortReg: return(InOutPortReg_table);
case ShiftCount: return(ShiftCount_table);
case Control: return(Control_table);
case Debug: return(Debug_table);
case Test: return(Test_table);
case FloatReg: return(FloatReg_table);
case FloatAcc: return(FloatAcc_table);
case SReg2: return(SReg2_table);
case SReg3: return(SReg3_table);
case Acc:
switch(type1){
case Reg8:
return(Acc8_table);
case Reg16:
return(Acc16_table);
case Reg64:
return(Acc64_table);
default:
return(Acc_table);
}
case JumpAbsolute: return(JumpAbsolute_table);
case RegMMX: return(RegMMX_table);
case RegXMM: return(RegXMM_table);
default: return(hosed_table);
}
}
int
main(
int argc,
char **argv)
{
const template *t;
uint32_t i, j, type0, type1, llvm_mc, bad_reg;
char **op0, **op1;
char *suffix;
llvm_mc = 0;
if(argc != 1){
if(argc == 2 && strcmp(argv[1], "-llvm-mc") == 0)
llvm_mc = 1;
}
for(t = i386_optab; t->name != NULL ; t++){
if(llvm_mc){
bad_reg = 0;
if(t->operands >= 1)
bad_reg |= t->operand_types[0] & Test;
if(t->operands >= 2)
bad_reg |= t->operand_types[1] & Test;
if(t->operands >= 1){
bad_reg |= t->operand_types[0] & SReg2;
bad_reg |= t->operand_types[0] & SReg3;
}
if(t->operands >= 2){
bad_reg |= t->operand_types[1] & SReg2;
bad_reg |= t->operand_types[1] & SReg3;
}
if(t->operands >= 1)
bad_reg |= t->operand_types[0] & Control;
if(t->operands >= 2)
bad_reg |= t->operand_types[1] & Control;
if(bad_reg)
continue;
}
if(t->opcode_modifier & IsPrefix)
continue;
if(t->opcode_modifier & IsString)
continue;
#ifdef ARCH64
if(t->cpu_flags & CpuNo64)
continue;
#else
if(t->cpu_flags & Cpu64)
continue;
if(t->cpu_flags & CpuK6)
continue;
if(t->cpu_flags & CpuSledgehammer)
continue;
#endif
if(t->operands == 0){
if((t->opcode_modifier & W) == 0) {
printf("\t%s\n", t->name);
}
else{
printf("\t%sb\n", t->name);
printf("\t%sw\n", t->name);
printf("\t%sl\n", t->name);
}
}
if(t->operands == 1){
for(i = 0; i < 32; i++){
type0 = 1 << i;
if((type0 & t->operand_types[0]) == 0)
continue;
#ifndef ARCH64
if(type0 == Reg64)
continue;
#endif
if(type0 >= EsSeg)
continue;
if((t->opcode_modifier & JumpByte) &&
(type0 == Disp16 || type0 == Disp32))
continue;
if(type0 == Disp8 &&
((t->operand_types[0] & (Disp16 | Disp32)) != 0))
continue;
suffix = "";
if((type0 & AnyMem) != 0 || (type0 & EncImm) != 0 ||
type0 == InOutPortReg)
suffix = get_suffix(type0, t->opcode_modifier);
#ifdef ARCH64
if(strcmp(t->name, "push") == 0 ||
strcmp(t->name, "pop") == 0)
suffix = "";
#endif
if((strcmp(t->name, "call") == 0 ||
strcmp(t->name, "lcall") == 0) &&
strcmp(suffix, "l") == 0)
suffix = "";
if(strcmp(t->name, "jmp") == 0 ||
strcmp(t->name, "jecxz") == 0 ||
strcmp(t->name, "jrcxz") == 0 ||
t->opcode_modifier & Jump)
suffix = "";
if(strncmp(t->name, "set", 3) == 0)
suffix = "";
if((strcmp(t->name, "fildl") == 0 ||
strcmp(t->name, "fistpl") == 0) &&
strcmp(suffix, "l") == 0)
suffix = "";
if((strcmp(t->name, "fisttpl") == 0 ||
strcmp(t->name, "fisttpll") == 0))
continue;
if((t->base_opcode & 0xff00) == 0x9b00 &&
strcmp(suffix, "w") == 0)
continue;
op0 = get_operand(type0, 0);
if(type0 == Imm8S &&
(strcmp(t->name, "aad") == 0 ||
strcmp(t->name, "aam") == 0))
op0 = Imm8_aad_aam_table;
if(t->opcode_modifier & JumpByte)
continue;
for( ; *op0; op0++){
if(((strcmp(t->name, "call") == 0 ||
strcmp(t->name, "jmp") == 0) &&
(type0 == BaseIndex || type0 == Reg16 ||
type0 == Reg32 || type0 == Reg64)) ||
((strcmp(t->name, "lcall") == 0 ||
strcmp(t->name, "ljmp") == 0) &&
type0 != JumpAbsolute))
printf("\t%s%s\t*%s\n", t->name, suffix, *op0);
else
printf("\t%s%s\t%s\n", t->name, suffix, *op0);
}
}
}
if(t->operands == 2){
for(i = 0; i < 32; i++){
type0 = 1 << i;
if((type0 & t->operand_types[0]) == 0)
continue;
#ifndef ARCH64
if(type0 == Reg64)
continue;
#endif
if(type0 >= EsSeg)
continue;
for(j = 0; j < 32; j++){
type1 = 1 << j;
if((type1 & t->operand_types[1]) == 0)
continue;
#ifndef ARCH64
if(type1 == Reg64)
continue;
#endif
if(type1 >= EsSeg)
continue;
if((type0 & Reg) != 0 && (type1 & Reg) != 0)
if(type0 != type1)
continue;
suffix = "";
if((type0 & (Imm|Imm1)) != 0 && (type1 & AnyMem) != 0)
suffix = get_suffix(type0, t->opcode_modifier);
if((type0 & AnyMem) != 0 && (type1 & (Imm|Imm1)) != 0)
suffix = get_suffix(type1, t->opcode_modifier);
if(strncmp(t->name, "bt", 2) == 0)
suffix = "";
op0 = get_operand(type0, type1);
op1 = get_operand(type1, type0);
if(strcmp(t->name, "mwait") == 0){
op0 = Acc_table;
op1 = Reg32_table;
}
for( ; *op0; op0++){
for( ; *op1; op1++){
printf("\t%s%s\t%s,%s\n", t->name, suffix,
*op0, *op1);
if(t->opcode_modifier & D){
printf("\t%s%s\t%s,%s\n", t->name, suffix,
*op1, *op0);
}
}
}
}
}
}
}
return(0);
}