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}