mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1254 lines
36 KiB
1254 lines
36 KiB
/*[
|
|
|
|
dasm.c
|
|
|
|
LOCAL CHAR SccsID[]="@(#)dasm386.c 1.14 07/25/94 Copyright Insignia Solutions Ltd.";
|
|
|
|
Dis-assemble an Intel Instruction
|
|
---------------------------------
|
|
|
|
The possible formats are:-
|
|
|
|
ssss:oooo 11223344 PRE INST ARGS
|
|
|
|
ssss:oooo 11223344556677
|
|
PRE PRE INST ARGS
|
|
|
|
ssss:oooo 1122334455667788 INST ARGS
|
|
99001122334455
|
|
|
|
ssss:oooo 1122334455667788
|
|
99001122334455
|
|
PRE PRE INST ARGS
|
|
|
|
ssss:oooo 1122334455667788 INST ARGS
|
|
|
|
etc.
|
|
]*/
|
|
|
|
#include "insignia.h"
|
|
#include "host_def.h"
|
|
#include "xt.h"
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
/* dasm386 forms part of the ccpu386.o (and ccpu386.o) libraries
|
|
* used for pigging, and as part of spc.ccpu386.
|
|
* When used for pigging the CCPU sas is not available, and will
|
|
* cause link errors is "sas_hw_at" is used in this file.
|
|
* We #undef CCPU to avoid this problem sogul "sas_xxx" be added
|
|
* in this file at a later date.
|
|
*/
|
|
#ifdef PIG
|
|
#undef CCPU
|
|
#endif /* PIG */
|
|
#include "sas.h"
|
|
|
|
#define DASM_INTERNAL
|
|
#include "decode.h"
|
|
#include "dasm.h"
|
|
#include "d_oper.h"
|
|
#include "d_inst.h"
|
|
|
|
#include CpuH
|
|
|
|
/*
|
|
The instruction names.
|
|
**MUST** be in same order as "d_inst.h".
|
|
*/
|
|
LOCAL CHAR *inst_name[] =
|
|
{
|
|
"AAA", /* I_AAA */
|
|
"AAD", /* I_AAD */
|
|
"AAM", /* I_AAM */
|
|
"AAS", /* I_AAS */
|
|
"ADC", /* I_ADC8 */
|
|
"ADC", /* I_ADC16 */
|
|
"ADC", /* I_ADC32 */
|
|
"ADD", /* I_ADD8 */
|
|
"ADD", /* I_ADD16 */
|
|
"ADD", /* I_ADD32 */
|
|
"AND", /* I_AND8 */
|
|
"AND", /* I_AND16 */
|
|
"AND", /* I_AND32 */
|
|
"ARPL", /* I_ARPL */
|
|
"BOUND", /* I_BOUND16 */
|
|
"BOUND", /* I_BOUND32 */
|
|
"BSF", /* I_BSF16 */
|
|
"BSF", /* I_BSF32 */
|
|
"BSR", /* I_BSR16 */
|
|
"BSR", /* I_BSR32 */
|
|
"BSWAP", /* I_BSWAP */
|
|
"BT", /* I_BT16 */
|
|
"BT", /* I_BT32 */
|
|
"BTC", /* I_BTC16 */
|
|
"BTC", /* I_BTC32 */
|
|
"BTR", /* I_BTR16 */
|
|
"BTR", /* I_BTR32 */
|
|
"BTS", /* I_BTS16 */
|
|
"BTS", /* I_BTS32 */
|
|
"CALLF", /* I_CALLF16 */
|
|
"CALLF", /* I_CALLF32 */
|
|
"CALLN", /* I_CALLN16 */
|
|
"CALLN", /* I_CALLN32 */
|
|
"CALLN", /* I_CALLR16 */
|
|
"CALLN", /* I_CALLR32 */
|
|
"CBW", /* I_CBW */
|
|
"CDQ", /* I_CDQ */
|
|
"CLC", /* I_CLC */
|
|
"CLD", /* I_CLD */
|
|
"CLI", /* I_CLI */
|
|
"CLTS", /* I_CLTS */
|
|
"CMC", /* I_CMC */
|
|
"CMP", /* I_CMP8 */
|
|
"CMP", /* I_CMP16 */
|
|
"CMP", /* I_CMP32 */
|
|
"CMPSB", /* I_CMPSB */
|
|
"CMPSD", /* I_CMPSD */
|
|
"CMPSW", /* I_CMPSW */
|
|
"CMPXCHG", /* I_CMPXCHG8 */
|
|
"CMPXCHG", /* I_CMPXCHG16 */
|
|
"CMPXCHG", /* I_CMPXCHG32 */
|
|
"CWD", /* I_CWD */
|
|
"CWDE", /* I_CWDE */
|
|
"DAA", /* I_DAA */
|
|
"DAS", /* I_DAS */
|
|
"DEC", /* I_DEC8 */
|
|
"DEC", /* I_DEC16 */
|
|
"DEC", /* I_DEC32 */
|
|
"DIV", /* I_DIV8 */
|
|
"DIV", /* I_DIV16 */
|
|
"DIV", /* I_DIV32 */
|
|
"ENTER", /* I_ENTER16 */
|
|
"ENTER", /* I_ENTER32 */
|
|
"F2XM1", /* I_F2XM1 */
|
|
"FABS", /* I_FABS */
|
|
"FADD", /* I_FADD */
|
|
"FADDP", /* I_FADDP */
|
|
"FBLD", /* I_FBLD */
|
|
"FBSTP", /* I_FBSTP */
|
|
"FCHS", /* I_FCHS */
|
|
"FCLEX", /* I_FCLEX */
|
|
"FCOM", /* I_FCOM */
|
|
"FCOMP", /* I_FCOMP */
|
|
"FCOMPP", /* I_FCOMPP */
|
|
"FCOS", /* I_FCOS */
|
|
"FDECSTP", /* I_FDECSTP */
|
|
"FDIV", /* I_FDIV */
|
|
"FDIVP", /* I_FDIVP */
|
|
"FDIVR", /* I_FDIVR */
|
|
"FDIVRP", /* I_FDIVRP */
|
|
"FFREE", /* I_FFREE */
|
|
"FFREEP", /* I_FFREEP */
|
|
"FIADD", /* I_FIADD */
|
|
"FICOM", /* I_FICOM */
|
|
"FICOMP", /* I_FICOMP */
|
|
"FIDIV", /* I_FIDIV */
|
|
"FIDIVR", /* I_FIDIVR */
|
|
"FILD", /* I_FILD */
|
|
"FIMUL", /* I_FIMUL */
|
|
"FINCSTP", /* I_FINCSTP */
|
|
"FINIT", /* I_FINIT */
|
|
"FIST", /* I_FIST */
|
|
"FISTP", /* I_FISTP */
|
|
"FISUB", /* I_FISUB */
|
|
"FISUBR", /* I_FISUBR */
|
|
"FLD", /* I_FLD */
|
|
"FLD1", /* I_FLD1 */
|
|
"FLDCW", /* I_FLDCW */
|
|
"FLDENV", /* I_FLDENV16 */
|
|
"FLDENV", /* I_FLDENV32 */
|
|
"FLDL2E", /* I_FLDL2E */
|
|
"FLDL2T", /* I_FLDL2T */
|
|
"FLDLG2", /* I_FLDLG2 */
|
|
"FLDLN2", /* I_FLDLN2 */
|
|
"FLDPI", /* I_FLDPI */
|
|
"FLDZ", /* I_FLDZ */
|
|
"FMUL", /* I_FMUL */
|
|
"FMULP", /* I_FMULP */
|
|
"FNOP", /* I_FNOP */
|
|
"FPATAN", /* I_FPATAN */
|
|
"FPREM", /* I_FPREM */
|
|
"FPREM1", /* I_FPREM1 */
|
|
"FPTAN", /* I_FPTAN */
|
|
"FRNDINT", /* I_FRNDINT */
|
|
"FRSTOR", /* I_FRSTOR16 */
|
|
"FRSTOR", /* I_FRSTOR32 */
|
|
"FSAVE", /* I_FSAVE16 */
|
|
"FSAVE", /* I_FSAVE32 */
|
|
"FSCALE", /* I_FSCALE */
|
|
"FSETPM", /* I_FSETPM */
|
|
"FSIN", /* I_FSIN */
|
|
"FSINCOS", /* I_FSINCOS */
|
|
"FSQRT", /* I_FSQRT */
|
|
"FST", /* I_FST */
|
|
"FSTCW", /* I_FSTCW */
|
|
"FSTENV", /* I_FSTENV16 */
|
|
"FSTENV", /* I_FSTENV32 */
|
|
"FSTP", /* I_FSTP */
|
|
"FSTSW", /* I_FSTSW */
|
|
"FSUB", /* I_FSUB */
|
|
"FSUBP", /* I_FSUBP */
|
|
"FSUBR", /* I_FSUBR */
|
|
"FSUBRP", /* I_FSUBRP */
|
|
"FTST", /* I_FTST */
|
|
"FUCOM", /* I_FUCOM */
|
|
"FUCOMP", /* I_FUCOMP */
|
|
"FUCOMPP", /* I_FUCOMPP */
|
|
"FXAM", /* I_FXAM */
|
|
"FXCH", /* I_FXCH */
|
|
"FXTRACT", /* I_FXTRACT */
|
|
"FYL2X", /* I_FYL2X */
|
|
"FYL2XP1", /* I_FYL2XP1 */
|
|
"HLT", /* I_HLT */
|
|
"IDIV", /* I_IDIV8 */
|
|
"IDIV", /* I_IDIV16 */
|
|
"IDIV", /* I_IDIV32 */
|
|
"IMUL", /* I_IMUL8 */
|
|
"IMUL", /* I_IMUL16 */
|
|
"IMUL", /* I_IMUL32 */
|
|
"IMUL", /* I_IMUL16T2 */
|
|
"IMUL", /* I_IMUL16T3 */
|
|
"IMUL", /* I_IMUL32T2 */
|
|
"IMUL", /* I_IMUL32T3 */
|
|
"IN", /* I_IN8 */
|
|
"IN", /* I_IN16 */
|
|
"IN", /* I_IN32 */
|
|
"INC", /* I_INC8 */
|
|
"INC", /* I_INC16 */
|
|
"INC", /* I_INC32 */
|
|
"INSB", /* I_INSB */
|
|
"INSD", /* I_INSD */
|
|
"INSW", /* I_INSW */
|
|
"INT", /* I_INT3 */
|
|
"INT", /* I_INT */
|
|
"INTO", /* I_INTO */
|
|
"INVD", /* I_INVD */
|
|
"INVLPG", /* I_INVLPG */
|
|
"IRET", /* I_IRET */
|
|
"IRETD", /* I_IRETD */
|
|
"JB", /* I_JB16 */
|
|
"JB", /* I_JB32 */
|
|
"JBE", /* I_JBE16 */
|
|
"JBE", /* I_JBE32 */
|
|
"JCXZ", /* I_JCXZ */
|
|
"JECXZ", /* I_JECXZ */
|
|
"JL", /* I_JL16 */
|
|
"JL", /* I_JL32 */
|
|
"JLE", /* I_JLE16 */
|
|
"JLE", /* I_JLE32 */
|
|
"JMP", /* I_JMPF16 */
|
|
"JMP", /* I_JMPF32 */
|
|
"JMP", /* I_JMPN */
|
|
"JMP", /* I_JMPR16 */
|
|
"JMP", /* I_JMPR32 */
|
|
"JNB", /* I_JNB16 */
|
|
"JNB", /* I_JNB32 */
|
|
"JNBE", /* I_JNBE16 */
|
|
"JNBE", /* I_JNBE32 */
|
|
"JNL", /* I_JNL16 */
|
|
"JNL", /* I_JNL32 */
|
|
"JNLE", /* I_JNLE16 */
|
|
"JNLE", /* I_JNLE32 */
|
|
"JNO", /* I_JNO16 */
|
|
"JNO", /* I_JNO32 */
|
|
"JNP", /* I_JNP16 */
|
|
"JNP", /* I_JNP32 */
|
|
"JNS", /* I_JNS16 */
|
|
"JNS", /* I_JNS32 */
|
|
"JNZ", /* I_JNZ16 */
|
|
"JNZ", /* I_JNZ32 */
|
|
"JO", /* I_JO16 */
|
|
"JO", /* I_JO32 */
|
|
"JP", /* I_JP16 */
|
|
"JP", /* I_JP32 */
|
|
"JS", /* I_JS16 */
|
|
"JS", /* I_JS32 */
|
|
"JZ", /* I_JZ16 */
|
|
"JZ", /* I_JZ32 */
|
|
"LAHF", /* I_LAHF */
|
|
"LAR", /* I_LAR */
|
|
"LDS", /* I_LDS */
|
|
"LEA", /* I_LEA */
|
|
"LEAVE", /* I_LEAVE16 */
|
|
"LEAVE", /* I_LEAVE32 */
|
|
"LES", /* I_LES */
|
|
"LFS", /* I_LFS */
|
|
"LGDT", /* I_LGDT16 */
|
|
"LGDT", /* I_LGDT32 */
|
|
"LGS", /* I_LGS */
|
|
"LIDT", /* I_LIDT16 */
|
|
"LIDT", /* I_LIDT32 */
|
|
"LLDT", /* I_LLDT */
|
|
"LMSW", /* I_LMSW */
|
|
"LOADALL", /* I_LOADALL */
|
|
"LOCK", /* I_LOCK */
|
|
"LODSB", /* I_LODSB */
|
|
"LODSD", /* I_LODSD */
|
|
"LODSW", /* I_LODSW */
|
|
"LOOP", /* I_LOOP16 */
|
|
"LOOP", /* I_LOOP32 */
|
|
"LOOPE", /* I_LOOPE16 */
|
|
"LOOPE", /* I_LOOPE32 */
|
|
"LOOPNE", /* I_LOOPNE16 */
|
|
"LOOPNE", /* I_LOOPNE32 */
|
|
"LSL", /* I_LSL */
|
|
"LSS", /* I_LSS */
|
|
"LTR", /* I_LTR */
|
|
"MOV", /* I_MOV_SR */
|
|
"MOV", /* I_MOV_CR */
|
|
"MOV", /* I_MOV_DR */
|
|
"MOV", /* I_MOV_TR */
|
|
"MOV", /* I_MOV8 */
|
|
"MOV", /* I_MOV16 */
|
|
"MOV", /* I_MOV32 */
|
|
"MOVSB", /* I_MOVSB */
|
|
"MOVSD", /* I_MOVSD */
|
|
"MOVSW", /* I_MOVSW */
|
|
"MOVSX", /* I_MOVSX8 */
|
|
"MOVSX", /* I_MOVSX16 */
|
|
"MOVZX", /* I_MOVZX8 */
|
|
"MOVZX", /* I_MOVZX16 */
|
|
"MUL", /* I_MUL8 */
|
|
"MUL", /* I_MUL16 */
|
|
"MUL", /* I_MUL32 */
|
|
"NEG", /* I_NEG8 */
|
|
"NEG", /* I_NEG16 */
|
|
"NEG", /* I_NEG32 */
|
|
"NOP", /* I_NOP */
|
|
"NOT", /* I_NOT8 */
|
|
"NOT", /* I_NOT16 */
|
|
"NOT", /* I_NOT32 */
|
|
"OR", /* I_OR8 */
|
|
"OR", /* I_OR16 */
|
|
"OR", /* I_OR32 */
|
|
"OUT", /* I_OUT8 */
|
|
"OUT", /* I_OUT16 */
|
|
"OUT", /* I_OUT32 */
|
|
"OUTSB", /* I_OUTSB */
|
|
"OUTSD", /* I_OUTSD */
|
|
"OUTSW", /* I_OUTSW */
|
|
"POP", /* I_POP16 */
|
|
"POP", /* I_POP32 */
|
|
"POP", /* I_POP_SR */
|
|
"POPA", /* I_POPA */
|
|
"POPAD", /* I_POPAD */
|
|
"POPF", /* I_POPF */
|
|
"POPFD", /* I_POPFD */
|
|
"PUSH", /* I_PUSH16 */
|
|
"PUSH", /* I_PUSH32 */
|
|
"PUSHA", /* I_PUSHA */
|
|
"PUSHAD", /* I_PUSHAD */
|
|
"PUSHF", /* I_PUSHF */
|
|
"PUSHFD", /* I_PUSHFD */
|
|
"RCL", /* I_RCL8 */
|
|
"RCL", /* I_RCL16 */
|
|
"RCL", /* I_RCL32 */
|
|
"RCR", /* I_RCR8 */
|
|
"RCR", /* I_RCR16 */
|
|
"RCR", /* I_RCR32 */
|
|
"RETF", /* I_RETF16 */
|
|
"RETF", /* I_RETF32 */
|
|
"RET", /* I_RETN16 */
|
|
"RET", /* I_RETN32 */
|
|
"ROL", /* I_ROL8 */
|
|
"ROL", /* I_ROL16 */
|
|
"ROL", /* I_ROL32 */
|
|
"ROR", /* I_ROR8 */
|
|
"ROR", /* I_ROR16 */
|
|
"ROR", /* I_ROR32 */
|
|
"REP INSB", /* I_R_INSB */
|
|
"REP INSD", /* I_R_INSD */
|
|
"REP INSW", /* I_R_INSW */
|
|
"REP OUTSB", /* I_R_OUTSB */
|
|
"REP OUTSD", /* I_R_OUTSD */
|
|
"REP OUTSW", /* I_R_OUTSW */
|
|
"REP LODSB", /* I_R_LODSB */
|
|
"REP LODSD", /* I_R_LODSD */
|
|
"REP LODSW", /* I_R_LODSW */
|
|
"REP MOVSB", /* I_R_MOVSB */
|
|
"REP MOVSD", /* I_R_MOVSD */
|
|
"REP MOVSW", /* I_R_MOVSW */
|
|
"REP STOSB", /* I_R_STOSB */
|
|
"REP STOSD", /* I_R_STOSD */
|
|
"REP STOSW", /* I_R_STOSW */
|
|
"REPE CMPSB", /* I_RE_CMPSB */
|
|
"REPE CMPSD", /* I_RE_CMPSD */
|
|
"REPE CMPSW", /* I_RE_CMPSW */
|
|
"REPNE CMPSB", /* I_RNE_CMPSB */
|
|
"REPNE CMPSD", /* I_RNE_CMPSD */
|
|
"REPNE CMPSW", /* I_RNE_CMPSW */
|
|
"REPE SCASB", /* I_RE_SCASB */
|
|
"REPE SCASD", /* I_RE_SCASD */
|
|
"REPE SCASW", /* I_RE_SCASW */
|
|
"REPNE SCASB", /* I_RNE_SCASB */
|
|
"REPNE SCASD", /* I_RNE_SCASD */
|
|
"REPNE SCASW", /* I_RNE_SCASW */
|
|
"SAHF", /* I_SAHF */
|
|
"SAR", /* I_SAR8 */
|
|
"SAR", /* I_SAR16 */
|
|
"SAR", /* I_SAR32 */
|
|
"SBB", /* I_SBB8 */
|
|
"SBB", /* I_SBB16 */
|
|
"SBB", /* I_SBB32 */
|
|
"SCASB", /* I_SCASB */
|
|
"SCASD", /* I_SCASD */
|
|
"SCASW", /* I_SCASW */
|
|
"SETB", /* I_SETB */
|
|
"SETBE", /* I_SETBE */
|
|
"SETL", /* I_SETL */
|
|
"SETLE", /* I_SETLE */
|
|
"SETNB", /* I_SETNB */
|
|
"SETNBE", /* I_SETNBE */
|
|
"SETNL", /* I_SETNL */
|
|
"SETNLE", /* I_SETNLE */
|
|
"SETNO", /* I_SETNO */
|
|
"SETNP", /* I_SETNP */
|
|
"SETNS", /* I_SETNS */
|
|
"SETNZ", /* I_SETNZ */
|
|
"SETO", /* I_SETO */
|
|
"SETP", /* I_SETP */
|
|
"SETS", /* I_SETS */
|
|
"SETZ", /* I_SETZ */
|
|
"SGDT", /* I_SGDT16 */
|
|
"SGDT", /* I_SGDT32 */
|
|
"SHL", /* I_SHL8 */
|
|
"SHL", /* I_SHL16 */
|
|
"SHL", /* I_SHL32 */
|
|
"SHLD", /* I_SHLD16 */
|
|
"SHLD", /* I_SHLD32 */
|
|
"SHR", /* I_SHR8 */
|
|
"SHR", /* I_SHR16 */
|
|
"SHR", /* I_SHR32 */
|
|
"SHRD", /* I_SHRD16 */
|
|
"SHRD", /* I_SHRD32 */
|
|
"SIDT", /* I_SIDT16 */
|
|
"SIDT", /* I_SIDT32 */
|
|
"SLDT", /* I_SLDT */
|
|
"SMSW", /* I_SMSW */
|
|
"STC", /* I_STC */
|
|
"STD", /* I_STD */
|
|
"STI", /* I_STI */
|
|
"STOSB", /* I_STOSB */
|
|
"STOSD", /* I_STOSD */
|
|
"STOSW", /* I_STOSW */
|
|
"STR", /* I_STR */
|
|
"SUB", /* I_SUB8 */
|
|
"SUB", /* I_SUB16 */
|
|
"SUB", /* I_SUB32 */
|
|
"TEST", /* I_TEST8 */
|
|
"TEST", /* I_TEST16 */
|
|
"TEST", /* I_TEST32 */
|
|
"VERR", /* I_VERR */
|
|
"VERW", /* I_VERW */
|
|
"WAIT", /* I_WAIT */
|
|
"WBINVD", /* I_WBINVD */
|
|
"XADD", /* I_XADD8 */
|
|
"XADD", /* I_XADD16 */
|
|
"XADD", /* I_XADD32 */
|
|
"XCHG", /* I_XCHG8 */
|
|
"XCHG", /* I_XCHG16 */
|
|
"XCHG", /* I_XCHG32 */
|
|
"XLAT", /* I_XLAT */
|
|
"XOR", /* I_XOR8 */
|
|
"XOR", /* I_XOR16 */
|
|
"XOR", /* I_XOR32 */
|
|
"????", /* I_ZBADOP */
|
|
"BOP", /* I_ZBOP */
|
|
"FRSRVD", /* I_ZFRSRVD */
|
|
"RSRVD", /* I_ZRSRVD */
|
|
"UNSIMULATE" /* I_ZZEXIT */
|
|
};
|
|
|
|
#define NR_VALID_INSTS (sizeof(inst_name)/sizeof(CHAR *))
|
|
|
|
/*
|
|
Character to print before each argument.
|
|
*/
|
|
LOCAL CHAR arg_preface[] = { ' ', ',', ',' };
|
|
|
|
/*
|
|
Register (byte) names.
|
|
*/
|
|
LOCAL CHAR *Rb_name[] =
|
|
{
|
|
"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"
|
|
};
|
|
|
|
/*
|
|
Register (word) names.
|
|
*/
|
|
LOCAL CHAR *Rw_name[] =
|
|
{
|
|
"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"
|
|
};
|
|
|
|
/*
|
|
Register (double word) names.
|
|
*/
|
|
LOCAL CHAR *Rd_name[] =
|
|
{
|
|
"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"
|
|
};
|
|
|
|
/*
|
|
Segment Register (word) names.
|
|
*/
|
|
LOCAL CHAR *Sw_name[] =
|
|
{
|
|
"ES", "CS", "SS", "DS", "FS", "GS"
|
|
};
|
|
|
|
/*
|
|
Control Register (double word) names.
|
|
*/
|
|
LOCAL CHAR *Cd_name[] =
|
|
{
|
|
"CR0", "CR1(UNDEF)", "CR2", "CR3",
|
|
"CR4(UNDEF)", "CR5(UNDEF)", "CR6(UNDEF)", "CR7(UNDEF)"
|
|
};
|
|
|
|
/*
|
|
Debug Register (double word) names.
|
|
*/
|
|
LOCAL CHAR *Dd_name[] =
|
|
{
|
|
"DR0", "DR1", "DR2", "DR3", "DR4(UNDEF)", "DR5(UNDEF)", "DR6", "DR7"
|
|
};
|
|
|
|
/*
|
|
Test Register (double word) names.
|
|
*/
|
|
LOCAL CHAR *Td_name[] =
|
|
{
|
|
"TR0(UNDEF)", "TR1(UNDEF)", "TR2(UNDEF)", "TR3",
|
|
"TR4", "TR5", "TR6", "TR7"
|
|
};
|
|
|
|
/*
|
|
Memory Addressing names.
|
|
*/
|
|
|
|
typedef struct
|
|
{
|
|
CHAR *positive;
|
|
CHAR *negative;
|
|
ULONG disp_mask;
|
|
ULONG sign_mask;
|
|
} MEM_RECORD;
|
|
|
|
LOCAL MEM_RECORD mem_name[] =
|
|
{
|
|
{ "%s[BX+SI%s]", "%s[BX+SI%s]", 0x00000000, 0x00000000}, /* A_1600 */
|
|
{ "%s[BX+DI%s]", "%s[BX+DI%s]", 0x00000000, 0x00000000}, /* A_1601 */
|
|
{ "%s[BP+SI%s]", "%s[BP+SI%s]", 0x00000000, 0x00000000}, /* A_1602 */
|
|
{ "%s[BP+DI%s]", "%s[BP+DI%s]", 0x00000000, 0x00000000}, /* A_1603 */
|
|
{ "%s[SI%s]", "%s[SI%s]", 0x00000000, 0x00000000}, /* A_1604 */
|
|
{ "%s[DI%s]", "%s[DI%s]", 0x00000000, 0x00000000}, /* A_1605 */
|
|
{ "%s[%s%04x]", "%s[%s%04x]", 0x0000ffff, 0x00000000}, /* A_1606 */
|
|
{ "%s[BX%s]", "%s[BX%s]", 0x00000000, 0x00000000}, /* A_1607 */
|
|
{ "%s[BX+SI%s+%02x]", "%s[BX+SI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1610 */
|
|
{ "%s[BX+DI%s+%02x]", "%s[BX+DI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1611 */
|
|
{ "%s[BP+SI%s+%02x]", "%s[BP+SI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1612 */
|
|
{ "%s[BP+DI%s+%02x]", "%s[BP+DI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1613 */
|
|
{ "%s[SI%s+%02x]", "%s[SI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1614 */
|
|
{ "%s[DI%s+%02x]", "%s[DI%s-%02x]", 0x000000ff, 0x00000080}, /* A_1615 */
|
|
{ "%s[BP%s+%02x]", "%s[BP%s-%02x]", 0x000000ff, 0x00000080}, /* A_1616 */
|
|
{ "%s[BX%s+%02x]", "%s[BX%s-%02x]", 0x000000ff, 0x00000080}, /* A_1617 */
|
|
{ "%s[BX+SI%s+%04x]", "%s[BX+SI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1620 */
|
|
{ "%s[BX+DI%s+%04x]", "%s[BX+DI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1621 */
|
|
{ "%s[BP+SI%s+%04x]", "%s[BP+SI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1622 */
|
|
{ "%s[BP+DI%s+%04x]", "%s[BP+DI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1623 */
|
|
{ "%s[SI%s+%04x]", "%s[SI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1624 */
|
|
{ "%s[DI%s+%04x]", "%s[DI%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1625 */
|
|
{ "%s[BP%s+%04x]", "%s[BP%s-%04x]", 0x0000ffff, 0x0000f000}, /* A_1626 */
|
|
{ "%s[BX%s+%04x]", "%s[BX%s+%04x]", 0x0000ffff, 0x00000000}, /* A_1627 */
|
|
{ "%s[EAX%s]", "%s[EAX%s]", 0x00000000, 0x00000000}, /* A_3200 */
|
|
{ "%s[ECX%s]", "%s[ECX%s]", 0x00000000, 0x00000000}, /* A_3201 */
|
|
{ "%s[EDX%s]", "%s[EDX%s]", 0x00000000, 0x00000000}, /* A_3202 */
|
|
{ "%s[EBX%s]", "%s[EBX%s]", 0x00000000, 0x00000000}, /* A_3203 */
|
|
{ "%s[%s%08x]", "%s[%s%08x]", 0xffffffff, 0x00000000}, /* A_3205 */
|
|
{ "%s[ESI%s]", "%s[ESI%s]", 0x00000000, 0x00000000}, /* A_3206 */
|
|
{ "%s[EDI%s]", "%s[EDI%s]", 0x00000000, 0x00000000}, /* A_3207 */
|
|
{ "%s[EAX+%s%02x]", "%s[EAX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3210 */
|
|
{ "%s[ECX+%s%02x]", "%s[ECX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3211 */
|
|
{ "%s[EDX+%s%02x]", "%s[EDX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3212 */
|
|
{ "%s[EBX+%s%02x]", "%s[EBX-%s%02x]", 0x000000ff, 0x00000080}, /* A_3213 */
|
|
{ "%s[EBP+%s%02x]", "%s[EBP-%s%02x]", 0x000000ff, 0x00000080}, /* A_3215 */
|
|
{ "%s[ESI+%s%02x]", "%s[ESI-%s%02x]", 0x000000ff, 0x00000080}, /* A_3216 */
|
|
{ "%s[EDI+%s%02x]", "%s[EDI-%s%02x]", 0x000000ff, 0x00000080}, /* A_3217 */
|
|
{ "%s[EAX+%s%08x]", "%s[EAX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3220 */
|
|
{ "%s[ECX+%s%08x]", "%s[ECX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3221 */
|
|
{ "%s[EDX+%s%08x]", "%s[EDX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3222 */
|
|
{ "%s[EBX+%s%08x]", "%s[EBX+%s%08x]", 0xffffffff, 0x00000000}, /* A_3223 */
|
|
{ "%s[EBP+%s%08x]", "%s[EBP-%s%08x]", 0xffffffff, 0xfff00000}, /* A_3225 */
|
|
{ "%s[ESI+%s%08x]", "%s[ESI+%s%08x]", 0xffffffff, 0x00000000}, /* A_3226 */
|
|
{ "%s[EDI+%s%08x]", "%s[EDI+%s%08x]", 0xffffffff, 0x00000000}, /* A_3227 */
|
|
{ "%s[EAX%s]", "%s[EAX%s]", 0x00000000, 0x00000000}, /* A_32S00 */
|
|
{ "%s[ECX%s]", "%s[ECX%s]", 0x00000000, 0x00000000}, /* A_32S01 */
|
|
{ "%s[EDX%s]", "%s[EDX%s]", 0x00000000, 0x00000000}, /* A_32S02 */
|
|
{ "%s[EBX%s]", "%s[EBX%s]", 0x00000000, 0x00000000}, /* A_32S03 */
|
|
{ "%s[ESP%s]", "%s[ESP%s]", 0x00000000, 0x00000000}, /* A_32S04 */
|
|
{ "%s[%08x%s]", "%s[%08x%s]", 0xffffffff, 0x00000000}, /* A_32S05 */
|
|
{ "%s[ESI%s]", "%s[ESI%s]", 0x00000000, 0x00000000}, /* A_32S06 */
|
|
{ "%s[EDI%s]", "%s[EDI%s]", 0x00000000, 0x00000000}, /* A_32S07 */
|
|
{ "%s[EAX%s+%02x]", "%s[EAX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S10 */
|
|
{ "%s[ECX%s+%02x]", "%s[ECX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S11 */
|
|
{ "%s[EDX%s+%02x]", "%s[EDX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S12 */
|
|
{ "%s[EBX%s+%02x]", "%s[EBX%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S13 */
|
|
{ "%s[ESP%s+%02x]", "%s[ESP%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S14 */
|
|
{ "%s[EBP%s+%02x]", "%s[EBP%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S15 */
|
|
{ "%s[ESI%s+%02x]", "%s[ESI%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S16 */
|
|
{ "%s[EDI%s+%02x]", "%s[EDI%s-%02x]", 0x000000ff, 0x00000080}, /* A_32S17 */
|
|
{ "%s[EAX%s+%08x]", "%s[EAX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S20 */
|
|
{ "%s[ECX%s+%08x]", "%s[ECX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S21 */
|
|
{ "%s[EDX%s+%08x]", "%s[EDX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S22 */
|
|
{ "%s[EBX%s+%08x]", "%s[EBX%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S23 */
|
|
{ "%s[ESP%s+%08x]", "%s[ESP%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S24 */
|
|
{ "%s[EBP%s+%08x]", "%s[EBP%s-%08x]", 0xffffffff, 0xfff00000}, /* A_32S25 */
|
|
{ "%s[ESI%s+%08x]", "%s[ESI%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S26 */
|
|
{ "%s[EDI%s+%08x]", "%s[EDI%s+%08x]", 0xffffffff, 0x00000000}, /* A_32S27 */
|
|
{ "%s[%s%04x]", "%s[%s%04x]", 0x0000ffff, 0x00000000}, /* A_MOFFS16 */
|
|
{ "%s[%s%08x]", "%s[%s%08x]", 0xffffffff, 0x00000000}, /* A_MOFFS32 */
|
|
{ "%s[BX+AL%s]", "%s[BX+AL%s]", 0x00000000, 0x00000000}, /* A_16XLT */
|
|
{ "%s[EBX+AL%s]", "%s[EBX+AL%s]", 0x00000000, 0x00000000}, /* A_32XLT */
|
|
{ "%s[SI%s]", "%s[SI%s]", 0x00000000, 0x00000000}, /* A_16STSRC */
|
|
{ "%s[ESI%s]", "%s[ESI%s]", 0x00000000, 0x00000000}, /* A_32STSRC */
|
|
{ "%s[DI%s]", "%s[DI%s]", 0x00000000, 0x00000000}, /* A_16STDST */
|
|
{ "%s[EDI%s]", "%s[EDI%s]", 0x00000000, 0x00000000} /* A_32STDST */
|
|
};
|
|
|
|
LOCAL char *mem_id[] =
|
|
{
|
|
"", /* A_M */
|
|
"", /* A_M14 */
|
|
"", /* A_M28 */
|
|
"", /* A_M94 */
|
|
"", /* A_M108 */
|
|
"DWord Ptr ", /* A_Ma16 */
|
|
"QWord Ptr ", /* A_Ma32 */
|
|
"Byte Ptr ", /* A_Mb */
|
|
"DWord Ptr ", /* A_Md */
|
|
"Word Ptr ", /* A_Mi16 */
|
|
"DWord Ptr ", /* A_Mi32 */
|
|
"QWord Ptr ", /* A_Mi64 */
|
|
"TByte Ptr ", /* A_Mi80 */
|
|
"DWord Ptr ", /* A_Mp16 */
|
|
"FWord Ptr ", /* A_Mp32 */
|
|
"DWord Ptr ", /* A_Mr32 */
|
|
"QWord Ptr ", /* A_Mr64 */
|
|
"Tbyte Ptr ", /* A_Mr80 */
|
|
"FWord Ptr ", /* A_Ms */
|
|
"Word Ptr " /* A_Mw */
|
|
};
|
|
|
|
/*
|
|
SIB byte names.
|
|
*/
|
|
LOCAL CHAR *sib_name[] =
|
|
{
|
|
"",
|
|
"+EAX", "+ECX", "+EDX", "+EBX",
|
|
"", "+EBP", "+ESI", "+EDI",
|
|
"+2*EAX", "+2*ECX", "+2*EDX", "+2*EBX",
|
|
"+undef", "+2*EBP", "+2*ESI", "+2*EDI",
|
|
"+4*EAX", "+4*ECX", "+4*EDX", "+4*EBX",
|
|
"+undef", "+4*EBP", "+4*ESI", "+4*EDI",
|
|
"+8*EAX", "+8*ECX", "+8*EDX", "+8*EBX",
|
|
"+undef", "+8*EBP", "+8*ESI", "+8*EDI"
|
|
};
|
|
|
|
|
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
/* Read a byte from the given Intel linear address, return -1 if */
|
|
/* unable to read a */
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
LOCAL IS32 read_byte IFN1(LIN_ADDR, linAddr)
|
|
{
|
|
IU8 res = Sas.Sas_hw_at(linAddr);
|
|
|
|
/* if (was_error)
|
|
* return -1;
|
|
* else
|
|
*/
|
|
return (IS32)(res);
|
|
}
|
|
|
|
/*
|
|
=====================================================================
|
|
EXECUTION STARTS HERE.
|
|
=====================================================================
|
|
*/
|
|
|
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
/* Dis-assemble a single Intel Instruction. */
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
GLOBAL IU16
|
|
dasm IFN4(char *, txt, IU16, seg, LIN_ADDR, off, SIZE_SPECIFIER, default_size)
|
|
{
|
|
/* txt Buffer to hold dis-assembly text (-1 means not required) */
|
|
/* seg Segment for instruction to be dis-assembled */
|
|
/* off Offset for instruction to be dis-assembled */
|
|
/* default_size 16BIT or 32BIT */
|
|
|
|
char *fmt, *newline;
|
|
|
|
/* format for seg:off */
|
|
if ( off & 0xffff0000 )
|
|
{
|
|
fmt = "%04x:%08x ";
|
|
newline = "\n ";
|
|
}
|
|
else
|
|
{
|
|
fmt = "%04x:%04x ";
|
|
newline = "\n ";
|
|
}
|
|
|
|
return (dasm_internal(txt,
|
|
seg,
|
|
off,
|
|
default_size,
|
|
effective_addr(seg, off),
|
|
read_byte,
|
|
fmt,
|
|
newline));
|
|
}
|
|
|
|
extern IU16 dasm_internal IFN8(
|
|
char *, txt, /* Buffer to hold dis-assembly text (-1 means not required) */
|
|
IU16, seg, /* Segment for xxxx:... text in dis-assembly */
|
|
LIN_ADDR, off, /* ditto offset */
|
|
SIZE_SPECIFIER, default_size,/* 16BIT or 32BIT code segment */
|
|
LIN_ADDR, p, /* linear address of start of instruction */
|
|
read_byte_proc, byte_at, /* like sas_hw_at() to use to read intel
|
|
* but will return -1 if there is an error
|
|
*/
|
|
char *, fmt, /* sprintf format for first line seg:offset */
|
|
char *, newline) /* strcat text to separate lines */
|
|
{
|
|
LIN_ADDR pp; /* pntr to prefix bytes */
|
|
DECODED_INST d_inst; /* Decoded form of Intel instruction */
|
|
DECODED_ARG *d_arg; /* pntr to decoded form of Intel operand */
|
|
USHORT inst_len; /* Nr. bytes in instruction */
|
|
USHORT mc; /* Nr. machine code bytes processed */
|
|
char *arg_name; /* pntr to symbolic argument name */
|
|
char *inst_txt;
|
|
INT i;
|
|
INT name_len; /* Nr. chars in symbolic instruction name */
|
|
MEM_RECORD *m_rec; /* pntr to memory addressing record */
|
|
UTINY args_out; /* Nr. arguments actually printed */
|
|
INT prefix_width; /* Width of prefixes actually printed */
|
|
UTINY memory_id; /* Memory identifier reference */
|
|
ULONG immed; /* value for immediate arithmetic */
|
|
IBOOL unreadable = FALSE; /* TRUE if instr bytes are not readable (past M?) */
|
|
char prefix_buf[16*4];
|
|
char *prefix_txt;
|
|
|
|
/* initialise */
|
|
args_out = prefix_width = 0;
|
|
|
|
pp=p;
|
|
|
|
/* get in decoded form */
|
|
decode(p, &d_inst, default_size, byte_at);
|
|
|
|
/* hence find length of instruction */
|
|
inst_len = d_inst.inst_sz;
|
|
|
|
/* if no text required, just return the length now */
|
|
if (txt == (char*)-1){
|
|
/* Check bytes were read without errors */
|
|
if ((byte_at(p) < 0) || (byte_at(p+inst_len-1) < 0))
|
|
{
|
|
int i = inst_len - 1;
|
|
while (i > 0)
|
|
{
|
|
if (byte_at(i) >= 0)
|
|
return (i);
|
|
}
|
|
return 0;
|
|
}
|
|
return inst_len;
|
|
}
|
|
|
|
/* output seg:off in requested format */
|
|
|
|
sprintf(txt, fmt, seg, off);
|
|
txt += strlen(txt);
|
|
|
|
/* Output upto eight machine code bytes */
|
|
for ( mc = 0; mc < 8; mc++)
|
|
{
|
|
if ( mc < inst_len )
|
|
{
|
|
IS32 b = byte_at(p++);
|
|
|
|
if (b < 0)
|
|
{
|
|
sprintf(txt, ".."); /* print ".." if not readable */
|
|
unreadable = TRUE;
|
|
inst_len = mc;
|
|
}
|
|
else
|
|
sprintf(txt, "%02x", b); /* print machine code byte */
|
|
}
|
|
else
|
|
sprintf(txt, " "); /* fill in with spaces */
|
|
txt += 2;
|
|
}
|
|
|
|
/* Check inst identifier is within our known range.
|
|
* Get text for opcode and length so we can see if the
|
|
* prefix will fit.
|
|
*/
|
|
if ( d_inst.inst_id >= NR_VALID_INSTS )
|
|
{
|
|
fprintf(stderr, "Bad decoded instruction found %d\n", d_inst.inst_id);
|
|
d_inst.inst_id = I_ZBADOP;
|
|
}
|
|
|
|
/* Obtain symbolic form of instruction */
|
|
inst_txt = inst_name[d_inst.inst_id];
|
|
name_len = 1 + strlen(inst_txt);
|
|
|
|
/* Format prefix bytes if any */
|
|
prefix_txt = prefix_buf;
|
|
*prefix_txt = '\0';
|
|
|
|
if ( d_inst.prefix_sz )
|
|
{
|
|
for ( i = 0; i < d_inst.prefix_sz; byte_at(pp), i++)
|
|
{
|
|
switch ( byte_at(pp) )
|
|
{
|
|
case 0xf1:
|
|
/* it don't do nothing -- don't display nothing */
|
|
|
|
case 0xf2:
|
|
case 0xf3:
|
|
/* if valid instructions will print them */
|
|
|
|
case 0x66:
|
|
case 0x67:
|
|
/* the effect is obvious from the operands */
|
|
break;
|
|
|
|
case 0xf0: sprintf(prefix_txt, " LOCK"); prefix_txt += 5; break;
|
|
case 0x26: sprintf(prefix_txt, " ES:"); prefix_txt += 4; break;
|
|
case 0x2e: sprintf(prefix_txt, " CS:"); prefix_txt += 4; break;
|
|
case 0x36: sprintf(prefix_txt, " SS:"); prefix_txt += 4; break;
|
|
case 0x3e: sprintf(prefix_txt, " DS:"); prefix_txt += 4; break;
|
|
case 0x64: sprintf(prefix_txt, " FS:"); prefix_txt += 4; break;
|
|
case 0x65: sprintf(prefix_txt, " GS:"); prefix_txt += 4; break;
|
|
|
|
default:
|
|
fprintf(stderr, "Bad prefix found %02x\n", byte_at(pp));
|
|
break;
|
|
} /* end switch */
|
|
|
|
pp++;
|
|
|
|
} /* end for */
|
|
} /* end if d_inst.prefix_sz */
|
|
|
|
prefix_width = strlen(prefix_buf);
|
|
if ( newline != NULL )
|
|
{
|
|
if ( ((inst_len * 2) + prefix_width) > 16)
|
|
{
|
|
/* start new line for instruction */
|
|
strcat(txt, newline);
|
|
txt += strlen(txt);
|
|
|
|
/* output rest of machine code bytes */
|
|
for ( ; mc < 16; mc++)
|
|
{
|
|
if ( mc < inst_len )
|
|
{
|
|
IS32 b = byte_at(p++);
|
|
|
|
if (b < 0)
|
|
{
|
|
sprintf(txt, ".."); /* print ".." if not readable */
|
|
unreadable = TRUE;
|
|
inst_len = mc;
|
|
}
|
|
else
|
|
sprintf(txt, "%02x", b); /* print machine code byte */
|
|
}
|
|
else
|
|
sprintf(txt, " "); /* fill in with spaces */
|
|
txt += 2;
|
|
}
|
|
}
|
|
if ( ((inst_len * 2) + prefix_width) > 32)
|
|
{
|
|
/* wont fit on two lines */
|
|
strcat(txt, newline);
|
|
txt += strlen(txt);
|
|
|
|
/* output rest of machine code bytes */
|
|
for ( ; mc < 24; mc++)
|
|
{
|
|
sprintf(txt, " "); /* fill in with spaces */
|
|
txt += 2;
|
|
}
|
|
}
|
|
txt -= (prefix_width <= 17 ? prefix_width: 17);
|
|
}
|
|
if (unreadable)
|
|
{
|
|
sprintf(txt, "<< Unreadable >>\n");
|
|
return inst_len;
|
|
}
|
|
|
|
sprintf(txt, "%s %s", prefix_buf, inst_txt);
|
|
txt += prefix_width + name_len;
|
|
|
|
/* pad out to 11 characters wide */
|
|
|
|
for (i = name_len; i <= 11; i++)
|
|
*txt++ = ' ';
|
|
|
|
if (d_inst.inst_id != I_ZBADOP)
|
|
{
|
|
/* output each valid argument in turn */
|
|
for ( i = 0; i < 3; i++ )
|
|
{
|
|
d_arg = &d_inst.args[i];
|
|
arg_name = (CHAR *)0;
|
|
|
|
if ( d_arg->arg_type != A_ )
|
|
{
|
|
/* process valid arg */
|
|
sprintf(txt, "%c", arg_preface[args_out++]);
|
|
txt += 1;
|
|
|
|
switch ( d_arg->arg_type )
|
|
{
|
|
case A_Rb: /* aka r8,r/m8 */
|
|
arg_name = Rb_name[DCD_IDENTIFIER(d_arg)];
|
|
break;
|
|
|
|
case A_Rw: /* aka r16,r/m16 */
|
|
arg_name = Rw_name[DCD_IDENTIFIER(d_arg)];
|
|
break;
|
|
|
|
case A_Rd: /* aka r32,r/m32 */
|
|
arg_name = Rd_name[DCD_IDENTIFIER(d_arg)];
|
|
break;
|
|
|
|
case A_Sw: /* aka Sreg */
|
|
arg_name = Sw_name[DCD_IDENTIFIER(d_arg)];
|
|
break;
|
|
|
|
case A_Cd: /* aka CRx */
|
|
arg_name = Cd_name[DCD_IDENTIFIER(d_arg)];
|
|
break;
|
|
|
|
case A_Dd: /* aka DRx */
|
|
arg_name = Dd_name[DCD_IDENTIFIER(d_arg)];
|
|
break;
|
|
|
|
case A_Td: /* aka TRx */
|
|
arg_name = Td_name[DCD_IDENTIFIER(d_arg)];
|
|
break;
|
|
|
|
case A_M: /* aka m */
|
|
case A_M14: /* aka m14byte */
|
|
case A_M28: /* aka m28byte */
|
|
case A_M94: /* aka m94byte */
|
|
case A_M108: /* aka m108byte */
|
|
case A_Ma16: /* aka m16&16 */
|
|
case A_Ma32: /* aka m32&32 */
|
|
case A_Mb: /* aka m8,r/m8,moffs8 */
|
|
case A_Md: /* aka m32,r/m32,moffs32 */
|
|
case A_Mi16: /* aka m16int */
|
|
case A_Mi32: /* aka m32int */
|
|
case A_Mi64: /* aka m64int */
|
|
case A_Mi80: /* aka m80dec */
|
|
case A_Mp16: /* aka m16:16 */
|
|
case A_Mp32: /* aka m16:32 */
|
|
case A_Mr32: /* aka m32real */
|
|
case A_Mr64: /* aka m64real */
|
|
case A_Mr80: /* aka m80real */
|
|
case A_Ms: /* aka m16&32 */
|
|
case A_Mw: /* aka m16,r/m16,moffs16 */
|
|
/* First work out memory identifier */
|
|
switch ( d_arg->arg_type )
|
|
{
|
|
case A_M: memory_id = 0; break;
|
|
case A_M14: memory_id = 1; break;
|
|
case A_M28: memory_id = 2; break;
|
|
case A_M94: memory_id = 3; break;
|
|
case A_M108: memory_id = 4; break;
|
|
case A_Ma16: memory_id = 5; break;
|
|
case A_Ma32: memory_id = 6; break;
|
|
case A_Mb: memory_id = 7; break;
|
|
case A_Md: memory_id = 8; break;
|
|
case A_Mi16: memory_id = 9; break;
|
|
case A_Mi32: memory_id = 10; break;
|
|
case A_Mi64: memory_id = 11; break;
|
|
case A_Mi80: memory_id = 12; break;
|
|
case A_Mp16: memory_id = 13; break;
|
|
case A_Mp32: memory_id = 14; break;
|
|
case A_Mr32: memory_id = 15; break;
|
|
case A_Mr64: memory_id = 16; break;
|
|
case A_Mr80: memory_id = 17; break;
|
|
case A_Ms: memory_id = 18; break;
|
|
case A_Mw: memory_id = 19; break;
|
|
}
|
|
|
|
/* output memory details */
|
|
m_rec = &mem_name[DCD_IDENTIFIER(d_arg)];
|
|
if ( m_rec->disp_mask == 0 )
|
|
{
|
|
/* no displacement to print out */
|
|
sprintf(txt, m_rec->positive,
|
|
mem_id[memory_id],
|
|
sib_name[DCD_SUBTYPE(d_arg)]);
|
|
}
|
|
else
|
|
{
|
|
/* displacement to print out */
|
|
IU32 disp = DCD_DISP(d_arg);
|
|
char *fmt;
|
|
|
|
/* Do we think this is a negative displacement ? */
|
|
if (m_rec->sign_mask && ((m_rec->sign_mask & disp) == m_rec->sign_mask))
|
|
{
|
|
disp = -disp;
|
|
fmt = m_rec->negative;
|
|
}
|
|
else
|
|
fmt = m_rec->positive;
|
|
disp &= m_rec->disp_mask;
|
|
if ( DCD_IDENTIFIER(d_arg) == A_32S05 )
|
|
sprintf(txt, fmt,
|
|
mem_id[memory_id],
|
|
disp,
|
|
sib_name[DCD_SUBTYPE(d_arg)]);
|
|
else
|
|
sprintf(txt, fmt,
|
|
mem_id[memory_id],
|
|
sib_name[DCD_SUBTYPE(d_arg)],
|
|
disp);
|
|
}
|
|
|
|
name_len = strlen(txt);
|
|
txt += name_len;
|
|
break;
|
|
|
|
case A_I: /* aka imm8,imm16,imm32 */
|
|
immed = DCD_IMMED1(d_arg);
|
|
switch ( DCD_IDENTIFIER(d_arg) )
|
|
{
|
|
case A_IMMC:
|
|
/* check for inbuilt zero - don't print */
|
|
if ( immed )
|
|
{
|
|
sprintf(txt, "%1d", immed); txt += 1;
|
|
}
|
|
else
|
|
{
|
|
/* kill preface */
|
|
args_out--;
|
|
txt -= 1;
|
|
*txt = '\0';
|
|
}
|
|
break;
|
|
|
|
case A_IMMB:
|
|
sprintf(txt, "%02x", immed); txt += 2;
|
|
break;
|
|
|
|
case A_IMMW:
|
|
sprintf(txt, "%04x", immed); txt += 4;
|
|
break;
|
|
|
|
case A_IMMD:
|
|
sprintf(txt, "%08x", immed); txt += 8;
|
|
break;
|
|
|
|
case A_IMMWB:
|
|
case A_IMMDB:
|
|
/* remove sign extension */
|
|
immed &= 0xff;
|
|
|
|
/* print byte with correct sign */
|
|
if ( immed <= 0x7f )
|
|
{
|
|
sprintf(txt, "+%02x", immed); txt += 3;
|
|
}
|
|
else
|
|
{
|
|
immed = 0x100 - immed;
|
|
sprintf(txt, "-%02x", immed); txt += 3;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case A_J: /* aka rel8,rel16,rel32 */
|
|
/* calc new dest */
|
|
immed = off + inst_len + DCD_IMMED1(d_arg);
|
|
|
|
/* handle as 16-bit mode or 32-bit mode */
|
|
switch ( d_inst.inst_id )
|
|
{
|
|
|
|
case I_JO16: case I_JNO16: case I_JB16:
|
|
case I_JNB16: case I_JZ16: case I_JNZ16:
|
|
case I_JBE16: case I_JNBE16: case I_JS16:
|
|
case I_JNS16: case I_JP16: case I_JNP16:
|
|
case I_JL16: case I_JNL16: case I_JLE16:
|
|
case I_JNLE16: case I_LOOPNE16: case I_LOOPE16:
|
|
case I_LOOP16: case I_JCXZ: case I_CALLR16:
|
|
case I_JMPR16:
|
|
immed &= 0xffff;
|
|
|
|
sprintf(txt, "%04x", immed);
|
|
txt += 4;
|
|
break;
|
|
|
|
default: /* 32-bit mode */
|
|
sprintf(txt, "%08x", immed);
|
|
txt += 8;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case A_K: /* aka ptr16:16,ptr16:32 */
|
|
{
|
|
/* handle as 16-bit mode or 32-bit mode */
|
|
|
|
char *sep = ":";
|
|
|
|
switch ( d_inst.inst_id )
|
|
{
|
|
case I_CALLF16: case I_JMPF16:
|
|
sprintf(txt, "%04x%s%04x", DCD_IMMED2(d_arg), sep, DCD_IMMED1(d_arg));
|
|
txt += 9;
|
|
break;
|
|
|
|
default: /* 32-bit mode */
|
|
sprintf(txt, "%04x%s%08x", DCD_IMMED2(d_arg), sep, DCD_IMMED1(d_arg));
|
|
txt += 13;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case A_V: /* aka ST,push onto ST, ST(i) */
|
|
switch ( DCD_IDENTIFIER(d_arg) )
|
|
{
|
|
case A_ST:
|
|
/* Some cases are obvious - so not all get printed */
|
|
switch ( d_inst.inst_id )
|
|
{
|
|
case I_F2XM1: case I_FABS: case I_FBSTP:
|
|
case I_FCHS: case I_FCOS: case I_FIST:
|
|
case I_FISTP: case I_FPATAN: case I_FPREM:
|
|
case I_FPREM1: case I_FPTAN: case I_FRNDINT:
|
|
case I_FSCALE: case I_FSIN: case I_FSINCOS:
|
|
case I_FSQRT: case I_FST: case I_FSTP:
|
|
case I_FTST: case I_FXAM: case I_FXTRACT:
|
|
case I_FYL2X: case I_FYL2XP1:
|
|
break;
|
|
|
|
default: /* do print */
|
|
arg_name = "ST";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case A_STP:
|
|
/* All cases are obvious - so no printing */
|
|
break;
|
|
|
|
case A_STI:
|
|
/* Some cases are obvious - so not all get printed */
|
|
switch ( d_inst.inst_id )
|
|
{
|
|
case I_FPATAN: case I_FPREM: case I_FPREM1:
|
|
case I_FSCALE: case I_FYL2X: case I_FYL2XP1:
|
|
break;
|
|
|
|
default: /* do print */
|
|
sprintf(txt, "ST(%1d", DCD_INDEX(d_arg));
|
|
txt += 4;
|
|
arg_name = ")";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* if we aren't printing - kill preface */
|
|
if ( arg_name == (CHAR *)0 )
|
|
{
|
|
args_out--;
|
|
txt -= 1;
|
|
*txt = '\0';
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "Bad decoded argument found %d\n",
|
|
d_arg->arg_type);
|
|
break;
|
|
} /* end switch */
|
|
} /* end if */
|
|
|
|
/* print something if we have it */
|
|
if ( arg_name != (CHAR *)0 )
|
|
{
|
|
sprintf(txt, "%s", arg_name);
|
|
name_len = strlen(arg_name);
|
|
txt += name_len;
|
|
}
|
|
} /* end for arg */
|
|
}
|
|
|
|
if (d_inst.inst_id == I_ZBOP)
|
|
{
|
|
IU8 num = DCD_IMMED1(&d_inst.args[0]);
|
|
extern char *bop_name IPT1(IU8, num);
|
|
char *name = bop_name(num);
|
|
if (name != NULL)
|
|
{
|
|
sprintf(txt, " : %s", name);
|
|
txt += strlen(txt);
|
|
}
|
|
}
|
|
|
|
|
|
/* Finally output any machine code bytes remaining */
|
|
/* iff bytes remaining && room in output format */
|
|
if ( (newline != NULL ) && ( mc < inst_len && mc < 16 ))
|
|
{
|
|
strcat(txt, newline);
|
|
txt += strlen(txt);
|
|
for ( ; mc < inst_len && mc < 16; mc++ )
|
|
{
|
|
IS32 b = byte_at(p++);
|
|
|
|
if (b < 0)
|
|
{
|
|
sprintf(txt, ".."); /* print ".." if not readable */
|
|
inst_len = mc;
|
|
}
|
|
else
|
|
sprintf(txt, "%02x", b); /* print machine code byte */
|
|
p++;
|
|
txt += 2;
|
|
}
|
|
}
|
|
|
|
sprintf(txt, "\n");
|
|
|
|
return inst_len;
|
|
}
|