1#![allow(clippy::unusual_byte_groupings)]
16
17use crate::addressing_modes::AddressingMode;
18use crate::instruction::{Direction, Size};
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum Condition {
23 T,
25 F,
27 HI,
29 LS,
31 CC,
33 CS,
35 NE,
37 EQ,
39 VC,
41 VS,
43 PL,
45 MI,
47 GE,
49 LT,
51 GT,
53 LE,
55}
56
57const MODES_2567: [u8; 4] = [2, 5, 6, 7];
59const MODES_234567: [u8; 6] = [2, 3, 4, 5, 6, 7];
61const MODES_0234567: [u8; 7] = [0, 2, 3, 4, 5, 6, 7];
63const MODES_01234567: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
65
66fn size_effective_address_immediate(bits8_15: u8, size: Size, am: AddressingMode, mut imm: u32) -> Vec<u16> {
68 let mut vec = Vec::new();
69
70 let (eafield, eaext) = am.assemble(size.is_long());
71 let opcode = (bits8_15 as u16) << 8
72 | Into::<u16>::into(size) << 6
73 | eafield;
74 vec.push(opcode);
75
76 if size.is_long() {
77 vec.push((imm >> 16) as u16);
78 } else if size.is_byte() {
79 imm &= 0x0000_00FF;
80 }
81 vec.push(imm as u16);
82 vec.extend(eaext.iter());
83
84 vec
85}
86
87fn effective_address_count(bits6_15: u16, am: AddressingMode, count: u8) -> Vec<u16> {
89 let mut vec = Vec::new();
90
91 let (eafield, eaext) = am.assemble(false);
92 let opcode = (bits6_15 & 0x3FF) << 6
93 | eafield;
94 vec.push(opcode);
95 vec.push(count as u16);
96 vec.extend(eaext.iter());
97
98 vec
99}
100
101fn effective_address(bits6_15: u16, am: AddressingMode) -> Vec<u16> {
103 let mut vec = Vec::new();
104
105 let (eafield, eaext) = am.assemble(false);
106 let opcode = (bits6_15 & 0x3FF) << 6
107 | eafield;
108 vec.push(opcode);
109 vec.extend(eaext.iter());
110
111 vec
112}
113
114fn size_effective_address(bits8_15: u8, size: Size, am: AddressingMode) -> Vec<u16> {
116 let mut vec = Vec::new();
117
118 let (eafield, eaext) = am.assemble(size.is_long());
119 let opcode = (bits8_15 as u16) << 8
120 | Into::<u16>::into(size) << 6
121 | eafield;
122 vec.push(opcode);
123 vec.extend(eaext.iter());
124
125 vec
126}
127
128fn register_effective_address(bits12_15: u16, reg: u16, bits6_8: u16, am: AddressingMode) -> Vec<u16> {
130 let mut vec = Vec::new();
131
132 let (eafield, eaext) = am.assemble(false);
133 let opcode = (bits12_15 & 0xF) << 12
134 | (reg & 7) << 9
135 | (bits6_8 & 7) << 6
136 | eafield;
137 vec.push(opcode);
138 vec.extend(eaext.iter());
139
140 vec
141}
142
143fn size_effective_address_effective_address(size: Size, dst: AddressingMode, src: AddressingMode) -> Vec<u16> {
145 let mut vec = Vec::new();
146
147 let src = src.assemble(size.is_long());
148 let dst = dst.assemble_move_dst();
149 let opcode = size.into_move() << 12 | dst.0 | src.0;
150
151 vec.push(opcode);
152 vec.extend(src.1.iter());
153 vec.extend(dst.1.iter());
154
155 vec
156}
157
158fn register(bits3_15: u16, reg: u8) -> u16 {
160 bits3_15 << 3 | reg as u16 & 7
161}
162
163fn data_size_effective_address(data: u8, bit8: u16, size: Size, am: AddressingMode) -> Vec<u16> {
165 let mut vec = Vec::new();
166
167 let (eafield, eaext) = am.assemble(size.is_long());
168 let opcode = 0b0101 << 12
169 | (data as u16 & 7) << 9
170 | (bit8 & 1) << 8
171 | Into::<u16>::into(size) << 6
172 | eafield;
173 vec.push(opcode);
174 vec.extend(eaext.iter());
175
176 vec
177}
178
179fn condition_displacement(cond: Condition, disp: i16) -> Vec<u16> {
183 let mut vec = Vec::new();
184
185 let mut opcode = 0b0110 << 12 | (cond as u16) << 8;
186
187 if disp < i8::MIN as i16 || disp > i8::MAX as i16 || disp == 0 {
188 vec.push(opcode);
189 vec.push(disp as u16);
190 } else {
191 opcode |= disp as u8 as u16;
192 vec.push(opcode);
193 }
194
195 vec
196}
197
198fn register_direction_size_effective_address(bits12_15: u16, reg: u8, dir: Direction, size: Size, am: AddressingMode) -> Vec<u16> {
202 let mut vec = Vec::new();
203
204 let (eafield, eaext) = am.assemble(size.is_long());
205 let opcode = bits12_15 << 12
206 | (reg as u16) << 9
207 | if dir == Direction::DstEa { 1 } else { 0 } << 8
208 | Into::<u16>::into(size) << 6
209 | eafield;
210 vec.push(opcode);
211 vec.extend(eaext.iter());
212
213 vec
214}
215
216fn register_size_effective_address(bits12_15: u16, reg: u8, size: Size, am: AddressingMode) -> Vec<u16> {
218 let mut vec = Vec::new();
219
220 let (eafield, eaext) = am.assemble(size.is_long());
221 let opcode = bits12_15 << 12
222 | (reg as u16 & 7) << 9
223 | size.into_bit() << 8
224 | 0b11 << 6
225 | eafield;
226 vec.push(opcode);
227 vec.extend(eaext.iter());
228
229 vec
230}
231
232fn register_size_mode_register(bits12_15: u16, dst: u8, size: Size, bits4_5: u16, mode: Direction, src: u8) -> u16 {
236 let mut opcode = (bits12_15 & 0xF) << 12
237 | (dst as u16 & 7) << 9
238 | 1 << 8
239 | Into::<u16>::into(size) << 6
240 | (bits4_5 & 3) << 4
241 | src as u16 & 7;
242 if mode == Direction::MemoryToMemory {
243 opcode |= 0x0008;
244 }
245
246 opcode
247}
248
249fn direction_effective_address(bits9_15: u16, dir: Direction, bits6_7: u16, am: AddressingMode) -> Vec<u16> {
251 let mut vec = Vec::new();
252
253 let (eafield, eaext) = am.assemble(false);
254 let mut opcode = (bits9_15 & 0x7F) << 9
255 | (bits6_7 & 3) << 6
256 | eafield;
257 if dir == Direction::Left {
258 opcode |= 0x0100;
259 }
260 vec.push(opcode);
261 vec.extend(eaext.iter());
262
263 vec
264}
265
266fn rotation_direction_size_mode_register(bits12_15: u16, count_reg: u16, dir: Direction, size: Size, ir: u16, bits3_4: u16, reg: u16) -> u16 {
268 let mut opcode = (bits12_15 & 0xF) << 12
269 | (count_reg & 7) << 9
270 | Into::<u16>::into(size) << 6
271 | (ir & 1) << 5
272 | (bits3_4 & 3) << 3
273 | reg & 7;
274 if dir == Direction::Left {
275 opcode |= 0x0100;
276 }
277
278 opcode
279}
280
281pub fn abcd(dst: u8, mode: Direction, src: u8) -> u16 {
283 assert!(dst <= 7, "Invalid destination register number {}.", dst);
284 assert!(mode == Direction::RegisterToRegister || mode == Direction::MemoryToMemory, "Invalid mode.");
285 assert!(src <= 7, "Invalid source register number {}.", dst);
286 register_size_mode_register(0b1100, dst, Size::Byte, 0, mode, src)
287}
288
289pub fn add(reg: u8, dir: Direction, size: Size, am: AddressingMode) -> Vec<u16> {
291 assert!(reg <= 7, "Invalid register.");
292 assert!(dir == Direction::DstEa || dir == Direction::DstReg, "Invalid direction.");
293 if dir == Direction::DstEa {
294 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode.");
295 } else {
296 assert!(!(am.is_ard() && size.is_byte()), "Byte size cannot be used with Address Register Direct source operand.");
297 assert!(am.verify(&MODES_01234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode.");
298 }
299 register_direction_size_effective_address(0b1101, reg, dir, size, am)
300}
301
302pub fn adda(reg: u8, size: Size, am: AddressingMode) -> Vec<u16> {
303 assert!(reg <= 7, "Invalid register.");
304 assert!(!size.is_byte(), "ADDA cannot be byte sized.");
305 register_size_effective_address(0b1101, reg, size, am)
306}
307
308pub fn addi(size: Size, am: AddressingMode, imm: u32) -> Vec<u16> {
309 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in ADDI assembler");
310 size_effective_address_immediate(0b0000_0110, size, am, imm)
311}
312
313pub fn addq(data: u8, size: Size, am: AddressingMode) -> Vec<u16> {
315 assert!(am.verify(&MODES_01234567, &[0, 1]), "Invalid addressing mode.");
316 assert!(!(am.is_ard() && size.is_byte()), "Byte size cannot be used with Address Register Direct destination operand.");
317 assert!(data >= 1 && data <= 8, "Invalid data.");
318 let data = if data == 8 { 0 } else { data };
319 data_size_effective_address(data, 0, size, am)
320}
321
322pub fn addx(dst: u8, size: Size, mode: Direction, src: u8) -> u16 {
324 assert!(dst <= 7, "Invalid destination register number {}.", dst);
325 assert!(mode == Direction::RegisterToRegister || mode == Direction::MemoryToMemory, "Invalid mode.");
326 assert!(src <= 7, "Invalid source register number {}.", dst);
327 register_size_mode_register(0b1101, dst, size, 0, mode, src)
328}
329
330pub fn and(reg: u8, dir: Direction, size: Size, am: AddressingMode) -> Vec<u16> {
332 assert!(reg <= 7, "Invalid register.");
333 assert!(dir == Direction::DstEa || dir == Direction::DstReg, "Invalid direction.");
334 if dir == Direction::DstEa {
335 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode.");
336 } else {
337 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode.");
338 }
339 register_direction_size_effective_address(0b1100, reg, dir, size, am)
340}
341
342pub fn andi(size: Size, am: AddressingMode, imm: u32) -> Vec<u16> {
343 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in ANDI assembler");
344 size_effective_address_immediate(0b0000_0010, size, am, imm)
345}
346
347pub fn andiccr(imm: u16) -> [u16; 2] {
348 [0x023C, imm & 0x00FF]
349}
350
351pub fn andisr(imm: u16) -> [u16; 2] {
352 [0x027C, imm]
353}
354
355pub fn asm(dir: Direction, am: AddressingMode) -> Vec<u16> {
357 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in ASm assembler: expected left or right, got {:?}", dir);
358 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode field in ASm assembler");
359 direction_effective_address(0b1110_000, dir, 0b11, am)
360}
361
362pub fn asr(count_reg: u16, dir: Direction, size: Size, reg_shift: bool, reg: u16) -> u16 {
364 assert!(count_reg <= 7, "Invalid count/register field in ASr assembler: expected 0 to 7, got {}", count_reg);
365 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in ASr assembler: expected left or right, got {:?}", dir);
366 assert!(reg <= 7, "Invalid register field in ASr assembler: expected 0 to 7, got {}", reg);
367 rotation_direction_size_mode_register(0b1110, count_reg, dir, size, reg_shift as u16, 0b00, reg)
368}
369
370pub fn bcc(cond: Condition, disp: i16) -> Vec<u16> {
372 assert!(cond != Condition::T && cond != Condition::F, "Invalid condition.");
373 condition_displacement(cond, disp)
374}
375
376pub fn bchg_dynamic(reg: u8, am: AddressingMode) -> Vec<u16> {
377 assert!(reg <= 7, "Invalid register field in BCHG dynamic assembler: expected 0 to 7, got {}", reg);
378 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in BCHG dynamic assembler");
379 register_effective_address(0b0000, reg as u16, 0b101, am)
380}
381
382pub fn bchg_static(am: AddressingMode, count: u8) -> Vec<u16> {
383 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in BCHG static assembler");
384 effective_address_count(0b0000_1000_01, am, count)
385}
386
387pub fn bclr_dynamic(reg: u8, am: AddressingMode) -> Vec<u16> {
388 assert!(reg <= 7, "Invalid register field in BCLR dynamic assembler: expected 0 to 7, got {}", reg);
389 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in BCLR dynamic assembler");
390 register_effective_address(0b0000, reg as u16, 0b110, am)
391}
392
393pub fn bclr_static(am: AddressingMode, count: u8) -> Vec<u16> {
394 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in BCLR static assembler");
395 effective_address_count(0b0000_1000_10, am, count)
396}
397
398pub fn bra(disp: i16) -> Vec<u16> {
400 condition_displacement(Condition::T, disp)
401}
402
403pub fn bset_dynamic(reg: u8, am: AddressingMode) -> Vec<u16> {
404 assert!(reg <= 7, "Invalid register field in BSET dynamic assembler: expected 0 to 7, got {}", reg);
405 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in BSET dynamic assembler");
406 register_effective_address(0b0000, reg as u16, 0b111, am)
407}
408
409pub fn bset_static(am: AddressingMode, count: u8) -> Vec<u16> {
410 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in BSET static assembler");
411 effective_address_count(0b0000_1000_11, am, count)
412}
413
414pub fn bsr(disp: i16) -> Vec<u16> {
416 condition_displacement(Condition::F, disp)
417}
418
419pub fn btst_dynamic(reg: u8, am: AddressingMode) -> Vec<u16> {
420 assert!(reg <= 7, "Invalid register field in BTST dynamic assembler: expected 0 to 7, got {}", reg);
421 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in BTST dynamic assembler");
422 register_effective_address(0b0000, reg as u16, 0b100, am)
423}
424
425pub fn btst_static(am: AddressingMode, count: u8) -> Vec<u16> {
426 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in BTST static assembler");
427 effective_address_count(0b0000_1000_00, am, count)
428}
429
430pub fn chk(reg: u8, am: AddressingMode) -> Vec<u16> {
431 assert!(reg <= 7, "Invalid register field in CHK assembler: expected 0 to 7, got {}", reg);
432 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in CHK assembler");
433 register_effective_address(0b0100, reg as u16, 0b110, am)
434}
435
436pub fn clr(size: Size, am: AddressingMode) -> Vec<u16> {
437 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in CLR assembler");
438 size_effective_address(0b0100_0010, size, am)
439}
440
441pub fn cmp(reg: u8, size: Size, am: AddressingMode) -> Vec<u16> {
442 assert!(reg <= 7, "Invalid register.");
443 assert!(!(am.is_ard() && size.is_byte()), "Byte size cannot be used with Address Register Direct source operand.");
444 assert!(am.verify(&MODES_01234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode.");
445 register_direction_size_effective_address(0b1011, reg, Direction::DstReg, size, am)
446}
447
448pub fn cmpa(reg: u8, size: Size, am: AddressingMode) -> Vec<u16> {
449 assert!(reg <= 7, "Invalid register.");
450 assert!(!size.is_byte(), "CMPA cannot be byte sized.");
451 register_size_effective_address(0b1011, reg, size, am)
452}
453
454pub fn cmpi(size: Size, am: AddressingMode, imm: u32) -> Vec<u16> {
455 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in CMPI assembler");
456 size_effective_address_immediate(0b0000_1100, size, am, imm)
457}
458
459pub fn cmpm(ax: u8, size: Size, ay: u8) -> u16 {
460 assert!(ax <= 7, "Invalid destination register.");
461 assert!(ay <= 7, "Invalid source register.");
462 0b1011_0001 << 8 | (ax as u16 & 7) << 9 | Into::<u16>::into(size) << 6 | 0b001 << 3 | ay as u16 & 7
463}
464
465pub fn dbcc(cond: Condition, reg: u8, disp: i16) -> [u16; 2] {
466 assert!(reg <= 7, "Invalid register.");
467 [0b0101 << 12 | (cond as u16) << 8 | 0b1100_1 << 3 | reg as u16 & 7, disp as u16]
468}
469
470pub fn divs(reg: u8, am: AddressingMode) -> Vec<u16> {
471 assert!(reg <= 7, "Invalid register field in DIVS assembler: expected 0 to 7, got {}", reg);
472 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in DIVS assembler");
473 register_effective_address(0b1000, reg as u16, 0b111, am)
474}
475
476pub fn divu(reg: u8, am: AddressingMode) -> Vec<u16> {
477 assert!(reg <= 7, "Invalid register field in DIVU assembler: expected 0 to 7, got {}", reg);
478 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in DIVU assembler");
479 register_effective_address(0b1000, reg as u16, 0b011, am)
480}
481
482pub fn eor(reg: u8, size: Size, am: AddressingMode) -> Vec<u16> {
483 assert!(reg <= 7, "Invalid register.");
484 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode.");
485 register_direction_size_effective_address(0b1011, reg, Direction::DstEa, size, am)
486}
487
488pub fn eori(size: Size, am: AddressingMode, imm: u32) -> Vec<u16> {
489 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in EORI assembler");
490 size_effective_address_immediate(0b0000_1010, size, am, imm)
491}
492
493pub fn eoriccr(imm: u16) -> [u16; 2] {
494 [0x0A3C, imm & 0x00FF]
495}
496
497pub fn eorisr(imm: u16) -> [u16; 2] {
498 [0x0A7C, imm]
499}
500
501pub fn exg(rx: u8, dir: Direction, ry: u8) -> u16 {
503 assert!(dir == Direction::ExchangeData || dir == Direction::ExchangeAddress || dir == Direction::ExchangeDataAddress, "Invalid operation");
504 assert!(rx <= 7, "Invalid Rx register.");
505 assert!(ry <= 7, "Invalid Ry register.");
506 let opmode = if dir == Direction::ExchangeData {
507 0b01000
508 } else if dir == Direction::ExchangeAddress {
509 0b01001
510 } else {
511 0b10001
512 };
513 0b1100_0001 << 8 | (rx as u16) << 9 | opmode << 3 | ry as u16 & 7
514}
515
516pub fn ext(word_to_long: bool, reg: u8) -> u16 {
518 assert!(reg <= 7, "Invalid register.");
519 0b0100_1000_1 << 7 | (word_to_long as u16) << 6 | reg as u16 & 7
520}
521
522pub fn illegal() -> u16 {
523 0x4AFC
524}
525
526pub fn jmp(am: AddressingMode) -> Vec<u16> {
527 assert!(am.verify(&MODES_2567, &[0, 1, 2, 3]), "Invalid addressing mode in JMP assembler");
528 effective_address(0b0100_1110_11, am)
529}
530
531pub fn jsr(am: AddressingMode) -> Vec<u16> {
532 assert!(am.verify(&MODES_2567, &[0, 1, 2, 3]), "Invalid addressing mode in JSR assembler");
533 effective_address(0b0100_1110_10, am)
534}
535
536pub fn lea(reg: u8, am: AddressingMode) -> Vec<u16> {
537 assert!(reg <= 7, "Invalid register field in LEA assembler: expected 0 to 7, got {}", reg);
538 assert!(am.verify(&MODES_2567, &[0, 1, 2, 3]), "Invalid addressing mode in LEA assembler");
539 register_effective_address(0b0100, reg as u16, 0b111, am)
540}
541
542pub fn link(reg: u8, disp: i16) -> [u16; 2] {
543 assert!(reg <= 7, "Invalid register.");
544 [0b0100_1110_0101_0 << 3 | reg as u16 & 7, disp as u16]
545}
546
547pub fn lsm(dir: Direction, am: AddressingMode) -> Vec<u16> {
549 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in LSm assembler: expected left or right, got {:?}", dir);
550 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode field in LSm assembler");
551 direction_effective_address(0b1110_001, dir, 0b11, am)
552}
553
554pub fn lsr(count_reg: u16, dir: Direction, size: Size, reg_shift: bool, reg: u16) -> u16 {
556 assert!(count_reg <= 7, "Invalid count/register field in LSr assembler: expected 0 to 7, got {}", count_reg);
557 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in LSr assembler: expected left or right, got {:?}", dir);
558 assert!(reg <= 7, "Invalid register field in LSr assembler: expected 0 to 7, got {}", reg);
559 rotation_direction_size_mode_register(0b1110, count_reg, dir, size, reg_shift as u16, 0b01, reg)
560}
561
562pub fn r#move(size: Size, dst: AddressingMode, src: AddressingMode) -> Vec<u16> {
563 assert!(dst.verify(&MODES_0234567, &[0, 1]), "Invalid destination addressing mode.");
564 assert!(!(src.is_ard() && size.is_byte()), "Byte size cannot be used with Address Register Direct source operand.");
565 size_effective_address_effective_address(size, dst, src)
566}
567
568pub fn movea(size: Size, dst_reg: u8, src: AddressingMode) -> Vec<u16> {
569 assert!(dst_reg <= 7, "Invalid address register.");
570 assert!(size != Size::Byte, "MOVEA cannot be byte sized.");
571 size_effective_address_effective_address(size, AddressingMode::Ard(dst_reg), src)
572}
573
574pub fn moveccr(am: AddressingMode) -> Vec<u16> {
575 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in MOVE to CCR assembler");
576 effective_address(0b0100_0100_11, am)
577}
578
579pub fn movefsr(am: AddressingMode) -> Vec<u16> {
580 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in MOVE from SR assembler");
581 effective_address(0b0100_0000_11, am)
582}
583
584pub fn movesr(am: AddressingMode) -> Vec<u16> {
585 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in MOVE to SR assembler");
586 effective_address(0b0100_0110_11, am)
587}
588
589pub fn moveusp(dir: Direction, reg: u8) -> u16 {
591 assert!(dir == Direction::UspToRegister || dir == Direction::RegisterToUsp, "Invalid direction.");
592 assert!(reg <= 7, "Invalid register");
593 let d = if dir == Direction::UspToRegister { 1 } else { 0 };
594 0b0100_1110_0110 << 4 | d << 3 | reg as u16 & 7
595}
596
597pub fn movem(dir: Direction, size: Size, am: AddressingMode, mask: u16) -> Vec<u16> {
599 assert!(dir == Direction::RegisterToMemory || dir == Direction::MemoryToRegister, "Invalid direction.");
600 assert!(!size.is_byte(), "Invalid byte size for MOVEM.");
601 let d = if dir == Direction::MemoryToRegister {
602 assert!(am.verify(&[2, 3, 5, 6, 7], &[0, 1, 2, 3]), "Invalid addressing mode.");
603 1
604 } else {
605 assert!(am.verify(&[2, 4, 5, 6, 7], &[0, 1]), "Invalid addressing mode.");
606 0
607 };
608
609 let mut vec = Vec::new();
610
611 let (eafield, eaext) = am.assemble(size.is_long());
612 let opcode = 0b0100_1 << 11
613 | d << 10
614 | 0b001 << 7
615 | size.into_bit() << 6
616 | eafield;
617
618 vec.push(opcode);
619 vec.push(mask);
620 vec.extend(eaext.iter());
621
622 vec
623}
624
625pub fn movep(data_reg: u8, dir: Direction, size: Size, addr_reg: u8, disp: i16) -> [u16; 2] {
627 assert!(data_reg <= 7, "Invalid data register.");
628 assert!(dir == Direction::RegisterToMemory || dir == Direction::MemoryToRegister, "Invalid direction.");
629 assert!(!size.is_byte(), "Invalid byte size for MOVEP.");
630 assert!(addr_reg <= 7, "Invalid address register.");
631
632 let mut opcode = (data_reg as u16 & 7) << 9
633 | 0b1_0000_1 << 3
634 | addr_reg as u16 & 7;
635 if dir == Direction::RegisterToMemory {
636 opcode |= 0x0080;
637 }
638 if size.is_long() {
639 opcode |= 0x0040;
640 }
641 [opcode, disp as u16]
642}
643
644pub fn moveq(reg: u8, data: i8) -> u16 {
645 assert!(reg <= 7, "Invalid register.");
646 0b0111 << 12 | (reg as u16) << 9 | data as u8 as u16
647}
648
649pub fn muls(reg: u8, am: AddressingMode) -> Vec<u16> {
650 assert!(reg <= 7, "Invalid register field in MULS assembler: expected 0 to 7, got {}", reg);
651 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in MULS assembler");
652 register_effective_address(0b1100, reg as u16, 0b111, am)
653}
654
655pub fn mulu(reg: u8, am: AddressingMode) -> Vec<u16> {
656 assert!(reg <= 7, "Invalid register field in MULU assembler: expected 0 to 7, got {}", reg);
657 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode in MULU assembler");
658 register_effective_address(0b1100, reg as u16, 0b011, am)
659}
660
661pub fn nbcd(am: AddressingMode) -> Vec<u16> {
662 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in NBCD assembler");
663 effective_address(0b0100_1000_00, am)
664}
665
666pub fn neg(size: Size, am: AddressingMode) -> Vec<u16> {
667 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in NEG assembler");
668 size_effective_address(0b0100_0100, size, am)
669}
670
671pub fn negx(size: Size, am: AddressingMode) -> Vec<u16> {
672 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in NEGX assembler");
673 size_effective_address(0b0100_0000, size, am)
674}
675
676pub fn nop() -> u16 {
677 0x4E71
678}
679
680pub fn not(size: Size, am: AddressingMode) -> Vec<u16> {
681 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in NOT assembler");
682 size_effective_address(0b0100_0110, size, am)
683}
684
685pub fn or(reg: u8, dir: Direction, size: Size, am: AddressingMode) -> Vec<u16> {
687 assert!(reg <= 7, "Invalid register.");
688 assert!(dir == Direction::DstEa || dir == Direction::DstReg, "Invalid direction.");
689 if dir == Direction::DstEa {
690 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode.");
691 } else {
692 assert!(am.verify(&MODES_0234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode.");
693 }
694 register_direction_size_effective_address(0b1000, reg, dir, size, am)
695}
696
697pub fn ori(size: Size, am: AddressingMode, imm: u32) -> Vec<u16> {
698 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in ORI assembler");
699 size_effective_address_immediate(0b0000_0000, size, am, imm)
700}
701
702pub fn oriccr(imm: u16) -> [u16; 2] {
703 [0x003C, imm & 0x00FF]
704}
705
706pub fn orisr(imm: u16) -> [u16; 2] {
707 [0x007C, imm]
708}
709
710pub fn pea(am: AddressingMode) -> Vec<u16> {
711 assert!(am.verify(&MODES_2567, &[0, 1, 2, 3]), "Invalid addressing mode in PEA assembler");
712 effective_address(0b0100_1000_01, am)
713}
714
715pub fn reset() -> u16 {
716 0x4E70
717}
718
719pub fn rom(dir: Direction, am: AddressingMode) -> Vec<u16> {
721 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in ROm assembler: expected left or right, got {:?}", dir);
722 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode field in ROm assembler");
723 direction_effective_address(0b1110_011, dir, 0b11, am)
724}
725
726pub fn ror(count_reg: u16, dir: Direction, size: Size, reg_shift: bool, reg: u16) -> u16 {
728 assert!(count_reg <= 7, "Invalid count/register field in ROr assembler: expected 0 to 7, got {}", count_reg);
729 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in ROr assembler: expected left or right, got {:?}", dir);
730 assert!(reg <= 7, "Invalid register field in ROr assembler: expected 0 to 7, got {}", reg);
731 rotation_direction_size_mode_register(0b1110, count_reg, dir, size, reg_shift as u16, 0b11, reg)
732}
733
734pub fn roxm(dir: Direction, am: AddressingMode) -> Vec<u16> {
736 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in ROXm assembler: expected left or right, got {:?}", dir);
737 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode field in ROXm assembler");
738 direction_effective_address(0b1110_010, dir, 0b11, am)
739}
740
741pub fn roxr(count_reg: u16, dir: Direction, size: Size, reg_shift: bool, reg: u16) -> u16 {
743 assert!(count_reg <= 7, "Invalid count/register field in ROXr assembler: expected 0 to 7, got {}", count_reg);
744 assert!(dir == Direction::Left || dir == Direction::Right, "Invalid direction field in ROXr assembler: expected left or right, got {:?}", dir);
745 assert!(reg <= 7, "Invalid register field in ROXr assembler: expected 0 to 7, got {}", reg);
746 rotation_direction_size_mode_register(0b1110, count_reg, dir, size, reg_shift as u16, 0b10, reg)
747}
748
749pub fn rte() -> u16 {
750 0x4E73
751}
752
753pub fn rtr() -> u16 {
754 0x4E77
755}
756
757pub fn rts() -> u16 {
758 0x4E75
759}
760
761pub fn sbcd(dst: u8, mode: Direction, src: u8) -> u16 {
763 assert!(dst <= 7, "Invalid destination register number {}.", dst);
764 assert!(mode == Direction::RegisterToRegister || mode == Direction::MemoryToMemory, "Invalid mode.");
765 assert!(src <= 7, "Invalid source register number {}.", dst);
766 register_size_mode_register(0b1000, dst, Size::Byte, 0, mode, src)
767}
768
769pub fn scc(cond: Condition, am: AddressingMode) -> Vec<u16> {
770 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode");
771 let mut vec = Vec::new();
772
773 let (eafield, eaext) = am.assemble(false);
774 let opcode = 0b0101 << 12
775 | (cond as u16) << 8
776 | 0b11 << 6
777 | eafield;
778 vec.push(opcode);
779 vec.extend(eaext.iter());
780
781 vec
782}
783
784pub fn stop(sr: u16) -> [u16; 2] {
785 [0x4E72, sr]
786}
787
788pub fn sub(reg: u8, dir: Direction, size: Size, am: AddressingMode) -> Vec<u16> {
790 assert!(reg <= 7, "Invalid register.");
791 assert!(dir == Direction::DstEa || dir == Direction::DstReg, "Invalid direction.");
792 if dir == Direction::DstEa {
793 assert!(am.verify(&MODES_234567, &[0, 1]), "Invalid addressing mode.");
794 } else {
795 assert!(!(am.is_ard() && size.is_byte()), "Byte size cannot be used with Address Register Direct source operand.");
796 assert!(am.verify(&MODES_01234567, &[0, 1, 2, 3, 4]), "Invalid addressing mode.");
797 }
798 register_direction_size_effective_address(0b1001, reg, dir, size, am)
799}
800
801pub fn suba(reg: u8, size: Size, am: AddressingMode) -> Vec<u16> {
802 assert!(reg <= 7, "Invalid register.");
803 assert!(!size.is_byte(), "SUBA cannot be byte sized.");
804 register_size_effective_address(0b1001, reg, size, am)
805}
806
807pub fn subi(size: Size, am: AddressingMode, imm: u32) -> Vec<u16> {
808 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in SUBI assembler");
809 size_effective_address_immediate(0b0000_0100, size, am, imm)
810}
811
812pub fn subq(data: u8, size: Size, am: AddressingMode) -> Vec<u16> {
814 assert!(am.verify(&MODES_01234567, &[0, 1]), "Invalid addressing mode.");
815 assert!(!(am.is_ard() && size.is_byte()), "Byte size cannot be used with Address Register Direct destination operand.");
816 assert!(data >= 1 && data <= 8, "Invalid data.");
817 let data = if data == 8 { 0 } else { data };
818 data_size_effective_address(data, 1, size, am)
819}
820
821pub fn subx(dst: u8, size: Size, mode: Direction, src: u8) -> u16 {
823 assert!(dst <= 7, "Invalid destination register number {}.", dst);
824 assert!(mode == Direction::RegisterToRegister || mode == Direction::MemoryToMemory, "Invalid mode.");
825 assert!(src <= 7, "Invalid source register number {}.", dst);
826 register_size_mode_register(0b1001, dst, size, 0, mode, src)
827}
828
829pub fn swap(reg: u8) -> u16 {
830 assert!(reg <= 7, "Invalid register.");
831 register(0b0100_1000_0100_0, reg)
832}
833
834pub fn tas(am: AddressingMode) -> Vec<u16> {
835 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in TAS assembler");
836 effective_address(0b0100_1010_11, am)
837}
838
839pub fn trap(vector: u8) -> u16 {
840 assert!(vector <= 15, "Invalid TRAP vector.");
841 0b0100_1110_0100 << 4 | vector as u16
842}
843
844pub fn trapv() -> u16 {
845 0x4E76
846}
847
848pub fn tst(size: Size, am: AddressingMode) -> Vec<u16> {
849 assert!(am.verify(&MODES_0234567, &[0, 1]), "Invalid addressing mode in TST assembler");
850 size_effective_address(0b0100_1010, size, am)
851}
852
853pub fn unlk(reg: u8) -> u16 {
854 assert!(reg <= 7, "Invalid register.");
855 register(0b0100_1110_0101_1, reg)
856}