1use crate::core::instructions::{ShiftCount, ShiftDirection}; 2use crate::core::{ 3 AddressingMode, ConditionCodes, DataRegister, Exception, ExecuteResult, InstructionExecutor, 4 OpSize, 5}; 6use crate::traits::BusInterface; 7use jgenesis_common::num::{GetBit, SignBit}; 8 9macro_rules! impl_bit_op { 10 ($name:ident, $operator:tt, $read_method:ident, $read_resolved_method:ident, $write_method:ident, $size:expr) => { 11 pub(super) fn $name(&mut self, source: AddressingMode, dest: AddressingMode) -> ExecuteResult<u32> { 12 let operand_l = self.$read_method(source)?; 13 14 let dest_resolved = self.resolve_address_with_post(dest, $size)?; 15 let operand_r = self.$read_resolved_method(dest_resolved)?; 16 17 let value = operand_l $operator operand_r; 18 19 self.cpu.registers.ccr = ConditionCodes { 20 carry: false, 21 overflow: false, 22 zero: value == 0, 23 negative: value.sign_bit(), 24 ..self.cpu.registers.ccr 25 }; 26 27 self.$write_method(dest_resolved, value)?; 28 29 Ok(super::binary_op_cycles($size, source, dest)) 30 } 31 } 32} 33 34macro_rules! impl_bit_op_all_sizes { 35 ($byte_name:ident, $word_name:ident, $long_word_name:ident, $operator:tt) => { 36 impl_bit_op!( 37 $byte_name, 38 $operator, 39 read_byte, 40 read_byte_resolved_as_result, 41 write_byte_resolved_as_result, 42 OpSize::Byte 43 ); 44 impl_bit_op!( 45 $word_name, 46 $operator, 47 read_word, 48 read_word_resolved, 49 write_word_resolved, 50 OpSize::Word 51 ); 52 impl_bit_op!( 53 $long_word_name, 54 $operator, 55 read_long_word, 56 read_long_word_resolved, 57 write_long_word_resolved, 58 OpSize::LongWord 59 ); 60 }; 61} 62 63macro_rules! impl_bit_op_to_ccr { 64 ($name:ident, $operator:tt) => { 65 pub(super) fn $name(&mut self) -> ExecuteResult<u32> { 66 let byte = self.read_byte(AddressingMode::Immediate)?; 67 let value = byte $operator (u8::from(self.cpu.registers.ccr)); 68 self.cpu.registers.ccr = value.into(); 69 70 Ok(20) 71 } 72 } 73} 74 75macro_rules! impl_bit_op_to_sr { 76 ($name:ident, $operator:tt) => { 77 pub(super) fn $name(&mut self) -> ExecuteResult<u32> { 78 if !self.cpu.registers.supervisor_mode { 79 return Err(Exception::PrivilegeViolation); 80 } 81 82 let word = self.read_word(AddressingMode::Immediate)?; 83 let value = word $operator self.cpu.registers.status_register(); 84 self.cpu.registers.set_status_register(value); 85 86 Ok(20) 87 } 88 } 89} 90 91macro_rules! impl_not { 92 ($name:ident, $read_method:ident, $write_method:ident, $size:expr) => { 93 pub(super) fn $name(&mut self, dest: AddressingMode) -> ExecuteResult<u32> { 94 let dest_resolved = self.resolve_address_with_post(dest, $size)?; 95 let value = self.$read_method(dest_resolved)?; 96 let negated = !value; 97 98 self.cpu.registers.ccr = ConditionCodes { 99 carry: false, 100 overflow: false, 101 zero: negated == 0, 102 negative: negated.sign_bit(), 103 ..self.cpu.registers.ccr 104 }; 105 106 self.$write_method(dest_resolved, negated)?; 107 108 Ok(super::unary_op_cycles($size, dest)) 109 } 110 }; 111} 112 113macro_rules! impl_clr { 114 ($name:ident, $read_method:ident, $write_method:ident, $size:expr) => { 115 pub(super) fn $name(&mut self, dest: AddressingMode) -> ExecuteResult<u32> { 116 let dest_resolved = self.resolve_address_with_post(dest, $size)?; 117 // No-op read 118 self.$read_method(dest_resolved)?; 119 120 self.cpu.registers.ccr = ConditionCodes { 121 carry: false, 122 overflow: false, 123 zero: true, 124 negative: false, 125 ..self.cpu.registers.ccr 126 }; 127 128 self.$write_method(dest_resolved, 0)?; 129 130 Ok(super::unary_op_cycles($size, dest)) 131 } 132 }; 133} 134 135macro_rules! impl_bit_test_op { 136 (@cycle_count $source:expr, $dest:expr, $bit:expr $(, $extra_d_write_cycles:expr)?) => { 137 { 138 let dest_cycles = if $dest.is_data_direct() { 139 2 $(+ $extra_d_write_cycles)? + if $bit % 32 < 16 { 0 } else { 2 } 140 } else { 141 4 + $dest.address_calculation_cycles(OpSize::Byte) 142 }; 143 144 let source_cycles = match $source { 145 AddressingMode::Immediate => 4, 146 _ => 0 147 }; 148 149 4 + source_cycles + dest_cycles 150 } 151 }; 152 ($name:ident, |$value:ident, $bit:ident| $body:block $(, extra_d_write_cycles: $extra_d_write_cycles:expr)?) => { 153 pub(super) fn $name(&mut self, source: AddressingMode, dest: AddressingMode) -> ExecuteResult<u32> { 154 let bit_index = self.read_byte(source)?; 155 156 match dest { 157 AddressingMode::DataDirect(register) => { 158 let $value = register.read_from(&self.cpu.registers); 159 let $bit = bit_index % 32; 160 self.cpu.registers.ccr.zero = !$value.bit($bit); 161 162 let value = $body; 163 register.write_long_word_to(&mut self.cpu.registers, value); 164 } 165 _ => { 166 let dest_resolved = self.resolve_address_with_post(dest, OpSize::Byte)?; 167 let $value = self.read_byte_resolved(dest_resolved); 168 let $bit = bit_index % 8; 169 self.cpu.registers.ccr.zero = !$value.bit($bit); 170 171 let value = $body; 172 self.write_byte_resolved(dest_resolved, value); 173 } 174 } 175 176 let cycles = impl_bit_test_op!(@cycle_count source, dest, bit_index $(, $extra_d_write_cycles)?); 177 Ok(cycles) 178 } 179 }; 180} 181 182macro_rules! impl_shift_register_op { 183 ( 184 $name:ident, 185 $operator:tt, 186 $signed_t:ty, 187 $unsigned_t:ty, 188 $register_write_method:ident, 189 carry: $carry_bit:expr 190 $(, set $overflow:ident)? 191 ) => { 192 fn $name(&mut self, register: DataRegister, count: ShiftCount) -> u32 { 193 let shifts = count.get(&self.cpu.registers) % 64; 194 195 self.cpu.registers.ccr.carry = false; 196 self.cpu.registers.ccr.overflow = false; 197 198 let mut value = register.read_from(&self.cpu.registers) as $signed_t; 199 200 for _ in 0..shifts { 201 let carry = value.bit($carry_bit); 202 self.cpu.registers.ccr.carry = carry; 203 self.cpu.registers.ccr.extend = carry; 204 205 $( 206 if value.sign_bit() != (value $operator 1).sign_bit() { 207 self.cpu.registers.ccr.$overflow = true; 208 } 209 )? 210 211 value = value $operator 1; 212 } 213 214 register.$register_write_method(&mut self.cpu.registers, value as $unsigned_t); 215 216 self.cpu.registers.ccr.zero = value == 0; 217 self.cpu.registers.ccr.negative = value.sign_bit(); 218 219 shifts.into() 220 } 221 } 222} 223 224macro_rules! impl_rotate_register_op { 225 (@set_initial_carry) => { 226 false 227 }; 228 (@set_initial_carry $extend:expr) => { 229 $extend 230 }; 231 (@set_carry $carry:expr) => { 232 $carry 233 }; 234 (@set_carry $carry:expr, $extend:expr) => { 235 $extend 236 }; 237 ( 238 $name:ident, 239 $operator:tt, 240 $t:ty, 241 $register_write_method:ident, 242 carry: $carry_bit:expr 243 $(, rotate_in: $opposite_op:tt $opposite_shift:expr)? 244 $(, thru $extend:ident)? 245 ) => { 246 fn $name(&mut self, register: DataRegister, count: ShiftCount) -> u32 { 247 let rotates = count.get(&self.cpu.registers) % 64; 248 249 self.cpu.registers.ccr.overflow = false; 250 self.cpu.registers.ccr.carry = impl_rotate_register_op!(@set_initial_carry $( self.cpu.registers.ccr.$extend )?); 251 252 let mut value = register.read_from(&self.cpu.registers) as $t; 253 for _ in 0..rotates { 254 let carry = value.bit($carry_bit); 255 let rotating_in = impl_rotate_register_op!(@set_carry carry $(, self.cpu.registers.ccr.$extend )?); 256 257 value = (value $operator 1) | (<$t>::from(rotating_in) $( $opposite_op $opposite_shift )? ); 258 259 self.cpu.registers.ccr.carry = carry; 260 $( 261 self.cpu.registers.ccr.$extend = carry; 262 )? 263 } 264 265 register.$register_write_method(&mut self.cpu.registers, value); 266 267 self.cpu.registers.ccr.zero = value == 0; 268 self.cpu.registers.ccr.negative = value.sign_bit(); 269 270 rotates.into() 271 } 272 }; 273} 274 275macro_rules! impl_tst { 276 ($name:ident, $read_method:ident, $size:expr) => { 277 pub(super) fn $name(&mut self, source: AddressingMode) -> ExecuteResult<u32> { 278 let value = self.$read_method(source)?; 279 280 self.cpu.registers.ccr = ConditionCodes { 281 carry: false, 282 overflow: false, 283 zero: value == 0, 284 negative: value.sign_bit(), 285 ..self.cpu.registers.ccr 286 }; 287 288 Ok(4 + source.address_calculation_cycles($size)) 289 } 290 }; 291} 292 293#[allow(clippy::assign_op_pattern)] 294impl<B: BusInterface> InstructionExecutor<'_, '_, B> { 295 impl_bit_op_all_sizes!(and_byte, and_word, and_long_word, &); 296 impl_bit_op_all_sizes!(or_byte, or_word, or_long_word, |); 297 impl_bit_op_all_sizes!(eor_byte, eor_word, eor_long_word, ^); 298 299 impl_bit_op_to_ccr!(andi_to_ccr, &); 300 impl_bit_op_to_ccr!(ori_to_ccr, |); 301 impl_bit_op_to_ccr!(eori_to_ccr, ^); 302 303 impl_bit_op_to_sr!(andi_to_sr, &); 304 impl_bit_op_to_sr!(ori_to_sr, |); 305 impl_bit_op_to_sr!(eori_to_sr, ^); 306 307 pub(super) fn btst( 308 &mut self, 309 source: AddressingMode, 310 dest: AddressingMode, 311 ) -> ExecuteResult<u32> { 312 let bit_index = self.read_byte(source)?; 313 314 match dest { 315 AddressingMode::DataDirect(register) => { 316 let value = register.read_from(&self.cpu.registers); 317 let bit = bit_index % 32; 318 self.cpu.registers.ccr.zero = !value.bit(bit); 319 } 320 _ => { 321 let dest_resolved = self.resolve_address_with_post(dest, OpSize::Byte)?; 322 let value = self.read_byte_resolved(dest_resolved); 323 let bit = bit_index % 8; 324 self.cpu.registers.ccr.zero = !value.bit(bit); 325 } 326 } 327 328 let dest_cycles = match dest { 329 AddressingMode::DataDirect(..) => 2, 330 AddressingMode::Immediate => 6, 331 _ => dest.address_calculation_cycles(OpSize::Byte), 332 }; 333 334 let source_cycles = match source { 335 AddressingMode::Immediate => 4, 336 _ => 0, 337 }; 338 339 Ok(4 + source_cycles + dest_cycles) 340 } 341 342 impl_bit_test_op!(bclr, |value, bit| { value & !(1 << bit) }, extra_d_write_cycles: 2); 343 impl_bit_test_op!(bset, |value, bit| { value | (1 << bit) }); 344 impl_bit_test_op!(bchg, |value, bit| { 345 if value.bit(bit) { value & !(1 << bit) } else { value | (1 << bit) } 346 }); 347 348 impl_shift_register_op!(asl_register_u8, <<, i8, u8, write_byte_to, carry: 7, set overflow); 349 impl_shift_register_op!(asl_register_u16, <<, i16, u16, write_word_to, carry: 15, set overflow); 350 impl_shift_register_op!(asl_register_u32, <<, i32, u32, write_long_word_to, carry: 31, set overflow); 351 352 impl_shift_register_op!(asr_register_u8, >>, i8, u8, write_byte_to, carry: 0, set overflow); 353 impl_shift_register_op!(asr_register_u16, >>, i16, u16, write_word_to, carry: 0, set overflow); 354 impl_shift_register_op!(asr_register_u32, >>, i32, u32, write_long_word_to, carry: 0, set overflow); 355 356 impl_shift_register_op!(lsl_register_u8, <<, u8, u8, write_byte_to, carry: 7); 357 impl_shift_register_op!(lsl_register_u16, <<, u16, u16, write_word_to, carry: 15); 358 impl_shift_register_op!(lsl_register_u32, <<, u32, u32, write_long_word_to, carry: 31); 359 360 impl_shift_register_op!(lsr_register_u8, >>, u8, u8, write_byte_to, carry: 0); 361 impl_shift_register_op!(lsr_register_u16, >>, u16, u16, write_word_to, carry: 0); 362 impl_shift_register_op!(lsr_register_u32, >>, u32, u32, write_long_word_to, carry: 0); 363 364 impl_rotate_register_op!(rol_register_u8, <<, u8, write_byte_to, carry: 7); 365 impl_rotate_register_op!(rol_register_u16, <<, u16, write_word_to, carry: 15); 366 impl_rotate_register_op!(rol_register_u32, <<, u32, write_long_word_to, carry: 31); 367 368 impl_rotate_register_op!(ror_register_u8, >>, u8, write_byte_to, carry: 0, rotate_in: << 7); 369 impl_rotate_register_op!(ror_register_u16, >>, u16, write_word_to, carry: 0, rotate_in: << 15); 370 impl_rotate_register_op!(ror_register_u32, >>, u32, write_long_word_to, carry: 0, rotate_in: << 31); 371 372 impl_rotate_register_op!(roxl_register_u8, <<, u8, write_byte_to, carry: 7, thru extend); 373 impl_rotate_register_op!(roxl_register_u16, <<, u16, write_word_to, carry: 15, thru extend); 374 impl_rotate_register_op!(roxl_register_u32, <<, u32, write_long_word_to, carry: 31, thru extend); 375 376 impl_rotate_register_op!(roxr_register_u8, >>, u8, write_byte_to, carry: 0, rotate_in: << 7, thru extend); 377 impl_rotate_register_op!(roxr_register_u16, >>, u16, write_word_to, carry: 0, rotate_in: << 15, thru extend); 378 impl_rotate_register_op!(roxr_register_u32, >>, u32, write_long_word_to, carry: 0, rotate_in: << 31, thru extend); 379 380 impl_not!(not_byte, read_byte_resolved_as_result, write_byte_resolved_as_result, OpSize::Byte); 381 impl_not!(not_word, read_word_resolved, write_word_resolved, OpSize::Word); 382 impl_not!(not_long_word, read_long_word_resolved, write_long_word_resolved, OpSize::LongWord); 383 384 impl_clr!(clr_byte, read_byte_resolved_as_result, write_byte_resolved_as_result, OpSize::Byte); 385 impl_clr!(clr_word, read_word_resolved, write_word_resolved, OpSize::Word); 386 impl_clr!(clr_long_word, read_long_word_resolved, write_long_word_resolved, OpSize::LongWord); 387 388 pub(super) fn ext(&mut self, size: OpSize, register: DataRegister) -> u32 { 389 let (zero, sign) = match size { 390 OpSize::Word => { 391 let byte = register.read_from(&self.cpu.registers) as u8; 392 let sign_extended = byte as i8 as u16; 393 register.write_word_to(&mut self.cpu.registers, sign_extended); 394 (sign_extended == 0, sign_extended.sign_bit()) 395 } 396 OpSize::LongWord => { 397 let word = register.read_from(&self.cpu.registers) as u16; 398 let sign_extended = word as i16 as u32; 399 register.write_long_word_to(&mut self.cpu.registers, sign_extended); 400 (sign_extended == 0, sign_extended.sign_bit()) 401 } 402 OpSize::Byte => panic!("EXT does not support size byte"), 403 }; 404 405 self.cpu.registers.ccr = ConditionCodes { 406 carry: false, 407 overflow: false, 408 zero, 409 negative: sign, 410 ..self.cpu.registers.ccr 411 }; 412 413 4 414 } 415 416 pub(super) fn swap(&mut self, register: DataRegister) -> u32 { 417 let [b3, b2, b1, b0] = register.read_from(&self.cpu.registers).to_be_bytes(); 418 let value = u32::from_be_bytes([b1, b0, b3, b2]); 419 register.write_long_word_to(&mut self.cpu.registers, value); 420 421 self.cpu.registers.ccr = ConditionCodes { 422 carry: false, 423 overflow: false, 424 zero: value == 0, 425 negative: value.sign_bit(), 426 ..self.cpu.registers.ccr 427 }; 428 429 4 430 } 431 432 pub(super) fn asd_register( 433 &mut self, 434 size: OpSize, 435 direction: ShiftDirection, 436 register: DataRegister, 437 count: ShiftCount, 438 ) -> u32 { 439 let shifts = match (size, direction) { 440 (OpSize::Byte, ShiftDirection::Left) => self.asl_register_u8(register, count), 441 (OpSize::Byte, ShiftDirection::Right) => self.asr_register_u8(register, count), 442 (OpSize::Word, ShiftDirection::Left) => self.asl_register_u16(register, count), 443 (OpSize::Word, ShiftDirection::Right) => self.asr_register_u16(register, count), 444 (OpSize::LongWord, ShiftDirection::Left) => self.asl_register_u32(register, count), 445 (OpSize::LongWord, ShiftDirection::Right) => self.asr_register_u32(register, count), 446 }; 447 448 shift_register_cycles(size, shifts) 449 } 450 451 pub(super) fn asd_memory( 452 &mut self, 453 direction: ShiftDirection, 454 dest: AddressingMode, 455 ) -> ExecuteResult<u32> { 456 let dest_resolved = self.resolve_address_with_post(dest, OpSize::Word)?; 457 let original = self.read_word_resolved(dest_resolved)?; 458 459 let (value, carry) = match direction { 460 ShiftDirection::Left => (original << 1, original.bit(15)), 461 ShiftDirection::Right => ((original >> 1) | (original & 0x8000), original.bit(0)), 462 }; 463 464 let overflow = original.sign_bit() != value.sign_bit(); 465 466 self.cpu.registers.ccr = ConditionCodes { 467 carry, 468 overflow, 469 zero: value == 0, 470 negative: value.sign_bit(), 471 extend: carry, 472 }; 473 474 self.write_word_resolved(dest_resolved, value)?; 475 476 Ok(shift_memory_cycles(dest)) 477 } 478 479 pub(super) fn lsd_register( 480 &mut self, 481 size: OpSize, 482 direction: ShiftDirection, 483 register: DataRegister, 484 count: ShiftCount, 485 ) -> u32 { 486 let shifts = match (size, direction) { 487 (OpSize::Byte, ShiftDirection::Left) => self.lsl_register_u8(register, count), 488 (OpSize::Byte, ShiftDirection::Right) => self.lsr_register_u8(register, count), 489 (OpSize::Word, ShiftDirection::Left) => self.lsl_register_u16(register, count), 490 (OpSize::Word, ShiftDirection::Right) => self.lsr_register_u16(register, count), 491 (OpSize::LongWord, ShiftDirection::Left) => self.lsl_register_u32(register, count), 492 (OpSize::LongWord, ShiftDirection::Right) => self.lsr_register_u32(register, count), 493 }; 494 495 shift_register_cycles(size, shifts) 496 } 497 498 pub(super) fn lsd_memory( 499 &mut self, 500 direction: ShiftDirection, 501 dest: AddressingMode, 502 ) -> ExecuteResult<u32> { 503 let dest_resolved = self.resolve_address_with_post(dest, OpSize::Word)?; 504 let original = self.read_word_resolved(dest_resolved)?; 505 506 let (value, carry) = match direction { 507 ShiftDirection::Left => (original << 1, original.bit(15)), 508 ShiftDirection::Right => (original >> 1, original.bit(0)), 509 }; 510 511 self.cpu.registers.ccr = ConditionCodes { 512 carry, 513 overflow: false, 514 zero: value == 0, 515 negative: value.sign_bit(), 516 extend: carry, 517 }; 518 519 self.write_word_resolved(dest_resolved, value)?; 520 521 Ok(shift_memory_cycles(dest)) 522 } 523 524 pub(super) fn rod_register( 525 &mut self, 526 size: OpSize, 527 direction: ShiftDirection, 528 register: DataRegister, 529 count: ShiftCount, 530 ) -> u32 { 531 let rotates = match (size, direction) { 532 (OpSize::Byte, ShiftDirection::Left) => self.rol_register_u8(register, count), 533 (OpSize::Byte, ShiftDirection::Right) => self.ror_register_u8(register, count), 534 (OpSize::Word, ShiftDirection::Left) => self.rol_register_u16(register, count), 535 (OpSize::Word, ShiftDirection::Right) => self.ror_register_u16(register, count), 536 (OpSize::LongWord, ShiftDirection::Left) => self.rol_register_u32(register, count), 537 (OpSize::LongWord, ShiftDirection::Right) => self.ror_register_u32(register, count), 538 }; 539 540 shift_register_cycles(size, rotates) 541 } 542 543 pub(super) fn rod_memory( 544 &mut self, 545 direction: ShiftDirection, 546 dest: AddressingMode, 547 ) -> ExecuteResult<u32> { 548 let dest_resolved = self.resolve_address_with_post(dest, OpSize::Word)?; 549 let original = self.read_word_resolved(dest_resolved)?; 550 551 let (value, carry) = match direction { 552 ShiftDirection::Left => { 553 ((original << 1) | u16::from(original.sign_bit()), original.sign_bit()) 554 } 555 ShiftDirection::Right => { 556 ((original >> 1) | (u16::from(original.bit(0)) << 15), original.bit(0)) 557 } 558 }; 559 560 self.cpu.registers.ccr = ConditionCodes { 561 carry, 562 overflow: false, 563 zero: value == 0, 564 negative: value.sign_bit(), 565 ..self.cpu.registers.ccr 566 }; 567 568 self.write_word_resolved(dest_resolved, value)?; 569 570 Ok(shift_memory_cycles(dest)) 571 } 572 573 pub(super) fn roxd_register( 574 &mut self, 575 size: OpSize, 576 direction: ShiftDirection, 577 register: DataRegister, 578 count: ShiftCount, 579 ) -> u32 { 580 let rotates = match (size, direction) { 581 (OpSize::Byte, ShiftDirection::Left) => self.roxl_register_u8(register, count), 582 (OpSize::Byte, ShiftDirection::Right) => self.roxr_register_u8(register, count), 583 (OpSize::Word, ShiftDirection::Left) => self.roxl_register_u16(register, count), 584 (OpSize::Word, ShiftDirection::Right) => self.roxr_register_u16(register, count), 585 (OpSize::LongWord, ShiftDirection::Left) => self.roxl_register_u32(register, count), 586 (OpSize::LongWord, ShiftDirection::Right) => self.roxr_register_u32(register, count), 587 }; 588 589 shift_register_cycles(size, rotates) 590 } 591 592 pub(super) fn roxd_memory( 593 &mut self, 594 direction: ShiftDirection, 595 dest: AddressingMode, 596 ) -> ExecuteResult<u32> { 597 let dest_resolved = self.resolve_address_with_post(dest, OpSize::Word)?; 598 let original = self.read_word_resolved(dest_resolved)?; 599 600 let extend = self.cpu.registers.ccr.extend; 601 let (value, carry) = match direction { 602 ShiftDirection::Left => ((original << 1) | u16::from(extend), original.bit(15)), 603 ShiftDirection::Right => ((original >> 1) | (u16::from(extend) << 15), original.bit(0)), 604 }; 605 606 self.cpu.registers.ccr = ConditionCodes { 607 carry, 608 overflow: false, 609 zero: value == 0, 610 negative: value.sign_bit(), 611 extend: carry, 612 }; 613 614 self.write_word_resolved(dest_resolved, value)?; 615 616 Ok(shift_memory_cycles(dest)) 617 } 618 619 impl_tst!(tst_byte, read_byte, OpSize::Byte); 620 impl_tst!(tst_word, read_word, OpSize::Word); 621 impl_tst!(tst_long_word, read_long_word, OpSize::LongWord); 622 623 pub(super) fn tas(&mut self, dest: AddressingMode) -> ExecuteResult<u32> { 624 let dest_resolved = self.resolve_address_with_post(dest, OpSize::Byte)?; 625 let value = self.read_byte_resolved(dest_resolved); 626 627 self.cpu.registers.ccr = ConditionCodes { 628 carry: false, 629 overflow: false, 630 zero: value == 0, 631 negative: value.sign_bit(), 632 ..self.cpu.registers.ccr 633 }; 634 635 if dest.is_data_direct() || self.cpu.allow_tas_writes { 636 self.write_byte_resolved(dest_resolved, value | 0x80); 637 } 638 639 Ok(if dest.is_data_direct() { 640 4 641 } else { 642 10 + dest.address_calculation_cycles(OpSize::Byte) 643 }) 644 } 645} 646 647fn shift_register_cycles(size: OpSize, shifts: u32) -> u32 { 648 let base_cycles = match size { 649 OpSize::Byte | OpSize::Word => 6, 650 OpSize::LongWord => 8, 651 }; 652 base_cycles + 2 * shifts 653} 654 655fn shift_memory_cycles(dest: AddressingMode) -> u32 { 656 8 + dest.address_calculation_cycles(OpSize::Word) 657}