-
Notifications
You must be signed in to change notification settings - Fork 1
/
switch.rs
160 lines (154 loc) · 4.74 KB
/
switch.rs
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
#![allow(dead_code)]
use super::{handler, Bits, Context, Outcome, Register, Target};
#[derive(Copy, Clone)]
pub enum Inst {
/// Adds the contents of `lhs` and `rhs` and stores the result into `result`.
Add {
result: Register,
lhs: Register,
rhs: Register,
},
/// Adds the constant `imm` and the contents of `src` and stores the result into `result`.
AddImm {
result: Register,
src: Register,
imm: Bits,
},
/// Subtracts the contents of `rhs` from `lhs` and stores the result into `result`.
Sub {
result: Register,
lhs: Register,
rhs: Register,
},
/// Subtracts the constant `imm` from the contents of `src` and stores the result into `result`.
SubImm {
result: Register,
src: Register,
imm: Bits,
},
/// Multiplies the contents of `lhs` and `rhs` and stores the result into `result`.
Mul {
result: Register,
lhs: Register,
rhs: Register,
},
/// Multiplies the constant `imm` and the contents of `src` and stores the result into `result`.
MulImm {
result: Register,
src: Register,
imm: Bits,
},
/// Branches to the instruction indexed by `target`.
Branch { target: Target },
/// Branches to the instruction indexed by `target` if the contents of `condition` are zero.
BranchEqz { target: Target, condition: Register },
/// Returns execution of the function and returns the result in `result`.
Return { result: Register },
}
impl Inst {
pub fn execute(&self, context: &mut Context) -> Outcome {
match self {
Inst::Add { result, lhs, rhs } => handler::add(context, *result, *lhs, *rhs),
Inst::AddImm { result, src, imm } => handler::add_imm(context, *result, *src, *imm),
Inst::Sub { result, lhs, rhs } => handler::sub(context, *result, *lhs, *rhs),
Inst::SubImm { result, src, imm } => handler::sub_imm(context, *result, *src, *imm),
Inst::Mul { result, lhs, rhs } => handler::mul(context, *result, *lhs, *rhs),
Inst::MulImm { result, src, imm } => handler::mul_imm(context, *result, *src, *imm),
Inst::Branch { target } => handler::branch(context, *target),
Inst::BranchEqz { target, condition } => {
handler::branch_eqz(context, *target, *condition)
}
Inst::Return { result } => handler::ret(context, *result),
}
}
}
/// Executes the list of instruction using the given [`Context`].
fn execute(insts: &[Inst], context: &mut Context) {
loop {
let pc = context.pc;
let inst = &insts[pc];
match inst.execute(context) {
Outcome::Continue => continue,
Outcome::Return => return,
}
}
}
#[test]
fn counter_loop() {
let repetitions = 100_000_000;
let insts = vec![
// Store `repetitions` into r0.
// Note: r0 is our loop counter register.
Inst::AddImm {
result: 0,
src: 0,
imm: repetitions,
},
// Branch to the end if r0 is zero.
Inst::BranchEqz {
target: 4,
condition: 0,
},
// Decrease r0 by 1.
Inst::SubImm {
result: 0,
src: 0,
imm: 1,
},
// Jump back to the loop header.
Inst::Branch { target: 1 },
// Return value and end function execution.
Inst::Return { result: 0 },
];
let mut context = Context::default();
execute(&insts, &mut context);
}
#[test]
fn more_comps() {
let repetitions = 100_000_000;
let insts = vec![
// Store `repetitions` into r0.
// Note: r0 is our loop counter register.
Inst::AddImm {
result: 0,
src: 0,
imm: repetitions,
},
// Store `1` into r1.
// Note: r1 is our accumulator register.
Inst::AddImm {
result: 1,
src: 1,
imm: 1,
},
// Branch to the end if r0 is zero.
Inst::BranchEqz {
target: 7,
condition: 0,
},
// Multiply r1 with r0.
Inst::Mul {
result: 1,
lhs: 1,
rhs: 0,
},
// Subtract r0 from r1.
Inst::Sub {
result: 1,
lhs: 1,
rhs: 0,
},
// Decrease r0 by 1.
Inst::SubImm {
result: 0,
src: 0,
imm: 1,
},
// Jump back to the loop header.
Inst::Branch { target: 2 },
// Return value and end function execution.
Inst::Return { result: 1 },
];
let mut context = Context::default();
execute(&insts, &mut context);
}