1#[allow(clippy::wildcard_imports)] 2use super::*; 3 4impl_modify_op!( 5 [ 6 accumulator -> asl_a, 7 direct_page -> asl_dp, 8 direct_page_x -> asl_dpx, 9 absolute -> asl_abs, 10 ] 11 (|registers, value| { 12 registers.psw.carry = value.sign_bit(); 13 14 let result = value << 1; 15 registers.psw.zero = result == 0; 16 registers.psw.negative = result.sign_bit(); 17 result 18 }) 19); 20 21impl_modify_op!( 22 [ 23 accumulator -> lsr_a, 24 direct_page -> lsr_dp, 25 direct_page_x -> lsr_dpx, 26 absolute -> lsr_abs, 27 ] 28 (|registers, value| { 29 registers.psw.carry = value.bit(0); 30 31 let result = value >> 1; 32 registers.psw.zero = result == 0; 33 registers.psw.negative = result.sign_bit(); 34 result 35 }) 36); 37 38impl_modify_op!( 39 [ 40 accumulator -> rol_a, 41 direct_page -> rol_dp, 42 direct_page_x -> rol_dpx, 43 absolute -> rol_abs, 44 ] 45 (|registers, value| { 46 let result = (value << 1) | u8::from(registers.psw.carry); 47 registers.psw.zero = result == 0; 48 registers.psw.negative = result.sign_bit(); 49 registers.psw.carry = value.sign_bit(); 50 result 51 }) 52); 53 54impl_modify_op!( 55 [ 56 accumulator -> ror_a, 57 direct_page -> ror_dp, 58 direct_page_x -> ror_dpx, 59 absolute -> ror_abs, 60 ] 61 (|registers, value| { 62 let result = (value >> 1) | (u8::from(registers.psw.carry) << 7); 63 registers.psw.zero = result == 0; 64 registers.psw.negative = result.sign_bit(); 65 registers.psw.carry = value.bit(0); 66 result 67 }) 68); 69 70macro_rules! bit_op { 71 (set $value:expr, $bit:expr) => { 72 $value | (1 << $bit) 73 }; 74 (clear $value:expr, $bit:expr) => { 75 $value & !(1 << $bit) 76 }; 77} 78 79macro_rules! impl_set_bit { 80 ($name:ident, $op:tt) => { 81 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B, bit: u8) { 82 match cpu.state.cycle { 83 1 => { 84 cpu.state.t0 = fetch_operand(cpu, bus); 85 } 86 2 => { 87 let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]); 88 cpu.state.t1 = bus.read(address); 89 } 90 3 => { 91 cpu.final_cycle(); 92 93 let value = bit_op!($op cpu.state.t1, bit); 94 95 let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]); 96 bus.write(address, value); 97 } 98 _ => invalid_cycle!(cpu) 99 } 100 } 101 }; 102} 103 104impl_set_bit!(set1, set); 105impl_set_bit!(clr1, clear); 106 107macro_rules! impl_and1 { 108 ($name:ident $($not:tt)?) => { 109 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 110 match cpu.state.cycle { 111 1 => { 112 cpu.state.t0 = fetch_operand(cpu, bus); 113 } 114 2 => { 115 cpu.state.t1 = fetch_operand(cpu, bus); 116 } 117 3 => { 118 cpu.final_cycle(); 119 120 let address_msb = cpu.state.t1 & 0x1F; 121 let address = u16::from_le_bytes([cpu.state.t0, address_msb]); 122 let value = bus.read(address); 123 124 let bit_index = cpu.state.t1 >> 5; 125 let bit = value.bit(bit_index); 126 127 cpu.registers.psw.carry &= $($not)? bit; 128 } 129 _ => invalid_cycle!(cpu) 130 } 131 } 132 } 133} 134 135impl_and1!(and1); 136impl_and1!(and1_cpl !); 137 138macro_rules! impl_or1 { 139 ($name:ident, $op:tt $(, $not:tt)?) => { 140 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 141 match cpu.state.cycle { 142 1 => { 143 cpu.state.t0 = fetch_operand(cpu, bus); 144 } 145 2 => { 146 cpu.state.t1 = fetch_operand(cpu, bus); 147 } 148 3 => { 149 let address_msb = cpu.state.t1 & 0x1F; 150 let address = u16::from_le_bytes([cpu.state.t0, address_msb]); 151 cpu.state.t2 = bus.read(address); 152 } 153 4 => { 154 cpu.final_cycle(); 155 bus.idle(); 156 157 let bit_index = cpu.state.t1 >> 5; 158 let bit = cpu.state.t2.bit(bit_index); 159 160 cpu.registers.psw.carry $op $($not)? bit; 161 } 162 _ => invalid_cycle!(cpu) 163 } 164 } 165 } 166} 167 168impl_or1!(or1, |=); 169impl_or1!(or1_cpl, |=, !); 170impl_or1!(eor1, ^=); 171 172pub(crate) fn not1<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 173 match cpu.state.cycle { 174 1 => { 175 cpu.state.t0 = fetch_operand(cpu, bus); 176 } 177 2 => { 178 cpu.state.t1 = fetch_operand(cpu, bus); 179 } 180 3 => { 181 let address_msb = cpu.state.t1 & 0x1F; 182 let address = u16::from_le_bytes([cpu.state.t0, address_msb]); 183 cpu.state.t2 = bus.read(address); 184 } 185 4 => { 186 cpu.final_cycle(); 187 188 let bit_index = cpu.state.t1 >> 5; 189 let value = cpu.state.t2 ^ (1 << bit_index); 190 191 let address_msb = cpu.state.t1 & 0x1F; 192 let address = u16::from_le_bytes([cpu.state.t0, address_msb]); 193 bus.write(address, value); 194 } 195 _ => invalid_cycle!(cpu), 196 } 197} 198 199pub(crate) fn mov1_c_bit<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 200 match cpu.state.cycle { 201 1 => { 202 cpu.state.t0 = fetch_operand(cpu, bus); 203 } 204 2 => { 205 cpu.state.t1 = fetch_operand(cpu, bus); 206 } 207 3 => { 208 cpu.final_cycle(); 209 210 let address_msb = cpu.state.t1 & 0x1F; 211 let address = u16::from_le_bytes([cpu.state.t0, address_msb]); 212 let value = bus.read(address); 213 214 let bit_index = cpu.state.t1 >> 5; 215 cpu.registers.psw.carry = value.bit(bit_index); 216 } 217 _ => invalid_cycle!(cpu), 218 } 219} 220 221pub(crate) fn mov1_bit_c<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 222 match cpu.state.cycle { 223 1 => { 224 cpu.state.t0 = fetch_operand(cpu, bus); 225 } 226 2 => { 227 cpu.state.t1 = fetch_operand(cpu, bus); 228 } 229 3 => { 230 let address_msb = cpu.state.t1 & 0x1F; 231 let address = u16::from_le_bytes([cpu.state.t0, address_msb]); 232 cpu.state.t2 = bus.read(address); 233 } 234 4 => { 235 bus.idle(); 236 } 237 5 => { 238 cpu.final_cycle(); 239 240 let bit_index = cpu.state.t1 >> 5; 241 let value = (cpu.state.t2 & !(1 << bit_index)) 242 | (u8::from(cpu.registers.psw.carry) << bit_index); 243 244 let address_msb = cpu.state.t1 & 0x1F; 245 let address = u16::from_le_bytes([cpu.state.t0, address_msb]); 246 bus.write(address, value); 247 } 248 _ => invalid_cycle!(cpu), 249 } 250} 251 252macro_rules! bits_op { 253 (set $value:expr, $a:expr) => { 254 $value | $a 255 }; 256 (clear $value:expr, $a:expr) => { 257 $value & !$a 258 }; 259} 260 261macro_rules! impl_test_and_set_bits { 262 ($name:ident, $op:tt) => { 263 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 264 match cpu.state.cycle { 265 1 => { 266 cpu.state.t0 = fetch_operand(cpu, bus); 267 } 268 2 => { 269 cpu.state.t1 = fetch_operand(cpu, bus); 270 } 271 3 => { 272 // No-op read 273 let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]); 274 bus.read(address); 275 } 276 4 => { 277 let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]); 278 cpu.state.t2 = bus.read(address); 279 } 280 5 => { 281 cpu.final_cycle(); 282 283 // Z and N flags are set based on (A - value) 284 let difference = cpu.registers.a.wrapping_sub(cpu.state.t2); 285 cpu.registers.psw.zero = difference == 0; 286 cpu.registers.psw.negative = difference.sign_bit(); 287 288 let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]); 289 let value = bits_op!($op cpu.state.t2, cpu.registers.a); 290 bus.write(address, value); 291 } 292 _ => invalid_cycle!(cpu) 293 } 294 } 295 } 296} 297 298impl_test_and_set_bits!(tset1, set); 299impl_test_and_set_bits!(tclr1, clear); 300 301pub(crate) fn xcn<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 302 match cpu.state.cycle { 303 1..=3 => { 304 bus.idle(); 305 } 306 4 => { 307 cpu.final_cycle(); 308 bus.idle(); 309 310 cpu.registers.a = cpu.registers.a.rotate_left(4); 311 cpu.registers.psw.zero = cpu.registers.a == 0; 312 cpu.registers.psw.negative = cpu.registers.a.sign_bit(); 313 } 314 _ => invalid_cycle!(cpu), 315 } 316}