1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert
3 
4 // NEC disassembler interface
5 
6 #ifndef MAME_CPU_NEC_NECDASM_H
7 #define MAME_CPU_NEC_NECDASM_H
8 
9 #pragma once
10 
11 class nec_disassembler : public util::disasm_interface
12 {
13 public:
14 	struct config {
15 	public:
16 		virtual ~config() = default;
17 		virtual int get_mode() const = 0;
18 	};
19 
20 	nec_disassembler(config *conf, const u8 *decryption_table = nullptr);
21 	virtual ~nec_disassembler() = default;
22 
23 	virtual u32 opcode_alignment() const override;
24 	virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
25 
26 private:
27 	enum
28 	{
29 		PARAM_REG8 = 1,     /* 8-bit register */
30 		PARAM_REG16,        /* 16-bit register */
31 		PARAM_REG2_8,       /* 8-bit register */
32 		PARAM_REG2_16,      /* 16-bit register */
33 		PARAM_RM8,          /* 8-bit memory or register */
34 		PARAM_RM16,         /* 16-bit memory or register */
35 		PARAM_RMPTR8,       /* 8-bit memory or register */
36 		PARAM_RMPTR16,      /* 16-bit memory or register */
37 		PARAM_I3,           /* 3-bit immediate */
38 		PARAM_I4,           /* 4-bit immediate */
39 		PARAM_I8,           /* 8-bit signed immediate */
40 		PARAM_I16,          /* 16-bit signed immediate */
41 		PARAM_UI8,          /* 8-bit unsigned immediate */
42 		PARAM_IMM,          /* 16-bit immediate */
43 		PARAM_ADDR,         /* 16:16 address */
44 		PARAM_REL8,         /* 8-bit PC-relative displacement */
45 		PARAM_REL16,        /* 16-bit PC-relative displacement */
46 		PARAM_MEM_OFFS,     /* 16-bit mem offset */
47 		PARAM_SREG,         /* segment register */
48 		PARAM_SFREG,        /* V25/V35 special function register */
49 		PARAM_1,            /* used by shift/rotate instructions */
50 		PARAM_AL,
51 		PARAM_CL,
52 		PARAM_DL,
53 		PARAM_BL,
54 		PARAM_AH,
55 		PARAM_CH,
56 		PARAM_DH,
57 		PARAM_BH,
58 		PARAM_AW,
59 		PARAM_CW,
60 		PARAM_DW,
61 		PARAM_BW,
62 		PARAM_SP,
63 		PARAM_BP,
64 		PARAM_IX,
65 		PARAM_IY
66 	};
67 
68 	enum
69 	{
70 		MODRM = 1,
71 		GROUP,
72 		FPU,
73 		TWO_BYTE,
74 		PREFIX,
75 		SEG_PS,
76 		SEG_DS0,
77 		SEG_DS1,
78 		SEG_SS
79 	};
80 
81 	struct NEC_I386_OPCODE {
82 		char mnemonic[32];
83 		uint32_t flags;
84 		uint32_t param1;
85 		uint32_t param2;
86 		uint32_t param3;
87 		offs_t dasm_flags;
88 	};
89 
90 	struct NEC_GROUP_OP {
91 		char mnemonic[32];
92 		const NEC_I386_OPCODE *opcode;
93 	};
94 
95 	static const NEC_I386_OPCODE necv_opcode_table1[256];
96 	static const NEC_I386_OPCODE necv_opcode_table2[256];
97 	static const NEC_I386_OPCODE immb_table[8];
98 	static const NEC_I386_OPCODE immw_table[8];
99 	static const NEC_I386_OPCODE immws_table[8];
100 	static const NEC_I386_OPCODE shiftbi_table[8];
101 	static const NEC_I386_OPCODE shiftwi_table[8];
102 	static const NEC_I386_OPCODE shiftb_table[8];
103 	static const NEC_I386_OPCODE shiftw_table[8];
104 	static const NEC_I386_OPCODE shiftbv_table[8];
105 	static const NEC_I386_OPCODE shiftwv_table[8];
106 	static const NEC_I386_OPCODE group1b_table[8];
107 	static const NEC_I386_OPCODE group1w_table[8];
108 	static const NEC_I386_OPCODE group2b_table[8];
109 	static const NEC_I386_OPCODE group2w_table[8];
110 	static const NEC_GROUP_OP group_op_table[];
111 	static const char *const nec_reg[8];
112 	static const char *const nec_reg8[8];
113 	static const char *const nec_sreg[8];
114 	static const char *const nec_sfreg[256];
115 
116 	config *m_config;
117 	const u8 *m_decryption_table;
118 
119 	u8 m_modrm;
120 	u32 m_segment;
121 	offs_t m_dasm_flags;
122 	std::string m_modrm_string;
123 
124 	inline u8 FETCH(offs_t pc_base, offs_t &pc, const data_buffer &opcodes);
125 	inline u16 FETCH16(offs_t pc_base, offs_t &pc, const data_buffer &opcodes);
126 	std::string hexstring(uint32_t value, int digits);
127 	std::string shexstring(uint32_t value, int digits, bool always);
128 	void handle_modrm(offs_t pc_base, offs_t &pc, const data_buffer &params);
129 	void handle_param(std::ostream &stream, uint32_t param, offs_t pc_base, offs_t &pc, const data_buffer &params);
130 	void handle_fpu(std::ostream &stream, uint8_t op1, uint8_t op2, offs_t pc_base, offs_t &pc, const data_buffer &params);
131 
132 	void decode_opcode(std::ostream &stream, const NEC_I386_OPCODE *op, uint8_t op1, offs_t pc_base, offs_t &pc, const data_buffer &opcodes, const data_buffer &params);
133 	offs_t dis80(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params);
134 };
135 
136 
137 #endif
138