Pristine Ack-5.5
[Ack-5.5.git] / mach / m68k2 / as / mach5.c
1 /* $Id: mach5.c,v 2.13 1994/06/24 13:02:56 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /* @(#)mach5.c  1.16 */
7 /*
8  * Motorola 68000/68010 auxiliary functions
9  */
10
11 static int
12 extension_offset()
13 {
14         switch(curr_instr) {
15         case MOVEM:
16         case FMOVE:
17         case FMOVEM:
18         case FDYADIC:
19         case FMONADIC:
20         case FSINCOS:
21         case FSCC:
22         case FTST:
23                 return 4;
24         }
25         return 2;
26 }
27
28 ea_1(sz, bits)
29 {
30         register flag;
31
32         if (mrg_1 > 074)
33                 serror("no specials");
34         if ((flag = eamode[mrg_1>>3]) == 0)
35                 if ((flag = eamode[010 + (mrg_1&07)]) == 0)
36                         flag = eamode[015 + (sz>>6)];
37         if ((mrg_1 & 070) == 010)
38                 checksize(sz, 2|4);
39         bits &= ~flag;
40         if (bits)
41                 serror("bad addressing category");
42         if (flag & FITW)
43                 Xfit (fitw(exp_1.val) ||
44                       (mrg_1 == 074 && fit16(exp_1.val))
45                 ) ;
46         if (flag & FITB) {
47                 Xfit (fitb(exp_1.val) ||
48                       (mrg_1 == 074 && fit8(exp_1.val))
49                 );
50                 if (mrg_1 == 074)
51                         exp_1.val &= 0xFF;
52         }
53 #ifdef RELOCATION
54         RELOMOVE(relonami, rel_1);
55         if (flag & ~0xFF)
56                 newrelo(exp_1.typ, (flag>>8) | RELBR | RELWR);
57 #endif
58         if (flag & PUTL)
59                 emit4(exp_1.val);
60         if (flag & PUTW)
61                 emit2(loww(exp_1.val));
62 }
63
64 ea_2(sz, bits)
65
66         mrg_1 = mrg_2;
67         exp_1 = exp_2;
68         RELOMOVE(rel_1, rel_2);
69         ea_1(sz, bits);
70 }
71
72 index(hibyte)
73 {
74         Xfit(fitb(exp_2.val));
75         exp_2.val = hibyte | lowb(exp_2.val);
76 }
77
78 checksize(sz, bits)
79 {
80         if ((bits & (1 << (sz>>6))) == 0)
81                 serror("bad size");
82 }
83
84 test68010()
85 {
86         if (model != 1 && pass == PASS_3)
87                 warning("68010 instruction");
88 }
89
90 badoperand()
91 {
92         serror("bad operands");
93 }
94
95 shift_op(opc, sz)
96 {
97         if (mrg_1 < 010 && mrg_2 < 010) {
98                 emit2((opc&0170470) | sz | mrg_1<<9 | mrg_2);
99                 return;
100         }
101         if (exp_1.typ != S_ABS || mrg_1 != 074) {
102                 badoperand();
103                 return;
104         }
105         if (mrg_2 < 010) {
106                 Xfit(fit3(exp_1.val));
107                 emit2((opc&0170430) | sz | low3(exp_1.val)<<9 | mrg_2);
108                 return;
109         }
110         checksize(sz, 2);
111         Xfit(exp_1.val == 1);
112         emit2((opc&0177700) | mrg_2);
113         ea_2(SIZE_W, MEM|ALT);
114 }
115
116 bitop(opc)
117 {
118         register bits;
119
120         bits = DTA|ALT;
121         if (opc == 0 && (mrg_1 < 010 || mrg_2 != 074))
122                 bits = DTA;
123         if (mrg_1 < 010) {
124                 emit2(opc | 0400 | mrg_1<<9 | mrg_2);
125                 ea_2(0, bits);
126                 return;
127         }
128         if (mrg_1 == 074) {
129                 emit2(opc | 04000 | mrg_2);
130                 ea_1(SIZE_W, 0);
131                 ea_2(0, bits);
132                 return;
133         }
134         badoperand();
135 }
136
137 add(opc, sz)
138 {
139         if ((mrg_2 & 070) == 010)
140                 checksize(sz, 2|4);
141         if (
142                 mrg_1 == 074
143                 &&
144                 small(
145                         exp_1.typ==S_ABS && fit3(exp_1.val),
146                         sz==SIZE_L ? 4 : 2
147                 )
148         ) {
149                 emit2((opc&0400) | 050000 | low3(exp_1.val)<<9 | sz | mrg_2);
150                 ea_2(sz, ALT);
151                 return;
152         }
153         if (mrg_1 == 074 && (mrg_2 & 070) != 010) {
154                 emit2((opc&03000) | sz | mrg_2);
155                 ea_1(sz, 0);
156                 ea_2(sz, DTA|ALT);
157                 return;
158         }
159         if ((mrg_2 & 070) == 010) {
160                 emit2((opc&0170300) | (mrg_2&7)<<9 | sz<<1 | mrg_1);
161                 ea_1(sz, 0);
162                 return;
163         }
164         if (to_dreg(opc, sz, 0))
165                 return;
166         if (from_dreg(opc, sz, ALT|MEM))
167                 return;
168         badoperand();
169 }
170
171 and(opc, sz)
172 {
173         if (mrg_1 == 074 && mrg_2 >= 076) {     /* ccr or sr */
174                 if (sz != SIZE_NON)
175                         checksize(sz, mrg_2==076 ? 1 : 2);
176                 else
177                         sz = (mrg_2==076 ? SIZE_B : SIZE_W);
178                 emit2((opc&07400) | sz | 074);
179                 ea_1(sz, 0);
180                 return;
181         }
182         if (sz == SIZE_NON)
183                 sz = SIZE_DEF;
184         if (mrg_1 == 074) {
185                 emit2((opc&07400) | sz | mrg_2);
186                 ea_1(sz, 0);
187                 ea_2(sz, DTA|ALT);
188                 return;
189         }
190         if ((opc & 010000) == 0 && to_dreg(opc, sz, DTA))
191                 return;
192         if (from_dreg(opc, sz, (opc & 010000) ? DTA|ALT : ALT|MEM))
193                 return;
194         badoperand();
195 }
196
197 to_dreg(opc, sz, bits)
198 {
199         if ((mrg_2 & 070) != 000)
200                 return(0);
201         emit2((opc & 0170000) | sz | (mrg_2&7)<<9 | mrg_1);
202         ea_1(sz, bits);
203         return(1);
204 }
205
206 from_dreg(opc, sz, bits)
207 {
208         if ((mrg_1 & 070) != 000)
209                 return(0);
210         emit2((opc & 0170000) | sz | (mrg_1&7)<<9 | 0400 | mrg_2);
211         ea_2(sz, bits);
212         return(1);
213 }
214
215 cmp(sz)
216 {
217         register opc;
218
219         if ((mrg_1&070) == 030 && (mrg_2&070) == 030) {
220                 emit2(0130410 | sz | (mrg_1&7) | (mrg_2&7)<<9);
221                 return;
222         }
223         if (mrg_1 == 074 && (mrg_2 & 070) != 010) {
224                 if (mrg_2 == 072) {
225                         /* In this case, the ea707172 routine changed the
226                            addressing mode to PC-relative. However, this is
227                            not allowed for this instruction. Change it back
228                            to absolute, but also correct for the optimization
229                            that the ea707172 routine thought it made.
230                         */
231                         if (pass == PASS_1) {
232                                 /* In this case, the user wrote it PC-relative.
233                                    Error.
234                                 */
235                                 badoperand();
236                         }
237                         mrg_2 = 071;
238                         exp_2.val += DOTVAL+2;
239                         if (pass == PASS_2) {
240                                 DOTGAIN -= 2;
241                         }
242                 }
243                 emit2(06000 | sz | mrg_2);
244                 ea_1(sz, 0);
245                 ea_2(sz, DTA|ALT);
246                 return;
247         }
248         if (mrg_2 < 020) {
249                 if (mrg_2 >= 010) {
250                         checksize(sz, 2|4);
251                         opc = 0130300 | sz<<1;
252                         mrg_2 &= 7;
253                 } else
254                         opc = 0130000 | sz;
255                 emit2(opc | mrg_2<<9 | mrg_1);
256                 ea_1(sz, 0);
257                 return;
258         }
259         badoperand();
260 }
261
262 move(sz)
263 {
264         register opc;
265
266         if (mrg_1 > 074 || mrg_2 > 074) {
267                 move_special(sz);
268                 return;
269         }
270         if (sz == SIZE_NON)
271                 sz = SIZE_DEF;
272         if (
273                 mrg_2<010
274                 &&
275                 mrg_1==074
276                 &&
277                 sz==SIZE_L
278                 &&
279                 small(exp_1.typ==S_ABS && fitb(exp_1.val), 4)
280         ) {
281                 emit2(070000 | mrg_2<<9 | lowb(exp_1.val));
282                 return;
283         }
284         switch (sz) {
285         case SIZE_B:    opc = 010000; break;
286         case SIZE_W:    opc = 030000; break;
287         case SIZE_L:    opc = 020000; break;
288         }
289         emit2(opc | mrg_1 | (mrg_2&7)<<9 | (mrg_2&070)<<3);
290         ea_1(sz, 0);
291         ea_2(sz, ALT);
292 }
293
294 move_special(sz)
295 {
296         if (mrg_2 >= 076) {
297                 if (sz != SIZE_NON)
298                         checksize(sz, 2);
299                 emit2(042300 | (mrg_2==076?0:01000) | mrg_1);
300                 ea_1(SIZE_W, DTA);
301                 return;
302         }
303         if (mrg_1 >= 076) {
304                 if (mrg_1 == 076)
305                         test68010();
306                 if (sz != SIZE_NON)
307                         checksize(sz, 2);
308                 emit2(040300 | (mrg_1==076?01000:0) | mrg_2);
309                 ea_2(SIZE_W, DTA|ALT);
310                 return;
311         }
312         if (sz != SIZE_NON)
313                 checksize(sz, 4);
314         if (mrg_1==075 && (mrg_2&070)==010) {
315                 emit2(047150 | (mrg_2&7));
316                 return;
317         }
318         if (mrg_2==075 && (mrg_1&070)==010) {
319                 emit2(047140 | (mrg_1&7));
320                 return;
321         }
322         badoperand();
323 }
324
325 int
326 reverse(regs, max)
327         register int regs;
328 {
329         register int r, i;
330
331         r = regs; regs = 0;
332         for (i = max; i > 0; i--) {
333                 regs <<= 1;
334                 if (r & 1) regs++;
335                 r >>= 1;
336         }
337         return regs;
338 }
339
340 movem(dr, sz, regs)
341 {
342         register i;
343
344         if ((mrg_2>>3) == 04) {
345                 regs = reverse(regs, 16);
346         }
347         checksize(sz, 2|4);
348         if ((mrg_2>>3)-3 == dr)
349                 badoperand();
350         emit2(044200 | dr<<10 | (sz & 0200) >> 1 | mrg_2);
351         emit2(regs);
352         i = CTR;
353         if (dr == 0 && (mrg_2&070) == 040)
354                 i = MEM;
355         if (dr != 0 && (mrg_2&070) == 030)
356                 i = MEM;
357         if (dr == 0)
358                 i |= ALT;
359         ea_2(sz, i);
360 }
361
362 movep(sz)
363 {
364         checksize(sz, 2|4);
365         if (mrg_1<010 && (mrg_2&070)==050) {
366                 emit2(0610 | (sz & 0200)>>1 | mrg_1<<9 | (mrg_2&7));
367                 ea_2(sz, 0);
368                 return;
369         }
370         if (mrg_2<010 && (mrg_1&070)==050) {
371                 emit2(0410 | (sz & 0200)>>1 | mrg_2<<9 | (mrg_1&7));
372                 ea_1(sz, 0);
373                 return;
374         }
375         badoperand();
376 }
377
378 branch(opc, exp)
379 expr_t exp;
380 {
381         register sm;
382
383         exp.val -= (DOTVAL + 2);
384         if ((pass == PASS_2) 
385             &&
386             (exp.val > 0)
387             &&
388             ((exp.typ & S_DOT) == 0)
389            )
390                 exp.val -= DOTGAIN;
391         sm = fitb(exp.val);
392         if ((exp.typ & ~S_DOT) != DOTTYP)
393                 sm = 0;
394         if (small(sm,2)) {
395                 if (exp.val == 0)
396                         emit2(047161);  /* NOP */
397                 else
398                         emit2(opc | lowb(exp.val));
399         } else {
400                 Xfit(fitw(exp.val));
401                 emit2(opc);
402 #ifdef RELOCATION
403                 newrelo(exp.typ, RELPC|RELO2|RELBR|RELWR);
404 #endif
405                 emit2(loww(exp.val));
406         }
407 }
408
409 ea5x73(rg, sz)
410 {
411         if ((exp_2.typ & ~S_DOT) == DOTTYP) {
412                 /* pc relative with index */
413                 if (sz == SIZE_NON)
414                         sz = SIZE_DEF;
415                 exp_2.val -= (DOTVAL + extension_offset());
416                 mrg_2 = 073;
417                 checksize(sz, 2|4);
418                 index(rg<<12 | (sz&0200)<<4);
419                 return;
420         }
421         /* displacement */
422         mrg_2 = 050 | rg;
423         if (pass == PASS_1)     /* tricky, maybe 073 in next passes */
424                 return;
425         if ((rg & 010) == 0 || sz != SIZE_NON)
426                 badoperand();
427 }
428
429 ea707172(sz)
430 {
431         register sm;
432
433         mrg_2 = 071;
434         switch (sz) {
435         case SIZE_B:
436                 badoperand();
437         case SIZE_W:
438                 mrg_2 = 070;
439         case SIZE_L:
440                 return;
441         case SIZE_NON:
442                 break;
443         }
444         if (pass == PASS_1) {
445                 /*
446                  * reserve a bit in the bittable
447                  * in the following passes one call to small()
448                  * will be done, but we don't know which one
449                  * since exp_2.typ cannot be trusted
450                  */
451                 small(0, 2);
452                 return;
453         }
454         if ((exp_2.typ & ~S_DOT) == DOTTYP) {
455                 int off = extension_offset();
456                 sm = fitw(exp_2.val-(DOTVAL+off));
457                 sm = small(sm, 2);
458                 if (sm) {       /* pc relative */
459                         exp_2.val -= (DOTVAL+off);
460                         mrg_2 = 072;
461                 }
462         } else {
463                 sm = fitw(exp_2.val);
464 #ifdef ASLD
465                 if (exp_2.typ & S_VAR)
466                         sm = 0;
467 #else
468                 if (exp_2.typ != S_ABS)
469                         sm = 0;
470 #endif /* ASLD */
471                 sm = small(sm, 2);
472                 if (sm)
473                         mrg_2 = 070;
474         }
475 }
476
477 ea6x(rg, ir, sz)
478 {
479         mrg_2 = 060 | rg;
480         checksize(sz, 2|4);
481         index(ir<<12 | (sz&0200)<<4);
482 }
483
484 ea72()
485 {
486         mrg_2 = 072;
487         exp_2.val -= (DOTVAL + extension_offset());
488 }
489
490 ea73(ri, sz)
491 {
492         mrg_2 = 073;
493         exp_2.val -= (DOTVAL + extension_offset());
494         checksize(sz, 2|4);
495         index(ri<<12 | (sz&0200)<<4);
496 }
497
498 Xnofit()
499 {
500         if (pass == PASS_3) serror("too big");
501 }
502
503 fbranch(opc, exp)
504 expr_t exp;
505 {
506         register sm;
507
508         exp.val -= (DOTVAL + 2);
509         if ((pass == PASS_2) 
510             &&
511             (exp.val > 0)
512             &&
513             ((exp.typ & S_DOT) == 0)
514            )
515                 exp.val -= DOTGAIN;
516         sm = fitw(exp.val);
517         if ((exp.typ & ~S_DOT) != DOTTYP)
518                 sm = 0;
519         if (small(sm,2)) {
520                 emit2(0170200|co_id|opc);
521                 emit2(loww(exp.val));
522                 return;
523         }
524         emit2(0170300|co_id|opc); /* 4 byte offset */
525 #ifdef RELOCATION
526         newrelo(exp.typ, RELPC|RELO4|RELBR|RELWR);
527 #endif
528         emit4(exp.val);
529 }
530
531 ch_sz_dreg(size, mode)
532 {
533         if (mode == 0 &&
534             (size == FSIZE_X || size == FSIZE_P || size == FSIZE_D))
535                 serror("illegal size for data register");
536 }
537
538 check_fsize(sz, size)
539 {
540         if (sz != size) serror("bad size");
541 }