+45
-20
src/main.rs
+45
-20
src/main.rs
···
21
.run();
22
}
23
24
#[derive(Default)]
25
pub struct Um<'a> {
26
program_counter: Platter,
···
275
/// Loads the value from the specified register.
276
fn load_register(&self, index: Parameter) -> Platter {
277
assert!(index < 8, "register index out of bounds");
278
-
self.registers[index as usize]
279
}
280
281
/// Saves a value to the specified register.
282
fn save_register(&mut self, index: Parameter, value: Platter) {
283
assert!(index < 8, "register index out of bounds");
284
-
self.registers[index as usize] = value;
285
}
286
287
fn load_memory(&self, block: Platter, offset: Platter) -> Platter {
288
-
assert!(
289
-
(block as usize) < self.memory.len()
290
-
&& (offset as usize) < self.memory[block as usize].len()
291
-
);
292
-
self.memory[block as usize][offset as usize]
293
}
294
295
fn store_memory(&mut self, block: Platter, offset: Platter, value: Platter) {
296
-
assert!(
297
-
(block as usize) < self.memory.len()
298
-
&& (offset as usize) < self.memory[block as usize].len()
299
-
);
300
-
self.memory[block as usize][offset as usize] = value;
301
}
302
303
fn duplicate_memory(&mut self, block: Platter) -> &[Platter] {
304
-
assert!((block as usize) < self.memory.len());
305
-
self.memory[0] = self.memory[block as usize].clone();
306
&self.memory[0]
307
}
308
309
#[cfg(not(feature = "reclaim-memory"))]
310
fn allocate_memory(&mut self, length: Platter) -> Platter {
311
-
self.memory.push(Self::new_block(length as usize));
312
(self.memory.len() - 1) as Platter
313
}
314
315
#[cfg(feature = "reclaim-memory")]
316
fn allocate_memory(&mut self, length: Platter) -> Platter {
317
if let Some(index) = self.free_blocks.pop() {
318
-
self.memory[index as usize] = Self::new_block(length as usize);
319
index as Platter
320
} else {
321
-
self.memory.push(Self::new_block(length as usize));
322
(self.memory.len() - 1) as Platter
323
}
324
}
325
326
fn free_memory(&mut self, block: Platter) {
327
-
assert!((block as usize) < self.memory.len());
328
#[cfg(feature = "reclaim-memory")]
329
{
330
self.free_blocks.push(block);
331
-
self.memory[block as usize] = Self::new_block(0);
332
}
333
}
334
···
337
fn panic(&self) -> ! {
338
panic!(
339
"universal machine failure: instruction: {:08x}, program_counter: {:08x}, registers: {:08x?}",
340
-
self.memory[0][self.program_counter as usize], self.program_counter, self.registers
341
)
342
}
343
···
21
.run();
22
}
23
24
+
/// Lossless conversion to `usize`.
25
+
///
26
+
/// This should only be implemented on types which can be losslessly
27
+
/// cast to a `usize`.
28
+
trait IntoIndex: Sized + Copy {
29
+
fn into_index(self) -> usize;
30
+
}
31
+
32
+
macro_rules! impl_into_index {
33
+
($t:ty) => {
34
+
impl IntoIndex for $t {
35
+
fn into_index(self) -> usize {
36
+
self as usize
37
+
}
38
+
}
39
+
};
40
+
}
41
+
42
+
#[cfg(target_pointer_width = "16")]
43
+
compile_error!("16 bit architectures are unsupported");
44
+
45
+
// usize *may* be 16 bits, so only implement if it is 32 or 64 bits.
46
+
#[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
47
+
impl_into_index!(Platter);
48
+
impl_into_index!(Parameter);
49
+
50
#[derive(Default)]
51
pub struct Um<'a> {
52
program_counter: Platter,
···
301
/// Loads the value from the specified register.
302
fn load_register(&self, index: Parameter) -> Platter {
303
assert!(index < 8, "register index out of bounds");
304
+
self.registers[index.into_index()]
305
}
306
307
/// Saves a value to the specified register.
308
fn save_register(&mut self, index: Parameter, value: Platter) {
309
assert!(index < 8, "register index out of bounds");
310
+
self.registers[index.into_index()] = value;
311
}
312
313
fn load_memory(&self, block: Platter, offset: Platter) -> Platter {
314
+
let block = block.into_index();
315
+
let offset = offset.into_index();
316
+
assert!(block < self.memory.len() && offset < self.memory[block].len());
317
+
self.memory[block][offset]
318
}
319
320
fn store_memory(&mut self, block: Platter, offset: Platter, value: Platter) {
321
+
let block = block.into_index();
322
+
let offset = offset.into_index();
323
+
assert!(block < self.memory.len() && offset < self.memory[block].len());
324
+
self.memory[block][offset] = value
325
}
326
327
fn duplicate_memory(&mut self, block: Platter) -> &[Platter] {
328
+
let block = block.into_index();
329
+
assert!(block < self.memory.len());
330
+
self.memory[0] = self.memory[block].clone();
331
&self.memory[0]
332
}
333
334
#[cfg(not(feature = "reclaim-memory"))]
335
fn allocate_memory(&mut self, length: Platter) -> Platter {
336
+
self.memory.push(Self::new_block(length.into_index()));
337
(self.memory.len() - 1) as Platter
338
}
339
340
#[cfg(feature = "reclaim-memory")]
341
fn allocate_memory(&mut self, length: Platter) -> Platter {
342
if let Some(index) = self.free_blocks.pop() {
343
+
self.memory[index.into_index()] = Self::new_block(length.into_index());
344
index as Platter
345
} else {
346
+
self.memory.push(Self::new_block(length.into_index()));
347
(self.memory.len() - 1) as Platter
348
}
349
}
350
351
fn free_memory(&mut self, block: Platter) {
352
+
assert!(block.into_index() < self.memory.len());
353
#[cfg(feature = "reclaim-memory")]
354
{
355
self.free_blocks.push(block);
356
+
self.memory[block.into_index()] = Self::new_block(0);
357
}
358
}
359
···
362
fn panic(&self) -> ! {
363
panic!(
364
"universal machine failure: instruction: {:08x}, program_counter: {:08x}, registers: {:08x?}",
365
+
self.memory[0][self.program_counter.into_index()], self.program_counter, self.registers
366
)
367
}
368