cambridge_asm/exec/
bitman.rs1use super::{Context, RtError::*, RtResult};
7use crate::inst::Op::{self, *};
8
9pub fn and(ctx: &mut Context, op: &Op) -> RtResult {
16 match op {
17 MultiOp(ops) => match ops[..] {
18 [ref dest, ref val] if dest.is_read_write() && val.is_usizeable() => {
19 let val = ctx.read(val)?;
20 ctx.modify(dest, |d| *d &= val)?;
21 }
22 [ref dest, ref a, ref b]
23 if dest.is_read_write() && a.is_usizeable() && b.is_usizeable() =>
24 {
25 let val = ctx.read(a)? & ctx.read(b)?;
26 ctx.modify(dest, |d| *d = val)?;
27 }
28 _ => return Err(InvalidMultiOp),
29 },
30 val if val.is_usizeable() => ctx.acc &= ctx.read(val)?,
31 Null => return Err(NoOperand),
32 _ => return Err(InvalidOperand),
33 }
34
35 Ok(())
36}
37
38pub fn or(ctx: &mut Context, op: &Op) -> RtResult {
45 match op {
46 MultiOp(ops) => match ops[..] {
47 [ref dest, ref val] if dest.is_read_write() && val.is_usizeable() => {
48 let val = ctx.read(val)?;
49 ctx.modify(dest, |d| *d |= val)?;
50 }
51 [ref dest, ref a, ref b]
52 if dest.is_read_write() && a.is_usizeable() && b.is_usizeable() =>
53 {
54 let val = ctx.read(a)? | ctx.read(b)?;
55 ctx.modify(dest, |d| *d = val)?;
56 }
57 _ => return Err(InvalidMultiOp),
58 },
59 val if val.is_usizeable() => ctx.acc |= ctx.read(val)?,
60 Null => return Err(NoOperand),
61 _ => return Err(InvalidOperand),
62 }
63
64 Ok(())
65}
66
67pub fn xor(ctx: &mut Context, op: &Op) -> RtResult {
74 match op {
75 MultiOp(ops) => match ops[..] {
76 [ref dest, ref val] if dest.is_read_write() && val.is_usizeable() => {
77 let val = ctx.read(val)?;
78 ctx.modify(dest, |d| *d ^= val)?;
79 }
80 [ref dest, ref a, ref b]
81 if dest.is_read_write() && a.is_usizeable() && b.is_usizeable() =>
82 {
83 let val = ctx.read(a)? ^ ctx.read(b)?;
84 ctx.modify(dest, |d| *d = val)?;
85 }
86 _ => return Err(InvalidMultiOp),
87 },
88 val if val.is_usizeable() => ctx.acc ^= ctx.read(val)?,
89 Null => return Err(NoOperand),
90 _ => return Err(InvalidOperand),
91 }
92
93 Ok(())
94}
95
96pub fn lsl(ctx: &mut Context, op: &Op) -> RtResult {
103 #[allow(clippy::cast_possible_truncation)]
104 fn checked_shl(dest: &mut usize, val: usize, mar: usize) {
105 if let Some(res) = dest.checked_shl(val as u32) {
106 *dest = res;
107 } else {
108 warn!("Shift left overflow detected at line {}", mar + 1);
109 *dest <<= val;
110 }
111 }
112
113 match op {
114 MultiOp(ops) => {
115 let line = ctx.mar;
116 match ops[..] {
117 [ref dest, ref val] if dest.is_read_write() && val.is_usizeable() => {
118 let val = ctx.read(val)?;
119 ctx.modify(dest, |d| checked_shl(d, val, line))
120 }
121 [ref dest, ref a, ref b]
122 if dest.is_read_write() && a.is_usizeable() && b.is_usizeable() =>
123 {
124 let mut a = ctx.read(a)?;
125 checked_shl(&mut a, ctx.read(b)?, line);
126 ctx.modify(dest, |d| *d = a)
127 }
128 _ => Err(InvalidMultiOp),
129 }
130 }
131 val if val.is_usizeable() => {
132 let x = ctx.read(val)?;
133 checked_shl(&mut ctx.acc, x, ctx.mar);
134 Ok(())
135 }
136 Null => Err(NoOperand),
137 _ => Err(InvalidOperand),
138 }
139}
140
141pub fn lsr(ctx: &mut Context, op: &Op) -> RtResult {
148 match op {
149 MultiOp(ops) => match ops[..] {
150 [ref dest, ref val] if dest.is_read_write() && val.is_usizeable() => {
151 let val = ctx.read(val)?;
152 ctx.modify(dest, |d| *d >>= val)
153 }
154 [ref dest, ref a, ref b]
155 if dest.is_read_write() && a.is_usizeable() && b.is_usizeable() =>
156 {
157 let val = ctx.read(a)? >> ctx.read(b)?;
158 ctx.modify(dest, |d| *d = val)
159 }
160 _ => Err(InvalidMultiOp),
161 },
162 val if val.is_usizeable() => {
163 ctx.acc >>= ctx.read(val)?;
164 Ok(())
165 }
166 Null => Err(NoOperand),
167 _ => Err(InvalidOperand),
168 }
169}