m68000/cpu_details.rs
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Trait that defines the instruction execution times and exception stack frame of the emulated CPU.
6
7mod mc68000;
8mod scc68070;
9
10pub use mc68000::Mc68000;
11pub use scc68070::Scc68070;
12
13/// The emulated stack formats.
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15#[non_exhaustive]
16pub enum StackFormat {
17 MC68000,
18 SCC68070,
19}
20
21/// Low level details of the emulated CPU.
22///
23/// m68000 emulates the ISA, but CPU implementations may have different instruction execution timings and exceptions processing.
24/// The [M68000](crate::M68000) structure is generic of an instance of this trait, and m68000 takes all the specific details
25/// from this instance so it can behave as specified.
26///
27/// To implement your own details, implement this trait on an empty structure and fill each constant.
28/// See the documentation of each constant for more details.
29/// - `STACK_FORMAT` is the stack format to use.
30/// - `VECTOR_RESET` is the time the CPU takes to reset itself (RESET vector 0).
31/// - [`vector_execution_time`](CpuDetails::vector_execution_time) returns the time it takes to process the given exception vector.
32/// - `EA_*` is the calculation time of each addressing mode for the byte and word sizes.
33/// For long size m68000 automatically adds 4 to these values.
34///
35/// The remaining constants are for instruction execution time.
36/// Each starts with the mnemonic of the instruction and is followed by instruction-specific details.
37///
38/// Below is a list of most of the instruction-specific details and what they mean:
39/// - `BW` means byte or word size.
40/// - `L` means long size.
41/// - `BYTE` means the operation is byte-sized.
42/// - `WORD` means the operation is word-sized.
43/// - `LONG` means the operation is long-sized.
44/// - `LONG_RDIMM` means the operation is long-sized and the addressing mode is Register Direct (data or address) or Immediate.
45///
46/// - `REG` means the operands are in registers.
47/// - `MEM` means the operands are in memory.
48///
49/// - `REG_BW` means destination operand is in a register with a byte or word size.
50/// - `REG_L` means destination operand is in a register with a long size.
51/// - `REG_L_RDIMM` means destination operand is in a register with a long size and the addressing mode is Register Direct (data or address) or Immediate.
52/// - `MEM_BW` means destination operand is in memory with a byte or word size.
53/// - `MEM_L` means destination operand is in memory with a long size.
54///
55/// - `COUNT` is the multiplier of the shift count when doing shifts/rotates in registers.
56///
57/// - `BRANCH` means the branch is taken in a branch instruction.
58/// - `NO_BRANCH_BYTE` means the branch is not taken in a branch instruction and the branch offset is byte sized.
59/// - `NO_BRANCH_WORD` means the branch is not taken in a branch instruction and the branch offset is word sized.
60///
61/// - `DYN_REG` means the bit number is dynamic and the destination is in a register.
62/// - `DYN_MEM` means the bit number is dynamic and the destination is in memory.
63/// - `STA_REG` means the bit number is static and the destination is in a register.
64/// - `STA_MEM` means the bit number is static and the destination is in memory.
65///
66/// - `NO_TRAP` means the TRAP is not taken.
67///
68/// - `TRUE` means the test is true in a DBcc instruction.
69/// - `FALSE_BRANCH` means the test is false and the branch is taken in a DBcc instruction.
70/// - `FALSE_NO_BRANCH` means the test is false and the branch is not taken in a DBcc instruction.
71///
72/// `JMP_*`, `JSR_*`, `LEA_*` and `PEA_*` timings are based on the addressing mode.
73pub trait CpuDetails : Default {
74 /// The stack format to use.
75 const STACK_FORMAT: StackFormat;
76
77 /// The time the CPU takes to reset itself (RESET vector 0).
78 const VECTOR_RESET: usize;
79 /// Returns the time it takes to process the given exception vector.
80 fn vector_execution_time(vector: u8) -> usize;
81
82 /// Calculation time of the Address Register Indirect addressing mode in byte/word size.
83 const EA_ARI: usize;
84 /// Calculation time of the Address Register Indirect With POst increment addressing mode in byte/word size.
85 const EA_ARIWPO: usize;
86 /// Calculation time of the Address Register Indirect With PRe decrement addressing mode in byte/word size.
87 const EA_ARIWPR: usize;
88 /// Calculation time of the Address Register Indirect With Displacement addressing mode in byte/word size.
89 const EA_ARIWD: usize;
90 /// Calculation time of the Address Register Indirect With Index addressing mode in byte/word size.
91 const EA_ARIWI8: usize;
92 /// Calculation time of the Absolute Short addressing mode in byte/word size.
93 const EA_ABSSHORT: usize;
94 /// Calculation time of the Absolute Long addressing mode in byte/word size.
95 const EA_ABSLONG: usize;
96 /// Calculation time of the Program Counter Indirect With Displacement addressing mode in byte/word size.
97 const EA_PCIWD: usize;
98 /// Calculation time of the Program Counter Indirect With Index addressing mode in byte/word size.
99 const EA_PCIWI8: usize;
100 /// Calculation time of the Immediate addressing mode in byte/word size.
101 const EA_IMMEDIATE: usize;
102
103 const ABCD_REG: usize;
104 const ABCD_MEM: usize;
105
106 const ADD_REG_BW: usize;
107 const ADD_REG_L: usize;
108 const ADD_REG_L_RDIMM: usize;
109 const ADD_MEM_BW: usize;
110 const ADD_MEM_L: usize;
111
112 const ADDA_WORD: usize;
113 const ADDA_LONG: usize;
114 const ADDA_LONG_RDIMM: usize;
115
116 const ADDI_REG_BW: usize;
117 const ADDI_REG_L: usize;
118 const ADDI_MEM_BW: usize;
119 const ADDI_MEM_L: usize;
120
121 const ADDQ_REG_BW: usize;
122 const ADDQ_REG_L: usize;
123 const ADDQ_MEM_BW: usize;
124 const ADDQ_MEM_L: usize;
125
126 const ADDX_REG_BW: usize;
127 const ADDX_REG_L: usize;
128 const ADDX_MEM_BW: usize;
129 const ADDX_MEM_L: usize;
130
131 const AND_REG_BW: usize;
132 const AND_REG_L: usize;
133 const AND_REG_L_RDIMM: usize;
134 const AND_MEM_BW: usize;
135 const AND_MEM_L: usize;
136
137 const ANDI_REG_BW: usize;
138 const ANDI_REG_L: usize;
139 const ANDI_MEM_BW: usize;
140 const ANDI_MEM_L: usize;
141
142 const ANDICCR: usize;
143
144 const ANDISR: usize;
145
146 /// Arithemtic Shift instructions with the operand in memory.
147 const ASM: usize;
148
149 /// Arithemtic Shift instructions with the operand in a register.
150 const ASR_COUNT: usize;
151 /// Arithemtic Shift instructions with the operand in a register.
152 const ASR_BW: usize;
153 /// Arithemtic Shift instructions with the operand in a register.
154 const ASR_L: usize;
155
156 const BCC_BRANCH: usize;
157 const BCC_NO_BRANCH_BYTE: usize;
158 const BCC_NO_BRANCH_WORD: usize;
159
160 const BCHG_DYN_REG: usize;
161 const BCHG_DYN_MEM: usize;
162 const BCHG_STA_REG: usize;
163 const BCHG_STA_MEM: usize;
164
165 const BCLR_DYN_REG: usize;
166 const BCLR_DYN_MEM: usize;
167 const BCLR_STA_REG: usize;
168 const BCLR_STA_MEM: usize;
169
170 const BRA_BYTE: usize;
171 const BRA_WORD: usize;
172
173 const BSET_DYN_REG: usize;
174 const BSET_DYN_MEM: usize;
175 const BSET_STA_REG: usize;
176 const BSET_STA_MEM: usize;
177
178 const BSR_BYTE: usize;
179 const BSR_WORD: usize;
180
181 const BTST_DYN_REG: usize;
182 const BTST_DYN_MEM: usize;
183 const BTST_STA_REG: usize;
184 const BTST_STA_MEM: usize;
185
186 const CHK_NO_TRAP: usize;
187
188 const CLR_REG_BW: usize;
189 const CLR_REG_L: usize;
190 const CLR_MEM_BW: usize; // Subtract one read cycle from effective address calculation.
191 const CLR_MEM_L: usize; // Subtract two read cycles from effective address calculation.
192
193 const CMP_BW: usize;
194 const CMP_L: usize;
195
196 const CMPA: usize;
197
198 const CMPI_REG_BW: usize;
199 const CMPI_REG_L: usize;
200 const CMPI_MEM_BW: usize;
201 const CMPI_MEM_L: usize;
202
203 const CMPM_BW: usize;
204 const CMPM_L: usize;
205
206 const DBCC_TRUE: usize;
207 const DBCC_FALSE_BRANCH: usize;
208 const DBCC_FALSE_NO_BRANCH: usize;
209
210 const DIVS: usize;
211
212 const DIVU: usize;
213
214 const EOR_REG_BW: usize;
215 const EOR_REG_L: usize;
216 const EOR_MEM_BW: usize;
217 const EOR_MEM_L: usize;
218
219 const EORI_REG_BW: usize;
220 const EORI_REG_L: usize;
221 const EORI_MEM_BW: usize;
222 const EORI_MEM_L: usize;
223
224 const EORICCR: usize;
225
226 const EORISR: usize;
227
228 const EXG: usize;
229
230 const EXT: usize;
231
232 const JMP_ARI: usize;
233 const JMP_ARIWD: usize;
234 const JMP_ARIWI8: usize;
235 const JMP_ABSSHORT: usize;
236 const JMP_ABSLONG: usize;
237 const JMP_PCIWD: usize;
238 const JMP_PCIWI8: usize;
239
240 const JSR_ARI: usize;
241 const JSR_ARIWD: usize;
242 const JSR_ARIWI8: usize;
243 const JSR_ABSSHORT: usize;
244 const JSR_ABSLONG: usize;
245 const JSR_PCIWD: usize;
246 const JSR_PCIWI8: usize;
247
248 const LEA_ARI: usize;
249 const LEA_ARIWD: usize;
250 const LEA_ARIWI8: usize;
251 const LEA_ABSSHORT: usize;
252 const LEA_ABSLONG: usize;
253 const LEA_PCIWD: usize;
254 const LEA_PCIWI8: usize;
255
256 const LINK: usize;
257
258 /// Logical Shift instructions with the operand in memory.
259 const LSM: usize;
260
261 /// Logical Shift instructions with the operand in a register.
262 const LSR_COUNT: usize;
263 /// Logical Shift instructions with the operand in a register.
264 const LSR_BW: usize;
265 /// Logical Shift instructions with the operand in a register.
266 const LSR_L: usize;
267
268 /// Base execution time when the destination operand is accessed with the [ARIWPR](crate::addressing_modes::AddressingMode::Ariwpr) addressing mode.
269 const MOVE_DST_ARIWPR: usize;
270 /// Base execution time for all other cases.
271 const MOVE_OTHER: usize;
272
273 const MOVEA: usize;
274
275 const MOVECCR: usize;
276
277 /// MOVE From Status Register instruction.
278 const MOVEFSR_REG: usize;
279 /// MOVE From Status Register instruction.
280 const MOVEFSR_MEM: usize;
281
282 /// MOVE to Status Register instruction.
283 const MOVESR: usize;
284
285 const MOVEUSP: usize;
286
287 const MOVEM_WORD: usize;
288 const MOVEM_LONG: usize;
289 const MOVEM_MTR: usize;
290 const MOVEM_ARI: usize; // R -> M, do +3 for M -> R.
291 const MOVEM_ARIWPO: usize;
292 const MOVEM_ARIWPR: usize;
293 const MOVEM_ARIWD: usize;
294 const MOVEM_ARIWI8: usize;
295 const MOVEM_ABSSHORT: usize;
296 const MOVEM_ABSLONG: usize;
297 const MOVEM_PCIWD: usize;
298 const MOVEM_PCIWI8: usize;
299
300 /// Register to Memory with word size.
301 const MOVEP_RTM_WORD: usize;
302 /// Register to Memory with long size.
303 const MOVEP_RTM_LONG: usize;
304 /// Memory to Register with word size.
305 const MOVEP_MTR_WORD: usize;
306 /// Memory to Register with long size.
307 const MOVEP_MTR_LONG: usize;
308
309 const MOVEQ: usize;
310
311 const MULS: usize;
312
313 const MULU: usize;
314
315 const NBCD_REG: usize;
316 const NBCD_MEM: usize;
317
318 const NEG_REG_BW: usize;
319 const NEG_REG_L: usize;
320 const NEG_MEM_BW: usize;
321 const NEG_MEM_L: usize;
322
323 const NEGX_REG_BW: usize;
324 const NEGX_REG_L: usize;
325 const NEGX_MEM_BW: usize;
326 const NEGX_MEM_L: usize;
327
328 const NOP: usize;
329
330 const NOT_REG_BW: usize;
331 const NOT_REG_L: usize;
332 const NOT_MEM_BW: usize;
333 const NOT_MEM_L: usize;
334
335 const OR_REG_BW: usize;
336 const OR_REG_L: usize;
337 const OR_REG_L_RDIMM: usize;
338 const OR_MEM_BW: usize;
339 const OR_MEM_L: usize;
340
341 const ORI_REG_BW: usize;
342 const ORI_REG_L: usize;
343 const ORI_MEM_BW: usize;
344 const ORI_MEM_L: usize;
345
346 const ORICCR: usize;
347
348 const ORISR: usize;
349
350 const PEA_ARI: usize;
351 const PEA_ARIWD: usize;
352 const PEA_ARIWI8: usize;
353 const PEA_ABSSHORT: usize;
354 const PEA_ABSLONG: usize;
355 const PEA_PCIWD: usize;
356 const PEA_PCIWI8: usize;
357
358 const RESET: usize;
359
360 /// Rotate instructions with the operand in memory.
361 const ROM: usize;
362
363 /// Rotate instructions with the operand in a register.
364 const ROR_COUNT: usize;
365 /// Rotate instructions with the operand in a register.
366 const ROR_BW: usize;
367 /// Rotate instructions with the operand in a register.
368 const ROR_L: usize;
369
370 /// Rotate with Extend instructions with the operand in memory.
371 const ROXM: usize;
372
373 /// Rotate with Extend instructions with the operand in a register.
374 const ROXR_COUNT: usize;
375 /// Rotate with Extend instructions with the operand in a register.
376 const ROXR_BW: usize;
377 /// Rotate with Extend instructions with the operand in a register.
378 const ROXR_L: usize;
379
380 const RTE: usize;
381
382 const RTR: usize;
383
384 const RTS: usize;
385
386 const SBCD_REG: usize;
387 const SBCD_MEM: usize;
388
389 /// Scc with the destination in a register and the condition is false.
390 const SCC_REG_FALSE: usize;
391 /// Scc with the destination in a register and the condition is true.
392 const SCC_REG_TRUE: usize;
393 /// Scc with the destination in memory and the condition is false.
394 const SCC_MEM_FALSE: usize;
395 /// Scc with the destination in memory and the condition is true.
396 const SCC_MEM_TRUE: usize;
397
398 const STOP: usize;
399
400 const SUB_REG_BW: usize;
401 const SUB_REG_L: usize;
402 const SUB_REG_L_RDIMM: usize;
403 const SUB_MEM_BW: usize;
404 const SUB_MEM_L: usize;
405
406 const SUBA_WORD: usize;
407 const SUBA_LONG: usize;
408 const SUBA_LONG_RDIMM: usize;
409
410 const SUBI_REG_BW: usize;
411 const SUBI_REG_L: usize;
412 const SUBI_MEM_BW: usize;
413 const SUBI_MEM_L: usize;
414
415 const SUBQ_DREG_BW: usize;
416 const SUBQ_AREG_BW: usize;
417 const SUBQ_REG_L: usize;
418 const SUBQ_MEM_BW: usize;
419 const SUBQ_MEM_L: usize;
420
421 const SUBX_REG_BW: usize;
422 const SUBX_REG_L: usize;
423 const SUBX_MEM_BW: usize;
424 const SUBX_MEM_L: usize;
425
426 const SWAP: usize;
427
428 const TAS_REG: usize;
429 const TAS_MEM: usize; // Subtract one read cycle from effective address calculation.
430
431 /// TRAPV instruction when the trap is not taken.
432 const TRAPV_NO_TRAP: usize;
433
434 const TST_REG_BW: usize;
435 const TST_REG_L: usize;
436 const TST_MEM_BW: usize;
437 const TST_MEM_L: usize;
438
439 const UNLK: usize;
440}