]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/1l/asm.c
cc: use 7 octal digits for 21 bit runes
[plan9front.git] / sys / src / cmd / 1l / asm.c
1 #include        "l.h"
2
3 short   opa[20];
4 short   *op;
5
6 long
7 entryvalue(void)
8 {
9         char *a;
10         Sym *s;
11
12         a = INITENTRY;
13         if(*a >= '0' && *a <= '9')
14                 return atolwhex(a);
15         s = lookup(a, 0);
16         if(s->type == 0)
17                 return INITTEXT;
18         if(s->type != STEXT)
19                 diag("entry not text: %s", s->name);
20         return s->value;
21 }
22
23 void
24 asmb(void)
25 {
26         Prog *p;
27         long v;
28         int a;
29         short *op1;
30
31         if(debug['v'])
32                 Bprint(&bso, "%5.2f asmb\n", cputime());
33         Bflush(&bso);
34
35         seek(cout, HEADR, 0);
36         pc = INITTEXT;
37         curp = firstp;
38         for(p = firstp; p != P; p = p->link) {
39                 if(p->as == ATEXT)
40                         curtext = p;
41                 if(p->pc != pc) {
42                         if(!debug['a'])
43                                 print("%P\n", curp);
44                         diag("phase error %.4lux sb %.4lux in %s", p->pc, pc, TNAME);
45                         pc = p->pc;
46                 }
47                 curp = p;
48                 if(debug['a'])
49                         Bprint(&bso, "%lux:%P\n", pc, curp);
50                 asmins(p);
51                 if(cbc < sizeof(opa))
52                         cflush();
53                 for(op1 = opa; op1 < op; op1++) {
54                         a = *op1;
55                         *cbp++ = a >> 8;
56                         *cbp++ = a;
57                 }
58                 a = 2*(op - opa);
59                 pc += a;
60                 cbc -= a;
61                 if(debug['a']) {
62                         for(op1 = opa; op1 < op; op1++)
63                                 if(op1 == opa)
64                                         Bprint(&bso, "\t\t%4ux", *op1 & 0xffff);
65                                 else
66                                         Bprint(&bso, " %4ux", *op1 & 0xffff);
67                         if(op != opa)
68                                 Bprint(&bso, "\n");
69                 }
70         }
71         cflush();
72         switch(HEADTYPE) {
73         case 0: /* this is garbage */
74                 seek(cout, rnd(HEADR+textsize, 8192), 0);
75                 break;
76         case 1: /* plan9 boot data goes into text */
77                 seek(cout, rnd(HEADR+textsize, INITRND), 0);
78                 break;
79         case 2: /* plan 9 */
80                 seek(cout, HEADR+textsize, 0);
81                 break;
82         case 3: /* next boot */
83                 seek(cout, HEADR+rnd(textsize, INITRND), 0);
84                 break;
85         case 4: /* preprocess pilot */
86                 seek(cout, HEADR+textsize, 0);
87                 break;
88         }
89
90         if(debug['v'])
91                 Bprint(&bso, "%5.2f datblk\n", cputime());
92         Bflush(&bso);
93
94         for(v = 0; v < datsize; v += sizeof(buf)-100) {
95                 if(datsize-v > sizeof(buf)-100)
96                         datblk(v, sizeof(buf)-100);
97                 else
98                         datblk(v, datsize-v);
99         }
100
101         symsize = 0;
102         spsize = 0;
103         lcsize = 0;
104         relocsize = 0;
105
106         Bflush(&bso);
107
108         switch(HEADTYPE) {
109         default:
110                 seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
111                 break;
112         case 1: /* plan9 boot data goes into text */
113                 seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
114                 break;
115         case 2: /* plan 9 */
116                 seek(cout, HEADR+textsize+datsize, 0);
117                 break;
118         case 3: /* next boot */
119                 seek(cout, HEADR+rnd(textsize, INITRND)+datsize, 0);
120                 break;
121         case 4: /* preprocess pilot */
122                 seek(cout, HEADR+textsize+datsize, 0);
123                 break;
124         }
125         if(!debug['s']) {
126                 if(debug['v'])
127                         Bprint(&bso, "%5.2f sym\n", cputime());
128                 asmsym();
129         }
130         Bflush(&bso);
131         if(!debug['s']) {
132                 if(debug['v'])
133                         Bprint(&bso, "%5.2f sp\n", cputime());
134                 asmsp();
135         }
136         Bflush(&bso);
137         if(!debug['s']) {
138                 if(debug['v'])
139                         Bprint(&bso, "%5.2f pc\n", cputime());
140                 asmlc();
141         }
142         Bflush(&bso);
143         if(!debug['s']) {
144                 if(debug['v'])
145                         Bprint(&bso, "%5.2f reloc\n", cputime());
146                 asmreloc();
147         }
148         cflush();
149
150         if(debug['v'])
151                 Bprint(&bso, "%5.2f headr\n", cputime());
152         Bflush(&bso);
153         seek(cout, 0L, 0);
154         switch(HEADTYPE) {
155         default:
156                 lput(0x160L<<16);               /* magic and sections */
157                 lput(0L);                       /* time and date */
158                 lput(rnd(HEADR+textsize, 4096)+datsize);
159                 lput(symsize);                  /* nsyms */
160                 lput((0x38L<<16)|7L);           /* size of optional hdr and flags */
161                 lput((0413<<16)|0437L);         /* magic and version */
162                 lput(rnd(HEADR+textsize, 4096));        /* sizes */
163                 lput(datsize);
164                 lput(bsssize);
165                 lput(entryvalue());             /* va of entry */
166                 lput(INITTEXT-HEADR);           /* va of base of text */
167                 lput(INITDAT);                  /* va of base of data */
168                 lput(INITDAT+datsize);          /* va of base of bss */
169                 lput(~0L);                      /* gp reg mask */
170                 lput(0L);
171                 lput(0L);
172                 lput(0L);
173                 lput(0L);
174                 lput(~0L);                      /* gp value ?? */
175                 break;
176         case 1: /* plan9 boot data goes into text */
177                 lput(0407);                     /* magic */
178                 lput(rnd(HEADR+textsize, INITRND)-HEADR+datsize);               /* sizes */
179                 lput(0);
180                 lput(bsssize);
181                 lput(symsize);                  /* nsyms */
182                 lput(entryvalue());             /* va of entry */
183                 lput(spsize);                   /* sp offsets */
184                 lput(lcsize);                   /* line offsets */
185                 break;
186         case 2: /* plan 9 */
187                 lput(0407);                     /* magic */
188                 lput(textsize);                 /* sizes */
189                 lput(datsize);
190                 lput(bsssize);
191                 lput(symsize);                  /* nsyms */
192                 lput(entryvalue());             /* va of entry */
193                 lput(spsize);                   /* sp offsets */
194                 lput(lcsize);                   /* line offsets */
195                 break;
196         case 3: /* next boot */
197                 /* header */
198                 lput(0xfeedfaceL);                      /* magic */
199                 lput(6);                                /* 68040 */
200                 lput(1);                                /* more 68040 */
201                 lput(5);                                /* file type 'boot' */
202                 lput(HEADTYPE);                         /* number commands */
203                 lput(HEADR-7*4);                        /* sizeof commands */
204                 lput(1);                                /* no undefineds */
205                 /* command 1 text */
206                 lput(1);                                /* command = 'segment' */
207                 lput(124);                              /* command size */
208                 s16put("__TEXT");
209                         /* botch?? entryvalue() */
210                 lput(INITTEXT);                         /* va of start */
211                 lput(rnd(textsize, 8192));              /* va size */
212                 lput(HEADR);                            /* file offset */
213                 lput(rnd(textsize, 8192));              /* file size */
214                 lput(7);                                /* max prot */
215                 lput(7);                                /* init prot */
216                 lput(1);                                /* number of sections */
217                 lput(0);                                /* flags */
218                 /* text section */
219                 s16put("__text");
220                 s16put("__TEXT");
221                         /* botch?? entryvalue() */
222                 lput(INITTEXT);                         /* va of start */
223                 lput(textsize);                         /* va size */
224                 lput(HEADR);                            /* file offset */
225                 lput(2);                                /* align */
226                 lput(0);                                /* reloff */
227                 lput(0);                                /* nreloc */
228                 lput(0);                                /* flags */
229                 lput(0);                                /* reserved1 */
230                 lput(0);                                /* reserved2 */
231                 /* command 1 data */
232                 lput(1);                                /* command = 'segment' */
233                 lput(192);                              /* command size */
234                 s16put("__DATA");
235                 lput(INITDAT);                          /* va of start */
236                 lput(rnd(datsize, 8192));               /* va size */
237                 lput(HEADR+rnd(textsize, 8192));        /* file offset */
238                 lput(rnd(datsize, 8192));               /* file size */
239                 lput(7);                                /* max prot */
240                 lput(7);                                /* init prot */
241                 lput(2);                                /* number of sections */
242                 lput(0);                                /* flags */
243                 /* data section */
244                 s16put("__data");
245                 s16put("__DATA");
246                 lput(INITDAT);                          /* va of start */
247                 lput(datsize);                          /* va size */
248                 lput(HEADR+rnd(textsize, 8192));        /* file offset */
249                 lput(2);                                /* align */
250                 lput(0);                                /* reloff */
251                 lput(0);                                /* nreloc */
252                 lput(0);                                /* flags */
253                 lput(0);                                /* reserved1 */
254                 lput(0);                                /* reserved2 */
255                 /* bss section */
256                 s16put("__bss");
257                 s16put("__DATA");
258                 lput(INITDAT+datsize);                  /* va of start */
259                 lput(bsssize);                          /* va size */
260                 lput(0);                                /* file offset */
261                 lput(2);                                /* align */
262                 lput(0);                                /* reloff */
263                 lput(0);                                /* nreloc */
264                 lput(1);                                /* flags = zero fill */
265                 lput(0);                                /* reserved1 */
266                 lput(0);                                /* reserved2 */
267                 /* command 2 symbol */
268                 lput(2);                                /* command = 'symbol' */
269                 lput(24);                               /* command size */
270                 lput(HEADR+rnd(textsize, INITRND)
271                         +datsize);                      /* symoff */
272                 lput(symsize);                          /* nsyms */
273                 lput(spsize);                           /* sp offsets */
274                 lput(lcsize);                           /* line offsets */
275                 break;
276         case 4: /* preprocess pilot */
277                 lput(0407);                     /* magic */
278                 lput(textsize);                 /* sizes */
279                 lput(datsize);
280                 lput(bsssize);
281                 lput(symsize);                  /* nsyms */
282                 lput(entryvalue());             /* va of entry */
283                 lput(spsize);                   /* sp offsets */
284                 lput(lcsize);                   /* line offsets */
285                 lput(relocsize);                /* relocation */
286                 break;
287         }
288         cflush();
289 }
290
291 void
292 asmins(Prog *p)
293 {
294         Optab *o;
295         int t, a, b;
296         long v;
297
298         op = opa + 1;
299         if(special[p->from.type])
300         switch(p->from.type) {
301
302         case D_CCR:
303                 if(p->as != AMOVW)
304                         goto bad;
305                 a = asmea(p, &p->to);
306                 if((a & 0170) == 010)
307                         goto bad;
308                 opa[0] = 0x42c0 | a;            /* mov from ccr */
309                 return;
310
311         case D_SR:
312                 if(p->as != AMOVW)
313                         goto bad;
314                 a = asmea(p, &p->to);
315                 if((a & 0170) == 010)
316                         goto bad;
317                 opa[0] = 0x40c0 | a;            /* mov from sr */
318                 return;
319
320         case D_USP:
321                 if(p->as != AMOVL)
322                         goto bad;
323                 a = asmea(p, &p->to);
324                 if((a & 0170) == 010) {
325                         opa[0] = 0x4e68|(a&7);  /* mov usp An */
326                         return;
327                 }
328                 t = 0x800;
329                 goto movec1;
330
331         case D_SFC:
332                 t = 0x000;
333                 goto movec1;
334
335         case D_DFC:
336                 t = 0x001;
337                 goto movec1;
338
339         case D_CACR:
340                 t = 0x002;
341                 goto movec1;
342
343         case D_TC:
344                 t = 0x003;
345                 goto movec1;
346
347         case D_ITT0:
348                 t = 0x004;
349                 goto movec1;
350
351         case D_ITT1:
352                 t = 0x005;
353                 goto movec1;
354
355         case D_DTT0:
356                 t = 0x006;
357                 goto movec1;
358
359         case D_DTT1:
360                 t = 0x007;
361                 goto movec1;
362
363         case D_VBR:
364                 t = 0x801;
365                 goto movec1;
366
367         case D_CAAR:
368                 t = 0x802;
369                 goto movec1;
370
371         case D_MSP:
372                 t = 0x803;
373                 goto movec1;
374
375         case D_ISP:
376                 t = 0x804;
377                 goto movec1;
378
379         case D_MMUSR:
380                 t = 0x805;
381                 goto movec1;
382
383         case D_URP:
384                 t = 0x806;
385                 goto movec1;
386
387         case D_SRP:
388                 t = 0x807;
389                 goto movec1;
390
391         movec1:
392                 if(p->as != AMOVL)
393                         goto bad;
394                 opa[0] = 0x4e7a;                        /* mov spc Dn */
395                 a = asmea(p, &p->to);
396                 b = a & 0170;
397                 if(b == 0 || b == 010) {
398                         *op++ = (a<<12) | t;
399                         return;
400                 }
401                 goto bad;
402
403         case D_FPCR:
404                 t = 0xb000;
405                 goto movec3;
406
407         case D_FPSR:
408                 t = 0xa800;
409                 goto movec3;
410
411         case D_FPIAR:
412                 t = 0xa400;
413
414         movec3:
415                 if(p->as != AMOVL)
416                         goto bad;
417                 op++;
418                 a = asmea(p, &p->to);
419                 opa[0] = optab[AFMOVEL].opcode0 | a;
420                 opa[1] = t;
421                 return;
422         }
423         if(special[p->to.type])
424         switch(p->to.type) {
425
426         case D_CCR:
427                 if(p->as != AMOVW)              /* botch, needs and, eor etc. */
428                         goto bad;
429                 a = asmea(p, &p->from);
430                 if((a & 0170) == 010)
431                         goto bad;
432                 opa[0] = 0x44c0 | a;            /* mov to ccr */
433                 return;
434
435         case D_SR:
436                 if(p->as != AMOVW)              /* botch, needs and, eor etc. */
437                         goto bad;
438                 a = asmea(p, &p->from);
439                 if((a & 0170) == 010)
440                         goto bad;
441                 opa[0] = 0x46c0 | a;            /* mov to sr */
442                 return;
443
444         case D_USP:
445                 if(p->as != AMOVL)
446                         goto bad;
447                 a = asmea(p, &p->from);
448                 if((a & 0170) == 010) {
449                         opa[0] = 0x4e60|(a&7);  /* mov An usp */
450                         return;
451                 }
452                 t = 0x800;
453                 goto movec2;
454
455         case D_SFC:
456                 t = 0x000;
457                 goto movec2;
458
459         case D_DFC:
460                 t = 0x001;
461                 goto movec2;
462
463         case D_CACR:
464                 t = 0x002;
465                 goto movec2;
466
467         case D_TC:
468                 t = 0x003;
469                 goto movec2;
470
471         case D_ITT0:
472                 t = 0x004;
473                 goto movec2;
474
475         case D_ITT1:
476                 t = 0x005;
477                 goto movec2;
478
479         case D_DTT0:
480                 t = 0x006;
481                 goto movec2;
482
483         case D_DTT1:
484                 t = 0x007;
485                 goto movec2;
486
487         case D_VBR:
488                 t = 0x801;
489                 goto movec2;
490
491         case D_CAAR:
492                 t = 0x802;
493                 goto movec2;
494
495         case D_MSP:
496                 t = 0x803;
497                 goto movec2;
498
499         case D_ISP:
500                 t = 0x804;
501                 goto movec2;
502
503         case D_MMUSR:
504                 t = 0x805;
505                 goto movec2;
506
507         case D_URP:
508                 t = 0x806;
509                 goto movec2;
510
511         case D_SRP:
512                 t = 0x807;
513                 goto movec2;
514
515         movec2:
516                 if(p->as != AMOVL)
517                         goto bad;
518                 opa[0] = 0x4e7b;                        /* mov Dn spc */
519                 a = asmea(p, &p->from);
520                 b = a & 0170;
521                 if(b == 0 || b == 010) {
522                         *op++ = (a<<12) | t;
523                         return;
524                 }
525                 goto bad;
526
527         case D_FPCR:
528                 t = 0x9000;
529                 goto movec4;
530
531         case D_FPSR:
532                 t = 0x8800;
533                 goto movec4;
534
535         case D_FPIAR:
536                 t = 0x8400;
537
538         movec4:
539                 if(p->as != AMOVL)
540                         goto bad;
541                 op++;
542                 a = asmea(p, &p->from);
543                 opa[0] = optab[AFMOVEL].opcode0 | a;
544                 opa[1] = t;
545                 return;
546         }
547
548         o = &optab[p->as];
549         t = o->opcode0;
550         switch(o->optype) {
551         case 0:         /* pseudo ops */
552                 if(p->as != ATEXT && p->as != ANOP) {
553                         if(!debug['a'])
554                                 print("%P\n", p);
555                         diag("unimplemented instruction in %s", TNAME);
556                         return;
557                 }
558                 op = opa;
559                 return;
560
561         case 1:         /* branches */
562                 if(p->to.type != D_BRANCH)
563                         goto bad;
564                 a = asmea(p, &p->to);
565                 if(a == 071)
566                         t = o->opcode1;
567                 t |= a;
568                 break;
569
570         case 2:         /* move */
571                 a = asmea(p, &p->from);
572                 b = asmea(p, &p->to);
573                 if((a & 0170) == 0110) { /* src quick */
574                         t = o->opcode1;
575                         if((b & 0170) != 0)
576                                 goto bad;
577                         t |= a >> 7;
578                         t |= b << 9;
579                         break;
580                 }
581                 t |= a;
582                 t |= (b&7) << 9;
583                 t |= (b&070) << 3;
584                 break;
585
586         case 3:         /* add */
587                 a = asmea(p, &p->from);
588                 b = asmea(p, &p->to);
589                 if((a & 0170) == 0110) { /* src quick */
590                         t = o->opcode1;
591                         t |= (a&01600) << 2;
592                         t |= b;
593                         break;
594                 }
595                 if((b & 0170) == 0) { /* dst Dn */
596                         t |= a;
597                         t |= (b & 7) << 9;
598                         break;
599                 }
600                 if((b & 0170) == 010) { /* dst An */
601                         if((t & 0xc0) == 0)
602                                 goto bad;
603                         t = o->opcode2;
604                         t |= a;                                         
605                         t |= (b & 7) << 9;
606                         break;
607                 }
608                 if((a & 0170) == 0) { /* src Dn */
609                         t |= 0x100;
610                         t |= (a & 7) << 9;
611                         t |= b;
612                         break;
613                 }
614                 if((a & 0177) == 074) { /* src immed */
615                         t = o->opcode3;
616                         t |= b;
617                         break;
618                 }
619                 goto bad;
620
621         case 4:         /* no operands */
622                 break;
623
624         case 5:         /* tst */
625                 t |= asmea(p, &p->to);
626                 if((t&0170) == 010)
627                         goto bad;
628                 break;
629
630         case 6:         /* lea */
631                 a = asmea(p, &p->from);
632                 b = asmea(p, &p->to);
633                 if((b & 0170) != 010)
634                         goto bad;
635                 t |= a;
636                 t |= (b & 7) << 9;
637                 break;
638
639         case 7:         /* cmp */
640                 b = asmea(p, &p->to);
641                 a = asmea(p, &p->from);
642                 if((a & 0170) == 010) { /* dst An */
643                         t = o->opcode1;
644                         if(t == 0)      /* cmpb illegal */
645                                 goto bad;
646                         t |= 0xc0;
647                         t |= b;                                         
648                         t |= (a & 7) << 9;
649                         break;
650                 }
651                 if((b & 0177) == 074) { /* src immed */
652                         t = o->opcode2;
653                         t |= a;
654                         break;
655                 }
656                 if((a & 0170) == 0) {   /* dst Dn */
657                         t |= b;
658                         t |= (a&7) << 9;
659                         break;
660                 }
661                 if((b&0170) == 030 && (a&0170) == 030) { /* (A)+,(A)+ */
662                         t = o->opcode3;
663                         t |= b & 7;
664                         t |= (a & 7) << 9;
665                         break;
666                 }
667                 goto bad;
668
669         case 8:         /* svc */
670                 *op++ = optab[ARTS].opcode0;
671                 break;
672
673         case 9:         /* and */
674                 a = asmea(p, &p->from);
675                 b = asmea(p, &p->to);
676                 if((a & 0170) == 010)
677                         goto bad;
678                 if((b & 0170) == 0) { /* dst Dn */
679                         t |= a;
680                         t |= (b&7) << 9;
681                         break;
682                 }
683                 if((a & 0170) == 0) { /* src Dn */
684                         t = o->opcode1;
685                         t |= b;
686                         t |= (a&7) << 9;
687                         break;
688                 }
689                 if((a & 0177) == 074) { /* src immed */
690                         t = o->opcode2;
691                         t |= b;
692                         break;
693                 }
694                 goto bad;
695
696         case 10:        /* eor */
697                 a = asmea(p, &p->from);
698                 b = asmea(p, &p->to);
699                 if((a & 0170) == 010)
700                         goto bad;
701                 if((a & 0170) == 0) { /* src Dn */
702                         t |= b;
703                         t |= (a&7) << 9;
704                         break;
705                 }
706                 if((a & 0177) == 074) { /* src immed */
707                         t = o->opcode1;
708                         t |= b;
709                         break;
710                 }
711                 goto bad;
712
713         case 11:        /* ext */
714                 b = asmea(p, &p->to);
715                 if((b & 0170) == 0) { /* dst Dn */
716                         t |= b;
717                         break;
718                 }
719                 goto bad;
720
721         case 12:        /* shift */
722                 a = asmea(p, &p->from);
723                 b = asmea(p, &p->to);
724                 if((b & 0170) == 0) { /* dst Dn */
725                         if((a & 0177) == 0110) { /* src quick */
726                                 t |= (a & 01600) << 2;
727                                 t |= b;
728                                 break;
729                         }
730                         if((a & 0170) == 0) { /* src Dn */
731                                 t |= 0x20;
732                                 t |= a << 9;
733                                 t |= b;
734                                 break;
735                         }
736                         goto bad;
737                 }
738                 goto bad;
739
740         case 13:        /* mul, div short */
741                 a = asmea(p, &p->from);
742                 b = asmea(p, &p->to);
743                 if((b & 0170) == 0) { /* dst Dn */
744                         if((a & 0170) == 010)
745                                 goto bad;       
746                         t |= a;
747                         t |= b << 9;
748                         break;
749                 }
750                 goto bad;
751
752         case 14:        /* mul, div long */
753                 *op++ = o->opcode1;
754                 a = asmea(p, &p->from);
755                 b = asmea(p, &p->to);
756                 if((b & 0170) == 0) { /* dst Dn */
757                         if((a & 0170) == 010)
758                                 goto bad;       
759                         t |= a;
760                         opa[1] |= b << 12;
761                         opa[1] |= b+1;
762                         break;
763                 }
764                 goto bad;
765
766         case 15:        /* dec and branch */
767                 if(p->to.type != D_BRANCH)
768                         goto bad;
769                 v = p->pcond->pc - p->pc - 2;
770                 if(v < -32768L || v >= 32768L)
771                         goto bad;
772                 *op++ = v;
773                 a = asmea(p, &p->from);
774                 if((a & 0170) != 0)
775                         goto bad;
776                 t |= a;
777                 break;
778
779         case 16:        /* fmove */
780                 *op++ = o->opcode1;
781                 a = asmea(p, &p->from);
782                 b = asmea(p, &p->to);
783                 if((a & 0170) == 0100) { /* src Fn */
784                         if((b & 0170) == 0100) { /* both Fn */
785                                 opa[1] |= (a&7) << 10;
786                                 opa[1] |= (b&7) << 7;
787                                 break;
788                         }
789                         t |= b;
790                         opa[1] = o->opcode2;
791                         opa[1] |= (a&7) << 7;
792                         break;
793                 }
794                 if((b & 0170) != 0100) /* dst Fn */
795                         goto bad;
796                 t |= a;
797                 opa[1] = o->opcode3;
798                 opa[1] |= (b&7) << 7;
799                 break;
800
801         case 17:        /* floating ea,Fn */
802                 *op++ = o->opcode1;
803                 a = asmea(p, &p->from);
804                 b = asmea(p, &p->to);
805                 if((b & 0170) != 0100) /* dst Fn */
806                         goto bad;
807                 if((a & 0170) == 0100) { /* both Fn */
808                         opa[1] |= (a&7) << 10;
809                         opa[1] |= (b&7) << 7;
810                         break;
811                 }
812                 t |= a;
813                 opa[1] = o->opcode2;
814                 opa[1] |= (b&7) << 7;
815                 break;
816
817         case 18:        /* floating branchs */
818                 if(p->to.type != D_BRANCH)
819                         goto bad;
820                 v = p->pcond->pc - p->pc - 2;
821                 if(v < -32768L || v >= 32768L)
822                         goto bad;
823                 *op++ = v;
824                 break;
825
826         case 19:        /* floating dec and branch */
827                 if(p->to.type != D_BRANCH)
828                         goto bad;
829                 *op++ = o->opcode1;
830                 v = p->pcond->pc - p->pc - 2;
831                 if(v < -32768L || v >= 32768L)
832                         goto bad;
833                 *op++ = v;
834                 a = asmea(p, &p->from);
835                 if((a & 0170) != 0)
836                         goto bad;
837                 t |= a;
838                 break;
839
840         case 20:        /* ftst ea */
841                 *op++ = o->opcode1;
842                 if(p->from.type != D_NONE)
843                         goto bad;
844                 a = asmea(p, &p->to);
845                 if((a & 0170) == 0100) { /* Fn */
846                         opa[1] |= (a&7) << 10;
847                         break;
848                 }
849                 t |= a;
850                 opa[1] = o->opcode2;
851                 break;
852
853         case 21:        /* fneg */
854                 *op++ = o->opcode1;
855                 if(p->from.type == D_NONE) {
856                         b = asmea(p, &p->to);
857                         a = b;
858                 } else {
859                         a = asmea(p, &p->from);
860                         b = asmea(p, &p->to);
861                 }
862                 if((b & 0170) != 0100) /* dst Fn */
863                         goto bad;
864                 if((a & 0170) == 0100) { /* both Fn */
865                         opa[1] |= (a&7) << 10;
866                         opa[1] |= (b&7) << 7;
867                         break;
868                 }
869                 t |= a;
870                 opa[1] = o->opcode2;
871                 opa[1] |= (b&7) << 7;
872                 break;
873
874         case 22:        /* floating cmp Fn,ea */
875                 *op++ = o->opcode1;
876                 a = asmea(p, &p->from);
877                 b = asmea(p, &p->to);
878                 if((a & 0170) != 0100) /* dst Fn */
879                         goto bad;
880                 if((b & 0170) == 0100) { /* both Fn */
881                         opa[1] |= (b&7) << 10;
882                         opa[1] |= (a&7) << 7;
883                         break;
884                 }
885                 t |= b;
886                 opa[1] = o->opcode2;
887                 opa[1] |= (a&7) << 7;
888                 break;
889
890         case 23:        /* word, long */
891                 op = opa;
892                 a = asmea(p, &p->to);
893                 if(a == ((7<<3)|4))
894                         return;
895                 if(a == ((7<<3)|1)) {
896                         if(p->as == AWORD) {
897                                 op = opa;
898                                 *op++ = opa[1];
899                         }
900                         return;
901                 }
902                 if(a == ((7<<3)|0)) {
903                         if(p->as == ALONG) {
904                                 *op++ = opa[0];
905                                 opa[0] = 0;
906                         }
907                         return;
908                 }
909                 goto bad;
910
911         case 24:        /* bit field */
912                 a = ((p->to.field&31)<<6) | (p->from.field&31);
913                 if(p->as == ABFINS) {
914                         b = asmea(p, &p->from);
915                         if((b&0170) != 0)
916                                 goto bad;
917                         a |= b<<12;
918                         *op++ = a;
919                         a = asmea(p, &p->to);
920                 } else {
921                         if(p->to.type != D_NONE) {
922                                 b = asmea(p, &p->to);
923                                 if((b&0170) != 0)
924                                         goto bad;
925                                 a |= b<<12;
926                         }
927                         *op++ = a;
928                         a = asmea(p, &p->from);
929                 }
930                 t |= a;
931                 a &= 0170;
932                 if(a == 010 || a == 030 || a == 040 || a == 074)
933                         goto bad;
934                 break;
935
936         case 25:        /* movem */
937                 if(p->from.type == D_CONST) { /* registers -> memory */
938                         asmea(p, &p->from);
939                         a = asmea(p, &p->to);
940                         if(a == 074)
941                                 goto bad;
942                         b = a & 0170;
943                         if(b == 000 || b == 010 || b == 030)
944                                 goto bad;
945                         t |= a;
946                         break;
947                 }
948                 if(p->to.type == D_CONST) { /* memory -> registers */
949                         t |= 0x400;
950                         asmea(p, &p->to);
951                         a = asmea(p, &p->from);
952                         if(a == 074)
953                                 goto bad;
954                         b = a & 0170;
955                         if(b == 000 || b == 010 || b == 040)
956                                 goto bad;
957                         t |= a;
958                         break;
959                 }
960                 goto bad;
961
962         case 26:        /* chk */
963                 a = asmea(p, &p->from);
964                 if((a&0170) == 010)
965                         goto bad;
966                 b = asmea(p, &p->to);
967                 if((b&0170) != 0)
968                         goto bad;
969                 t |= a;
970                 t |= b<<9;
971                 break;
972
973         case 27:        /* btst */
974                 a = asmea(p, &p->from);
975                 if(a == 074) {
976                         t = o->opcode1;
977                 } else
978                 if((a&0170) != 0)
979                         goto bad;
980                 b = asmea(p, &p->to);
981                 if(b == 074 || (b&0170) == 010)
982                         goto bad;
983                 t |= b;
984                 break;
985
986         case 28:        /* fmovem */
987                 if(p->from.type == D_CONST) { /* registers -> memory */
988                         b = p->from.offset & 0xff;
989                         b |= 0xf000;            /* control or postinc */
990                         *op++ = b;
991                         a = asmea(p, &p->to);
992                         if(a == 074)
993                                 goto bad;
994                         b = a & 0170;
995                         if(b == 000 || b == 010 || b == 030)
996                                 goto bad;
997                         if(b == 040)
998                                 op[-1] &= ~0x1000;      /* predec */
999                         t |= a;
1000                         break;
1001                 }
1002                 if(p->to.type == D_CONST) { /* memory -> registers */
1003                         b = p->to.offset & 0xff;
1004                         b |= 0xd000;            /* control or postinc */
1005                         *op++ = b;
1006                         a = asmea(p, &p->from);
1007                         if(a == 074)
1008                                 goto bad;
1009                         b = a & 0170;
1010                         if(b == 000 || b == 010 || b == 040)
1011                                 goto bad;
1012                         t |= a;
1013                         break;
1014                 }
1015                 goto bad;
1016
1017         case 29:        /* fmovemc */
1018                 if(p->from.type == D_CONST) { /* registers -> memory */
1019                         b = (p->from.offset & 0x7) << 10;
1020                         b |= 0xa000;
1021                         *op++ = b;
1022                         a = asmea(p, &p->to);
1023                         if(a == 074)
1024                                 goto bad;
1025                         b = a & 0170;
1026                         if(b == 000 || b == 010 || b == 030)
1027                                 goto bad;
1028                         t |= a;
1029                         break;
1030                 }
1031                 if(p->to.type == D_CONST) { /* memory -> registers */
1032                         b = (p->to.offset & 0x7) << 10;
1033                         b |= 0x8000;
1034                         *op++ = b;
1035                         a = asmea(p, &p->from);
1036                         if(a == 074)
1037                                 goto bad;
1038                         b = a & 0170;
1039                         if(b == 000 || b == 010 || b == 040)
1040                                 goto bad;
1041                         t |= a;
1042                         break;
1043                 }
1044                 goto bad;
1045
1046         case 30:        /* trap */
1047                 if(p->to.type == D_CONST) {
1048                         t |= p->to.offset & 0xf;
1049                         break;
1050                 }
1051                 goto bad;
1052
1053         case 31:        /* chk2, cmp2 */
1054                 b = asmea(p, &p->to);
1055                 a = b & 0170;
1056                 if(a == 000 || a == 010) {
1057                         *op++ = o->opcode1 | (b << 12);
1058                         t |= asmea(p, &p->from);
1059                         break;
1060                 }
1061                 goto bad;
1062
1063         case 32:        /* casew */
1064                 /* jmp (0,pc,r0.w*1) */
1065                 casepc = p->pc;
1066                 *op++ = o->opcode1;
1067                 break;
1068
1069         case 34:        /* moves */
1070                 op++;
1071                 a = asmea(p, &p->from);
1072                 b = a & 0170;
1073                 if(b == 0 || b == 010) {
1074                         opa[1] = (a << 12) | 0x800;
1075                         b = asmea(p, &p->to);
1076                         a = b & 0170;
1077                         if(a == 0 || a == 010)
1078                                 goto bad;
1079                         t |= b;
1080                         break;
1081                 }
1082                 t |= a;
1083                 b = asmea(p, &p->to);
1084                 a = b & 0170;
1085                 if(a != 0 && a != 010)
1086                         goto bad;
1087                 opa[1] = (b << 12);
1088                 break;
1089
1090         case 35:        /* swap */
1091                 a = asmea(p, &p->to);
1092                 if((a & 0170) == 0) {
1093                         t |= a;
1094                         break;
1095                 }
1096                 goto bad;
1097         }
1098         opa[0] = t;
1099         return;
1100
1101 bad:
1102         if(!debug['a'])
1103                 print("%P\n", p);
1104         diag("bad combination of addressing in %s", TNAME);
1105         opa[0] = 0;
1106 }
1107
1108 int
1109 asmea(Prog *p, Adr *a)
1110 {
1111         Optab *o;
1112         int f, t, r, i;
1113         long v;
1114
1115         t = a->type;
1116         r = simple[t];
1117         v = a->offset;
1118         if(r != 0177) {
1119                 if(v == 0)
1120                         return r;
1121                 if((r & 070) != 020)
1122                         return r;
1123                 if(v >= -32768L && v < 32768L) {
1124                         *op++ = v;
1125                         return t-D_A0-I_INDIR+050;      /* d(Ax) */
1126                 }
1127                 goto toobig;
1128         }
1129         f = 0;
1130         if(a == &p->from)
1131                 f++;
1132         o = &optab[p->as];
1133         switch(t) {
1134         case D_TOS:
1135                 if(f) {
1136                         if(o->srcsp)
1137                                 return (3<<3) | 7;      /* (A7)+ */
1138                 } else
1139                         if(o->dstsp)
1140                                 return (4<<3) | 7;      /* -(A7) */
1141                 return (2<<3) | 7;                      /* (A7) */
1142                 
1143         case D_BRANCH:
1144                 v = p->pcond->pc - p->pc - 2;
1145                 if(v < -32768L || v >= 32768L) {
1146                         if(p->as == ABSR || p->as == ABRA) {
1147                                 v = p->pcond->pc;
1148                                 *op++ = v>>16;
1149                                 *op++ = v;
1150                                 return (7<<3) | 1;
1151                         }
1152                         goto toobig;
1153                 }
1154                 if(v < -128 || v >= 128 || p->mark == 4) {
1155                         *op++ = v;
1156                         return 0;
1157                 }
1158                 return v & 0xff;
1159
1160         case I_ADDR|D_STATIC:
1161         case I_ADDR|D_EXTERN:
1162                 t = a->sym->type;
1163                 if(t == 0 || t == SXREF) {
1164                         diag("undefined external: %s in %s",
1165                                 a->sym->name, TNAME);
1166                         a->sym->type = SDATA;
1167                 }
1168                 v = a->sym->value + a->offset;
1169                 if(t != STEXT)
1170                         v += INITDAT;
1171                 if(strcmp(a->sym->name, "a6base"))
1172                         break;
1173
1174         case D_CONST:
1175                 switch(f? o->srcsp: o->dstsp) {
1176                 case 4:
1177                         *op++ = v>>16;
1178
1179                 case 2:
1180                         *op++ = v;
1181                         break;
1182
1183                 default:
1184                         diag("unknown srcsp asmea in %s", TNAME);
1185                 }
1186                 return (7<<3) | 4;
1187
1188         case D_FCONST:
1189                 r = f? o->srcsp: o->dstsp;
1190                 for(i=0; i<r; i++)
1191                         ((char*)op)[i] = gnuxi(&a->ieee, i, r);
1192                 op += r/2;
1193                 return (7<<3) | 4;
1194
1195         case D_QUICK:
1196                 v = a->offset & 0xff;
1197                 return 0110 | (v<<7);
1198                         
1199         case D_STACK:
1200         case D_AUTO:
1201         case D_PARAM:
1202                 if(v == 0)
1203                         return (2<<3) | 7;      /* (A7) */
1204                 if(v >= -32768L && v < 32768L) {
1205                         *op++ = v;
1206                         return (5<<3) | 7;      /* d(A7) */
1207                 }
1208                 goto toobig;
1209
1210         case I_INDIR|D_CONST:
1211                 if(v >= -32768L && v < 32768L) {
1212                         *op++ = v;
1213                         return (7<<3) | 0;
1214                 }
1215                 *op++ = v>>16;
1216                 *op++ = v;
1217                 return (7<<3) | 1;
1218
1219         case D_STATIC:
1220         case D_EXTERN:
1221                 t = a->sym->type;
1222                 if(t == 0 || t == SXREF) {
1223                         diag("undefined external: %s in %s",
1224                                 a->sym->name, TNAME);
1225                         a->sym->type = SDATA;
1226                 }
1227                 if(t == STEXT) {
1228                         if(HEADTYPE == 4) {
1229                                 v = a->sym->value + a->offset - p->pc - 2;
1230                                 if(v >= -32768L && v < 32768L) {
1231                                         *op++ = v;
1232                                         return (7<<3) | 2;
1233                                 }
1234                                 goto toobig;
1235                         }
1236                         v = a->sym->value + a->offset;
1237                         *op++ = v>>16;
1238                         *op++ = v;
1239                         return (7<<3) | 1;
1240                 }
1241                 v = a->sym->value + a->offset - A6OFFSET;
1242                 if(v < -32768L || v >= 32768L) {
1243                         v += INITDAT + A6OFFSET;
1244                         if(v >= -32768L && v < 32768L) {
1245                                 *op++ = v;
1246                                 return (7<<3) | 0;
1247                         }
1248                         *op++ = v>>16;
1249                         *op++ = v;
1250                         return (7<<3) | 1;
1251                 }
1252                 if(v == 0)
1253                         return (2<<3) | 6;
1254                 *op++ = v;
1255                 return (5<<3) | 6;
1256         }
1257         if(!debug['a'])
1258                 print("%P\n", p);
1259         diag("unknown addressing mode: %d in %s", t, TNAME);
1260         return 0;
1261
1262 toobig:
1263         if(!debug['a'])
1264                 print("%P\n", p);
1265         diag("addressing mode >> 2^16: %d in %s", t, TNAME);
1266         return 0;
1267 }
1268
1269 void
1270 lput(long l)
1271 {
1272
1273         CPUT(l>>24)
1274         CPUT(l>>16)
1275         CPUT(l>>8)
1276         CPUT(l)
1277 }
1278
1279 void
1280 s16put(char *n)
1281 {
1282         char name[16];
1283         int i;
1284
1285         strncpy(name, n, sizeof(name));
1286         for(i=0; i<sizeof(name); i++)
1287                 CPUT(name[i])
1288 }
1289
1290 void
1291 cflush(void)
1292 {
1293         int n;
1294
1295         n = sizeof(buf.cbuf) - cbc;
1296         if(n)
1297                 write(cout, buf.cbuf, n);
1298         cbp = buf.cbuf;
1299         cbc = sizeof(buf.cbuf);
1300 }
1301
1302 void
1303 datblk(long s, long n)
1304 {
1305         Prog *p;
1306         char *cast;
1307         long l, fl, j;
1308         int i, c;
1309
1310         memset(buf.dbuf, 0, n+100);
1311         for(p = datap; p != P; p = p->link) {
1312                 curp = p;
1313                 l = p->from.sym->value + p->from.offset - s;
1314                 c = p->from.displace;
1315                 i = 0;
1316                 if(l < 0) {
1317                         if(l+c <= 0)
1318                                 continue;
1319                         while(l < 0) {
1320                                 l++;
1321                                 i++;
1322                         }
1323                 }
1324                 if(l >= n)
1325                         continue;
1326                 for(j=l+(c-i)-1; j>=l; j--)
1327                         if(buf.dbuf[j]) {
1328                                 print("%P\n", p);
1329                                 diag("multiple initialization");
1330                                 break;
1331                         }
1332                 switch(p->to.type) {
1333                 case D_FCONST:
1334                         switch(c) {
1335                         default:
1336                         case 4:
1337                                 fl = ieeedtof(&p->to.ieee);
1338                                 cast = (char*)&fl;
1339                                 if(debug['a'] && i == 0) {
1340                                         Bprint(&bso, "%lux:%P\n\t\t", l+s+INITDAT, curp);
1341                                         for(j=0; j<c; j++)
1342                                                 Bprint(&bso, "%.2ux", cast[fnuxi8[j+4]] & 0xff);
1343                                         Bprint(&bso, "\n");
1344                                 }
1345                                 for(; i<c; i++) {
1346                                         buf.dbuf[l] = cast[fnuxi8[i+4]];
1347                                         l++;
1348                                 }
1349                                 break;
1350                         case 8:
1351                                 cast = (char*)&p->to.ieee;
1352                                 if(debug['a'] && i == 0) {
1353                                         Bprint(&bso, "%lux:%P\n\t\t", l+s+INITDAT, curp);
1354                                         for(j=0; j<c; j++)
1355                                                 Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
1356                                         Bprint(&bso, "\n");
1357                                 }
1358                                 for(; i<c; i++) {
1359                                         buf.dbuf[l] = cast[fnuxi8[i]];
1360                                         l++;
1361                                 }
1362                                 break;
1363                         }
1364                         break;
1365
1366                 case D_SCONST:
1367                         if(debug['a'] && i == 0) {
1368                                 Bprint(&bso, "%.4lux:%P\n\t\t", l+s+INITDAT, curp);
1369                                 for(j=0; j<c; j++)
1370                                         Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
1371                                 Bprint(&bso, "\n");
1372                         }
1373                         for(; i<c; i++) {
1374                                 buf.dbuf[l] = p->to.scon[i];
1375                                 l++;
1376                         }
1377                         break;
1378                 default:
1379                         fl = p->to.offset;
1380                         if(p->to.sym) {
1381                                 if(p->to.sym->type == STEXT)
1382                                         fl += p->to.sym->value;
1383                                 if(p->to.sym->type == SDATA)
1384                                         fl += p->to.sym->value + INITDAT;
1385                                 if(p->to.sym->type == SBSS)
1386                                         fl += p->to.sym->value + INITDAT;
1387                         }
1388
1389                         cast = (char*)&fl;
1390                         switch(c) {
1391                         default:
1392                                 diag("bad nuxi %d %d\n%P", c, i, curp);
1393                                 break;
1394                         case 1:
1395                                 if(debug['a'] && i == 0) {
1396                                         Bprint(&bso, "%.4lux:%P\n\t\t", l+s+INITDAT, curp);
1397                                         for(j=0; j<c; j++)
1398                                                 Bprint(&bso, "%.2ux",cast[inuxi1[j]] & 0xff);
1399                                         Bprint(&bso, "\n");
1400                                 }
1401                                 for(; i<c; i++) {
1402                                         buf.dbuf[l] = cast[inuxi1[i]];
1403                                         l++;
1404                                 }
1405                                 break;
1406                         case 2:
1407                                 if(debug['a'] && i == 0) {
1408                                         Bprint(&bso, "%.4lux:%P\n\t\t", l+s+INITDAT, curp);
1409                                         for(j=0; j<c; j++)
1410                                                 Bprint(&bso, "%.2ux",cast[inuxi2[j]] & 0xff);
1411                                         Bprint(&bso, "\n");
1412                                 }
1413                                 for(; i<c; i++) {
1414                                         buf.dbuf[l] = cast[inuxi2[i]];
1415                                         l++;
1416                                 }
1417                                 break;
1418                         case 4:
1419                                 if(debug['a'] && i == 0) {
1420                                         Bprint(&bso, "%.4lux:%P\n\t\t", l+s+INITDAT, curp);
1421                                         for(j=0; j<c; j++)
1422                                                 Bprint(&bso, "%.2ux",cast[inuxi4[j]] & 0xff);
1423                                         Bprint(&bso, "\n");
1424                                 }
1425                                 for(; i<c; i++) {
1426                                         buf.dbuf[l] = cast[inuxi4[i]];
1427                                         l++;
1428                                 }
1429                                 break;
1430                         }
1431                         break;
1432                 }
1433         }
1434         write(cout, buf.dbuf, n);
1435 }
1436
1437 void
1438 asmreloc(void)
1439 {
1440         Prog *p;
1441         Sym *s1, *s2;
1442         int c1, c2, c3;
1443         long v;
1444
1445         if(HEADTYPE != 4)
1446                 return;
1447         for(p = datap; p != P; p = p->link) {
1448                 curp = p;
1449                 s1 = p->to.sym;
1450                 if(s1 == S)
1451                         continue;
1452                 c1 = 'D';
1453                 c3 = p->from.displace;
1454                 s2 = p->from.sym;
1455                 v = s2->value + INITDAT;
1456                 switch(s1->type) {
1457                 default:
1458                         diag("unknown reloc %d", s1->type);
1459                         continue;
1460                 case STEXT:
1461                         c2 = 'T';
1462                         break;
1463
1464                 case SDATA:
1465                         c2 = 'D';
1466                         break;
1467
1468                 case SBSS:
1469                         c2 = 'B';
1470                         break;
1471                 }
1472                 CPUT(c1);
1473                 CPUT(c2);
1474                 CPUT(c3);
1475                 lput(v);
1476                 if(debug['a'])
1477                         Bprint(&bso, "r %c%c%d %.8lux %s $%s\n",
1478                                 c1, c2, c3, v, s2->name, s1->name);
1479                 relocsize += 7;
1480         }
1481 }
1482
1483 int
1484 gnuxi(Ieee *d, int i, int c)
1485 {
1486         char *p;
1487         long l;
1488
1489         switch(c) {
1490         default:
1491                 diag("bad nuxi %d %d\n%P", c, i, curp);
1492                 return 0;
1493         
1494                 /*
1495                  * 2301 vax
1496                  * 0123 68k
1497                  */
1498         case 4:
1499                 l = ieeedtof(d);
1500                 p = (char*)&l;
1501                 i = gnuxi8[i+4];
1502                 break;
1503
1504                 /*
1505                  * 67452301 vax
1506                  * 45670123 68k
1507                  */
1508         case 8:
1509                 p = (char*)d;
1510                 i = gnuxi8[i];
1511                 break;
1512         }
1513         return p[i];
1514 }
1515
1516 long
1517 rnd(long v, long r)
1518 {
1519         long c;
1520
1521         if(r <= 0)
1522                 return v;
1523         v += r - 1;
1524         c = v % r;
1525         if(c < 0)
1526                 c += r;
1527         v -= c;
1528         return v;
1529 }