11/// Human-oriented formatting for instructions (or parts of instructions).
22use std:: fmt:: { self , Display , Formatter , Octal , Write } ;
33
4+ use super :: super :: bitselect:: { BitPos , BitSelector , bit_select} ;
45use 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}
0 commit comments