1use std::ops::Range;
19use std::borrow::Cow;
20
21use smallvec::SmallVec;
22use ron_uuid::UUID;
23
24use {
25 Region,
26 Result,
27 Value,
28 Variable,
29 Statement,
30 Operation,
31 FlowOperation,
32 MemoryOperation,
33 Guard,
34 Str,
35 Names,
36 Segments,
37 Segment,
38 Name,
39 Endianess,
40 Strings,
41};
42
43pub trait Architecture: Clone {
45 type Configuration: Clone + Send;
48
49 fn prepare(&Region, &Self::Configuration) -> Result<Cow<'static, [(&'static str, u64, &'static str)]>>;
53
54 fn decode(&Region, u64, &Self::Configuration, names: &mut Names,
56 segments: &mut Segments, strings: &mut Strings,
57 matches: &mut Vec<Match>) -> Result<()>;
58}
59
60#[derive(Debug,Clone)]
62pub struct Match {
63 pub area: Range<u64>,
65 pub opcode: Str,
67 pub operands: SmallVec<[Value; 3]>,
69 pub instructions: Vec<Statement>,
72
73 pub jumps: SmallVec<[(u64, Value, Guard); 2]>,
75}
76
77#[derive(Debug,Clone)]
99pub struct TestArch;
100
101impl TestArch {
102 fn read_value(reg: &Region, entry: &mut u64, len: usize, names: &mut Names) -> Result<Value> {
103 match reg.read_integer(*entry,Endianess::Little,1).map(|x| x as u8) {
104 Ok(b) => match b {
105 b'a'...b'z' => {
106 let nam = names.insert(&Name::new(format!("{}",char::from(b)).into(),None));
107
108 *entry += 1;
109 Value::var(nam,len)
110 }
111 b'0'...b'9' => {
112 Value::val(Self::read_address(reg,entry)?,32)
113 }
114 _ => Err(format!("'{}' is nor a variable name neither a constant",b).into())
115 }
116 _ => Err(format!("premature end while decoding rvalue at {}",*entry).into())
117 }
118 }
119
120 fn read_variable(reg: &Region, entry: &mut u64, len: usize, names: &mut Names) -> Result<Variable> {
121 match reg.read_integer(*entry,Endianess::Little,1).map(|x| x as u8) {
122 Ok(b) => match b {
123 b'a'...b'z' => {
124 let nam = names.insert(&Name::new(format!("{}",char::from(b)).into(),None));
125
126 *entry += 1;
127 Variable::new(nam,len)
128 }
129 _ => Err(format!("'{}' is not a variable name",b).into())
130 }
131 _ => Err(format!("Premature end while decoding lvalue at {}",*entry).into())
132 }
133 }
134
135 fn read_address(reg: &Region, entry: &mut u64) -> Result<u64> {
136 match reg.read_integer(*entry,Endianess::Little,1).map(|x| x as u8) {
137 Ok(b@b'0'...b'9') => {
138 let value = (b - b'0') as u64;
139
140 *entry += 1;
141 match Self::read_address(reg,entry) {
142 Ok(x) => Ok(value * 10 + x),
143 Err(_) => Ok(value)
144 }
145 }
146 Ok(b) => Err(format!("'{}' is not a number",b).into()),
147 _ => Err(format!("Premature end while decoding address at {}",*entry).into())
148 }
149 }
150}
151
152impl Architecture for TestArch {
153 type Configuration = ();
154
155 fn prepare(_: &Region, _: &()) -> Result<Cow<'static, [(&'static str, u64, &'static str)]>> {
156 Ok(Cow::default())
157 }
158
159 fn decode(reg: &Region, mut entry: u64, _: &(), names: &mut Names,
160 segments: &mut Segments, strings: &mut Strings,
161 matches: &mut Vec<Match>) -> Result<()>
162 {
163 let start = entry;
164 let opcode = reg.read_integer(entry,Endianess::Little,1);
165 entry += 1;
166
167 match opcode.map(|x| x as u8) {
168 Ok(b'M') => {
169 let var = Self::read_variable(reg, &mut entry, 32, names)?;
170 let val = Self::read_value(reg, &mut entry, 32, names)?;
171 let instr = Statement::Expression{
172 result: var.clone(),
173 op: Operation::Move(val.clone())
174 };
175 let m = Match{
176 area: start..entry,
177 opcode: "mov".into(),
178 operands: SmallVec::from_vec(vec![var.into(), val]),
179 instructions: vec![instr],
180 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
181 };
182
183 matches.push(m);
184 Ok(())
185 }
186 Ok(b'G') => {
187 let addr = Self::read_variable(reg, &mut entry, 32, names)?;
188 let instr = Statement::Flow{
189 op: FlowOperation::IndirectCall{ target: addr },
190 };
191 let m = Match{
192 area: start..entry,
193 opcode: "call".into(),
194 operands: SmallVec::from_vec(vec![addr.into()]),
195 instructions: vec![instr],
196 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
197 };
198
199 matches.push(m);
200 Ok(())
201 }
202 Ok(b'F') => {
203 let instr = Statement::Flow{
204 op: FlowOperation::Call{ function: UUID::now() },
205 };
206 let m = Match{
207 area: start..entry,
208 opcode: "call".into(),
209 operands: SmallVec::default(),
210 instructions: vec![instr],
211 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
212 };
213
214 matches.push(m);
215 Ok(())
216 }
217 Ok(b'H') => {
218 let s = match reg.read_integer(entry,Endianess::Little,1) {
219 Ok(b) => {
220 entry += 1;
221 strings.insert(&format!("{}", char::from(b as u8)).into())
222 }
223 _ => {
224 return Err(format!("premature end while decoding stub name {}",entry).into());
225 }
226 };
227 let instr = Statement::Flow{
228 op: FlowOperation::ExternalCall{ external: s.into() },
229 };
230 let m = Match{
231 area: start..entry,
232 opcode: "call".into(),
233 operands: SmallVec::default(),
234 instructions: vec![instr],
235 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
236 };
237
238 matches.push(m);
239 Ok(())
240 }
241 Ok(b'A') => {
242 let var = Self::read_variable(reg, &mut entry, 32, names)?;
243 let val1 = Self::read_value(reg, &mut entry, 32, names)?;
244 let val2 = Self::read_value(reg, &mut entry, 32, names)?;
245 let instr = Statement::Expression{
246 result: var,
247 op: Operation::Add(val1.clone(),val2.clone())
248 };
249 let m = Match{
250 area: start..entry,
251 opcode: "add".into(),
252 operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
253 instructions: vec![instr],
254 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
255 };
256
257 matches.push(m);
258 Ok(())
259 }
260 Ok(b'U') => {
261 let var = Self::read_variable(reg, &mut entry, 32, names)?;
262 let val1 = Self::read_value(reg, &mut entry, 32, names)?;
263 let val2 = Self::read_value(reg, &mut entry, 32, names)?;
264 let instr = Statement::Expression{
265 result: var,
266 op: Operation::Subtract(val1.clone(),val2.clone())
267 };
268 let m = Match{
269 area: start..entry,
270 opcode: "sub".into(),
271 operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
272 instructions: vec![instr],
273 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
274 };
275
276 matches.push(m);
277 Ok(())
278 }
279 Ok(b'X') => {
280 let var = Self::read_variable(reg, &mut entry, 32, names)?;
281 let val1 = Self::read_value(reg, &mut entry, 32, names)?;
282 let val2 = Self::read_value(reg, &mut entry, 32, names)?;
283 let instr = Statement::Expression{
284 result: var,
285 op: Operation::Multiply(val1,val2)
286 };
287 let m = Match{
288 area: start..entry,
289 opcode: "mul".into(),
290 operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
291 instructions: vec![instr],
292 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
293 };
294
295 matches.push(m);
296 Ok(())
297 }
298 Ok(b'C') => {
299 let var = Self::read_variable(reg, &mut entry, 1, names)?;
300 let val1 = Self::read_value(reg, &mut entry, 32, names)?;
301 let val2 = Self::read_value(reg, &mut entry, 32, names)?;
302 let instr = Statement::Expression{
303 result: var,
304 op: Operation::LessOrEqualUnsigned(val1,val2)
305 };
306 let m = Match{
307 area: start..entry,
308 opcode: "leq".into(),
309 operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
310 instructions: vec![instr],
311 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
312 };
313
314 matches.push(m);
315 Ok(())
316 }
317 Ok(b'E') => {
318 let var = Self::read_variable(reg, &mut entry, 1, names)?;
319 let val1 = Self::read_value(reg, &mut entry, 32, names)?;
320 let val2 = Self::read_value(reg, &mut entry, 32, names)?;
321 let instr = Statement::Expression{
322 result: var,
323 op: Operation::Equal(val1,val2)
324 };
325 let m = Match{
326 area: start..entry,
327 opcode: "eq".into(),
328 operands: SmallVec::from_vec(vec![var.clone().into(),val1.clone(),val2.clone()]),
329 instructions: vec![instr],
330 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
331 };
332
333 matches.push(m);
334 Ok(())
335 }
336 Ok(b'B') => {
337 let bit = Self::read_variable(reg, &mut entry, 1, names)?;
338 let brtgt = Self::read_address(reg, &mut entry)?;
339 let guard = Guard::Predicate{ flag: bit, expected: true };
340 let nguard = Guard::Predicate{ flag: bit, expected: false };
341 let m = Match{
342 area: start..entry,
343 opcode: "br".into(),
344 operands: SmallVec::from_vec(vec![Value::Variable(bit.clone()),Value::val(brtgt, 32)?]),
345 instructions: vec![],
346 jumps: SmallVec::from_vec(vec![
347 (start,Value::val(entry, 32)?,nguard),
348 (start,Value::val(brtgt, 32)?,guard)
349 ]),
350 };
351
352 matches.push(m);
353 Ok(())
354 }
355 Ok(b'J') => {
356 let jtgt = Self::read_value(reg, &mut entry, 32, names)?;
357 let m = Match{
358 area: start..entry,
359 opcode: "jmp".into(),
360 operands: SmallVec::from_vec(vec![jtgt]),
361 instructions: vec![],
362 jumps: SmallVec::from_vec(vec![(start,jtgt,Guard::True)]),
363 };
364
365 matches.push(m);
366 Ok(())
367 }
368 Ok(b'R') => {
369 let instr = Statement::Flow{
370 op: FlowOperation::Return
371 };
372 let m = Match{
373 area: start..entry,
374 opcode: "ret".into(),
375 operands: SmallVec::default(),
376 instructions: vec![instr],
377 jumps: SmallVec::default(),
378 };
379
380 matches.push(m);
381 Ok(())
382 }
383 Ok(b'S') => {
384 let addr = Self::read_value(reg, &mut entry, 32, names)?;
385 let val = Self::read_value(reg, &mut entry, 32, names)?;
386 let seg = Segment{ name: segments.insert(&Name::new("ram".into(),None)) };
387 let instr = Statement::Memory{
388 result: seg,
389 op: MemoryOperation::Store{
390 segment: seg,
391 endianess: Endianess::Little,
392 bytes: 4,
393 address: addr,
394 value: val,
395 }
396 };
397 let m = Match{
398 area: start..entry,
399 opcode: "store".into(),
400 operands: SmallVec::from_vec(vec![addr.clone().into(),val.clone()]),
401 instructions: vec![instr],
402 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
403 };
404
405 matches.push(m);
406 Ok(())
407 }
408 Ok(b'L') => {
409 let val = Self::read_variable(reg, &mut entry, 32, names)?;
410 let addr = Self::read_value(reg, &mut entry, 32, names)?;
411 let seg = segments.insert(&Name::new("ram".into(),None));
412 let instr = Statement::Expression{
413 result: val,
414 op: Operation::Load(Segment{ name: seg },Endianess::Little,4,addr)
415 };
416 let m = Match{
417 area: start..entry,
418 opcode: "load".into(),
419 operands: SmallVec::from_vec(vec![val.clone().into(),addr.clone()]),
420 instructions: vec![instr],
421 jumps: SmallVec::from_vec(vec![(start,Value::val(entry, 32)?,Guard::True)]),
422 };
423
424 matches.push(m);
425 Ok(())
426 }
427 Ok(o) => {
428 Err(format!("Unknown opcode '{}' at {}",o,start).into())
429 }
430 _ => {
431 Err(format!("Premature end while decoding opcode {}",start).into())
432 }
433 }
434 }
435}
436
437#[cfg(test)]
438mod tests {
439 use super::*;
440 use {Function, Region};
441
442 #[test]
443 fn test_arch() {
444 let reg = Region::from_buf("",16,b"Mi1MiiAiiiAi1iAii1Ai11CiiiCi1iCii1Ci11Bi0RSiiS1iS11LiiLi1".to_vec(),0,None);
445 let _ = Function::new::<TestArch>((), 0, ®, UUID::now()).unwrap();
446 }
447}