1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//! Motorola 68000 interpreter, disassembler and assembler (code emitter).
//!
//! This library emulates the common user and supervisor instructions of the M68k ISA.
//! It is configurable to behave like the given CPU type (see below), changing the instruction's execution times and exception handling.
//!
//! This library has been designed to be used in two different contexts:
//!
//! - It can be used to emulate a whole CPU, and the user of this library only have to call the interpreter methods
//! and [M68000::exception] when an interrupt or reset occurs. This is usually the case in an emulator.
//! - It can also be used as a M68k user-land interpreter to run an M68k program, but without the requirement of having an
//! operating system compiled to binary M68k. In this case, the application runs the program until an exception occurs (TRAP for
//! syscalls, zero divide, etc.) and treat the exception in Rust code (or any other language using the C interface), so the
//! application can implement the surrounding environment required by the M68k program in a high level language and not in M68k assembly.
//!
//! # Supported CPUs
//!
//! The CPU type is specified with a generic parameter on the main structure.
//! The trait [CpuDetails] contains all the details of the emulated CPU:
//! - Instruction execution times
//! - Exception processing times
//! - Exception stack format
//!
//! m68000 provides CPU details for the following CPUs:
//! * MC68000 (as described in the M68000 8-/16-/32-Bit Microprocessors User's Manual, Ninth Edition)
//! * SCC68070 microcontroller
//!
//! # How to use
//!
//! m68000 requires a nightly compiler as it uses the `btree_extract_if` and `bigint_helper_methods` features of the std.
//!
//! First, since the memory map is application-dependant, it is the user's responsibility to define it by implementing
//! the `MemoryAccess` trait on their memory structure, and passing it to the core on each instruction execution.
//!
//! Second, choose the CPU behavior by specifying the instance that implements the `CpuDetails` trait,
//! whether it is your own or one the provided ones.
//!
//! The file `src/bin/scc68070.rs` is a usage example that implements the SCC68070 microcontroller.
//!
//! ## Basic usage:
//!
//! ```ignore
//! const MEM_SIZE: u32 = 65536;
//! struct Memory([u8; MEM_SIZE as usize]); // Define your memory management system.
//!
//! impl MemoryAccess for Memory { // Implement the MemoryAccess trait.
//! fn get_byte(&mut self, addr: u32) -> Option<u8> {
//! if addr < MEM_SIZE {
//! Some(self.0[addr as usize])
//! } else {
//! None
//! }
//! }
//!
//! // And so on...
//! }
//!
//! fn main() {
//! let mut memory = Memory([0; MEM_SIZE as usize]);
//! // Load the program in memory here.
//! let mut cpu: M68000<m68000::cpu_details::Mc68000> = M68000::new();
//!
//! // Execute instructions
//! cpu.interpreter(&mut memory);
//! }
//! ```
//!
//! ## FFI and C interface
//!
//! By enabling the `ffi` feature, the following structs and enums are made `repr(C)`:
//! - [AddressingMode](addressing_modes::AddressingMode)
//! - [BriefExtensionWord](addressing_modes::BriefExtensionWord)
//! - [Direction](instruction::Direction)
//! - [Instruction](instruction::Instruction)
//! - [Operands](instruction::Operands)
//! - [Registers]
//! - [Size](instruction::Size)
//! - [StatusRegister]
//! - [Vector]
//!
//! The crate `m68000-ffi` in the repo is a collection of structures and functions that allows using m68000's
//! interpreter and disassembler in other languages through a C interface.
//!
//! See the `CINTERFACE.md` file in the repo for more information.
//!
//! ## Potential issues
//! - DIVS/DIVU may not always procuce the correct CCR flags when an overflow occured.
//! - DIVS/DIVU always execute using their maximum execution time.
//! - Long exception stack frame writes the current opcode and fills the other information with 0.
//!
//! ## TODO
//! - Let memory access return extra read or write cycles for accuracy.
use ;
pub use ;
pub use MemoryAccess;
use StatusRegister;
use BTreeSet;
use Wrapping;
/// M68000 registers.
/// A M68000 core.