disassembler: implement disassembler
The disassembler will be useful in tracking down build errors. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
		@@ -8,7 +8,8 @@ edition = "2018"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[features]
 | 
					[features]
 | 
				
			||||||
macro-debug = []
 | 
					macro-debug = []
 | 
				
			||||||
default = []
 | 
					std = []
 | 
				
			||||||
 | 
					default = ["std"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										217
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										217
									
								
								src/lib.rs
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
#![cfg_attr(feature="macro-debug",feature(trace_macros))]
 | 
					#![cfg_attr(feature = "macro-debug", feature(trace_macros))]
 | 
				
			||||||
#![cfg_attr(feature="macro-debug",feature(log_syntax))]
 | 
					#![cfg_attr(feature = "macro-debug", feature(log_syntax))]
 | 
				
			||||||
#[cfg(feature="macro-debug")]
 | 
					#[cfg(feature = "macro-debug")]
 | 
				
			||||||
trace_macros!{true}
 | 
					trace_macros! {true}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
   opcodes
 | 
					   opcodes
 | 
				
			||||||
@@ -27,6 +27,19 @@ trace_macros!{true}
 | 
				
			|||||||
   BRZ  0x2, r1      // if r1 is 0, mpc = mpc + 0x2
 | 
					   BRZ  0x2, r1      // if r1 is 0, mpc = mpc + 0x2
 | 
				
			||||||
 loop:
 | 
					 loop:
 | 
				
			||||||
   BRZ  loop, r2     // if r2 is 0, go to label "loop"
 | 
					   BRZ  loop, r2     // if r2 is 0, go to label "loop"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Basic opcode format:
 | 
				
			||||||
 | 
					        0b_rrrrrrrrr_ddddd_y_bbbbb_x_aaaaa_oooooo
 | 
				
			||||||
 | 
					    Where:
 | 
				
			||||||
 | 
					        o: Opcode
 | 
				
			||||||
 | 
					        a: Source register a
 | 
				
			||||||
 | 
					        x: `1` if A is a constant rather than register
 | 
				
			||||||
 | 
					        b: Source register b
 | 
				
			||||||
 | 
					        y: `1` if B is a constant rather than a register
 | 
				
			||||||
 | 
					        d: Destination register index
 | 
				
			||||||
 | 
					        r: Reserved (set to 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A compile-time map from identifiers to arbitrary (heterogeneous) expressions
 | 
					/// A compile-time map from identifiers to arbitrary (heterogeneous) expressions
 | 
				
			||||||
@@ -44,7 +57,6 @@ macro_rules! ident_map {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Returns the number of comma-separated expressions passed to it
 | 
					/// Returns the number of comma-separated expressions passed to it
 | 
				
			||||||
#[macro_export]
 | 
					#[macro_export]
 | 
				
			||||||
#[doc(hidden)]
 | 
					#[doc(hidden)]
 | 
				
			||||||
@@ -54,9 +66,6 @@ macro_rules! codelen {
 | 
				
			|||||||
    ( $first:expr, $($rest:expr),+ ) => { 1 + codelen!($($rest),+) };
 | 
					    ( $first:expr, $($rest:expr),+ ) => { 1 + codelen!($($rest),+) };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Replace elements of "arrays" of expressions with sorted replacements by
 | 
					/// Replace elements of "arrays" of expressions with sorted replacements by
 | 
				
			||||||
/// seeking along a "positional array" containing n expressions, then replacing
 | 
					/// seeking along a "positional array" containing n expressions, then replacing
 | 
				
			||||||
/// elements in the source array.
 | 
					/// elements in the source array.
 | 
				
			||||||
@@ -120,7 +129,6 @@ macro_rules! lockstep_replace {
 | 
				
			|||||||
/// Relocation formats:
 | 
					/// Relocation formats:
 | 
				
			||||||
/// { $label as ABS16 @ [$lockstepmcpos] }
 | 
					/// { $label as ABS16 @ [$lockstepmcpos] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// $pos is
 | 
					 | 
				
			||||||
#[macro_export]
 | 
					#[macro_export]
 | 
				
			||||||
#[doc(hidden)]
 | 
					#[doc(hidden)]
 | 
				
			||||||
macro_rules! reloc {
 | 
					macro_rules! reloc {
 | 
				
			||||||
@@ -149,13 +157,11 @@ macro_rules! reloc {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
// $attr is a label
 | 
					// $attr is a label
 | 
				
			||||||
// $mcode is a list that contains the machine code opcodes
 | 
					// $mcode is a list that contains the machine code opcodes
 | 
				
			||||||
// $ident is the identifier list
 | 
					// $ident is the identifier list
 | 
				
			||||||
// $reloc is the relocation list
 | 
					// $reloc is the relocation list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[macro_export]
 | 
					#[macro_export]
 | 
				
			||||||
#[doc(hidden)]
 | 
					#[doc(hidden)]
 | 
				
			||||||
macro_rules! asm_ {
 | 
					macro_rules! asm_ {
 | 
				
			||||||
@@ -180,33 +186,33 @@ macro_rules! asm_ {
 | 
				
			|||||||
    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
					    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
				
			||||||
        add % $wd:tt, % $ra:tt , % $rb:tt
 | 
					        add % $wd:tt, % $ra:tt , % $rb:tt
 | 
				
			||||||
    $($rest:tt)* ) => {
 | 
					    $($rest:tt)* ) => {
 | 
				
			||||||
        asm_!({ $($attr)* } [ $($mcode,)* $wd << 16 | 0 << 11 | $ra << 6 | 0 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
					        asm_!({ $($attr)* } [ $($mcode,)* $wd << 18 | 0 << 11 | $ra << 6 | 0 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
					    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
				
			||||||
        add % $wd:tt, % $ra:tt , # $rb:tt
 | 
					        add % $wd:tt, % $ra:tt , # $rb:tt
 | 
				
			||||||
    $($rest:tt)* ) => {
 | 
					    $($rest:tt)* ) => {
 | 
				
			||||||
        asm_!({ $($attr)* } [ $($mcode,)* $wd << 16 | 0 << 11 | $ra << 6 | 1 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
					        asm_!({ $($attr)* } [ $($mcode,)* $wd << 18 | 0 << 11 | $ra << 6 | 1 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
					    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
				
			||||||
        add % $wd:tt, # $ra:tt , % $rb:tt
 | 
					        add % $wd:tt, # $ra:tt , % $rb:tt
 | 
				
			||||||
    $($rest:tt)* ) => {
 | 
					    $($rest:tt)* ) => {
 | 
				
			||||||
        asm_!({ $($attr)* } [ $($mcode,)* $wd << 16 | 1 << 11 | $ra << 6 | 0 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
					        asm_!({ $($attr)* } [ $($mcode,)* $wd << 18 | 1 << 11 | $ra << 6 | 0 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
					    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
				
			||||||
        add % $wd:tt, # $ra:tt , # $rb:tt
 | 
					        add % $wd:tt, # $ra:tt , # $rb:tt
 | 
				
			||||||
    $($rest:tt)* ) => {
 | 
					    $($rest:tt)* ) => {
 | 
				
			||||||
        asm_!({ $($attr)* } [ $($mcode,)* $wd << 16 | 1 << 11 | $ra << 6 | 1 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
					        asm_!({ $($attr)* } [ $($mcode,)* $wd << 18 | 1 << 11 | $ra << 6 | 1 << 17 | $rb << 12 | 0x5 ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // BRZ
 | 
					    // BRZ
 | 
				
			||||||
 | 
					    // ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
				
			||||||
 | 
					    //     brz $label:ident , % $ra:tt
 | 
				
			||||||
 | 
					    // $($rest:tt)* ) => {
 | 
				
			||||||
 | 
					    //     asm_!({ $($attr)* } [ $($mcode,)* 0x0 ],
 | 
				
			||||||
 | 
					    //         [ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [ $($mcode,)* ] } ], $($rest)*)
 | 
				
			||||||
 | 
					    // };
 | 
				
			||||||
    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
					    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
				
			||||||
        brz $label:ident , % $ra:tt
 | 
					        brz $label:ident , #$ra:tt
 | 
				
			||||||
    $($rest:tt)* ) => {
 | 
					 | 
				
			||||||
        asm_!({ $($attr)* } [ $($mcode,)* 0x0 ],
 | 
					 | 
				
			||||||
            [ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [ $($mcode,)* ] } ], $($rest)*)
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
 | 
					 | 
				
			||||||
        brz $label:ident , # $ra:tt
 | 
					 | 
				
			||||||
    $($rest:tt)* ) => {
 | 
					    $($rest:tt)* ) => {
 | 
				
			||||||
        asm_!({ $($attr)* } [ $($mcode,)* 0 << 23 | 1 << 11 | $ra << 6 | 0x9 ],
 | 
					        asm_!({ $($attr)* } [ $($mcode,)* 0 << 23 | 1 << 11 | $ra << 6 | 0x9 ],
 | 
				
			||||||
            [ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [$($mcode,)* 0 << 23 | 1 << 11 | $ra << 6 | 0x9] } ], $($rest)*)
 | 
					            [ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [$($mcode,)* 0 << 23 | 1 << 11 | $ra << 6 | 0x9] } ], $($rest)*)
 | 
				
			||||||
@@ -249,41 +255,154 @@ macro_rules! assemble_engine25519 {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					
 | 
				
			||||||
/// Does anything work
 | 
					// /// Does anything work
 | 
				
			||||||
#[test]
 | 
					// #[test]
 | 
				
			||||||
fn basic_syntax() {
 | 
					// fn basic_syntax() {
 | 
				
			||||||
    let mcode = assemble_engine25519!(
 | 
					//     let mcode = assemble_engine25519!(
 | 
				
			||||||
        start:
 | 
					//         start:
 | 
				
			||||||
            add %0, %1, %2
 | 
					//             add %0, %1, %2
 | 
				
			||||||
            add %2, %3, #4
 | 
					//             add %2, %3, #4
 | 
				
			||||||
            add %5, #6, %7
 | 
					//             add %5, #6, %7
 | 
				
			||||||
            add %8, #9, #10
 | 
					//             add %8, #9, #10
 | 
				
			||||||
            brz start, %11
 | 
					//             brz start, #11
 | 
				
			||||||
    );
 | 
					//     );
 | 
				
			||||||
    assert_eq!(mcode, [
 | 
					//     assert_eq!(
 | 
				
			||||||
        0 << 16 | 0 << 11 | 1  << 6 | 0 << 17 | 2  << 12 | 0x5,
 | 
					//         mcode,
 | 
				
			||||||
        2 << 16 | 0 << 11 | 3  << 6 | 1 << 17 | 4  << 12 | 0x5,
 | 
					//         [
 | 
				
			||||||
        5 << 16 | 1 << 11 | 6  << 6 | 0 << 17 | 7  << 12 | 0x5,
 | 
					//             0 << 16 | 0 << 11 | 1 << 6 | 0 << 17 | 2 << 12 | 0x5,
 | 
				
			||||||
        8 << 16 | 1 << 11 | 9  << 6 | 1 << 17 | 10 << 12 | 0x5,
 | 
					//             2 << 16 | 0 << 11 | 3 << 6 | 1 << 17 | 4 << 12 | 0x5,
 | 
				
			||||||
        0x3FC << 23 | 0 << 11 | 11 << 6 | 0x9,
 | 
					//             5 << 16 | 1 << 11 | 6 << 6 | 0 << 17 | 7 << 12 | 0x5,
 | 
				
			||||||
     ]);
 | 
					//             8 << 16 | 1 << 11 | 9 << 6 | 1 << 17 | 10 << 12 | 0x5,
 | 
				
			||||||
 | 
					//             0x3FC << 23 | 0 << 11 | 11 << 6 | 0x9,
 | 
				
			||||||
 | 
					//         ]
 | 
				
			||||||
 | 
					//     );
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum Operand {
 | 
				
			||||||
 | 
					    Register(i32),
 | 
				
			||||||
 | 
					    Constant(i32),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Operand {
 | 
				
			||||||
 | 
					    pub fn from_i32_r(op: i32) -> Operand {
 | 
				
			||||||
 | 
					        if (op >> 5) & 1 == 0 {
 | 
				
			||||||
 | 
					            Operand::Register(op & (32 - 1))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Operand::Constant(op & (32 - 1))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn from_i32_w(op: i32) -> Operand {
 | 
				
			||||||
 | 
					        Operand::Register(op & (32 - 1))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#[cfg(feature = "std")]
 | 
				
			||||||
 | 
					impl std::fmt::Display for Operand {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
 | 
					        use Operand::*;
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Register(r) => write!(f, "%{}", r),
 | 
				
			||||||
 | 
					            Constant(c) => write!(f, "#{}", c),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum Opcode {
 | 
				
			||||||
 | 
					    PSA(Operand, Operand),
 | 
				
			||||||
 | 
					    PSB(Operand, Operand),
 | 
				
			||||||
 | 
					    MSK(Operand, Operand),
 | 
				
			||||||
 | 
					    XOR,
 | 
				
			||||||
 | 
					    NOT,
 | 
				
			||||||
 | 
					    ADD(Operand, Operand, Operand),
 | 
				
			||||||
 | 
					    SUB,
 | 
				
			||||||
 | 
					    MUL,
 | 
				
			||||||
 | 
					    TRD,
 | 
				
			||||||
 | 
					    BRZ(Operand, i32),
 | 
				
			||||||
 | 
					    UDF,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Opcode {
 | 
				
			||||||
 | 
					    pub fn from_i32(op: i32) -> Opcode {
 | 
				
			||||||
 | 
					        match op & (32 - 1) {
 | 
				
			||||||
 | 
					            0 => Opcode::PSA(Operand::from_i32_r(op >> 6), Operand::from_i32_w(op >> 18)),
 | 
				
			||||||
 | 
					            1 => Opcode::PSB(Operand::from_i32_r(op >> 6), Operand::from_i32_w(op >> 18)),
 | 
				
			||||||
 | 
					            2 => Opcode::MSK(Operand::from_i32_r(op >> 6), Operand::from_i32_r(op >> 12)),
 | 
				
			||||||
 | 
					            3 => Opcode::XOR,
 | 
				
			||||||
 | 
					            4 => Opcode::NOT,
 | 
				
			||||||
 | 
					            5 => Opcode::ADD(Operand::from_i32_r(op >> 6), Operand::from_i32_r(op >> 12), Operand::from_i32_w(op >> 18)),
 | 
				
			||||||
 | 
					            6 => Opcode::SUB,
 | 
				
			||||||
 | 
					            7 => Opcode::MUL,
 | 
				
			||||||
 | 
					            8 => Opcode::TRD,
 | 
				
			||||||
 | 
					            9 => Opcode::BRZ(Operand::from_i32_r(op >> 6), op >> 23),
 | 
				
			||||||
 | 
					            _ => Opcode::UDF,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(feature = "std")]
 | 
				
			||||||
 | 
					impl std::fmt::Display for Opcode {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
 | 
					        use Opcode::*;
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            PSA(ra, rd) => write!(f, "PSA {}, {}", ra, rd),
 | 
				
			||||||
 | 
					            PSB(ra, rd) => write!(f, "PSB {}, {}", ra, rd),
 | 
				
			||||||
 | 
					            MSK(ra, rb) => write!(f, "MSK {}, {}", ra, rb),
 | 
				
			||||||
 | 
					            XOR => write!(f, "XOR"),
 | 
				
			||||||
 | 
					            NOT => write!(f, "NOT"),
 | 
				
			||||||
 | 
					            ADD(ra, rb, rd) => write!(f, "ADD {}, {}, {}", rd, ra, rb),
 | 
				
			||||||
 | 
					            SUB => write!(f, "SUB"),
 | 
				
			||||||
 | 
					            MUL => write!(f, "MUL"),
 | 
				
			||||||
 | 
					            TRD => write!(f, "TRD"),
 | 
				
			||||||
 | 
					            BRZ(ra, rb) => write!(f, "BRZ {}, {}", rb, ra),
 | 
				
			||||||
 | 
					            _ => write!(f, "invalid"),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					fn print_opcode(op: i32) {
 | 
				
			||||||
 | 
					    println!(
 | 
				
			||||||
 | 
					        "{:09b} {:05b} {:01b} {:05b} {:01b} {:05b} {:05b} | {}",
 | 
				
			||||||
 | 
					        (op >> 23) & (512 - 1),
 | 
				
			||||||
 | 
					        (op >> 18) & (32 - 1),
 | 
				
			||||||
 | 
					        (op >> 17) & 1,
 | 
				
			||||||
 | 
					        (op >> 12) & (32 - 1),
 | 
				
			||||||
 | 
					        (op >> 11) & 1,
 | 
				
			||||||
 | 
					        (op >> 6) & (32 - 1),
 | 
				
			||||||
 | 
					        op & (32 - 1),
 | 
				
			||||||
 | 
					        Opcode::from_i32(op),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Simple jump
 | 
					/// Simple jump
 | 
				
			||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn simple_jmp() {
 | 
					fn simple_jmp() {
 | 
				
			||||||
    let mcode = assemble_engine25519!(
 | 
					    let mcode = assemble_engine25519!(
 | 
				
			||||||
        start:
 | 
					            start:
 | 
				
			||||||
            add %0, %1, %2
 | 
					                add %8, #9, #11
 | 
				
			||||||
            brz start, %11
 | 
					            mid:
 | 
				
			||||||
 | 
					                brz start, #11
 | 
				
			||||||
 | 
					                add %8, #9, #12
 | 
				
			||||||
 | 
					                add %8, #9, #10
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    print!("{}", mcode);
 | 
					    println!("Assembled output:");
 | 
				
			||||||
    assert_eq!(mcode, [
 | 
					    for op in &mcode {
 | 
				
			||||||
        0 << 16 | 0 << 11 | 1  << 6 | 0 << 17 | 2  << 12 | 0x5,
 | 
					        print_opcode(*op);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let target = [
 | 
				
			||||||
 | 
					        8 << 18 | 1 << 11 | 9 << 6 | 1 << 17 | 11 << 12 | 0x5,
 | 
				
			||||||
        0x3FE << 23 | 0 << 11 | 11 << 6 | 0x9,
 | 
					        0x3FE << 23 | 0 << 11 | 11 << 6 | 0x9,
 | 
				
			||||||
     ]);
 | 
					        8 << 18 | 1 << 11 | 9 << 6 | 1 << 17 | 12 << 12 | 0x5,
 | 
				
			||||||
 | 
					        8 << 18 | 1 << 11 | 9 << 6 | 1 << 17 | 10 << 12 | 0x5,
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    println!("Target output:");
 | 
				
			||||||
 | 
					    for op in &target {
 | 
				
			||||||
 | 
					        print_opcode(*op);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert_eq!(mcode, target);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user