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