Skip to content

Commit e78219d

Browse files
committed
Use Opcode::Opr for opcode 0o04 (IOS and AOP are variants).
1 parent d2ee0f5 commit e78219d

File tree

5 files changed

+95
-8
lines changed

5 files changed

+95
-8
lines changed

assembler/src/asmlib/driver/output.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ fn create_begin_block(
134134
// 027: ¹IOS₅₂ 20000 ** Disconnect PETR, load report word into E.
135135
held: false,
136136
configuration: u5!(1), // signals that PETR report word should be loaded into E
137-
opcode: Opcode::Ios,
137+
opcode: Opcode::Opr,
138138
index: u6!(0o52),
139139
operand_address: OperandAddress::direct(Address::from(u18!(0o020_000))),
140140
};

base/src/instruction.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ pub enum Opcode {
307307
/// IOS is the I/O select instruction and is described in the TX-2
308308
/// Users Handbook, section 4-3.5.
309309
///
310+
/// Bits 2.7 and 2.8 of the instruction work determine whether an
311+
/// OPR instruction is IOS or AOP (or invalid).
312+
///
310313
/// AOP is (apparently, documentation is a bit thin) the
311314
/// Arithmetic Operation instruction. This operates only on the
312315
/// Arithmetic unit (that is, it makes no memory reference).
@@ -316,7 +319,7 @@ pub enum Opcode {
316319
/// AOP, see physical PDF page number 45). Section 16-5.1 claims
317320
/// that AOP is described in detail in chapter 4 of the Technical
318321
/// Manual.
319-
Ios = 0o4,
322+
Opr = 0o4,
320323
Jmp = 0o5,
321324
Jpx = 0o6,
322325
Jnx = 0o7,
@@ -411,7 +414,7 @@ impl TryFrom<u8> for Opcode {
411414
Err(DisassemblyFailure::UnimplementedOpcode(opcode))
412415
}
413416
3 => Err(DisassemblyFailure::InvalidOpcode(opcode)),
414-
0o4 => Ok(Ios),
417+
0o4 => Ok(Opr),
415418
0o5 => Ok(Jmp),
416419
0o6 => Ok(Jpx),
417420
0o7 => Ok(Jnx),

base/src/instruction/format.rs

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// Human-oriented formatting for instructions (or parts of instructions).
22
use std::fmt::{self, Display, Formatter, Octal, Write};
33

4+
use super::super::bitselect::{BitPos, BitSelector, bit_select};
45
use super::super::charset::{
56
NoSubscriptKnown, NoSuperscriptKnown, subscript_char, superscript_char,
67
};
@@ -20,7 +21,7 @@ impl Display for Opcode {
2021
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
2122
use Opcode::*;
2223
f.write_str(match self {
23-
Ios => "IOS",
24+
Opr => "OPR",
2425
Jmp => "JMP",
2526
Jpx => "JPX",
2627
Jnx => "JNX",
@@ -121,12 +122,39 @@ fn octal_subscript_number(n: u8) -> String {
121122
subscript(&format!("{n:o}")).unwrap()
122123
}
123124

124-
fn write_opcode(op: Opcode, cfg: Unsigned5Bit, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
125+
fn write_opcode(
126+
op: Opcode,
127+
cfg: Unsigned5Bit,
128+
base_address_bits: Unsigned18Bit,
129+
f: &mut Formatter<'_>,
130+
) -> Result<(), fmt::Error> {
131+
let w = Unsigned36Bit::from(base_address_bits);
132+
let bit_2_8 = bit_select(
133+
w,
134+
BitSelector {
135+
quarter: Quarter::Q2,
136+
bitpos: BitPos::B8,
137+
},
138+
);
139+
let bit_2_7 = bit_select(
140+
w,
141+
BitSelector {
142+
quarter: Quarter::Q2,
143+
bitpos: BitPos::B8,
144+
},
145+
);
125146
// Where there is a supernumerary mnemonic, prefer it.
126147
// This list is taken from table 7-3 in the Users
127148
// Handbook.
128149
let cfg = u8::from(cfg);
129150
match op {
151+
Opcode::Opr => f.write_str(if bit_2_8 {
152+
"OPR"
153+
} else if bit_2_7 {
154+
"AOP"
155+
} else {
156+
"IOS"
157+
}),
130158
Opcode::Jmp => f.write_str(match cfg {
131159
0o00 => "JMP",
132160
0o01 => "BRC",
@@ -251,7 +279,8 @@ impl Display for SymbolicInstruction {
251279
let cf: u8 = self.configuration().into();
252280
f.write_str(&octal_superscript_u8(cf).unwrap())?;
253281
}
254-
write_opcode(self.opcode(), self.configuration(), f)?;
282+
let base_address = self.operand_address_and_defer_bit();
283+
write_opcode(self.opcode(), self.configuration(), base_address, f)?;
255284
let j = self.index_address();
256285
match self.opcode() {
257286
Opcode::Skm => {
@@ -426,4 +455,59 @@ mod tests {
426455
};
427456
assert_eq!(&sinst.to_string(), "h ³⁴RSX₇₁ 377762"); // the 'h' indicates `held`
428457
}
458+
459+
#[test]
460+
fn test_display_ios() {
461+
// This instruction appears in the listing for the "READER
462+
// LEADER" in section 5-5.2 of the Users Handbook.
463+
let sinst = SymbolicInstruction {
464+
operand_address: OperandAddress::direct(Address::from(u18!(0o020_000_u32))),
465+
index: Unsigned6Bit::try_from(0o52_u8).unwrap(),
466+
// Bits 2.7 and 2.8 in the base address field distinguish
467+
// the IOS and AOP variants of the OPR opcode. If they're
468+
// both zero, we're looking at IOS.
469+
//
470+
// This distinction and the bits used to make it are
471+
// described in section 7-11 ("MISCELLANEOUS OPERATION
472+
// CODES") of Volume 1 of the TX-2 Technical Manual.
473+
opcode: Opcode::Opr,
474+
configuration: config_value(0o1),
475+
held: false,
476+
};
477+
assert_eq!(&sinst.to_string(), "¹IOS₅₂ 20000");
478+
}
479+
480+
#[test]
481+
fn test_disassemble_ios() {
482+
// This instruction appears in the listing for the "READER
483+
// LEADER" in section 5-5.2 of the Users Handbook.
484+
let inst = Instruction::from(u36!(0o010_452_020_000));
485+
assert_eq!(
486+
SymbolicInstruction::try_from(&inst),
487+
Ok(SymbolicInstruction {
488+
operand_address: OperandAddress::direct(Address::from(u18!(0o020_000_u32))),
489+
index: Unsigned6Bit::try_from(0o52_u8).unwrap(),
490+
opcode: Opcode::Opr,
491+
configuration: config_value(0o1),
492+
held: false,
493+
})
494+
);
495+
}
496+
#[test]
497+
fn test_assemble_ios() {
498+
// This instruction appears in the listing for the "READER
499+
// LEADER" in section 5-5.2 of the Users Handbook, in both
500+
// symbolic and octal form.
501+
assert_eq!(
502+
Instruction::from(&SymbolicInstruction {
503+
operand_address: OperandAddress::direct(Address::from(u18!(0o020_000_u32))),
504+
index: Unsigned6Bit::try_from(0o52_u8).unwrap(),
505+
opcode: Opcode::Opr,
506+
configuration: config_value(0o1),
507+
held: false,
508+
})
509+
.bits(),
510+
u36!(0o010_452_020_000)
511+
);
512+
}
429513
}

cpu/src/control.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1189,7 +1189,7 @@ impl ControlUnit {
11891189
Opcode::Jnx => control.op_jnx(ctx, mem),
11901190
Opcode::Skm => control.op_skm(ctx, mem),
11911191
Opcode::Spg => control.op_spg(ctx, mem),
1192-
Opcode::Ios => control.op_opr(ctx, mem, devices),
1192+
Opcode::Opr => control.op_opr(ctx, mem, devices),
11931193
Opcode::Tsd => control.op_tsd(ctx, devices, prev_program_counter, mem),
11941194
Opcode::Sed => control.op_sed(ctx, mem),
11951195
Opcode::Exx => Err(Alarm {

cpu/src/control/timing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub(crate) fn estimate_instruction_ns(
5151
};
5252
if let Ok(opcode) = Opcode::try_from(op) {
5353
tenths += match opcode {
54-
Opcode::Ios => 72,
54+
Opcode::Opr => 72,
5555
Opcode::Jmp => 56,
5656
Opcode::Jpx => 76,
5757
Opcode::Jnx => 76,

0 commit comments

Comments
 (0)