2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // DSP56L_MACH.C - Code Generation for Motorola DSP56001
4 // Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
9 #include "dsp56k_mach.h"
22 unsigned int dsp_orgaddr; // DSP 56001 ORG address
23 unsigned int dsp_orgseg; // DSP 56001 ORG segment
26 // Fucntion prototypes
27 int m_unimp(WORD, WORD), m_badmode(WORD, WORD);
29 int dsp_baab(LONG inst);
30 int dsp_acc48(LONG inst);
31 int dsp_self(LONG inst);
32 int dsp_xyab(LONG inst);
33 int dsp_x0y0ab(LONG inst);
34 int dsp_immcr(LONG inst);
35 int dsp_immmovec(LONG inst);
36 int dsp_imm12(LONG inst);
37 int dsp_tcc2(LONG inst);
38 int dsp_tcc4(LONG inst);
39 int dsp_ea(LONG inst);
40 int dsp_ea_imm5(LONG inst);
41 int dsp_abs12(LONG inst);
42 int dsp_reg_imm5(LONG inst);
43 int dsp_ea_abs16(LONG inst);
44 int dsp_reg_abs16(LONG inst);
45 int dsp_imm12_abs16(LONG inst);
46 int dsp_alu24_abs16(LONG inst);
47 int dsp_reg(LONG inst);
48 int dsp_alu24(LONG inst);
49 int dsp_reg_imm5_abs16(LONG inst);
50 int dsp_ea_imm5_abs16(LONG inst);
51 int dsp_ea_lua(LONG inst);
52 int dsp_ab_rn(LONG inst);
53 int dsp_movec_ea(LONG inst);
54 int dsp_movec_aa(LONG inst);
55 int dsp_movec_reg(LONG inst);
56 int dsp_mult(LONG inst);
57 int dsp_movem_ea(LONG inst);
58 int dsp_movem_aa(LONG inst);
59 int dsp_movep_ea(LONG inst);
60 int dsp_movep_reg(LONG inst);
63 // Common error messages
66 // Include code tables
67 MNTABDSP dsp56k_machtab[] = {
68 { 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0x0000, 0, (int (*)(LONG))m_badmode }, // 0
69 #include "dsp56ktab.h"
70 { 0L, 0L, 0x0000, 0x0000, 0, (int (*)(LONG))m_unimp } // Last entry
74 static inline int dsp_extra_ea()
76 if (deposit_extra_ea == DEPOSIT_EXTRA_WORD)
78 if (!(dspImmedEXATTR & FLOAT))
80 if (dspImmedEXATTR & DEFINED)
86 // TODO: what if it's an address and not an immediate? Does it matter at all?
87 AddFixup(FU_DSPIMM24, sloc, dspImmedEXPR);
93 if (dspImmedEXATTR & DEFINED)
99 // TODO: what if it's an address and not an immediate? Does it matter at all?
100 AddFixup(FU_DSPIMMFL24, sloc, dspImmedEXPR);
105 else if (deposit_extra_ea == DEPOSIT_EXTRA_FIXUP)
107 // Probably superfluous check (we're not likely to land here with a
108 // known aa) but oh well
109 if (!(dspImmedEXATTR & DEFINED))
111 // Since we already deposited the word to be fixup'd we need to
112 // subtract 1 from sloc
114 AddFixup(FU_DSPADR06, sloc - 1, dspImmedEXPR);
123 int dsp_ab(LONG inst)
125 inst |= (dsp_a0reg & 1) << 3;
127 dsp_extra_ea(); // Deposit effective address if needed
132 int dsp_baab(LONG inst)
134 if (dsp_a0reg == dsp_a1reg)
135 return error("source and destination registers must not be the same");
137 inst |= ((dsp_a0reg + 1) & 1) << 3;
139 dsp_extra_ea(); // Deposit effective address if needed
145 int dsp_acc48(LONG inst)
147 if (dsp_a0reg == dsp_a1reg)
148 return error("source and destination registers must not be the same");
150 inst |= (dsp_a1reg & 1) << 3;
154 case KW_X: inst |= 2 << 4; break;
155 case KW_Y: inst |= 3 << 4; break;
156 case KW_X0: inst |= 4 << 4;break;
157 case KW_Y0: inst |= 5 << 4;break;
158 case KW_X1: inst |= 6 << 4;break;
159 case KW_Y1: inst |= 7 << 4;break;
160 default: return error("dsp_acc48: shouldn't reach here!");
164 dsp_extra_ea(); // Deposit effective address if needed
170 int dsp_self(LONG inst)
173 dsp_extra_ea(); // Deposit effective address if needed
179 int dsp_xyab(LONG inst)
181 if (dsp_a0reg == dsp_a1reg)
182 return error("source and destination registers must not be the same");
184 inst |= (dsp_a0reg & 1) << 4;
185 inst |= (dsp_a1reg & 1) << 3;
187 dsp_extra_ea(); // Deposit effective address if needed
193 int dsp_x0y0ab(LONG inst)
195 if (dsp_a0reg == dsp_a1reg)
196 return error("source and destination registers must not be the same");
198 int inverse = (dsp_a0reg & 3);
199 inverse = ((inverse & 1) << 1) | ((inverse & 2) >> 1);
200 inst |= inverse << 4;
201 inst |= (dsp_a1reg & 1) << 3;
203 dsp_extra_ea(); // Deposit effective address if needed
209 int dsp_immcr(LONG inst)
213 case KW_CCR: inst |= 1; break;
214 case KW_MR:inst |= 0; break;
215 case KW_OMR:inst |= 2; break;
216 default: return error("invalid destination register (only ccr, mr, omr allowed");
219 if (dsp_a0exattr & DEFINED)
221 inst |= dsp_a0exval << 8;
226 AddFixup(FU_DSPIMM8, sloc, dsp_a0expr);
234 int dsp_immmovec(LONG inst)
245 case 7: inst |= dsp_a1reg; break; // M0-M7
246 case KW_SR: inst |= 25; break;
247 case KW_OMR: inst |= 26; break;
248 case KW_SP: inst |= 27; break;
249 case KW_SSH: inst |= 28; break;
250 case KW_SSL: inst |= 29; break;
251 case KW_LA: inst |= 30; break;
252 case KW_LC: inst |= 31; break;
253 default: return error("invalid destination register (only m0-m7, SR, OMR, SP, SSH, SSL, LA, LC allowed");
256 if (dsp_a0exattr & DEFINED)
258 inst |= (dsp_a0exval & 0xff) << 8;
263 AddFixup(FU_DSPIMM8, sloc, dsp_a0expr);
271 int dsp_imm12(LONG inst)
273 if (dsp_a0exattr & DEFINED)
275 if ((dsp_am0 & (M_DSPIM12 | M_DSPIM8)) == 0)
276 return error("immediate out of range ($000-$fff)");
277 inst |= ((dsp_a0exval & 0x0ff) << 8) | ((dsp_a0exval & 0xf00) >> 8);
282 AddFixup(FU_DSPIMM12, sloc, dsp_a0expr);
290 // Tcc instructions with 2 operands (48bit)
291 int dsp_tcc2(LONG inst)
293 if (dsp_a0reg == dsp_a1reg)
294 return error("First pair of source and destination registers must not be the same");
297 inverse = (dsp_a0reg & 7);
298 inverse = ((inverse & 1) << 1) | ((inverse & 2) >> 1) | (inverse & 4);
299 inst |= inverse << 4;
300 inst |= ((dsp_a1reg) & 1) << 3;
307 // Tcc instructions with 4 operands
308 int dsp_tcc4(LONG inst)
310 if (dsp_a0reg == dsp_a1reg)
311 return error("First pair of source and destination registers must not be the same");
313 if (dsp_am2 != M_DSPR || dsp_am3 != M_DSPR)
314 return error("Second pair of source and destination registers must be R0-R7");
316 if (dsp_am0 == M_ACC56 && dsp_am1 == M_ACC56)
318 inst |= ((dsp_a0reg + 1) & 1) << 3;
323 inverse = (dsp_a0reg & 7);
324 inverse = ((inverse & 1) << 1) | ((inverse & 2) >> 1) | (inverse & 4);
325 inst |= inverse << 4;
326 inst |= ((dsp_a1reg) & 1) << 3;
330 inst |= (dsp_a2reg << 8) | (dsp_a3reg);
338 int dsp_ea(LONG inst)
340 inst |= dsp_a0reg << 8;
342 if (dsp_a0memspace != -1)
343 inst |= dsp_a0memspace;
345 if (dsp_am0 == M_DSPAA)
346 inst |= ((dsp_a0exval & 0x3f) << 8);
350 if (dsp_a0reg == DSP_EA_ABS)
352 if (dsp_a0exattr & DEFINED)
358 AddFixup(FU_DSPADR24, sloc, dsp_a0expr);
367 // Store ea and 5-bit constant
368 int dsp_ea_imm5(LONG inst)
370 if (dsp_a1memspace == -1)
371 return error("Only X: or Y: memory space allowed");
373 if (dsp_a0exattr & DEFINED)
375 int v = (int)dsp_a0exval;
378 return error("immediate value must be between 0 and 23");
380 if (dsp_a1reg == DSP_EA_ABS)
382 inst |= (v | dsp_a1memspace | (dsp_a1reg << 8));
386 inst |= ((dsp_a1exval & 0x3F) << 8) | v | dsp_a1memspace | (dsp_a1reg << 8);
391 if (dsp_a1reg == DSP_EA_ABS)
393 if (dsp_a1exattr & DEFINED)
399 AddFixup(FU_DSPADR24, sloc, dsp_a1expr);
406 if (dsp_a1reg == DSP_EA_ABS)
408 inst |= dsp_a1memspace | (dsp_a1reg << 8);
412 inst |= ((dsp_a1exval & 0x3F) << 8) | dsp_a1memspace | (dsp_a1reg << 8);
415 AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
418 if (dsp_a1reg == DSP_EA_ABS)
420 if (dsp_a1exattr & DEFINED)
426 AddFixup(FU_DSPADR24, sloc, dsp_a1expr);
436 // Processes the input register according to table A-18 of the Motorola DSP
437 // manual and returns the correct encoding.
438 // Note: returns only the 3 lower bits of the table. The rest is handled in
440 static inline LONG tab_A18(int *am, int *reg)
463 case KW_SR: return 1; break;
464 case KW_OMR: return 2; break;
465 case KW_SP: return 3; break;
466 case KW_SSH: return 4; break;
467 case KW_SSL: return 5; break;
468 case KW_LA: return 6; break;
469 case KW_LC: return 7; break;
471 return error("specified control register not allowed as destination");
477 return error("reached at the end of tab_A18 - shouldn't happen!");
482 // Store register (table A-18 in the motorola manual) and 5-bit constant
483 int dsp_reg_imm5(LONG inst)
487 if ((reg = tab_A18(&dsp_am1, &dsp_a1reg)) == ERROR)
492 if (dsp_a0exattr & DEFINED)
494 int v = (int)dsp_a0exval;
497 return error("immediate value must be between 0 and 23");
504 AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
512 // Store 12-bit address
513 int dsp_abs12(LONG inst)
515 if (dsp_a0exattr & DEFINED)
517 int v = (int)dsp_a0exval;
519 if (v < 0 || v > 0xFFF)
520 return error("immediate out of range ($000-$FFF)");
527 AddFixup(FU_DSPADR12, sloc, dsp_a0expr);
535 // Manipulate expr to append a '-1'. Used specifically for DO.
536 void append_minus_1(TOKEN * expr)
538 // Find where the end of expression is
539 while (*expr != ENDEXPR)
541 if (*expr == SYMBOL || *expr == CONST || *expr == FCONST)
543 else if (*expr == ACONST)
549 // Overwrite ENDEXPR and append '-1'
551 uint64_t *expr64 = (uint64_t *)expr;
553 expr = (uint32_t *)expr64;
559 // Store a 12bit immediate and 16bit address.
560 // Note: This function is specifically handling DO. DO has a requirement of
561 // storing the address of a label minus 1! Quoting the manual:
562 // "Note: The assembler calculates the end-of-loop address to be loaded
563 // into LA (the absolute address extension word) by evaluating the end
564 // -of-loop expression <expr> and subtracting one. This is done to
565 // accommodate the case where the last word in the DO loop is a two-word
566 // instruction. Thus, the end-of-loop expression <expr> in the source
567 // code must represent the address of the instruction AFTER the last
568 // instruction in the loop as shown in the example."
569 // This is fine if we know the address already, but a problem when we
571 int dsp_imm12_abs16(LONG inst)
573 if (dsp_a0exattr & DEFINED)
575 if ((dsp_am0 & (M_DSPIM12 | M_DSPIM8)) == 0)
576 return error("immediate out of range ($000-$FFF)");
578 inst |= ((dsp_a0exval & 0x0FF) << 8) | ((dsp_a0exval & 0xF00) >> 8);
583 AddFixup(FU_DSPIMM12, sloc, dsp_a0expr);
587 if (dsp_a1exattr & DEFINED)
589 D_dsp((a1exval - 1));
593 append_minus_1(dsp_a1expr);
594 AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
602 // Just store ea and 16bit address
603 // Note: this function is specifically handling DO.
604 // The same notes as dsp_imm12_abs16 apply here.
605 int dsp_ea_abs16(LONG inst)
607 if ((dsp_a0reg == DSP_EA_ABS && dsp_a0memspace == -1) || dsp_a1reg == DSP_EA_IMM)
608 return error("immediate values > 31 or absolute values not allowed");
610 if (dsp_a0exattr & DEFINED)
612 if (dsp_a0exval > 31)
613 return error("absolute address (aa) bigger than $1F");
615 inst |= dsp_a0exval << 8;
618 inst |= dsp_a0reg << 8;
620 if (dsp_a0memspace == -1)
621 return error("only X:, Y: address spaces allowed");
623 if ((deposit_extra_ea == DEPOSIT_EXTRA_FIXUP) || (dsp_a0reg == DSP_EA_ABS && dsp_am0 == M_DSPEA))
625 // Change instruction to aa instead of ea. TODO: check if this is true
628 inst |= dsp_a0memspace;
630 // Probably superfluous check (we're not likely to land here with a
631 // known aa) but oh well
632 if (!(dsp_a0exattr & DEFINED))
634 AddFixup(FU_DSPADR06, sloc, dsp_a0expr);
644 inst |= dsp_a0memspace;
648 if (dsp_a1exattr & DEFINED)
650 D_dsp((dsp_a1exval - 1));
654 append_minus_1(dsp_a1expr);
655 AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
663 // Store register (table A-18 in the motorola manual) 5-bit constant and 16bit address
664 // Note: this function is specifically handling DO.
665 // The same notes as dsp_imm12_abs16 apply here.
666 int dsp_reg_abs16(LONG inst)
670 if ((reg = tab_A18(&dsp_am0, &dsp_a0reg)) == ERROR)
675 if (dsp_a1exattr & DEFINED)
677 int v = (int)dsp_a1exval - 1;
684 append_minus_1(dsp_a1expr);
685 AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
693 // Store ALU24 register and 16bit address
694 // Note: this function is specifically handling DO.
695 // The same notes as dsp_imm12_abs16 apply here.
696 int dsp_alu24_abs16(LONG inst)
698 inst |= (dsp_a0reg & 7) << 8;
700 if (dsp_a1exattr & DEFINED)
702 int v = (int)dsp_a1exval - 1;
709 append_minus_1(dsp_a1expr);
710 AddFixup(FU_DSPADR16, sloc, dsp_a1expr);
718 // Store register (table A-18 in the motorola manual)
719 int dsp_reg(LONG inst)
723 if ((reg = tab_A18(&dsp_am0, &dsp_a0reg)) == ERROR)
733 int dsp_alu24(LONG inst)
735 inst |= (dsp_a0reg & 7) << 8;
742 // Store register (table A-18 in the motorola manual) and 5-bit constant
743 int dsp_reg_imm5_abs16(LONG inst)
747 // First, check that we have at best an 16bit absolute address in
748 // operand 3 since we don't check that anywhere else
749 if (dsp_a2exattr & DEFINED)
751 if ((dsp_am2 & C_DSPABS16) == 0)
752 return error("expected 16-bit address as third operand.");
755 if ((reg = tab_A18(&dsp_am1, &dsp_a1reg)) == ERROR)
760 if (dsp_a0exattr & DEFINED)
762 int v = (int)dsp_a0exval;
765 return error("immediate value must be between 0 and 23");
770 if (dsp_a2exattr & DEFINED)
772 int v = (int)dsp_a2exval;
777 AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
783 AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
786 if (dsp_a2exattr & DEFINED)
788 int v = (int)dsp_a2exval;
793 AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
802 // Store ea, 5-bit constant and 16-bit address in the extension word
803 int dsp_ea_imm5_abs16(LONG inst)
805 // First, check that we have at best an 16bit absolute address in
806 // operand 3 since we don't check that anywhere else
807 if (dsp_a2exattr&DEFINED)
809 if ((dsp_am2&C_DSPABS16) == 0)
810 return error("expected 16-bit address as third operand.");
813 if (dsp_a1memspace == -1)
814 return error("Only X: or Y: memory space allowed");
816 if (dsp_am1 == M_DSPAA)
818 if (dsp_a1exattr & DEFINED)
819 inst |= (dsp_a1exval & 0x3F) << 8;
821 AddFixup(FU_DSPADR06, sloc, dsp_a1expr);
824 if (dsp_am1 == M_DSPPP)
826 if (dsp_a1exattr & DEFINED)
827 inst |= (dsp_a1exval & 0x3f) << 8;
829 AddFixup(FU_DSPPP06, sloc, dsp_a1expr);
832 if (dsp_a0exattr & DEFINED)
834 int v = (int)dsp_a0exval;
837 return error("immediate value must be between 0 and 23");
839 inst |= (dsp_a1reg << 8) | v | dsp_a1memspace;
842 if (dsp_a2exattr & DEFINED)
844 int v = (int)dsp_a2exval;
849 AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
855 inst |= (dsp_a1reg << 8) | dsp_a1memspace;
856 AddFixup(FU_DSPIMM5, sloc, dsp_a0expr);
859 if (dsp_a2exattr & DEFINED)
861 int v = (int)dsp_a2exval;
866 AddFixup(FU_DSPADR16, sloc, dsp_a2expr);
875 int dsp_ea_lua(LONG inst)
877 int am = dsp_a0reg & 0x38;
879 if (am != DSP_EA_POSTDEC && am != DSP_EA_POSTINC &&
880 am != DSP_EA_POSTDEC1 && am != DSP_EA_POSTINC1)
881 return error("addressing mode not allowed");
883 inst |= dsp_a0reg << 8;
885 if (dsp_am1 == M_DSPN)
895 int dsp_ab_rn(LONG inst)
897 inst |= (dsp_a1reg & 1) << 3;
898 inst |= (dsp_a0reg) << 8;
905 int dsp_movec_ea(LONG inst)
908 int memspace = dsp_a1memspace;
909 WORD exattr = dsp_a1exattr;
910 LONG exval = (uint32_t)dsp_a1exval;
911 TOKEN * expr = dsp_a1expr;
914 int reg2 = dsp_a1reg;
916 if (dsp_am0 == M_DSPEA || (dsp_am0 & C_DSPIM))
919 exattr = dsp_a0exattr;
920 exval = (uint32_t)dsp_a0exval;
921 memspace = dsp_a0memspace;
928 // Abort if unsupported registers are requested
929 if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
930 return error("illegal registers for instruction.");
932 if (dsp_am0 & C_DSPIM)
936 return error("only x: or y: memory spaces allowed.");
938 // No memspace required when loading an immediate
939 if (dsp_am0 & C_DSPIM)
942 reg = tab_A18(&am, ®);
943 inst |= (ea << 8) | memspace | reg;
950 if (reg2 == DSP_EA_ABS || (dsp_am0 & C_DSPIM))
952 if (exattr & DEFINED)
959 if (dsp_am0 == M_DSPIM)
961 AddFixup(FU_DSPIMM24, sloc, expr);
966 AddFixup(FU_DSPADR24, sloc, expr);
976 int dsp_movec_aa(LONG inst)
979 int memspace = dsp_a1memspace;
980 WORD exattr = dsp_a1exattr;
981 LONG exval = (uint32_t)dsp_a1exval;
982 TOKEN * expr = dsp_a1expr;
985 int reg2 = dsp_a1reg;
987 if (dsp_am0 == M_DSPAA)
990 exattr = dsp_a0exattr;
991 exval = (uint32_t)dsp_a0exval;
992 memspace = dsp_a0memspace;
999 // Abort if unsupported registers are requested
1000 if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
1001 return error("PC, MR, CCR are illegal registers for this instruction.");
1004 return error("only x: or y: memory spaces allowed.");
1006 reg = tab_A18(&am, ®);
1007 inst |= (ea << 8) | memspace | reg;
1012 if (exattr & DEFINED)
1019 AddFixup(FU_DSPADR06, sloc, expr);
1027 int dsp_movec_reg(LONG inst)
1032 // Abort if unsupported registers are requested
1033 if (dsp_a0reg == KW_PC || dsp_a0reg == KW_MR || dsp_a0reg == KW_CCR ||
1034 dsp_a1reg == KW_PC || dsp_a1reg == KW_MR || dsp_a1reg == KW_CCR)
1035 return error("PC, MR, CCR are illegal registers for this instruction.");
1037 int reg1 = tab_A18(&dsp_am0, &dsp_a0reg);
1038 int reg2 = tab_A18(&dsp_am1, &dsp_a1reg);
1040 if (inst & (1 << 15))
1057 case M_ALU24: reg1 |= 0x00; break;
1059 case M_ACC24: reg1 |= 0x08; break;
1060 case M_ACC56: reg1 |= 0x0E; break;
1061 case M_DSPR: reg1 |= 0x10; break;
1062 case M_DSPN: reg1 |= 0x18; break;
1063 case M_DSPM: reg1 |= 0x20; break;
1064 case M_DSPPCU: reg1 |= 0x38; break;
1066 return error("reached the end of dsp_movec_reg case 1 - should not happen!");
1071 case M_DSPM: reg2 |= 0x00; break;
1072 case M_DSPPCU: reg2 |= 0x18; break;
1074 return error("reached the end of dsp_movec_reg case 2 - should not happen!");
1077 inst |= (reg1 << 8) | reg2;
1084 int dsp_mult(LONG inst)
1086 if (dsp_am2 != M_ACC56)
1087 return error("only A or B allowed as third operand.");
1089 switch (((dsp_a0reg & 3) << 2) + (dsp_a1reg & 3))
1091 case (0 << 2) + 0: inst |= 0 << 4; break; // x0 x0
1092 case (2 << 2) + 2: inst |= 1 << 4; break; // y0 y0
1093 case (1 << 2) + 0: inst |= 2 << 4; break; // x1 x0
1094 case (0 << 2) + 1: inst |= 2 << 4; break; // x0 x1
1095 case (3 << 2) + 2: inst |= 3 << 4; break; // y1 y0
1096 case (2 << 2) + 3: inst |= 3 << 4; break; // y0 y1
1097 case (0 << 2) + 3: inst |= 4 << 4; break; // x0 y1
1098 case (3 << 2) + 0: inst |= 4 << 4; break; // y1 x0
1099 case (2 << 2) + 0: inst |= 5 << 4; break; // y0 x0
1100 case (0 << 2) + 2: inst |= 5 << 4; break; // x0 y0
1101 case (1 << 2) + 2: inst |= 6 << 4; break; // x1 y0
1102 case (2 << 2) + 1: inst |= 6 << 4; break; // y0 x1
1103 case (3 << 2) + 1: inst |= 7 << 4; break; // y1 x1
1104 case (1 << 2) + 3: inst |= 7 << 4; break; // x1 y1
1106 return error("x0/y0/x1/y1 combination not allowed for multiplication.");
1109 if (dsp_a2reg == KW_B)
1114 dsp_extra_ea(); // Deposit effective address if needed
1120 int dsp_movem_ea(LONG inst)
1123 int memspace = dsp_a0memspace;
1124 WORD exattr = dsp_a1exattr;
1125 LONG exval = (uint32_t)dsp_a1exval;
1126 TOKEN * expr = dsp_a1expr;
1127 int reg = dsp_a0reg;
1129 int reg2 = dsp_a1reg;
1131 if (dsp_am0 == M_DSPEA || dsp_am0 == M_DSPIM)
1134 exattr = dsp_a0exattr;
1135 exval = (uint32_t)dsp_a0exval;
1136 memspace = dsp_a0memspace;
1144 // Abort if unsupported registers are requested
1145 if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
1146 return error("illegal registers for instruction.");
1149 return error("only p: memory space allowed.");
1151 reg = tab_A18(&am, ®);
1152 inst |= (ea << 8) | reg;
1159 if (reg2 == DSP_EA_ABS || dsp_am0 == M_DSPIM)
1161 if (exattr & DEFINED)
1168 if (dsp_am0 == M_DSPIM)
1170 AddFixup(FU_DSPIMM24, sloc, expr);
1175 AddFixup(FU_DSPADR24, sloc, expr);
1185 int dsp_movem_aa(LONG inst)
1188 int memspace = dsp_a1memspace;
1189 WORD exattr = dsp_a1exattr;
1190 LONG exval = (uint32_t)dsp_a1exval;
1191 TOKEN * expr = dsp_a1expr;
1192 int reg = dsp_a0reg;
1194 int reg2 = dsp_a1reg;
1196 if (dsp_am0 == M_DSPAA)
1199 exattr = dsp_a0exattr;
1200 exval = (uint32_t)dsp_a0exval;
1201 memspace = dsp_a0memspace;
1208 // Abort if unsupported registers are requested
1209 if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
1210 return error("PC, MR, CCR are illegal registers for this instruction.");
1213 return error("only p: memory space allowed.");
1215 reg = tab_A18(&am, ®);
1216 inst |= (ea << 8) | reg;
1221 if (exattr & DEFINED)
1228 AddFixup(FU_DSPADR06, sloc, expr);
1236 int dsp_movep_ea(LONG inst)
1238 // movep doesn't allow any aa modes but we might detect this during amode
1239 // detection. No worries, just change it to ea with extra address instead
1240 if (dsp_am0 == M_DSPAA)
1242 dsp_a0reg = DSP_EA_ABS;
1245 if (dsp_am1 == M_DSPAA)
1248 dsp_a1reg = DSP_EA_ABS;
1251 // So we might encounter something like 'movep x:pp,x:pp' which we
1252 // obviously flagged as M_DSPPP during ea parsing. In this case we give up
1253 // and declare the second term as a classic absolute address (we chop off
1254 // the high bits too) and let the routine treat is as such. At least that's
1255 // what Motorola's assembler seems to be doing.
1256 if (dsp_am0 == M_DSPPP && dsp_am1 == M_DSPPP)
1258 dsp_am1 = DSP_EA_ABS;
1259 dsp_a1reg = DSP_EA_ABS;
1260 dsp_a1exval &= 0xFFFF;
1263 // Assume first operand is :pp
1265 int memspace = dsp_a1memspace;
1266 int perspace = dsp_a0perspace;
1267 WORD exattr = dsp_a1exattr;
1268 WORD exattr2 = dsp_a0exattr;
1269 LONG exval = (uint32_t)dsp_a1exval;
1270 LONG exval2 = (uint32_t)dsp_a0exval;
1271 TOKEN * expr = dsp_a1expr;
1272 TOKEN * expr2 = dsp_a0expr;
1273 int reg = dsp_a0reg;
1275 int reg2 = dsp_a1reg;
1277 if (dsp_am1 == M_DSPPP)
1280 exattr = dsp_a0exattr;
1281 exattr2 = dsp_a1exattr;
1282 exval = (uint32_t)dsp_a0exval;
1283 exval2 = (uint32_t)dsp_a1exval;
1284 memspace = dsp_a0memspace;
1285 perspace = dsp_a1perspace;
1293 if (dsp_a0perspace == -1 && dsp_a1perspace == -1)
1295 // Ok, so now we have to guess which of the two parameters is X:pp or
1296 // Y:pp. This happened because we didn't get a << marker in any of the
1298 if (((dsp_a0exattr | dsp_a1exattr) & DEFINED) == 0)
1299 // You have got to be shitting me...
1300 // One way to deal with this (for example X:ea,X:pp / X:pp,X:ea
1301 // aliasing would be to check number ranges and see which one is
1302 // negative. ...unless one of the two isn't known during this phase
1303 return error("internal assembler error: could not deduce movep syntax");
1305 if (dsp_a0exattr & DEFINED)
1307 if (dsp_a0exval >= 0xFFC0 && dsp_a0exval <= 0xFFFF)
1309 // First operand is :pp - do nothing
1310 perspace = dsp_a0memspace << 10;
1311 // When the source contains a << then we bolt on the :pp
1312 // address during ea parsing, but since we couldn't recognise
1313 // the addressing mode in this case let's just insert it right
1315 reg |= (dsp_a0exval & 0x3F);
1319 if (dsp_a1exattr & DEFINED)
1321 if (dsp_a1exval >= 0xFFC0 && dsp_a1exval <= 0xFFFF)
1324 exattr = dsp_a0exattr;
1325 exval = (uint32_t)dsp_a0exval;
1326 memspace = dsp_a0memspace;
1327 perspace = dsp_a1memspace << 10;
1333 reg |= (dsp_a1exval & 0x3F);
1338 // You have got to be shitting me (twice)...
1339 return error("internal assembler error: could not deduce movep syntax");
1342 inst |= reg | (ea << 8) | perspace; // reg contains memory space
1344 if ((dsp_am0 & (M_DSPIM | M_DSPIM8 | M_DSPIM12)) == 0)
1357 if (exattr2&DEFINED)
1359 inst |= (exval2 & 0x3F);
1364 AddFixup(FU_DSPIMM5, sloc, expr2);
1373 if (dsp_am0 & (M_DSPIM | M_DSPIM8 | M_DSPIM12))
1375 if (dsp_a0exattr & DEFINED)
1377 int v = (int)dsp_a0exval;
1382 AddFixup(FU_DSPADR16, sloc, dsp_a0expr);
1386 else if (reg2 == DSP_EA_ABS)
1388 if (exattr & DEFINED)
1395 AddFixup(FU_DSPADR24, sloc, expr);
1404 int dsp_movep_reg(LONG inst)
1406 // Assume first operand is :pp
1408 int memspace = dsp_a0memspace;
1409 int perspace = dsp_a0perspace;
1410 WORD exattr = dsp_a1exattr;
1411 LONG exval = (uint32_t)dsp_a1exval;
1412 TOKEN * expr = dsp_a1expr;
1413 int reg = dsp_a0reg;
1415 int reg2 = dsp_a1reg;
1417 if (dsp_am1 == M_DSPPP)
1420 exattr = dsp_a0exattr;
1421 exval = (uint32_t)dsp_a0exval;
1422 memspace = dsp_a1memspace;
1423 perspace = dsp_a1perspace;
1430 // Abort if unsupported registers are requested
1431 if (reg == KW_PC || reg == KW_MR || reg == KW_CCR)
1432 return error("illegal registers for instruction.");
1434 reg2 = tab_A18(&am, ®2);
1435 inst |= (reg2 << 8) | reg;
1438 return error("only x: or y: memory space allowed.");
1444 if (reg2 == DSP_EA_ABS)
1446 if (exattr & DEFINED)
1453 AddFixup(FU_DSPADR24, sloc, expr);