1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! **`procem_default`** is a toy Rust library that provides a default implementation of the [`Instruction`](../procem/instruction/trait.Instruction.html) trait of the [`procem`](../procem/index.html) library.
//!
//! # Instruction set
//!
//! ## Syntax
//!
//! All instructions can be written in mixed case.
//! All operations that can be suffixed with an 'S', set the flag registers depending on the operation.
//! - *Labels* (**\<LABEL>**) are used to mark specific locations in the program. They are denoted using a dot ('.') followed by a string (e.g., '.label').
//! - *Registers* (**\<REG>**) must be a valid register name (e.g., 'R0', 'r1', 'R2', 'PC', 'sp').
//! - *Literals* (**\<LIT>**) are decimal, binary, hexadecimal, octal, boolean or char constants.
//! They are denoted using a '#' followed by a valid literal value.
//! - Decimal values start with '0d' (optional), followed by a sequence of '0's through '9's.
//! - Binary values start with '0b', followed by a sequence of '0's and '1's.
//! - Hexadecimal values start with '0x', followed by a sequence of digits from '0' through '9' and letters from 'a' through 'f'.
//! - Octal values start with '0o', followed by a sequence of '0's through '7's.
//! - Boolean values are either 'true' or 'false'.
//! - Character values are enclosed in single quotes, e.g., 'a', 'B', '5'.
//! - *Operands* (**\<OP>**) can be a register name or a literal.
//!
//! 'END' marks the end of the program. It is only used as a guide for the assembler and not part of the assembled program.
//!
//! ### Operations
//!
//! - **NOP**: No operation.
//! - **MOV \<REG>, \<OP>**: Copy a value from the operand to the register.
//! - **PUSH \<OP>**: Push a value from the operand to the stack.
//! - **POP \<REG>**: Pop a value from the stack to the register.
//! - **CALL \<OP>**: Call a subroutine at the program address specified by the operand. Pushes the current program counter onto the stack and sets the program counter to the address of the subroutine.
//! - **RET**: Return from a subroutine. Pops the return address from the stack and sets the program counter to the popped value.
//! - **ADD\[S] \<REG>, \<OP>**: Add the value of the operand to the register. The result is stored in the register.
//! - **SUB\[S] \<REG>, \<OP>**: Subtract the value of the operand from the register. The result is stored in the register.
//! - **MUL\[S] \<REG>, \<OP>**: Multiply the value of the operand with the value of the register. The result is stored in the register.
//! - **DIV\[S] \<REG>, \<OP>**: Divide the value of the register by the value of the operand. The result is stored in the register.
//! - **INC\[S] \<REG>**: Increment the value in a register by one.
//! - **DEC\[S] \<REG>**: Decrement the value in a register by one.
//! - **JMP \<LABEL>**: Set program counter to the address of the label (first instruction after the label), effectively jumping to the instruction at this point in the program.
//! - **JZ \<LABEL>**: Jump to the label if the zero flag (Z) is set.
//! - **JNZ \<LABEL>**: Jump to the label if the zero flag (Z) is not set.
//! - **JC \<LABEL>**: Jump to the label if the carry flag (C) is set.
//! - **JNC \<LABEL>**: Jump to the label if the carry flag (C) is not set.
//! - **JS \<LABEL>**: Jump to the label if the signed flag (S) is set.
//! - **JNS \<LABEL>**: Jump to the label if the signed flag (S) is not set.
//! - **JG \<LABEL>**: Jump to the label if the zero flag (Z) and signed flag (S) are not set.
//! - **JGE \<LABEL>**: Jump to the label if the zero flag (Z) is set or signed flag (S) is not set.
//! - **JL \<LABEL>**: Jump to the label if the zero flag (Z) is not set and the signed flag (S) is set.
//! - **JLE \<LABEL>**: Jump to the label if the zero flag (Z) or signed flag (S) is set.
//! - **CMP \<OP>, \<OP>**: Compare the values of two operands and set the flags accordingly. This is the same as `SUBS` but disregards the result of the subtraction.
//! - **XOR \<REG>, \<OP>**: Perform a bitwise xor operation on the value in the register with the value of the operand.
//! - **AND \<REG>, \<OP>**: Perform a bitwise and operation on the value in the register with the value of the operand.
//! - **OR \<REG>, \<OP>**: Perform a bitwise or operation on the value in the register with the value of the operand.
//! - **NOT \<REG>**: Perform a bitwise not operation on the value in the register.
//! - **SHL \<REG>, \<LIT>**: Shift the value in the register left by the specified number of bits. Only use values between 1 and the number of bits of the Word size minus 1.
//! - **SHR \<REG>, \<LIT>**: Shift the value in the register right by the specified number of bits. Only use values between 1 and the number of bits of the Word size minus 1.
//! - **ROL \<REG>, \<LIT>**: Rotate the value in the register left by the specified number of bits. Only use values between 1 and the number of bits of the Word size minus 1.
//! - **ROR \<REG>, \<LIT>**: Rotate the value in the register right by the specified number of bits. Only use values between 1 and the number of bits of the Word size minus 1.
//!
//! # Usage
//! To assemble a [`Program`](../procem/program/struct.Program.html) from assembly code use the [`assemble`] function.
//!
//! # Example
//! ```
//! use procem::{processor::Processor, register::Register, word::I32};
//! use procem_default::assemble;
//!
//! // Assemble a program from asm
//! let program = assemble::<I32>(
//! "
//! mov R0, #10
//! mov R1, #5
//! add R0, R1
//! sub R0, #3
//! mul R0, #2
//! div R0, #4
//! "
//! ).unwrap();
//!
//! // Create a processor and run the program
//! const STACK_SIZE: usize = 1024;
//!
//! let mut processor = Processor::<STACK_SIZE, _, _, _>::builder()
//! .with_program(&program)
//! .build();
//!
//! let _ = processor.run_program();
//!
//! // Inspect register values
//! assert_eq!(processor.registers.get_reg(Register::R0), 6.into());
//! ```
//!
use crateInstruction;
use crate;
use crate;
use Program;
use Word;
use Error;
pub type AssembledProgram<W> = ;
/// Assembles Program from assembly code.
///
/// # Errors
/// Returns a vector of all errors that a happened during either the tokenizing or the parsing.
///
/// # Example
/// ```
/// use procem::{program::Program, register::Register, word::I32};
/// use procem_default::{assemble, instruction::{Instruction, jump_condition::JumpCondition, operand::Operand} };
///
/// const STACK_SIZE: usize = 1024;
///
/// let program = assemble::<I32>(
/// "
/// .input
/// mov R0, #2
/// add R1, R0
/// jmp .input
/// ",
/// )
/// .unwrap();
///
/// assert_eq!(
/// program,
/// Program::<Instruction<I32>, Vec<Instruction<I32>>, I32>::new(vec![
/// Instruction::Mov {
/// to: Register::R0,
/// from: Operand::Value(2.into())
/// },
/// Instruction::Add {
/// acc: Register::R1,
/// rhs: Operand::Register(Register::R0),
/// signed: false
/// },
/// Instruction::Jump {
/// to: 0.into(),
/// condition: JumpCondition::Unconditional
/// }
/// ])
/// );
/// ```