Refactor of Mnemonic lookup, DUART bug fix

This commit is contained in:
Seth Morabito 2018-12-29 11:09:13 -08:00
parent 91c8817585
commit 78472a9ec6
5 changed files with 360 additions and 208 deletions

View File

@ -1,7 +1,7 @@
[package]
name = "dmd_core"
description = "AT&T / Teletype DMD 5620 Terminal Emulator - Core Library"
version = "0.5.0"
version = "0.6.0"
authors = ["Seth Morabito <web@loomcom.com>"]
homepage = "https://github.com/sethm/dmd_core"
repository = "https://github.com/sethm/dmd_core"
@ -14,6 +14,9 @@ categories = ["simulation"]
lazy_static = "^1.2.0"
libc = "^0.2.45"
[profile.release]
debug = true
[lib]
crate-type = ["staticlib", "rlib"]

View File

@ -27,6 +27,13 @@ however.
## Changelog
0.6.0: Breaking change. Refactor DMD a bit to rename the function
`read` to `read_word`, and added a `read_byte` function
as well. Also refactored the CPU mnemonic lookup to be
more efficient using a lookup table instead of a HashMap.
Lastly, fixed a bug in the DUART that set the wrong
delay for one baud rate.
0.5.0: Non-breaking but major change. `dmd_core` now presents a
C compatible API to make interacting with C and C++ code
easier, without needed to write a full stub library.
@ -44,7 +51,12 @@ however.
0.2.1: Initial release.
## Emulator Reference Implementation
## Emulator Reference Implementations
For a reference implementation emulator that uses this library,
please see the ["DMD" project on GitHub](https://github.com/sethm/dmd).
Two implementations of DMD 5620 emulator use this core library.
* The Linux native GTK application `dmd5620`: [https://github.com/sethm/dmd_gtk](https://github.com/sethm/dmd_gtk)
* The Macintosh native Cocoa application `DMD 5620`: [https://github.com/sethm/dmd_mac](https://github.com/sethm/dmd_mac)
A Windows native application is in the works.

View File

@ -3,7 +3,6 @@
use crate::bus::{AccessCode, Bus};
use crate::err::*;
use crate::instr::*;
use std::collections::HashMap;
///
/// PSW Flags and Offsets
@ -51,6 +50,7 @@ const IPL_TABLE: [u32; 64] = [
];
const WE32100_VERSION: u32 = 0x1a;
const HALFWORD_MNEMONIC_COUNT: usize = 11;
pub enum ExceptionType {
ExternalMemory
@ -84,6 +84,7 @@ pub enum OpType {
Lit,
Src,
Dest,
None,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
@ -162,7 +163,7 @@ struct Mnemonic {
opcode: u16,
dtype: Data,
name: &'static str,
ops: Vec<OpType>,
ops: [OpType; 4],
}
#[derive(Debug, Eq, PartialEq)]
@ -204,194 +205,281 @@ fn add_offset(val: u32, offset: u32) -> u32 {
((val as i32).wrapping_add(offset as i32)) as u32
}
lazy_static! {
static ref MNEMONICS: HashMap<u16, Mnemonic> = {
let mut m = HashMap::new();
static BYTE_MNEMONICS: [Option<Mnemonic>; 256] = [
Some(mn!(0x00, Data::None, "halt", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x02, Data::Word, "SPOPRD", [OpType::Lit, OpType::Src, OpType::None, OpType::None])),
Some(mn!(0x03, Data::Word, "SPOPRD2", [OpType::Lit, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0x04, Data::Word, "MOVAW", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0x06, Data::Word, "SPOPRT", [OpType::Lit, OpType::Src, OpType::None, OpType::None])),
Some(mn!(0x07, Data::Word, "SPOPT2", [OpType::Lit, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0x08, Data::None, "RET", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
None,
None,
Some(mn!(0x0C, Data::Word, "MOVTRW", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
None,
None,
Some(mn!(0x10, Data::Word, "SAVE", [OpType::Src, OpType::None, OpType::None, OpType::None])),
None,
None,
Some(mn!(0x13, Data::Word, "SPOPWD", [OpType::Lit, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x14, Data::Byte, "EXTOP", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
None,
Some(mn!(0x17, Data::Word, "SPOPWT", [OpType::Lit, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x18, Data::None, "RESTORE", [OpType::Src, OpType::None, OpType::None, OpType::None])),
None,
None,
None,
Some(mn!(0x1C, Data::Word, "SWAPWI", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x1E, Data::Half, "SWAPHI", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x1F, Data::Byte, "SWAPBI", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x20, Data::Word, "POPW", [OpType::Src, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x22, Data::Word, "SPOPRS", [OpType::Lit, OpType::Src, OpType::None, OpType::None])),
Some(mn!(0x23, Data::Word, "SPOPS2", [OpType::Lit, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0x24, Data::Word, "JMP", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
None,
None,
Some(mn!(0x27, Data::None, "CFLUSH", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x28, Data::Word, "TSTW", [OpType::Src, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x2A, Data::Half, "TSTH", [OpType::Src, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x2B, Data::Byte, "TSTB", [OpType::Src, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x2C, Data::Word, "CALL", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0x2E, Data::None, "BPT", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x2F, Data::None, "WAIT", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
None,
Some(mn!(0x32, Data::Word, "SPOP", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x33, Data::Word, "SPOPWS", [OpType::Lit, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x34, Data::Word, "JSB", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x36, Data::Half, "BSBH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x37, Data::Byte, "BSBB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x38, Data::Word, "BITW", [OpType::Src, OpType::Src, OpType::None, OpType::None])),
None,
Some(mn!(0x3A, Data::Half, "BITH", [OpType::Src, OpType::Src, OpType::None, OpType::None])),
Some(mn!(0x3B, Data::Byte, "BITB", [OpType::Src, OpType::Src, OpType::None, OpType::None])),
Some(mn!(0x3C, Data::Word, "CMPW", [OpType::Src, OpType::Src, OpType::None, OpType::None])),
None,
Some(mn!(0x3E, Data::Half, "CMPH", [OpType::Src, OpType::Src, OpType::None, OpType::None])),
Some(mn!(0x3F, Data::Byte, "CMPB", [OpType::Src, OpType::Src, OpType::None, OpType::None])),
Some(mn!(0x40, Data::None, "RGEQ", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x42, Data::Half, "BGEH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x43, Data::Byte, "BGEB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x44, Data::None, "RGTR", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x46, Data::Half, "BGH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x47, Data::Byte, "BGB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x48, Data::None, "RLSS", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x4A, Data::Half, "BLH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x4B, Data::Byte, "BLB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x4C, Data::None, "RLEQ", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x4E, Data::Half, "BLEH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x4F, Data::Byte, "BLEB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x50, Data::None, "RGEQU", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x52, Data::Half, "BGEUH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x53, Data::Byte, "BGEUB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x54, Data::None, "RGTRU", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x56, Data::Half, "BGUH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x57, Data::Byte, "BGUB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x58, Data::None, "RLSSU", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x5A, Data::Half, "BLUH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x5B, Data::Byte, "BLUB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x5C, Data::None, "RLEQU", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x5E, Data::Half, "BLEUH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x5F, Data::Byte, "BLEUB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x60, Data::None, "RVC", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x62, Data::Half, "BVCH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x63, Data::Byte, "BVCB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x64, Data::None, "RNEQU", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x66, Data::Half, "BNEH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x67, Data::Byte, "BNEB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x68, Data::None, "RVS", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x6A, Data::Half, "BVSH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x6B, Data::Byte, "BVSB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x6C, Data::None, "REQLU", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x6E, Data::Half, "BEH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x6F, Data::Byte, "BEB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x70, Data::None, "NOP", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x72, Data::None, "NOP3", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x73, Data::None, "NOP2", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x74, Data::None, "RNEQ", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x76, Data::Half, "BNEH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x77, Data::Byte, "BNEB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x78, Data::None, "RSB", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x7A, Data::Half, "BRH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x7B, Data::Byte, "BRB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x7C, Data::None, "REQL", [OpType::None, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x7E, Data::Half, "BEH", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x7F, Data::Byte, "BEB", [OpType::Lit, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x80, Data::Word, "CLRW", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x82, Data::Half, "CLRH", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x83, Data::Byte, "CLRB", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x84, Data::Word, "MOVW", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0x86, Data::Half, "MOVH", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x87, Data::Byte, "MOVB", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x88, Data::Word, "MCOMW", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0x8A, Data::Half, "MCOMH", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x8B, Data::Byte, "MCOMB", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x8C, Data::Word, "MNEGW", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0x8E, Data::Half, "MNEGH", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x8F, Data::Byte, "MNEGB", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x90, Data::Word, "INCW", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x92, Data::Half, "INCH", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x93, Data::Byte, "INCB", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x94, Data::Word, "DECW", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
None,
Some(mn!(0x96, Data::Half, "DECH", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x97, Data::Byte, "DECB", [OpType::Dest, OpType::None, OpType::None, OpType::None])),
None,
None,
None,
None,
Some(mn!(0x9C, Data::Word, "ADDW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0x9E, Data::Half, "ADDH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0x9F, Data::Byte, "ADDB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xA0, Data::Word, "PUSHW", [OpType::Src, OpType::None, OpType::None, OpType::None])),
None,
None,
None,
Some(mn!(0xA4, Data::Word, "MODW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0xA6, Data::Half, "MODH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xA7, Data::Byte, "MODB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xA8, Data::Word, "MULW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0xAA, Data::Half, "MULH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xAB, Data::Byte, "MULB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xAC, Data::Word, "DIVW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0xAE, Data::Half, "DIVH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xAF, Data::Byte, "DIVB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xB0, Data::Word, "ORW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0xB2, Data::Half, "ORH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xB3, Data::Byte, "ORB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xB4, Data::Word, "XORW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0xB6, Data::Half, "XORH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xB7, Data::Byte, "XORB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xB8, Data::Word, "ANDW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0xBA, Data::Half, "ANDH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xBB, Data::Byte, "ANDB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xBC, Data::Word, "SUBW2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
None,
Some(mn!(0xBE, Data::Half, "SUBH2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xBF, Data::Byte, "SUBB2", [OpType::Src, OpType::Dest, OpType::None, OpType::None])),
Some(mn!(0xC0, Data::Word, "ALSW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
None,
None,
Some(mn!(0xC4, Data::Word, "ARSW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xC6, Data::Half, "ARSH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xC7, Data::Byte, "ARSB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xC8, Data::Word, "INSFW", [OpType::Src, OpType::Src, OpType::Src, OpType::Dest])),
None,
Some(mn!(0xCA, Data::Half, "INSFH", [OpType::Src, OpType::Src, OpType::Src, OpType::Dest])),
Some(mn!(0xCB, Data::Byte, "INSFB", [OpType::Src, OpType::Src, OpType::Src, OpType::Dest])),
Some(mn!(0xCC, Data::Word, "EXTFW", [OpType::Src, OpType::Src, OpType::Src, OpType::Dest])),
None,
Some(mn!(0xCE, Data::Half, "EXTFH", [OpType::Src, OpType::Src, OpType::Src, OpType::Dest])),
Some(mn!(0xCF, Data::Byte, "EXTFB", [OpType::Src, OpType::Src, OpType::Src, OpType::Dest])),
Some(mn!(0xD0, Data::Word, "LLSW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xD2, Data::Half, "LLSH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xD3, Data::Byte, "LLSB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xD4, Data::Word, "LRSW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
None,
None,
Some(mn!(0xD8, Data::Word, "ROTW", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
None,
None,
Some(mn!(0xDC, Data::Word, "ADDW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xDE, Data::Half, "ADDH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xDF, Data::Byte, "ADDB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xE0, Data::Word, "PUSHAW", [OpType::Src, OpType::None, OpType::None, OpType::None])),
None,
None,
None,
Some(mn!(0xE4, Data::Word, "MODW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xE6, Data::Half, "MODH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xE7, Data::Byte, "MODB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xE8, Data::Word, "MULW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xEA, Data::Half, "MULH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xEB, Data::Byte, "MULB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xEC, Data::Word, "DIVW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xEE, Data::Half, "DIVH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xEF, Data::Byte, "DIVB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xF0, Data::Word, "ORW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xF2, Data::Half, "ORH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xF3, Data::Byte, "ORB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xF4, Data::Word, "XORW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xF6, Data::Half, "XORH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xF7, Data::Byte, "XORB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xF8, Data::Word, "ANDW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xFA, Data::Half, "ANDH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xFB, Data::Byte, "ANDB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xFC, Data::Word, "SUBW3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
None,
Some(mn!(0xFE, Data::Half, "SUBH3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None])),
Some(mn!(0xFF, Data::Byte, "SUBB3", [OpType::Src, OpType::Src, OpType::Dest, OpType::None]))
];
m.insert(0x00, mn!(0x00, Data::None, "halt", vec!()));
m.insert(0x02, mn!(0x02, Data::Word, "SPOPRD", vec!(OpType::Lit, OpType::Src)));
m.insert(0x03, mn!(0x03, Data::Word, "SPOPRD2", vec!(OpType::Lit, OpType::Src, OpType::Dest)));
m.insert(0x04, mn!(0x04, Data::Word, "MOVAW", vec!(OpType::Src, OpType::Dest)));
m.insert(0x06, mn!(0x06, Data::Word, "SPOPRT", vec!(OpType::Lit, OpType::Src)));
m.insert(0x07, mn!(0x07, Data::Word, "SPOPT2", vec!(OpType::Lit, OpType::Src, OpType::Dest)));
m.insert(0x08, mn!(0x08, Data::None, "RET", vec!()));
m.insert(0x0C, mn!(0x0C, Data::Word, "MOVTRW", vec!(OpType::Src, OpType::Dest)));
m.insert(0x10, mn!(0x10, Data::Word, "SAVE", vec!(OpType::Src)));
m.insert(0x13, mn!(0x13, Data::Word, "SPOPWD", vec!(OpType::Lit, OpType::Dest)));
m.insert(0x14, mn!(0x14, Data::Byte, "EXTOP", vec!()));
m.insert(0x17, mn!(0x17, Data::Word, "SPOPWT", vec!(OpType::Lit, OpType::Dest)));
m.insert(0x18, mn!(0x18, Data::None, "RESTORE", vec!(OpType::Src)));
m.insert(0x1C, mn!(0x1C, Data::Word, "SWAPWI", vec!(OpType::Dest)));
m.insert(0x1E, mn!(0x1E, Data::Half, "SWAPHI", vec!(OpType::Dest)));
m.insert(0x1F, mn!(0x1F, Data::Byte, "SWAPBI", vec!(OpType::Dest)));
m.insert(0x20, mn!(0x20, Data::Word, "POPW", vec!(OpType::Src)));
m.insert(0x22, mn!(0x22, Data::Word, "SPOPRS", vec!(OpType::Lit, OpType::Src)));
m.insert(0x23, mn!(0x23, Data::Word, "SPOPS2", vec!(OpType::Lit, OpType::Src, OpType::Dest)));
m.insert(0x24, mn!(0x24, Data::Word, "JMP", vec!(OpType::Dest)));
m.insert(0x27, mn!(0x27, Data::None, "CFLUSH", vec!()));
m.insert(0x28, mn!(0x28, Data::Word, "TSTW", vec!(OpType::Src)));
m.insert(0x2A, mn!(0x2A, Data::Half, "TSTH", vec!(OpType::Src)));
m.insert(0x2B, mn!(0x2B, Data::Byte, "TSTB", vec!(OpType::Src)));
m.insert(0x2C, mn!(0x2C, Data::Word, "CALL", vec!(OpType::Src, OpType::Dest)));
m.insert(0x2E, mn!(0x2E, Data::None, "BPT", vec!()));
m.insert(0x2F, mn!(0x2F, Data::None, "WAIT", vec!()));
m.insert(0x32, mn!(0x32, Data::Word, "SPOP", vec!(OpType::Lit)));
m.insert(0x33, mn!(0x33, Data::Word, "SPOPWS", vec!(OpType::Lit, OpType::Dest)));
m.insert(0x34, mn!(0x34, Data::Word, "JSB", vec!(OpType::Dest)));
m.insert(0x36, mn!(0x36, Data::Half, "BSBH", vec!(OpType::Lit)));
m.insert(0x37, mn!(0x37, Data::Byte, "BSBB", vec!(OpType::Lit)));
m.insert(0x38, mn!(0x38, Data::Word, "BITW", vec!(OpType::Src, OpType::Src)));
m.insert(0x3A, mn!(0x3A, Data::Half, "BITH", vec!(OpType::Src, OpType::Src)));
m.insert(0x3B, mn!(0x3B, Data::Byte, "BITB", vec!(OpType::Src, OpType::Src)));
m.insert(0x3C, mn!(0x3C, Data::Word, "CMPW", vec!(OpType::Src, OpType::Src)));
m.insert(0x3E, mn!(0x3E, Data::Half, "CMPH", vec!(OpType::Src, OpType::Src)));
m.insert(0x3F, mn!(0x3F, Data::Byte, "CMPB", vec!(OpType::Src, OpType::Src)));
m.insert(0x40, mn!(0x40, Data::None, "RGEQ", vec!()));
m.insert(0x42, mn!(0x42, Data::Half, "BGEH", vec!(OpType::Lit)));
m.insert(0x43, mn!(0x43, Data::Byte, "BGEB", vec!(OpType::Lit)));
m.insert(0x44, mn!(0x44, Data::None, "RGTR", vec!()));
m.insert(0x46, mn!(0x46, Data::Half, "BGH", vec!(OpType::Lit)));
m.insert(0x47, mn!(0x47, Data::Byte, "BGB", vec!(OpType::Lit)));
m.insert(0x48, mn!(0x48, Data::None, "RLSS", vec!()));
m.insert(0x4A, mn!(0x4A, Data::Half, "BLH", vec!(OpType::Lit)));
m.insert(0x4B, mn!(0x4B, Data::Byte, "BLB", vec!(OpType::Lit)));
m.insert(0x4C, mn!(0x4C, Data::None, "RLEQ", vec!()));
m.insert(0x4E, mn!(0x4E, Data::Half, "BLEH", vec!(OpType::Lit)));
m.insert(0x4F, mn!(0x4F, Data::Byte, "BLEB", vec!(OpType::Lit)));
m.insert(0x50, mn!(0x50, Data::None, "RGEQU", vec!()));
m.insert(0x52, mn!(0x52, Data::Half, "BGEUH", vec!(OpType::Lit)));
m.insert(0x53, mn!(0x53, Data::Byte, "BGEUB", vec!(OpType::Lit)));
m.insert(0x54, mn!(0x54, Data::None, "RGTRU", vec!()));
m.insert(0x56, mn!(0x56, Data::Half, "BGUH", vec!(OpType::Lit)));
m.insert(0x57, mn!(0x57, Data::Byte, "BGUB", vec!(OpType::Lit)));
m.insert(0x58, mn!(0x58, Data::None, "RLSSU", vec!()));
m.insert(0x5A, mn!(0x5A, Data::Half, "BLUH", vec!(OpType::Lit)));
m.insert(0x5B, mn!(0x5B, Data::Byte, "BLUB", vec!(OpType::Lit)));
m.insert(0x5C, mn!(0x5C, Data::None, "RLEQU", vec!()));
m.insert(0x5E, mn!(0x5E, Data::Half, "BLEUH", vec!(OpType::Lit)));
m.insert(0x5F, mn!(0x5F, Data::Byte, "BLEUB", vec!(OpType::Lit)));
m.insert(0x60, mn!(0x60, Data::None, "RVC", vec!()));
m.insert(0x62, mn!(0x62, Data::Half, "BVCH", vec!(OpType::Lit)));
m.insert(0x63, mn!(0x63, Data::Byte, "BVCB", vec!(OpType::Lit)));
m.insert(0x64, mn!(0x64, Data::None, "RNEQU", vec!()));
m.insert(0x66, mn!(0x66, Data::Half, "BNEH", vec!(OpType::Lit)));
m.insert(0x67, mn!(0x67, Data::Byte, "BNEB", vec!(OpType::Lit)));
m.insert(0x68, mn!(0x68, Data::None, "RVS", vec!()));
m.insert(0x6A, mn!(0x6A, Data::Half, "BVSH", vec!(OpType::Lit)));
m.insert(0x6B, mn!(0x6B, Data::Byte, "BVSB", vec!(OpType::Lit)));
m.insert(0x6C, mn!(0x6C, Data::None, "REQLU", vec!()));
m.insert(0x6E, mn!(0x6E, Data::Half, "BEH", vec!(OpType::Lit)));
m.insert(0x6F, mn!(0x6F, Data::Byte, "BEB", vec!(OpType::Lit)));
m.insert(0x70, mn!(0x70, Data::None, "NOP", vec!()));
m.insert(0x72, mn!(0x72, Data::None, "NOP3", vec!()));
m.insert(0x73, mn!(0x73, Data::None, "NOP2", vec!()));
m.insert(0x74, mn!(0x74, Data::None, "RNEQ", vec!()));
m.insert(0x76, mn!(0x76, Data::Half, "BNEH", vec!(OpType::Lit)));
m.insert(0x77, mn!(0x77, Data::Byte, "BNEB", vec!(OpType::Lit)));
m.insert(0x78, mn!(0x78, Data::None, "RSB", vec!()));
m.insert(0x7A, mn!(0x7A, Data::Half, "BRH", vec!(OpType::Lit)));
m.insert(0x7B, mn!(0x7B, Data::Byte, "BRB", vec!(OpType::Lit)));
m.insert(0x7C, mn!(0x7C, Data::None, "REQL", vec!()));
m.insert(0x7E, mn!(0x7E, Data::Half, "BEH", vec!(OpType::Lit)));
m.insert(0x7F, mn!(0x7F, Data::Byte, "BEB", vec!(OpType::Lit)));
m.insert(0x80, mn!(0x80, Data::Word, "CLRW", vec!(OpType::Dest)));
m.insert(0x82, mn!(0x82, Data::Half, "CLRH", vec!(OpType::Dest)));
m.insert(0x83, mn!(0x83, Data::Byte, "CLRB", vec!(OpType::Dest)));
m.insert(0x84, mn!(0x84, Data::Word, "MOVW", vec!(OpType::Src, OpType::Dest)));
m.insert(0x86, mn!(0x86, Data::Half, "MOVH", vec!(OpType::Src, OpType::Dest)));
m.insert(0x87, mn!(0x87, Data::Byte, "MOVB", vec!(OpType::Src, OpType::Dest)));
m.insert(0x88, mn!(0x88, Data::Word, "MCOMW", vec!(OpType::Src, OpType::Dest)));
m.insert(0x8A, mn!(0x8A, Data::Half, "MCOMH", vec!(OpType::Src, OpType::Dest)));
m.insert(0x8B, mn!(0x8B, Data::Byte, "MCOMB", vec!(OpType::Src, OpType::Dest)));
m.insert(0x8C, mn!(0x8C, Data::Word, "MNEGW", vec!(OpType::Src, OpType::Dest)));
m.insert(0x8E, mn!(0x8E, Data::Half, "MNEGH", vec!(OpType::Src, OpType::Dest)));
m.insert(0x8F, mn!(0x8F, Data::Byte, "MNEGB", vec!(OpType::Src, OpType::Dest)));
m.insert(0x90, mn!(0x90, Data::Word, "INCW", vec!(OpType::Dest)));
m.insert(0x92, mn!(0x92, Data::Half, "INCH", vec!(OpType::Dest)));
m.insert(0x93, mn!(0x93, Data::Byte, "INCB", vec!(OpType::Dest)));
m.insert(0x94, mn!(0x94, Data::Word, "DECW", vec!(OpType::Dest)));
m.insert(0x96, mn!(0x96, Data::Half, "DECH", vec!(OpType::Dest)));
m.insert(0x97, mn!(0x97, Data::Byte, "DECB", vec!(OpType::Dest)));
m.insert(0x9C, mn!(0x9C, Data::Word, "ADDW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0x9E, mn!(0x9E, Data::Half, "ADDH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0x9F, mn!(0x9F, Data::Byte, "ADDB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xA0, mn!(0xA0, Data::Word, "PUSHW", vec!(OpType::Src)));
m.insert(0xA4, mn!(0xA4, Data::Word, "MODW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xA6, mn!(0xA6, Data::Half, "MODH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xA7, mn!(0xA7, Data::Byte, "MODB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xA8, mn!(0xA8, Data::Word, "MULW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xAA, mn!(0xAA, Data::Half, "MULH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xAB, mn!(0xAB, Data::Byte, "MULB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xAC, mn!(0xAC, Data::Word, "DIVW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xAE, mn!(0xAE, Data::Half, "DIVH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xAF, mn!(0xAF, Data::Byte, "DIVB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xB0, mn!(0xB0, Data::Word, "ORW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xB2, mn!(0xB2, Data::Half, "ORH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xB3, mn!(0xB3, Data::Byte, "ORB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xB4, mn!(0xB4, Data::Word, "XORW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xB6, mn!(0xB6, Data::Half, "XORH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xB7, mn!(0xB7, Data::Byte, "XORB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xB8, mn!(0xB8, Data::Word, "ANDW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xBA, mn!(0xBA, Data::Half, "ANDH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xBB, mn!(0xBB, Data::Byte, "ANDB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xBC, mn!(0xBC, Data::Word, "SUBW2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xBE, mn!(0xBE, Data::Half, "SUBH2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xBF, mn!(0xBF, Data::Byte, "SUBB2", vec!(OpType::Src, OpType::Dest)));
m.insert(0xC0, mn!(0xC0, Data::Word, "ALSW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xC4, mn!(0xC4, Data::Word, "ARSW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xC6, mn!(0xC6, Data::Half, "ARSH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xC7, mn!(0xC7, Data::Byte, "ARSB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xC8, mn!(0xC8, Data::Word, "INSFW", vec!(OpType::Src, OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xCA, mn!(0xCA, Data::Half, "INSFH", vec!(OpType::Src, OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xCB, mn!(0xCB, Data::Byte, "INSFB", vec!(OpType::Src, OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xCC, mn!(0xCC, Data::Word, "EXTFW", vec!(OpType::Src, OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xCE, mn!(0xCE, Data::Half, "EXTFH", vec!(OpType::Src, OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xCF, mn!(0xCF, Data::Byte, "EXTFB", vec!(OpType::Src, OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xD0, mn!(0xD0, Data::Word, "LLSW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xD2, mn!(0xD2, Data::Half, "LLSH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xD3, mn!(0xD3, Data::Byte, "LLSB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xD4, mn!(0xD4, Data::Word, "LRSW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xD8, mn!(0xD8, Data::Word, "ROTW", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xDC, mn!(0xDC, Data::Word, "ADDW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xDE, mn!(0xDE, Data::Half, "ADDH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xDF, mn!(0xDF, Data::Byte, "ADDB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xE0, mn!(0xE0, Data::Word, "PUSHAW", vec!(OpType::Src)));
m.insert(0xE4, mn!(0xE4, Data::Word, "MODW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xE6, mn!(0xE6, Data::Half, "MODH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xE7, mn!(0xE7, Data::Byte, "MODB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xE8, mn!(0xE8, Data::Word, "MULW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xEA, mn!(0xEA, Data::Half, "MULH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xEB, mn!(0xEB, Data::Byte, "MULB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xEC, mn!(0xEC, Data::Word, "DIVW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xEE, mn!(0xEE, Data::Half, "DIVH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xEF, mn!(0xEF, Data::Byte, "DIVB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xF0, mn!(0xF0, Data::Word, "ORW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xF2, mn!(0xF2, Data::Half, "ORH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xF3, mn!(0xF3, Data::Byte, "ORB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xF4, mn!(0xF4, Data::Word, "XORW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xF6, mn!(0xF6, Data::Half, "XORH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xF7, mn!(0xF7, Data::Byte, "XORB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xF8, mn!(0xF8, Data::Word, "ANDW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xFA, mn!(0xFA, Data::Half, "ANDH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xFB, mn!(0xFB, Data::Byte, "ANDB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xFC, mn!(0xFC, Data::Word, "SUBW3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xFE, mn!(0xFE, Data::Half, "SUBH3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0xFF, mn!(0xFF, Data::Byte, "SUBB3", vec!(OpType::Src, OpType::Src, OpType::Dest)));
m.insert(0x3009, mn!(0x3009, Data::None, "MVERNO", vec!()));
m.insert(0x300d, mn!(0x300d, Data::None, "ENBVJMP", vec!()));
m.insert(0x3013, mn!(0x3013, Data::None, "DISVJMP", vec!()));
m.insert(0x3019, mn!(0x3019, Data::None, "MOVBLW", vec!()));
m.insert(0x301f, mn!(0x301f, Data::None, "STREND", vec!()));
m.insert(0x302f, mn!(0x302f, Data::None, "INTACK", vec!()));
m.insert(0x303f, mn!(0x303f, Data::None, "STRCPY", vec!()));
m.insert(0x3045, mn!(0x3045, Data::None, "RETG", vec!()));
m.insert(0x3061, mn!(0x3061, Data::None, "GATE", vec!()));
m.insert(0x30ac, mn!(0x30ac, Data::None, "CALLPS", vec!()));
m.insert(0x30c8, mn!(0x30c8, Data::None, "RETPS", vec!()));
m
};
}
static HALFWORD_MNEMONICS: [Option<Mnemonic>; HALFWORD_MNEMONIC_COUNT] = [
Some(mn!(0x3009, Data::None, "MVERNO", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x300d, Data::None, "ENBVJMP", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x3013, Data::None, "DISVJMP", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x3019, Data::None, "MOVBLW", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x301f, Data::None, "STREND", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x302f, Data::None, "INTACK", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x303f, Data::None, "STRCPY", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x3045, Data::None, "RETG", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x3061, Data::None, "GATE", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x30ac, Data::None, "CALLPS", [OpType::None, OpType::None, OpType::None, OpType::None])),
Some(mn!(0x30c8, Data::None, "RETPS", [OpType::None, OpType::None, OpType::None, OpType::None]))
];
static NULL_MNEMONIC: Option<Mnemonic> = None;
pub struct Cpu {
//
@ -1991,6 +2079,7 @@ impl Cpu {
match ot {
OpType::Lit => self.decode_literal_operand(bus, index, mn, addr),
OpType::Src | OpType::Dest => self.decode_descriptor_operand(bus, index, mn.dtype, etype, addr, false),
OpType::None => Ok(())
}
}
@ -2009,16 +2098,24 @@ impl Cpu {
// Map the Mnemonic to the opcode we just read. But there's a special
// case if the value we read was '0x30'. This indicates that the instruction
// we're reading is a halfword, requiring two bytes.
let index: u16 = if b1 == 0x30 {
// Special case for half-word opcodes
let mut mn: &Option<Mnemonic> = &NULL_MNEMONIC;
if b1 == 0x30 {
let b2 = bus.read_byte(addr, AccessCode::InstrFetch)?;
addr += 1;
(u16::from(b1) << 8) | u16::from(b2)
} else {
u16::from(b1)
};
let mn = MNEMONICS.get(&index);
let opcode = (u16::from(b1) << 8) | u16::from(b2);
for m in &HALFWORD_MNEMONICS {
if m.is_some() && m.as_ref().unwrap().opcode == opcode {
mn = m;
break;
}
}
} else {
mn = &BYTE_MNEMONICS[b1 as usize];
};
// If we found a valid mnemonic, read in and decode all of its operands.
// Otherwise, we must return a CpuException::IllegalOpcode
@ -2027,6 +2124,9 @@ impl Cpu {
let mut etype: Option<Data> = None;
for (index, ot) in mn.ops.iter().enumerate() {
if *ot == OpType::None {
break;
}
// Push a decoded operand
self.decode_operand(bus, index, mn, *ot, etype, addr)?;
etype = self.ir.operands[index].expanded_type;
@ -2041,7 +2141,7 @@ impl Cpu {
self.ir.bytes = total_bytes as u8;
self.ir.operand_count = mn.ops.len() as u8;
}
None => return Err(CpuError::Exception(CpuException::IllegalOpcode)),
None => return Err(CpuError::Exception(CpuException::IllegalOpcode))
}
Ok(())
@ -2264,7 +2364,7 @@ mod tests {
let program: [u8; 2] = [0x4f, 0x06]; // BLEB 0x6
do_with_program(&program, |cpu, mut bus| {
cpu.decode_literal_operand(&mut bus, 0, MNEMONICS.get(&0x4F).unwrap(), BASE + 1).unwrap();
cpu.decode_literal_operand(&mut bus, 0, BYTE_MNEMONICS[0x4F as usize].as_ref().unwrap(), BASE + 1).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(1, AddrMode::None, Data::Byte, None, None, 6));
})
}
@ -2274,7 +2374,7 @@ mod tests {
let program: [u8; 3] = [0x4e, 0xff, 0x0f]; // BLEH 0xfff
do_with_program(&program, |cpu, mut bus| {
cpu.decode_literal_operand(&mut bus, 0, MNEMONICS.get(&0x4e).unwrap(), BASE + 1).unwrap();
cpu.decode_literal_operand(&mut bus, 0, BYTE_MNEMONICS[0x4e as usize].as_ref().unwrap(), BASE + 1).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(2, AddrMode::None, Data::Half, None, None, 0xfff));
})
}
@ -2284,7 +2384,7 @@ mod tests {
let program: [u8; 5] = [0x32, 0xff, 0x4f, 0x00, 0x00]; // SPOP 0x4fff
do_with_program(&program, |cpu, mut bus| {
cpu.decode_literal_operand(&mut bus, 0, MNEMONICS.get(&0x32).unwrap(), BASE + 1).unwrap();
cpu.decode_literal_operand(&mut bus, 0, BYTE_MNEMONICS[0x32 as usize].as_ref().unwrap(), BASE + 1).unwrap();
assert_eq!(cpu.ir.operands[0], Operand::new(4, AddrMode::None, Data::Word, None, None, 0x4fff));
});
}

View File

@ -68,13 +68,20 @@ impl Dmd {
self.cpu.r[(reg & 0xf) as usize]
}
pub fn read(&mut self, addr: usize) -> Option<u32> {
pub fn read_word(&mut self, addr: usize) -> Option<u32> {
match self.bus.read_word(addr, AccessCode::AddressFetch) {
Ok(d) => Some(d),
_ => None,
}
}
pub fn read_byte(&mut self, addr: usize) -> Option<u8> {
match self.bus.read_byte(addr, AccessCode::AddressFetch) {
Ok(d) => Some(d),
_ => None,
}
}
pub fn step(&mut self) {
self.cpu.step(&mut self.bus);
}
@ -197,6 +204,38 @@ fn dmd_get_register(reg: uint8_t, val: &mut uint32_t) -> c_int {
}
}
#[no_mangle]
fn dmd_read_word(addr: uint32_t, val: &mut uint32_t) -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
match dmd.read_word(addr as usize) {
Some(word) => {
*val = word;
SUCCESS
},
None => ERROR
}
},
Err(_) => ERROR
}
}
#[no_mangle]
fn dmd_read_byte(addr: uint32_t, val: &mut uint8_t) -> c_int {
match DMD.lock() {
Ok(mut dmd) => {
match dmd.read_byte(addr as usize) {
Some(byte) => {
*val = byte;
SUCCESS
},
None => ERROR
}
},
Err(_) => ERROR
}
}
#[no_mangle]
fn dmd_get_duart_output_port(oport: &mut uint8_t) -> c_int {
match DMD.lock() {
@ -350,4 +389,4 @@ mod tests {
assert_eq!(0xa5, new_nvram[0xfff]);
assert_eq!(0xff, new_nvram[0x1fff]);
}
}
}

View File

@ -30,7 +30,7 @@ const DELAY_RATES_A: [u32;13] = [
const DELAY_RATES_B: [u32;13] = [
133_333_344, 90_909_096, 74_074_072, 66_666_672,
33_333_336, 16_666_668, 8_333_334, 5_000_000,
4_166_667, 205_338, 5_555_555, 1_041_666, 520_833,
4_166_667, 2_083_333, 5_555_555, 1_041_666, 52_083,
];
const PORT_0: usize = 0;
@ -199,8 +199,6 @@ impl Duart {
ctx.stat |= STS_RXR;
self.istat |= istat;
self.ivec |= ivec;
} else {
ctx.stat |= STS_OER;
}
}