1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont, Karl Stenerud
3 /*
4 
5 Mitsubishi 7700 Series CPU disassembler v1.1
6 
7 By R. Belmont
8 Based on G65C816 CPU Emulator by Karl Stenerud
9 
10 */
11 
12 #include "emu.h"
13 #include "m7700ds.h"
14 
15 #define ADDRESS_24BIT(A) ((A)&0xffffff)
16 
17 const char *const m7700_disassembler::s_opnames[] =
18 {
19 	"ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", "BPL", "BRA",
20 	"BRK", "BRL", "BVC", "BVS", "CLC", "CLD", "CLI", "CLV", "CMP", "COP", "CPX",
21 	"CPY", "DEA", "DEC", "DEX", "DEY", "EOR", "INA", "INC", "INX", "INY", "JML",
22 	"JMP", "JSL", "JSR", "LDA", "LDX", "LDY", "LSR", "MVN", "MVP", "NOP", "ORA",
23 	"PEA", "PEI", "PER", "PHA", "PHT", "PHD", "PHK", "PHP", "PHX", "PHY", "PLA",
24 	"PLT", "PLD", "PLP", "PLX", "PLY", "CLP", "ROL", "ROR", "RTI", "RTL", "RTS",
25 	"SBC", "SEC", "SED", "SEI", "SEP", "STA", "STP", "STX", "STY", "STZ", "TAX",
26 	"TAY", "TCS", "TCD", "TDC", "TRB", "TSB", "TSC", "TSX", "TXA", "TXS", "TXY",
27 	"TYA", "TYX", "WAI", "WDM", "XBA", "XCE", "MPY", "DIV", "MPYS","DIVS","RLA",
28 	"EXTS","EXTZ","LDT", "LDM", "UNK", "SEB", "SEM", "CLM", "STB", "LDB", "ADCB",
29 	"SBCB","EORB","TBX", "CMPB","INB", "DEB", "TXB", "TYB", "LSRB","ORB", "CLB",
30 	"BBC", "BBS", "TBY", "ANDB","PUL", "PSH", "PLB", "XAB", "PHB",
31 };
32 
33 const m7700_disassembler::m7700_opcode_struct m7700_disassembler::s_opcodes[256] =
34 {
35 	{op::BRK, I, SIG  }, {op::ORA, M, DXI }, {op::UNK, I, SIG }, {op::ORA, M, S    },
36 	{op::SEB, M, LDM4 }, {op::ORA, M, D   }, {op::ASL, M, D   }, {op::ORA, M, DLI  },
37 	{op::PHP, I, IMP  }, {op::ORA, M, IMM }, {op::ASL, M, ACC }, {op::PHD, I, IMP  },
38 	{op::SEB, M, LDM5 }, {op::ORA, M, A   }, {op::ASL, M, A   }, {op::ORA, M, AL   },
39 // 0x10
40 	{op::BPL, I, RELB }, {op::ORA, M, DIY }, {op::ORA, M, DI  }, {op::ORA, M, SIY  },
41 	{op::CLB, M, LDM4 }, {op::ORA, M, DX  }, {op::ASL, M, DX  }, {op::ORA, M, DLIY },
42 	{op::CLC, I, IMP  }, {op::ORA, M, AY  }, {op::DEA, I, IMP }, {op::TCS, I, IMP  },
43 	{op::CLB, M, LDM5 }, {op::ORA, M, AX  }, {op::ASL, M, AX  }, {op::ORA, M, ALX  },
44 // 0x20
45 	{op::JSR, I, A    }, {op::AND, M, DXI }, {op::JSL, I, AL  }, {op::AND, M, S    },
46 	{op::BBS, M, BBCD }, {op::AND, M, D   }, {op::ROL, M, D   }, {op::AND, M, DLI  },
47 	{op::PLP, I, IMP  }, {op::AND, M, IMM }, {op::ROL, M, ACC }, {op::PLD, I, IMP  },
48 	{op::BBS, M, BBCA }, {op::AND, M, A   }, {op::ROL, M, A   }, {op::AND, M, AL   },
49 // 0x30
50 	{op::BMI, I, RELB }, {op::AND, M, DIY }, {op::AND, M, DI  }, {op::AND, M, SIY  },
51 	{op::BBC, M, BBCD }, {op::AND, M, DX  }, {op::ROL, M, DX  }, {op::AND, M, DLIY },
52 	{op::SEC, I, IMP  }, {op::AND, M, AY  }, {op::INA, I, IMP }, {op::TSC, I, IMP  },
53 	{op::BBC, M, BBCA }, {op::AND, M, AX  }, {op::ROL, M, AX  }, {op::AND, M, ALX  },
54 // 0x40
55 	{op::RTI, I, IMP  }, {op::EOR, M, DXI }, {op::WDM, I, IMP }, {op::EOR, M, S    },
56 	{op::MVP, I, MVP  }, {op::EOR, M, D   }, {op::LSR, M, D   }, {op::EOR, M, DLI  },
57 	{op::PHA, I, IMP  }, {op::EOR, M, IMM }, {op::LSR, M, ACC }, {op::PHK, I, IMP  },
58 	{op::JMP, I, A    }, {op::EOR, M, A   }, {op::LSR, M, A   }, {op::EOR, M, AL   },
59 // 0x50
60 	{op::BVC, I, RELB }, {op::EOR, M, DIY }, {op::EOR, M, DI  }, {op::EOR, M, SIY  },
61 	{op::MVN, I, MVN  }, {op::EOR, M, DX  }, {op::LSR, M, DX  }, {op::EOR, M, DLIY },
62 	{op::CLI, I, IMP  }, {op::EOR, M, AY  }, {op::PHY, I, IMP }, {op::TCD, I, IMP  },
63 	{op::JMP, I, AL   }, {op::EOR, M, AX  }, {op::LSR, M, AX  }, {op::EOR, M, ALX  },
64 // 0x60
65 	{op::RTS, I, IMP  }, {op::ADC, M, DXI }, {op::PER, I, PER }, {op::ADC, M, S    },
66 	{op::LDM, M, LDM4 }, {op::ADC, M, D   }, {op::ROR, M, D   }, {op::ADC, M, DLI  },
67 	{op::PLA, I, IMP  }, {op::ADC, M, IMM }, {op::ROR, M, ACC }, {op::RTL, I, IMP  },
68 	{op::JMP, I, AI   }, {op::ADC, M, A   }, {op::ROR, M, A   }, {op::ADC, M, AL   },
69 // 0x70
70 	{op::BVS, I, RELB }, {op::ADC, M, DIY }, {op::ADC, M, DI  }, {op::ADC, M, SIY  },
71 	{op::LDM, M, LDM4X}, {op::ADC, M, DX  }, {op::ROR, M, DX  }, {op::ADC, M, DLIY },
72 	{op::SEI, I, IMP  }, {op::ADC, M, AY  }, {op::PLY, I, IMP }, {op::TDC, I, IMP  },
73 	{op::JMP, I, AXI  }, {op::ADC, M, AX  }, {op::ROR, M, AX  }, {op::ADC, M, ALX  },
74 // 0x80
75 	{op::BRA, I, RELB }, {op::STA, M, DXI }, {op::BRL, I, RELW}, {op::STA, M, S    },
76 	{op::STY, X, D    }, {op::STA, M, D   }, {op::STX, X, D   }, {op::STA, M, DLI  },
77 	{op::DEY, I, IMP  }, {op::BIT, M, IMM }, {op::TXA, I, IMP }, {op::PHT, I, IMP  },
78 	{op::STY, X, A    }, {op::STA, M, A   }, {op::STX, X, A   }, {op::STA, M, AL   },
79 // 0x90
80 	{op::BCC, I, RELB }, {op::STA, M, DIY }, {op::STA, M, DI  }, {op::STA, M, SIY  },
81 	{op::STY, X, DX   }, {op::STA, M, DX  }, {op::STX, X, DY  }, {op::STA, M, DLIY },
82 	{op::TYA, I, IMP  }, {op::STA, M, AY  }, {op::TXS, I, IMP }, {op::TXY, I, IMP  },
83 	{op::LDM, M, LDM5 }, {op::STA, M, AX  }, {op::LDM, M, LDM5X},{op::STA, M, ALX  },
84 // 0xA0
85 	{op::LDY, X, IMM  }, {op::LDA, M, DXI }, {op::LDX, X, IMM }, {op::LDA, M, S    },
86 	{op::LDY, X, D    }, {op::LDA, M, D   }, {op::LDX, X, D   }, {op::LDA, M, DLI  },
87 	{op::TAY, I, IMP  }, {op::LDA, M, IMM }, {op::TAX, I, IMP }, {op::PLB, I, IMP  },
88 	{op::LDY, X, A    }, {op::LDA, M, A   }, {op::LDX, X, A   }, {op::LDA, M, AL   },
89 // 0xB0
90 	{op::BCS, I, RELB }, {op::LDA, M, DIY }, {op::LDA, M, DI  }, {op::LDA, M, SIY  },
91 	{op::LDY, X, DX   }, {op::LDA, M, DX  }, {op::LDX, X, DY  }, {op::LDA, M, DLIY },
92 	{op::CLV, I, IMP  }, {op::LDA, M, AY  }, {op::TSX, I, IMP }, {op::TYX, I, IMP  },
93 	{op::LDY, X, AX   }, {op::LDA, M, AX  }, {op::LDX, X, AY  }, {op::LDA, M, ALX  },
94 // 0xC0
95 	{op::CPY, X, IMM  }, {op::CMP, M, DXI }, {op::CLP, I, IMM }, {op::CMP, M, S    },
96 	{op::CPY, X, D    }, {op::CMP, M, D   }, {op::DEC, M, D   }, {op::CMP, M, DLI  },
97 	{op::INY, I, IMP  }, {op::CMP, M, IMM }, {op::DEX, I, IMP }, {op::WAI, I, IMP  },
98 	{op::CPY, X, A    }, {op::CMP, M, A   }, {op::DEC, M, A   }, {op::CMP, M, AL   },
99 // 0xD0
100 	{op::BNE, I, RELB }, {op::CMP, M, DIY }, {op::CMP, M, DI  }, {op::CMP, M, SIY  },
101 	{op::PEI, I, PEI  }, {op::CMP, M, DX  }, {op::DEC, M, DX  }, {op::CMP, M, DLIY },
102 	{op::CLM, I, IMP  }, {op::CMP, M, AY  }, {op::PHX, I, IMP }, {op::STP, I, IMP  },
103 	{op::JML, I, AI   }, {op::CMP, M, AX  }, {op::DEC, M, AX  }, {op::CMP, M, ALX  },
104 // 0xE0
105 	{op::CPX, X, IMM  }, {op::SBC, M, DXI }, {op::SEP, I, IMM }, {op::SBC, M, S    },
106 	{op::CPX, X, D    }, {op::SBC, M, D   }, {op::INC, M, D   }, {op::SBC, M, DLI  },
107 	{op::INX, M, IMP  }, {op::SBC, M, IMM }, {op::NOP, I, IMP }, {op::PSH, I, IMM  },
108 	{op::CPX, X, A    }, {op::SBC, M, A   }, {op::INC, M, A   }, {op::SBC, M, AL   },
109 // 0xF0
110 	{op::BEQ, I, RELB }, {op::SBC, M, DIY }, {op::SBC, M, DI  }, {op::SBC, M, SIY  },
111 	{op::PEA, I, PEA  }, {op::SBC, M, DX  }, {op::INC, M, DX  }, {op::SBC, M, DLIY },
112 	{op::SEM, I, IMP  }, {op::SBC, M, AY  }, {op::PLX, I, IMP }, {op::PUL, I, IMM  },
113 	{op::JSR, I, AXI  }, {op::SBC, M, AX  }, {op::INC, M, AX  }, {op::SBC, M, ALX  }
114 };
115 
116 const m7700_disassembler::m7700_opcode_struct m7700_disassembler::s_opcodes_prefix42[256] =
117 {
118 	{op::BRK, I, SIG  }, {op::ORB, M, DXI }, {op::COP, I, SIG }, {op::ORB,  M, S   },
119 	{op::TSB, M, D    }, {op::ORB, M, D   }, {op::ASL, M, D   }, {op::ORB,  M, DLI },
120 	{op::PHP, I, IMP  }, {op::ORB, M, IMM }, {op::ASL, M, ACCB}, {op::PHD,  I, IMP },
121 	{op::TSB, M, A    }, {op::ORB, M, A   }, {op::ASL, M, A   }, {op::ORB,  M, AL  },
122 // 0x10
123 	{op::BPL, I, RELB }, {op::ORB, M, DIY }, {op::ORB, M, DI  }, {op::ORB,  M, SIY },
124 	{op::TRB, M, D    }, {op::ORB, M, DX  }, {op::ASL, M, DX  }, {op::ORB,  M, DLIY},
125 	{op::CLC, I, IMP  }, {op::ORB, M, AY  }, {op::DEB, I, IMP }, {op::TCS,  I, IMP },
126 	{op::TRB, M, A    }, {op::ORB, M, AX  }, {op::ASL, M, AX  }, {op::ORB,  M, ALX },
127 // 0x20
128 	{op::JSR, I, A    }, {op::ANDB,M, DXI }, {op::JSL, I, AL  }, {op::ANDB, M, S   },
129 	{op::BIT, M, D    }, {op::ANDB,M, D   }, {op::ROL, M, D   }, {op::ANDB, M, DLI },
130 	{op::PLP, I, IMP  }, {op::ANDB,M, IMM }, {op::ROL, M, ACCB}, {op::PLD,  I, IMP },
131 	{op::BIT, M, A    }, {op::ANDB,M, A   }, {op::ROL, M, A   }, {op::ANDB, M, AL  },
132 // 0x30
133 	{op::BMI, I, RELB }, {op::AND, M, DIY }, {op::AND, M, DI  }, {op::AND,  M, SIY },
134 	{op::BIT, M, DX   }, {op::AND, M, DX  }, {op::ROL, M, DX  }, {op::AND,  M, DLIY},
135 	{op::SEC, I, IMP  }, {op::AND, M, AY  }, {op::INB, I, IMP }, {op::TSC,  I, IMP },
136 	{op::BIT, M, AX   }, {op::AND, M, AX  }, {op::ROL, M, AX  }, {op::AND,  M, ALX },
137 // 0x40
138 	{op::RTI, I, IMP  }, {op::EORB,M, DXI }, {op::WDM, I, IMP }, {op::EORB, M, S   },
139 	{op::MVP, I, MVP  }, {op::EORB,M, D   }, {op::LSRB,M, D   }, {op::EORB, M, DLI },
140 	{op::PHB, I, IMP  }, {op::EORB,M, IMM }, {op::LSRB,M, ACC }, {op::PHK,  I, IMP },
141 	{op::JMP, I, A    }, {op::EORB,M, A   }, {op::LSRB,M, A   }, {op::EORB, M, AL  },
142 // 0x50
143 	{op::BVC, I, RELB }, {op::EORB,M, DIY }, {op::EORB,M, DI  }, {op::EORB, M, SIY },
144 	{op::MVN, I, MVN  }, {op::EORB,M, DX  }, {op::LSRB,M, DX  }, {op::EORB, M, DLIY},
145 	{op::CLI, I, IMP  }, {op::EORB,M, AY  }, {op::PHY, I, IMP }, {op::TCD,  I, IMP },
146 	{op::JMP, I, AL   }, {op::EORB,M, AX  }, {op::LSRB,M, AX  }, {op::EORB, M, ALX },
147 // 0x60
148 	{op::RTS, I, IMP  }, {op::ADCB,M, DXI }, {op::PER, I, PER }, {op::ADCB, M, S   },
149 	{op::STZ, M, D    }, {op::ADCB,M, D   }, {op::ROR, M, D   }, {op::ADCB, M, DLI },
150 	{op::PLAB,I, IMP  }, {op::ADCB,M, IMM }, {op::ROR, M, ACC }, {op::RTL,  I, IMP },
151 	{op::JMP, I, AI   }, {op::ADCB,M, A   }, {op::ROR, M, A   }, {op::ADCB, M, AL  },
152 // 0x70
153 	{op::BVS, I, RELB }, {op::ADCB,M, DIY }, {op::ADCB,M, DI  }, {op::ADCB, M, SIY },
154 	{op::STZ, M, DX   }, {op::ADCB,M, DX  }, {op::ROR, M, DX  }, {op::ADCB, M, DLIY},
155 	{op::SEI, I, IMP  }, {op::ADCB,M, AY  }, {op::PLY, I, IMP }, {op::TDC,  I, IMP },
156 	{op::JMP, I, AXI  }, {op::ADCB,M, AX  }, {op::ROR, M, AX  }, {op::ADCB, M, ALX },
157 // 0x80
158 	{op::BRA, I, RELB }, {op::STB, M, DXI }, {op::BRL, I, RELW}, {op::STB,  M, S   },
159 	{op::STY, X, D    }, {op::STB, M, D   }, {op::STX, X, D   }, {op::STB,  M, DLI },
160 	{op::DEY, I, IMP  }, {op::BIT, M, IMM }, {op::TXB, I, IMP }, {op::PHB,  I, IMP },
161 	{op::STY, X, A    }, {op::STB, M, A   }, {op::STX, X, A   }, {op::STB,  M, AL  },
162 // 0x90
163 	{op::BCC, I, RELB }, {op::STB, M, DIY }, {op::STB, M, DI  }, {op::STB,  M, SIY },
164 	{op::STY, X, DX   }, {op::STB, M, DX  }, {op::STX, X, DY  }, {op::STB,  M, DLIY},
165 	{op::TYB, I, IMP  }, {op::STB, M, AY  }, {op::TXS, I, IMP }, {op::TXY,  I, IMP },
166 	{op::STZ, M, A    }, {op::STB, M, AX  }, {op::STZ, M, AX  }, {op::STB,  M, ALX },
167 // 0xA0
168 	{op::LDY, X, IMM  }, {op::LDB, M, DXI }, {op::LDX, X, IMM }, {op::LDB,  M, S   },
169 	{op::LDY, X, D    }, {op::LDB, M, D   }, {op::LDX, X, D   }, {op::LDB,  M, DLI },
170 	{op::TBY, I, IMP  }, {op::LDB, M, IMM }, {op::TBX, I, IMP }, {op::PLB,  I, IMP },
171 	{op::LDY, X, A    }, {op::LDB, M, A   }, {op::LDX, X, A   }, {op::LDB,  M, AL  },
172 // 0xB0
173 	{op::BCS, I, RELB }, {op::LDB, M, DIY }, {op::LDB, M, DI  }, {op::LDB,  M, SIY },
174 	{op::LDY, X, DX   }, {op::LDB, M, DX  }, {op::LDX, X, DY  }, {op::LDB,  M, DLIY},
175 	{op::CLV, I, IMP  }, {op::LDB, M, AY  }, {op::TSX, I, IMP }, {op::TYX,  I, IMP },
176 	{op::LDY, X, AX   }, {op::LDB, M, AX  }, {op::LDX, X, AY  }, {op::LDB,  M, ALX },
177 // 0xC0
178 	{op::CPY, X, IMM  }, {op::CMPB,M, DXI }, {op::CLP, I, IMM }, {op::CMPB, M, S   },
179 	{op::CPY, X, D    }, {op::CMPB,M, D   }, {op::DEC, M, D   }, {op::CMPB, M, DLI },
180 	{op::INY, I, IMP  }, {op::CMPB,M, IMM }, {op::DEX, I, IMP }, {op::WAI,  I, IMP },
181 	{op::CPY, X, A    }, {op::CMPB,M, A   }, {op::DEC, M, A   }, {op::CMPB, M, AL  },
182 // 0xD0
183 	{op::BNE, I, RELB }, {op::CMPB,M, DIY }, {op::CMPB,M, DI  }, {op::CMPB, M, SIY },
184 	{op::PEI, I, PEI  }, {op::CMPB,M, DX  }, {op::DEC, M, DX  }, {op::CMPB, M, DLIY},
185 	{op::CLD, I, IMP  }, {op::CMPB,M, AY  }, {op::PHX, I, IMP }, {op::STP,  I, IMP },
186 	{op::JML, I, AI   }, {op::CMPB,M, AX  }, {op::DEC, M, AX  }, {op::CMPB, M, ALX },
187 // 0xE0
188 	{op::CPX, X, IMM  }, {op::SBCB,M, DXI }, {op::SEP, I, IMM }, {op::SBCB, M, S   },
189 	{op::CPX, X, D    }, {op::SBCB,M, D   }, {op::INC, M, D   }, {op::SBCB, M, DLI },
190 	{op::INX, M, IMP  }, {op::SBCB,M, IMM }, {op::NOP, I, IMP }, {op::XBA,  I, IMP },
191 	{op::CPX, X, A    }, {op::SBCB,M, A   }, {op::INC, M, A   }, {op::SBCB, M, AL  },
192 // 0xF0
193 	{op::BEQ, I, RELB }, {op::SBCB,M, DIY }, {op::SBCB,M, DI  }, {op::SBCB, M, SIY },
194 	{op::PEA, I, PEA  }, {op::SBCB,M, DX  }, {op::INC, M, DX  }, {op::SBCB, M, DLIY},
195 	{op::SED, I, IMP  }, {op::SBCB,M, AY  }, {op::PLX, I, IMP }, {op::XCE,  I, IMP },
196 	{op::JSR, I, AXI  }, {op::SBCB,M, AX  }, {op::INC, M, AX  }, {op::SBCB, M, ALX }
197 };
198 
199 const m7700_disassembler::m7700_opcode_struct m7700_disassembler::s_opcodes_prefix89[256] =
200 {
201 	{op::BRK, I, SIG  }, {op::MPY, M, DXI }, {op::COP, I, SIG }, {op::MPY, M, S    },
202 	{op::TSB, M, D    }, {op::MPY, M, D   }, {op::ASL, M, D   }, {op::MPY, M, DLI  },
203 	{op::PHP, I, IMP  }, {op::MPY, M, IMM }, {op::ASL, M, ACC }, {op::PHD, I, IMP  },
204 	{op::TSB, M, A    }, {op::MPY, M, A   }, {op::ASL, M, A   }, {op::MPY, M, AL   },
205 // 0x10
206 	{op::BPL, I, RELB }, {op::ORA, M, DIY }, {op::ORA, M, DI  }, {op::ORA, M, SIY  },
207 	{op::TRB, M, D    }, {op::MPY, M, DX  }, {op::ASL, M, DX  }, {op::ORA, M, DLIY },
208 	{op::CLC, I, IMP  }, {op::MPY, M, AY  }, {op::INA, I, IMP }, {op::TCS, I, IMP  },
209 	{op::TRB, M, A    }, {op::ORA, M, AX  }, {op::ASL, M, AX  }, {op::ORA, M, ALX  },
210 // 0x20
211 	{op::JSR, I, A    }, {op::AND, M, DXI }, {op::JSL, I, AL  }, {op::AND, M, S    },
212 	{op::BIT, M, D    }, {op::AND, M, D   }, {op::ROL, M, D   }, {op::AND, M, DLI  },
213 	{op::XAB, I, IMP  }, {op::AND, M, IMM }, {op::ROL, M, ACC }, {op::PLD, I, IMP  },
214 	{op::BIT, M, A    }, {op::AND, M, A   }, {op::ROL, M, A   }, {op::AND, M, AL   },
215 // 0x30
216 	{op::BMI, I, RELB }, {op::AND, M, DIY }, {op::AND, M, DI  }, {op::AND, M, SIY  },
217 	{op::BIT, M, DX   }, {op::AND, M, DX  }, {op::ROL, M, DX  }, {op::AND, M, DLIY },
218 	{op::SEC, I, IMP  }, {op::AND, M, AY  }, {op::DEA, I, IMP }, {op::TSC, I, IMP  },
219 	{op::BIT, M, AX   }, {op::AND, M, AX  }, {op::ROL, M, AX  }, {op::AND, M, ALX  },
220 // 0x40
221 	{op::RTI, I, IMP  }, {op::EOR, M, DXI }, {op::WDM, I, IMP }, {op::EOR, M, S    },
222 	{op::MVP, I, MVP  }, {op::EOR, M, D   }, {op::LSR, M, D   }, {op::EOR, M, DLI  },
223 	{op::PHA, I, IMP  }, {op::RLA, M, IMM }, {op::LSR, M, ACC }, {op::PHK, I, IMP  },
224 	{op::JMP, I, A    }, {op::EOR, M, A   }, {op::LSR, M, A   }, {op::EOR, M, AL   },
225 // 0x50
226 	{op::BVC, I, RELB }, {op::EOR, M, DIY }, {op::EOR, M, DI  }, {op::EOR, M, SIY  },
227 	{op::MVN, I, MVN  }, {op::EOR, M, DX  }, {op::LSR, M, DX  }, {op::EOR, M, DLIY },
228 	{op::CLI, I, IMP  }, {op::EOR, M, AY  }, {op::PHY, I, IMP }, {op::TCD, I, IMP  },
229 	{op::JMP, I, AL   }, {op::EOR, M, AX  }, {op::LSR, M, AX  }, {op::EOR, M, ALX  },
230 // 0x60
231 	{op::RTS, I, IMP  }, {op::ADC, M, DXI }, {op::PER, I, PER }, {op::ADC, M, S    },
232 	{op::STZ, M, D    }, {op::ADC, M, D   }, {op::ROR, M, D   }, {op::ADC, M, DLI  },
233 	{op::PLA, I, IMP  }, {op::ADC, M, IMM }, {op::ROR, M, ACC }, {op::RTL, I, IMP  },
234 	{op::JMP, I, AI   }, {op::ADC, M, A   }, {op::ROR, M, A   }, {op::ADC, M, AL   },
235 // 0x70
236 	{op::BVS, I, RELB }, {op::ADC, M, DIY }, {op::ADC, M, DI  }, {op::ADC, M, SIY  },
237 	{op::STZ, M, DX   }, {op::ADC, M, DX  }, {op::ROR, M, DX  }, {op::ADC, M, DLIY },
238 	{op::SEI, I, IMP  }, {op::ADC, M, AY  }, {op::PLY, I, IMP }, {op::TDC, I, IMP  },
239 	{op::JMP, I, AXI  }, {op::ADC, M, AX  }, {op::ROR, M, AX  }, {op::ADC, M, ALX  },
240 // 0x80
241 	{op::BRA, I, RELB }, {op::STA, M, DXI }, {op::BRL, I, RELW}, {op::STA, M, S    },
242 	{op::STY, X, D    }, {op::STA, M, D   }, {op::STX, X, D   }, {op::STA, M, DLI  },
243 	{op::DEY, I, IMP  }, {op::BIT, M, IMM }, {op::TXA, I, IMP }, {op::PHB, I, IMP  },
244 	{op::STY, X, A    }, {op::STA, M, A   }, {op::STX, X, A   }, {op::STA, M, AL   },
245 // 0x90
246 	{op::BCC, I, RELB }, {op::STA, M, DIY }, {op::STA, M, DI  }, {op::STA, M, SIY  },
247 	{op::STY, X, DX   }, {op::STA, M, DX  }, {op::STX, X, DY  }, {op::STA, M, DLIY },
248 	{op::TYA, I, IMP  }, {op::STA, M, AY  }, {op::TXS, I, IMP }, {op::TXY, I, IMP  },
249 	{op::STZ, M, A    }, {op::STA, M, AX  }, {op::STZ, M, AX  }, {op::STA, M, ALX  },
250 // 0xA0
251 	{op::LDY, X, IMM  }, {op::LDA, M, DXI }, {op::LDX, X, IMM }, {op::LDA, M, S    },
252 	{op::LDY, X, D    }, {op::LDA, M, D   }, {op::LDX, X, D   }, {op::LDA, M, DLI  },
253 	{op::TAY, I, IMP  }, {op::LDA, M, IMM }, {op::TAX, I, IMP }, {op::PLB, I, IMP  },
254 	{op::LDY, X, A    }, {op::LDA, M, A   }, {op::LDX, X, A   }, {op::LDA, M, AL   },
255 // 0xB0
256 	{op::BCS, I, RELB }, {op::LDA, M, DIY }, {op::LDA, M, DI  }, {op::LDA, M, SIY  },
257 	{op::LDY, X, DX   }, {op::LDA, M, DX  }, {op::LDX, X, DY  }, {op::LDA, M, DLIY },
258 	{op::CLV, I, IMP  }, {op::LDA, M, AY  }, {op::TSX, I, IMP }, {op::TYX, I, IMP  },
259 	{op::LDY, X, AX   }, {op::LDA, M, AX  }, {op::LDX, X, AY  }, {op::LDA, M, ALX  },
260 // 0xC0
261 	{op::CPY, X, IMM  }, {op::CMP, M, DXI }, {op::LDT, I, IMM }, {op::CMP, M, S    },
262 	{op::CPY, X, D    }, {op::CMP, M, D   }, {op::DEC, M, D   }, {op::CMP, M, DLI  },
263 	{op::INY, I, IMP  }, {op::CMP, M, IMM }, {op::DEX, I, IMP }, {op::WAI, I, IMP  },
264 	{op::CPY, X, A    }, {op::CMP, M, A   }, {op::DEC, M, A   }, {op::CMP, M, AL   },
265 // 0xD0
266 	{op::BNE, I, RELB }, {op::CMP, M, DIY }, {op::CMP, M, DI  }, {op::CMP, M, SIY  },
267 	{op::PEI, I, PEI  }, {op::CMP, M, DX  }, {op::DEC, M, DX  }, {op::CMP, M, DLIY },
268 	{op::CLD, I, IMP  }, {op::CMP, M, AY  }, {op::PHX, I, IMP }, {op::STP, I, IMP  },
269 	{op::JML, I, AI   }, {op::CMP, M, AX  }, {op::DEC, M, AX  }, {op::CMP, M, ALX  },
270 // 0xE0
271 	{op::CPX, X, IMM  }, {op::SBC, M, DXI }, {op::SEP, I, IMM }, {op::SBC, M, S    },
272 	{op::CPX, X, D    }, {op::SBC, M, D   }, {op::INC, M, D   }, {op::SBC, M, DLI  },
273 	{op::INX, M, IMP  }, {op::SBC, M, IMM }, {op::NOP, I, IMP }, {op::XBA, I, IMP  },
274 	{op::CPX, X, A    }, {op::SBC, M, A   }, {op::INC, M, A   }, {op::SBC, M, AL   },
275 // 0xF0
276 	{op::BEQ, I, RELB }, {op::SBC, M, DIY }, {op::SBC, M, DI  }, {op::SBC, M, SIY  },
277 	{op::PEA, I, PEA  }, {op::SBC, M, DX  }, {op::INC, M, DX  }, {op::SBC, M, DLIY },
278 	{op::SEM, I, IMP  }, {op::SBC, M, AY  }, {op::PLX, I, IMP }, {op::XCE, I, IMP  },
279 	{op::JSR, I, AXI  }, {op::SBC, M, AX  }, {op::INC, M, AX  }, {op::SBC, M, ALX  }
280 };
281 
int_8_str(unsigned int val)282 inline std::string m7700_disassembler::int_8_str(unsigned int val)
283 {
284 	val &= 0xff;
285 
286 	if(val & 0x80)
287 		return util::string_format("-$%x", (0-val) & 0xff);
288 	else
289 		return util::string_format("$%x", val & 0xff);
290 }
291 
int_16_str(unsigned int val)292 inline std::string m7700_disassembler::int_16_str(unsigned int val)
293 {
294 	val &= 0xffff;
295 
296 	if(val & 0x8000)
297 		return util::string_format("-$%x", (0-val) & 0xffff);
298 	else
299 		return util::string_format("$%x", val & 0xffff);
300 }
301 
m7700_disassembler(config * conf)302 m7700_disassembler::m7700_disassembler(config *conf) : m_config(conf)
303 {
304 }
305 
opcode_alignment() const306 u32 m7700_disassembler::opcode_alignment() const
307 {
308 	return 1;
309 }
310 
disassemble(std::ostream & stream,offs_t pc,const data_buffer & opcodes,const data_buffer & params)311 offs_t m7700_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
312 {
313 	unsigned int instruction;
314 	const m7700_opcode_struct *opcode;
315 	int var;
316 	signed char varS;
317 	int length = 1;
318 	//unsigned int start;
319 	uint32_t flags = 0;
320 
321 	offs_t address = pc;
322 	u32 pg = pc & 0xff0000;
323 	pc &= 0xffff;
324 	address = pc | pg;
325 
326 	instruction = opcodes.r8(address);
327 
328 	int m_flag = m_config->get_m_flag();
329 	int x_flag = m_config->get_x_flag();
330 
331 	// check for prefixes
332 	switch (instruction)
333 	{
334 	case 0x42:
335 		address++;
336 		length++;
337 		instruction = opcodes.r8(address);
338 		opcode = &m7700_opcode_struct::get_prefix42(instruction);
339 		break;
340 
341 	case 0x89:
342 		address++;
343 		length++;
344 		instruction = opcodes.r8(address);
345 		opcode = &m7700_opcode_struct::get_prefix89(instruction);
346 		break;
347 
348 	default:
349 		opcode = &m7700_opcode_struct::get(instruction);
350 		break;
351 	}
352 
353 	if (opcode->is_call())
354 		flags = STEP_OVER;
355 	else if (opcode->is_return())
356 		flags = STEP_OUT;
357 
358 	stream << opcode->name();
359 
360 	switch(opcode->ea)
361 	{
362 		case IMP :
363 			break;
364 		case ACC :
365 			util::stream_format(stream, " A");
366 			break;
367 		case ACCB :
368 			util::stream_format(stream, " B");
369 			break;
370 		case RELB:
371 			varS = opcodes.r8(address + 1);
372 			length++;
373 			util::stream_format(stream, " %06x (%s)", pg | ((pc + length + varS)&0xffff), int_8_str(varS));
374 			break;
375 		case RELW:
376 		case PER :
377 			var = opcodes.r16(address + 1);
378 			length += 2;
379 			util::stream_format(stream, " %06x (%s)", pg | ((pc + length + var)&0xffff), int_16_str(var));
380 			break;
381 		case IMM :
382 			if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
383 			{
384 				util::stream_format(stream, " #$%04x", opcodes.r16(address + 1));
385 				length += 2;
386 			}
387 			else
388 			{
389 				util::stream_format(stream, " #$%02x", opcodes.r8(address + 1));
390 				length++;
391 			}
392 			break;
393 		case BBCD:
394 			if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
395 			{
396 				varS = opcodes.r8(address + 4);
397 				length += 4;
398 				util::stream_format(stream, " #$%04x, $%02x, %06x (%s)", opcodes.r16(address + 2), opcodes.r8(address + 1), pg | ((pc + length + varS)&0xffff), int_8_str(varS));
399 			}
400 			else
401 			{
402 				varS = opcodes.r8(address + 3);
403 				length += 3;
404 				util::stream_format(stream, " #$%02x, $%02x, %06x (%s)", opcodes.r8(address + 2), opcodes.r8(address + 1), pg | ((pc + length + varS)&0xffff), int_8_str(varS));
405 			}
406 			break;
407 		case BBCA:
408 			if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
409 			{
410 				length += 5;
411 				varS = opcodes.r8(address + 5);
412 				util::stream_format(stream, " #$%04x, $%04x, %06x (%s)", opcodes.r16(address + 3), opcodes.r16(address + 1), pg | ((pc + length + varS)&0xffff), int_8_str(varS));
413 			}
414 			else
415 			{
416 				length += 4;
417 				varS = opcodes.r8(address + 4);
418 				util::stream_format(stream, " #$%02x, $%04x, %06x (%s)", opcodes.r8(address + 3), opcodes.r16(address + 1), pg | ((pc + length + varS)&0xffff), int_8_str(varS));
419 			}
420 			break;
421 		case LDM4:
422 			if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
423 			{
424 				util::stream_format(stream, " #$%04x, $%02x", opcodes.r16(address + 2), opcodes.r8(address + 1));
425 				length += 3;
426 			}
427 			else
428 			{
429 				util::stream_format(stream, " #$%02x, $%02x", opcodes.r8(address + 2), opcodes.r8(address + 1));
430 				length += 2;
431 			}
432 			break;
433 		case LDM5:
434 			if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
435 			{
436 				util::stream_format(stream, " #$%04x, $%04x", opcodes.r16(address + 3), opcodes.r16(address + 1));
437 				length += 4;
438 			}
439 			else
440 			{
441 				util::stream_format(stream, " #$%02x, $%04x", opcodes.r8(address + 3), opcodes.r16(address + 1));
442 				length += 3;
443 			}
444 			break;
445 		case LDM4X:
446 			if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
447 			{
448 				util::stream_format(stream, " #$%04x, $%02x, X", opcodes.r16(address + 2), opcodes.r8(address + 1));
449 				length += 3;
450 			}
451 			else
452 			{
453 				util::stream_format(stream, " #$%02x, $%02x, X", opcodes.r8(address + 2), opcodes.r8(address + 1));
454 				length += 2;
455 			}
456 			break;
457 		case LDM5X:
458 			if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
459 			{
460 				util::stream_format(stream, " #$%04x, $%04x, X", opcodes.r16(address + 3), opcodes.r16(address + 1));
461 				length += 4;
462 			}
463 			else
464 			{
465 				util::stream_format(stream, " #$%02x, $%04x, X", opcodes.r8(address + 3), opcodes.r16(address + 1));
466 				length += 3;
467 			}
468 			break;
469 		case A   :
470 		case PEA :
471 			util::stream_format(stream, " $%04x", opcodes.r16(address + 1));
472 			length += 2;
473 			break;
474 		case AI  :
475 			util::stream_format(stream, " ($%04x)", opcodes.r16(address + 1));
476 			length += 2;
477 			break;
478 		case AL  :
479 			util::stream_format(stream, " $%06x", opcodes.r32(address + 1) & 0xffffff);
480 			length += 3;
481 			break;
482 		case ALX :
483 			util::stream_format(stream, " $%06x,X", opcodes.r32(address + 1) & 0xffffff);
484 			length += 3;
485 			break;
486 		case AX  :
487 			util::stream_format(stream, " $%04x,X", opcodes.r16(address + 1));
488 			length += 2;
489 			break;
490 		case AXI :
491 			util::stream_format(stream, " ($%04x,X)", opcodes.r16(address + 1));
492 			length += 2;
493 			break;
494 		case AY  :
495 			util::stream_format(stream, " $%04x,Y", opcodes.r16(address + 1));
496 			length += 2;
497 			break;
498 		case D   :
499 			util::stream_format(stream, " $%02x", opcodes.r8(address + 1));
500 			length++;
501 			break;
502 		case DI  :
503 		case PEI :
504 			util::stream_format(stream, " ($%02x)", opcodes.r8(address + 1));
505 			length++;
506 			break;
507 		case DIY :
508 			util::stream_format(stream, " ($%02x),Y", opcodes.r8(address + 1));
509 			length++;
510 			break;
511 		case DLI :
512 			util::stream_format(stream, " [$%02x]", opcodes.r8(address + 1));
513 			length++;
514 			break;
515 		case DLIY:
516 			util::stream_format(stream, " [$%02x],Y", opcodes.r8(address + 1));
517 			length++;
518 			break;
519 		case DX  :
520 			util::stream_format(stream, " $%02x,X", opcodes.r8(address + 1));
521 			length++;
522 			break;
523 		case DXI :
524 			util::stream_format(stream, " ($%02x,X)", opcodes.r8(address + 1));
525 			length++;
526 			break;
527 		case DY  :
528 			util::stream_format(stream, " $%02x,Y", opcodes.r8(address + 1));
529 			length++;
530 			break;
531 		case S   :
532 			util::stream_format(stream, " %s,S", int_8_str(opcodes.r8(address + 1)));
533 			length++;
534 			break;
535 		case SIY :
536 			util::stream_format(stream, " (%s,S),Y", int_8_str(opcodes.r8(address + 1)));
537 			length++;
538 			break;
539 		case SIG :
540 			util::stream_format(stream, " #$%02x", opcodes.r8(address + 1));
541 			length++;
542 			break;
543 		case MVN :
544 		case MVP :
545 			util::stream_format(stream, " $%02x, $%02x", opcodes.r8(address + 2), opcodes.r8(address + 1));
546 			length += 2;
547 			break;
548 	}
549 
550 	return length | flags | SUPPORTED;
551 }
552