]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/kl/asm.c
sshfs: usage
[plan9front.git] / sys / src / cmd / kl / asm.c
1 #include        "l.h"
2
3 #define LPUT(c)\
4         {\
5                 cbp[0] = (c)>>24;\
6                 cbp[1] = (c)>>16;\
7                 cbp[2] = (c)>>8;\
8                 cbp[3] = (c);\
9                 cbp += 4;\
10                 cbc -= 4;\
11                 if(cbc <= 0)\
12                         cflush();\
13         }
14
15 #define CPUT(c)\
16         {\
17                 cbp[0] = (c);\
18                 cbp++;\
19                 cbc--;\
20                 if(cbc <= 0)\
21                         cflush();\
22         }
23
24 long
25 entryvalue(void)
26 {
27         char *a;
28         Sym *s;
29
30         a = INITENTRY;
31         if(*a >= '0' && *a <= '9')
32                 return atolwhex(a);
33         s = lookup(a, 0);
34         if(s->type == 0)
35                 return INITTEXT;
36         if(s->type != STEXT && s->type != SLEAF)
37                 diag("entry not text: %s", s->name);
38         return s->value;
39 }
40
41 void
42 asmb(void)
43 {
44         Prog *p;
45         long t;
46         Optab *o;
47
48         if(debug['v'])
49                 Bprint(&bso, "%5.2f asm\n", cputime());
50         Bflush(&bso);
51         seek(cout, HEADR, 0);
52         pc = INITTEXT;
53         for(p = firstp; p != P; p = p->link) {
54                 if(p->as == ATEXT) {
55                         curtext = p;
56                         autosize = p->to.offset + 4;
57                 }
58                 if(p->pc != pc) {
59                         diag("phase error %lux sb %lux",
60                                 p->pc, pc);
61                         if(!debug['a'])
62                                 prasm(curp);
63                         pc = p->pc;
64                 }
65                 curp = p;
66                 o = oplook(p);  /* could probably avoid this call */
67                 if(asmout(p, o, 0)) {
68                         p = p->link;
69                         pc += 4;
70                 }
71                 pc += o->size;
72         }
73         if(debug['a'])
74                 Bprint(&bso, "\n");
75         Bflush(&bso);
76         cflush();
77
78         curtext = P;
79         switch(HEADTYPE) {
80         case 0:
81         case 3:
82                 seek(cout, HEADR+textsize, 0);
83                 break;
84         case 1:
85         case 2:
86                 seek(cout, HEADR+textsize, 0);
87                 break;
88         }
89         for(t = 0; t < datsize; t += sizeof(buf)-100) {
90                 if(datsize-t > sizeof(buf)-100)
91                         datblk(t, sizeof(buf)-100);
92                 else
93                         datblk(t, datsize-t);
94         }
95
96         symsize = 0;
97         lcsize = 0;
98         if(!debug['s']) {
99                 if(debug['v'])
100                         Bprint(&bso, "%5.2f sym\n", cputime());
101                 Bflush(&bso);
102                 switch(HEADTYPE) {
103                 case 0:
104                 case 3:
105                         seek(cout, HEADR+textsize+datsize, 0);
106                         break;
107                 case 2:
108                 case 1:
109                         seek(cout, HEADR+textsize+datsize, 0);
110                         break;
111                 }
112                 if(!debug['s'])
113                         asmsym();
114                 if(debug['v'])
115                         Bprint(&bso, "%5.2f sp\n", cputime());
116                 Bflush(&bso);
117                 if(!debug['s'])
118                         asmlc();
119                  /* round up file length for boot image */
120                 if(HEADTYPE == 0 || HEADTYPE == 3)
121                         if((symsize+lcsize) & 1)
122                                 CPUT(0);
123                 cflush();
124         }
125
126         seek(cout, 0L, 0);
127         switch(HEADTYPE) {
128         case 0:
129                 lput(0x1030107);                /* magic and sections */
130                 lput(textsize);                 /* sizes */
131                 lput(datsize);
132                 lput(bsssize);
133                 lput(symsize);                  /* nsyms */
134                 lput(entryvalue());             /* va of entry */
135                 lput(0L);
136                 lput(lcsize);
137                 break;
138         case 1:
139                 break;
140         case 2:
141                 lput(4*13*13+7);                /* magic */
142                 lput(textsize);                 /* sizes */
143                 lput(datsize);
144                 lput(bsssize);
145                 lput(symsize);                  /* nsyms */
146                 lput(entryvalue());             /* va of entry */
147                 lput(0L);
148                 lput(lcsize);
149                 break;
150         case 3:
151                 lput(0x1030107);                /* magic and sections */
152                 lput(0x90100000);
153 #define SPARC_NOOP 0x01000000
154                 lput(SPARC_NOOP);
155                 lput(SPARC_NOOP);
156                 lput(SPARC_NOOP);
157                 lput(SPARC_NOOP);
158                 lput(SPARC_NOOP);
159                 lput(SPARC_NOOP);
160                 break;
161         }
162         cflush();
163 }
164
165 void
166 lput(long l)
167 {
168
169         LPUT(l);
170 }
171
172 void
173 cflush(void)
174 {
175         int n;
176
177         n = sizeof(buf.cbuf) - cbc;
178         if(n)
179                 write(cout, buf.cbuf, n);
180         cbp = buf.cbuf;
181         cbc = sizeof(buf.cbuf);
182 }
183
184 void
185 asmsym(void)
186 {
187         Prog *p;
188         Auto *a;
189         Sym *s;
190         int h;
191
192         s = lookup("etext", 0);
193         if(s->type == STEXT)
194                 putsymb(s->name, 'T', s->value, s->version);
195
196         for(h=0; h<NHASH; h++)
197                 for(s=hash[h]; s!=S; s=s->link)
198                         switch(s->type) {
199                         case SCONST:
200                                 putsymb(s->name, 'D', s->value, s->version);
201                                 continue;
202
203                         case SDATA:
204                                 putsymb(s->name, 'D', s->value+INITDAT, s->version);
205                                 continue;
206
207                         case SBSS:
208                                 putsymb(s->name, 'B', s->value+INITDAT, s->version);
209                                 continue;
210
211                         case SFILE:
212                                 putsymb(s->name, 'f', s->value, s->version);
213                                 continue;
214                         }
215
216         for(p=textp; p!=P; p=p->cond) {
217                 s = p->from.sym;
218                 if(s->type != STEXT && s->type != SLEAF)
219                         continue;
220
221                 /* filenames first */
222                 for(a=p->to.autom; a; a=a->link)
223                         if(a->type == D_FILE)
224                                 putsymb(a->asym->name, 'z', a->aoffset, 0);
225                         else
226                         if(a->type == D_FILE1)
227                                 putsymb(a->asym->name, 'Z', a->aoffset, 0);
228
229                 if(s->type == STEXT)
230                         putsymb(s->name, 'T', s->value, s->version);
231                 else
232                         putsymb(s->name, 'L', s->value, s->version);
233
234                 /* frame, auto and param after */
235                 putsymb(".frame", 'm', p->to.offset+4, 0);
236                 for(a=p->to.autom; a; a=a->link)
237                         if(a->type == D_AUTO)
238                                 putsymb(a->asym->name, 'a', -a->aoffset, 0);
239                         else
240                         if(a->type == D_PARAM)
241                                 putsymb(a->asym->name, 'p', a->aoffset, 0);
242         }
243         if(debug['v'] || debug['n'])
244                 Bprint(&bso, "symsize = %lud\n", symsize);
245         Bflush(&bso);
246 }
247
248 void
249 putsymb(char *s, int t, long v, int ver)
250 {
251         int i, f;
252
253         if(t == 'f')
254                 s++;
255         LPUT(v);
256         if(ver)
257                 t += 'a' - 'A';
258         CPUT(t+0x80);                   /* 0x80 is variable length */
259
260         if(t == 'Z' || t == 'z') {
261                 CPUT(s[0]);
262                 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
263                         CPUT(s[i]);
264                         CPUT(s[i+1]);
265                 }
266                 CPUT(0);
267                 CPUT(0);
268                 i++;
269         }
270         else {
271                 for(i=0; s[i]; i++)
272                         CPUT(s[i]);
273                 CPUT(0);
274         }
275         symsize += 4 + 1 + i + 1;
276
277         if(debug['n']) {
278                 if(t == 'z' || t == 'Z') {
279                         Bprint(&bso, "%c %.8lux ", t, v);
280                         for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
281                                 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
282                                 Bprint(&bso, "/%x", f);
283                         }
284                         Bprint(&bso, "\n");
285                         return;
286                 }
287                 if(ver)
288                         Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
289                 else
290                         Bprint(&bso, "%c %.8lux %s\n", t, v, s);
291         }
292 }
293
294 #define MINLC   4
295 void
296 asmlc(void)
297 {
298         long oldpc, oldlc;
299         Prog *p;
300         long v, s;
301
302         oldpc = INITTEXT;
303         oldlc = 0;
304         for(p = firstp; p != P; p = p->link) {
305                 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
306                         if(p->as == ATEXT)
307                                 curtext = p;
308                         if(debug['L'])
309                                 Bprint(&bso, "%6lux %P\n",
310                                         p->pc, p);
311                         continue;
312                 }
313                 if(debug['L'])
314                         Bprint(&bso, "\t\t%6ld", lcsize);
315                 v = (p->pc - oldpc) / MINLC;
316                 while(v) {
317                         s = 127;
318                         if(v < 127)
319                                 s = v;
320                         CPUT(s+128);    /* 129-255 +pc */
321                         if(debug['L'])
322                                 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
323                         v -= s;
324                         lcsize++;
325                 }
326                 s = p->line - oldlc;
327                 oldlc = p->line;
328                 oldpc = p->pc + MINLC;
329                 if(s > 64 || s < -64) {
330                         CPUT(0);        /* 0 vv +lc */
331                         CPUT(s>>24);
332                         CPUT(s>>16);
333                         CPUT(s>>8);
334                         CPUT(s);
335                         if(debug['L']) {
336                                 if(s > 0)
337                                         Bprint(&bso, " lc+%ld(%d,%ld)\n",
338                                                 s, 0, s);
339                                 else
340                                         Bprint(&bso, " lc%ld(%d,%ld)\n",
341                                                 s, 0, s);
342                                 Bprint(&bso, "%6lux %P\n",
343                                         p->pc, p);
344                         }
345                         lcsize += 5;
346                         continue;
347                 }
348                 if(s > 0) {
349                         CPUT(0+s);      /* 1-64 +lc */
350                         if(debug['L']) {
351                                 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
352                                 Bprint(&bso, "%6lux %P\n",
353                                         p->pc, p);
354                         }
355                 } else {
356                         CPUT(64-s);     /* 65-128 -lc */
357                         if(debug['L']) {
358                                 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
359                                 Bprint(&bso, "%6lux %P\n",
360                                         p->pc, p);
361                         }
362                 }
363                 lcsize++;
364         }
365         while(lcsize & 1) {
366                 s = 129;
367                 CPUT(s);
368                 lcsize++;
369         }
370         if(debug['v'] || debug['L'])
371                 Bprint(&bso, "lcsize = %ld\n", lcsize);
372         Bflush(&bso);
373 }
374
375 void
376 datblk(long s, long n)
377 {
378         Prog *p;
379         char *cast;
380         long l, fl, j, d;
381         int i, c;
382
383         memset(buf.dbuf, 0, n+100);
384         for(p = datap; p != P; p = p->link) {
385                 curp = p;
386                 l = p->from.sym->value + p->from.offset - s;
387                 c = p->reg;
388                 i = 0;
389                 if(l < 0) {
390                         if(l+c <= 0)
391                                 continue;
392                         while(l < 0) {
393                                 l++;
394                                 i++;
395                         }
396                 }
397                 if(l >= n)
398                         continue;
399                 if(p->as != AINIT && p->as != ADYNT && !p->from.sym->dupok) {
400                         for(j=l+(c-i)-1; j>=l; j--)
401                                 if(buf.dbuf[j]) {
402                                         print("%P\n", p);
403                                         diag("multiple initialization");
404                                         break;
405                                 }
406                 }
407                 switch(p->to.type) {
408                 default:
409                         diag("unknown mode in initialization\n%P", p);
410                         break;
411
412                 case D_FCONST:
413                         switch(c) {
414                         default:
415                         case 4:
416                                 fl = ieeedtof(&p->to.ieee);
417                                 cast = (char*)&fl;
418                                 for(; i<c; i++) {
419                                         buf.dbuf[l] = cast[fnuxi8[i+4]];
420                                         l++;
421                                 }
422                                 break;
423                         case 8:
424                                 cast = (char*)&p->to.ieee;
425                                 for(; i<c; i++) {
426                                         buf.dbuf[l] = cast[fnuxi8[i]];
427                                         l++;
428                                 }
429                                 break;
430                         }
431                         break;
432
433                 case D_SCONST:
434                         for(; i<c; i++) {
435                                 buf.dbuf[l] = p->to.sval[i];
436                                 l++;
437                         }
438                         break;
439
440                 case D_CONST:
441                         d = p->to.offset;
442                         if(p->to.sym) {
443                                 if(p->to.sym->type == STEXT ||
444                                    p->to.sym->type == SLEAF)
445                                         d += p->to.sym->value;
446                                 if(p->to.sym->type == SDATA)
447                                         d += p->to.sym->value + INITDAT;
448                                 if(p->to.sym->type == SBSS)
449                                         d += p->to.sym->value + INITDAT;
450                         }
451                         cast = (char*)&d;
452                         switch(c) {
453                         default:
454                                 diag("bad nuxi %d %d\n%P", c, i, curp);
455                                 break;
456                         case 1:
457                                 for(; i<c; i++) {
458                                         buf.dbuf[l] = cast[inuxi1[i]];
459                                         l++;
460                                 }
461                                 break;
462                         case 2:
463                                 for(; i<c; i++) {
464                                         buf.dbuf[l] = cast[inuxi2[i]];
465                                         l++;
466                                 }
467                                 break;
468                         case 4:
469                                 for(; i<c; i++) {
470                                         buf.dbuf[l] = cast[inuxi4[i]];
471                                         l++;
472                                 }
473                                 break;
474                         }
475                         break;
476                 }
477         }
478         write(cout, buf.dbuf, n);
479 }
480
481 #define OP2(x)  (0x80000000|((x)<<19))
482 #define OP3(x)  (0xc0000000|((x)<<19))
483 #define OPB(x)  (0x00800000|((x)<<25))
484 #define OPT(x)  (0x81d02000|((x)<<25))
485 #define OPF1(x) (0x81a00000|((x)<<5))
486 #define OPF2(x) (0x81a80000|((x)<<5))
487 #define OPFB(x) (0x01800000|((x)<<25))
488
489 #define OP_RRR(op,r1,r2,r3)\
490         (0x00000000 | op |\
491         (((r1)&31L)<<0) |\
492         (((r2)&31L)<<14) |\
493         (((r3)&31L)<<25))
494 #define OP_IRR(op,i,r2,r3)\
495         (0x00002000L | (op) |\
496         (((i)&0x1fffL)<<0) |\
497         (((r2)&31L)<<14) |\
498         (((r3)&31L)<<25))
499 #define OP_BRA(op,pc)\
500         ((op) |\
501         (((pc)&0x3fffff)<<0))
502
503 int
504 asmout(Prog *p, Optab *o, int aflag)
505 {
506         long o1, o2, o3, o4, o5, v;
507         Prog *ct;
508         int r;
509
510         o1 = 0;
511         o2 = 0;
512         o3 = 0;
513         o4 = 0;
514         o5 = 0;
515
516         switch(o->type) {
517         default:
518                 if(aflag)
519                         return 0;
520                 diag("unknown type %d", o->type);
521                 if(!debug['a'])
522                         prasm(p);
523                 break;
524
525         case 0:         /* pseudo ops */
526                 if(aflag) {
527                         if(p->link) {
528                                 if(p->as == ATEXT) {
529                                         ct = curtext;
530                                         o2 = autosize;
531                                         curtext = p;
532                                         autosize = p->to.offset + 4;
533                                         o1 = asmout(p->link, oplook(p->link), aflag);
534                                         curtext = ct;
535                                         autosize = o2;
536                                 } else
537                                         o1 = asmout(p->link, oplook(p->link), aflag);
538                         }
539                         return o1;
540                 }
541                 break;
542
543         case 1:         /* mov r1,r2 ==> OR r1,r0,r2 */
544                 o1 = OP_RRR(opcode(AOR), p->from.reg, REGZERO, p->to.reg);
545                 break;
546
547         case 2:         /* mov $c,r ==> add r1,r0,r2 */
548                 r = p->from.reg;
549                 if(r == NREG)
550                         r = o->param;
551                 v = regoff(&p->from);
552                 o1 = OP_IRR(opcode(AADD), v, r, p->to.reg);
553                 break;
554
555         case 3:         /* mov soreg, r */
556                 r = p->from.reg;
557                 if(r == NREG)
558                         r = o->param;
559                 v = regoff(&p->from);
560                 if(v == 0 && p->reg != NREG)
561                         o1 = OP_RRR(opcode(p->as), p->reg, r, p->to.reg);
562                 else
563                         o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
564                 break;
565
566         case 4:         /* mov r, soreg */
567                 r = p->to.reg;
568                 if(r == NREG)
569                         r = o->param;
570                 v = regoff(&p->to);
571                 if(v == 0 && p->reg != NREG)
572                         o1 = OP_RRR(opcode(p->as+AEND), p->reg, r, p->from.reg);
573                 else
574                         o1 = OP_IRR(opcode(p->as+AEND), v, r, p->from.reg);
575                 break;
576
577         case 5:         /* mov $lcon, reg => sethi, add */
578                 v = regoff(&p->from);
579                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
580                 o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
581                 break;
582
583         case 6:         /* mov asi, r[+r] */
584                 o1 = OP_RRR(opcode(p->as), p->reg, p->from.reg, p->to.reg);
585                 o1 |= (1<<23) | ((p->from.offset&0xff)<<5);
586                 break;
587
588         case 7:         /* mov [+r]r, asi */
589                 o1 = OP_RRR(opcode(p->as+AEND), p->reg, p->to.reg, p->from.reg);
590                 o1 |= (1<<23) | ((p->to.offset&0xff)<<5);
591                 break;
592
593         case 8:         /* mov r, preg and mov preg, r */
594                 if(p->to.type == D_PREG) {
595                         r = p->from.reg;
596                         switch(p->to.reg)
597                         {
598                         default:
599                                 diag("unknown register P%d", p->to.reg);
600                         case D_Y:
601                                 o1 = OP2(48);   /* wry */
602                                 break;
603                         case D_PSR:
604                                 o1 = OP2(49);   /* wrpsr */
605                                 break;
606                         case D_WIM:
607                                 o1 = OP2(50);   /* wrwim */
608                                 break;
609                         case D_TBR:
610                                 o1 = OP2(51);   /* wrtbr */
611                                 break;
612                         }
613                         o1 = OP_IRR(o1, 0, r, 0);
614                         break;
615                 }
616                 if(p->from.type == D_PREG) {
617                         r = p->to.reg;
618                         switch(p->from.reg)
619                         {
620                         default:
621                                 diag("unknown register P%d", p->to.reg);
622                         case D_Y:
623                                 o1 = OP2(40);   /* rdy */
624                                 break;
625                         case D_PSR:
626                                 o1 = OP2(41);   /* rdpsr */
627                                 break;
628                         case D_WIM:
629                                 o1 = OP2(42);   /* rdwim */
630                                 break;
631                         case D_TBR:
632                                 o1 = OP2(43);   /* rdtbr */
633                                 break;
634                         }
635                         o1 = OP_RRR(o1, 0, 0, r);
636                         break;
637                 }
638                 break;
639
640         case 9:         /* movb r,r */
641                 v = 24;
642                 if(p->as == AMOVH || p->as == AMOVHU)
643                         v = 16;
644                 r = ASRA;
645                 if(p->as == AMOVBU || p->as == AMOVHU)
646                         r = ASRL;
647                 o1 = OP_IRR(opcode(ASLL), v, p->from.reg, p->to.reg);
648                 o2 = OP_IRR(opcode(r), v, p->to.reg, p->to.reg);
649                 break;
650
651         case 10:        /* mov $loreg, reg */
652                 r = p->from.reg;
653                 if(r == NREG)
654                         r = o->param;
655                 v = regoff(&p->from);
656                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
657                 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
658                 o3 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
659                 break;
660
661         case 11:        /* mov loreg, r */
662                 r = p->from.reg;
663                 if(r == NREG)
664                         r = o->param;
665                 v = regoff(&p->from);
666                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
667                 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
668                 o3 = OP_IRR(opcode(p->as), (v&0x3ff), REGTMP, p->to.reg);
669                 break;
670
671         case 12:        /* mov r, loreg */
672                 r = p->to.reg;
673                 if(r == NREG)
674                         r = o->param;
675                 v = regoff(&p->to);
676                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
677                 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
678                 o3 = OP_IRR(opcode(p->as+AEND), (v&0x3ff), REGTMP, p->from.reg);
679                 break;
680
681         case 13:        /* mov $ucon, r */
682                 v = regoff(&p->from);
683                 o1 = 0x1000000 | (p->to.reg<<25) | ((v>>10) & 0x3fffff);        /* sethi */
684                 break;
685
686         case 20:        /* op $scon,r */
687                 v = regoff(&p->from);
688                 r = p->reg;
689                 if(r == NREG)
690                         r = p->to.reg;
691                 o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
692                 break;
693
694         case 21:        /* op r1,r2 */
695                 r = p->reg;
696                 if(r == NREG)
697                         r = p->to.reg;
698                 o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
699                 break;
700
701         case 22:        /* op $lcon,r */
702                 v = regoff(&p->from);
703                 r = p->reg;
704                 if(r == NREG)
705                         r = p->to.reg;
706                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
707                 o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, REGTMP);
708                 o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
709                 break;
710
711         case 23:        /* cmp r,r */
712                 o1 = OP_RRR(opcode(ASUBCC), p->to.reg, p->from.reg, REGZERO);
713                 break;
714
715         case 24:        /* cmp r,$c */
716                 v = regoff(&p->to);
717                 o1 = OP_IRR(opcode(ASUBCC), v, p->from.reg, REGZERO);
718                 break;
719
720         case 25:        /* cmp $c,r BOTCH, fix compiler */
721                 v = regoff(&p->from);
722                 o1 = OP_IRR(opcode(AADD), v, NREG, REGTMP);
723                 o2 = OP_RRR(opcode(ASUBCC), p->to.reg, REGTMP, REGZERO);
724                 break;
725
726         case 26:        /* op $ucon,r */
727                 v = regoff(&p->from);
728                 r = p->reg;
729                 if(r == NREG)
730                         r = p->to.reg;
731                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
732                 o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
733                 break;
734
735         case 30:        /* jmp/jmpl soreg */
736                 if(aflag)
737                         return 0;
738                 v = regoff(&p->to);
739                 r = p->reg;
740                 if(r == NREG && p->as == AJMPL)
741                         r = 15;
742                 o1 = OP_IRR(opcode(AJMPL), v, p->to.reg, r);
743                 break;
744
745         case 31:        /* ba jmp */
746                 if(aflag)
747                         return 0;
748                 r = p->as;
749                 if(r == AJMP)
750                         r = ABA;
751                 v = 0;
752                 if(p->cond)
753                         v = p->cond->pc - p->pc;
754                 o1 = OP_BRA(opcode(r), v/4);
755                 if(r == ABA && p->link && p->cond && isnop(p->link)) {
756                         o2 = asmout(p->cond, oplook(p->cond), 1);
757                         if(o2) {
758                                 o1 += 1;
759                                 if(debug['a'])
760                                         Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
761                                 LPUT(o1);
762                                 LPUT(o2);
763                                 return 1;
764                         }
765                         /* cant set annul here because pc has already been counted */
766                 }
767                 break;
768
769         case 32:        /* jmpl lbra */
770                 if(aflag)
771                         return 0;
772                 v = 0;
773                 if(p->cond)
774                         v = p->cond->pc - p->pc;
775                 r = p->reg;
776                 if(r != NREG && r != 15)
777                         diag("cant jmpl other than R15");
778                 o1 = 0x40000000 | ((v/4) & 0x3fffffffL);        /* call */
779                 if(p->link && p->cond && isnop(p->link)) {
780                         o2 = asmout(p->cond, oplook(p->cond), 1);
781                         if(o2) {
782                                 o1 += 1;
783                                 if(debug['a'])
784                                         Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
785                                 LPUT(o1);
786                                 LPUT(o2);
787                                 return 1;
788                         }
789                 }
790                 break;
791
792         case 33:        /* trap r */
793                 if(aflag)
794                         return 0;
795                 o1 = opcode(p->as) | (p->from.reg<<14);
796                 break;
797
798         case 34:        /* rett r1,r2 -> jmpl (r1); rett (r2) */
799                 if(aflag)
800                         return 0;
801                 o1 = OP_IRR(opcode(AJMPL), 0, p->from.reg, REGZERO);
802                 o2 = OP_IRR(opcode(ARETT), 0, p->to.reg, REGZERO);
803                 break;
804
805         case 40:        /* ldfsr, stfsr, stdq */
806                 if(p->to.type == D_PREG) {
807                         r = p->from.reg;
808                         if(r == NREG)
809                                 r = o->param;
810                         v = regoff(&p->from);
811                         if(p->to.reg == D_FSR) {
812                                 o1 = OP_IRR(OP3(33), v, r, 0);
813                                 break;
814                         }
815                         diag("unknown reg load %d", p->to.reg);
816                 } else {
817                         r = p->to.reg;
818                         if(r == NREG)
819                                 r = o->param;
820                         v = regoff(&p->to);
821                         if(p->from.reg == D_FSR) {
822                                 o1 = OP_IRR(OP3(37), v, r, 0);
823                                 break;
824                         }
825                         if(p->as == AMOVD && p->from.reg == D_FPQ) {
826                                 o1 = OP_IRR(OP3(38), v, r, 0);
827                                 break;
828                         }
829                         diag("unknown reg store %d", p->from.reg);
830                 }
831                 break;
832
833         case 41:        /* ldf,ldd */
834                 r = p->from.reg;
835                 if(r == NREG)
836                         r = o->param;
837                 v = regoff(&p->from);
838                 if(p->as == AFMOVF || p->as == AMOVW) {
839                         o1 = OP_IRR(OP3(32), v, r, p->to.reg);
840                         break;
841                 }
842                 if(p->as == AMOVD || p->as == AFMOVD) {
843                         o1 = OP_IRR(OP3(35), v, r, p->to.reg);
844                         break;
845                 }
846                 diag("only MOVD and MOVW to FREG");
847                 break;
848
849         case 42:        /* ldd -> ldf,ldf */
850                 /* note should be ldd with proper allignment */
851                 r = p->from.reg;
852                 if(r == NREG)
853                         r = o->param;
854                 v = regoff(&p->from);
855                 o1 = OP_IRR(OP3(32), v, r, p->to.reg);
856                 o2 = OP_IRR(OP3(32), v+4, r, p->to.reg+1);
857                 break;
858
859         case 43:        /* stf */
860                 r = p->to.reg;
861                 if(r == NREG)
862                         r = o->param;
863                 v = regoff(&p->to);
864                 if(p->as == AFMOVF || p->as == AMOVW) {
865                         o1 = OP_IRR(OP3(36), v, r, p->from.reg);
866                         break;
867                 }
868                 if(p->as == AMOVD || p->as == AFMOVD) {
869                         o1 = OP_IRR(OP3(39), v, r, p->from.reg);
870                         break;
871                 }
872                 diag("only MOVD and MOVW from FREG");
873                 break;
874
875         case 44:        /* std -> stf,stf */
876                 /* note should be std with proper allignment */
877                 r = p->to.reg;
878                 if(r == NREG)
879                         r = o->param;
880                 v = regoff(&p->to);
881                 o1 = OP_IRR(OP3(36), v, r, p->from.reg);
882                 o2 = OP_IRR(OP3(36), v+4, r, p->from.reg+1);
883                 break;
884
885         case 45:        /* ldf lorg */
886                 r = p->from.reg;
887                 if(r == NREG)
888                         r = o->param;
889                 v = regoff(&p->from);
890                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
891                 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
892                 o3 = OP_IRR(OP3(32), v&0x3ff, REGTMP, p->to.reg);
893                 break;
894
895         case 46:        /* ldd lorg -> ldf,ldf */
896                 /* note should be ldd with proper allignment */
897                 r = p->from.reg;
898                 if(r == NREG)
899                         r = o->param;
900                 v = regoff(&p->from);
901                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
902                 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
903                 o3 = OP_IRR(OP3(32), (v&0x3ff), REGTMP, p->to.reg);
904                 o4 = OP_IRR(OP3(32), (v&0x3ff)+4, REGTMP, p->to.reg+1);
905                 break;
906
907         case 47:        /* stf lorg */
908                 r = p->to.reg;
909                 if(r == NREG)
910                         r = o->param;
911                 v = regoff(&p->to);
912                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
913                 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
914                 o3 = OP_IRR(OP3(36), v&0x3ff, REGTMP, p->from.reg);
915                 break;
916
917         case 48:        /* std lorg -> stf,stf */
918                 /* note should be std with proper allignment */
919                 r = p->to.reg;
920                 if(r == NREG)
921                         r = o->param;
922                 v = regoff(&p->to);
923                 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);   /* sethi */
924                 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
925                 o3 = OP_IRR(OP3(36), (v&0x3ff), REGTMP, p->from.reg);
926                 o4 = OP_IRR(OP3(36), (v&0x3ff)+4, REGTMP, p->from.reg+1);
927                 break;
928
929         case 49:        /* fmovd -> fmovf,fmovf */
930                 o1 = OP_RRR(opcode(AFMOVF), p->from.reg, 0, p->to.reg);
931                 o2 = OP_RRR(opcode(AFMOVF), p->from.reg+1, 0, p->to.reg+1);
932                 break;
933
934         case 50:        /* fcmp */
935                 o1 = OP_RRR(opcode(p->as), p->to.reg, p->from.reg, 0);
936                 break;
937
938         case 51:        /* word */
939                 if(aflag)
940                         return 0;
941                 o1 = regoff(&p->from);
942                 break;
943
944         case 52:        /* div */
945                 r = p->reg;
946                 if(r == NREG)
947                         r = p->to.reg;
948                 o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
949                 o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
950                 o3 = OP_RRR(opcode(ADIV), p->from.reg, r, p->to.reg);
951                 break;
952
953         case 53:        /* divl */
954                 r = p->reg;
955                 if(r == NREG)
956                         r = p->to.reg;
957                 o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
958                 o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, p->to.reg);
959                 break;
960
961         case 54:        /* mod */
962                 r = p->reg;
963                 if(r == NREG)
964                         r = p->to.reg;
965                 o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
966                 o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
967                 o3 = OP_RRR(opcode(ADIV), p->from.reg, r, REGTMP);
968                 o4 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
969                 o5 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
970                 break;
971
972         case 55:        /* modl */
973                 r = p->reg;
974                 if(r == NREG)
975                         r = p->to.reg;
976                 o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
977                 o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, REGTMP);
978                 o3 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
979                 o4 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
980                 break;
981
982         case 56:        /* b(cc) -- annullable */
983                 if(aflag)
984                         return 0;
985                 r = p->as;
986                 v = 0;
987                 if(p->cond)
988                         v = p->cond->pc - p->pc;
989                 o1 = OP_BRA(opcode(r), v/4);
990                 if(p->link && p->cond && isnop(p->link))
991                 if(!debug['A']) {
992                         o2 = asmout(p->cond, oplook(p->cond), 2);
993                         if(o2) {
994                                 o1 |= 1<<29;    /* annul */
995                                 o1 += 1;
996                                 if(debug['a'])
997                                         Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
998                                 LPUT(o1);
999                                 LPUT(o2);
1000                                 return 1;
1001                         }
1002                 }
1003                 break;
1004
1005         case 57:        /* op r1,r2 with reserved rs1 */
1006                 r = 0;
1007                 o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
1008                 break;
1009         }
1010         if(aflag)
1011                 return o1;
1012         v = p->pc;
1013         switch(o->size) {
1014         default:
1015                 if(debug['a'])
1016                         Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
1017                 break;
1018         case 4:
1019                 if(debug['a'])
1020                         Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
1021                 LPUT(o1);
1022                 break;
1023         case 8:
1024                 if(debug['a'])
1025                         Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
1026                 LPUT(o1);
1027                 LPUT(o2);
1028                 break;
1029         case 12:
1030                 if(debug['a'])
1031                         Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
1032                 LPUT(o1);
1033                 LPUT(o2);
1034                 LPUT(o3);
1035                 break;
1036         case 16:
1037                 if(debug['a'])
1038                         Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
1039                                 v, o1, o2, o3, o4, p);
1040                 LPUT(o1);
1041                 LPUT(o2);
1042                 LPUT(o3);
1043                 LPUT(o4);
1044                 break;
1045         case 20:
1046                 if(debug['a'])
1047                         Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1048                                 v, o1, o2, o3, o4, o5, p);
1049                 LPUT(o1);
1050                 LPUT(o2);
1051                 LPUT(o3);
1052                 LPUT(o4);
1053                 LPUT(o5);
1054                 break;
1055         }
1056         return 0;
1057 }
1058
1059 int
1060 isnop(Prog *p)
1061 {
1062         if(p->as != AORN)
1063                 return 0;
1064         if(p->reg != REGZERO && p->reg != NREG)
1065                 return 0;
1066         if(p->from.type != D_REG || p->from.reg != REGZERO)
1067                 return 0;
1068         if(p->to.type != D_REG || p->to.reg != REGZERO)
1069                 return 0;
1070         return 1;
1071 }
1072
1073 long
1074 opcode(int a)
1075 {
1076         switch(a) {
1077         case AADD:      return OP2(0);
1078         case AADDCC:    return OP2(16);
1079         case AADDX:     return OP2(8);
1080         case AADDXCC:   return OP2(24);
1081
1082         case AMUL:      return OP2(10);
1083         case ADIV:      return OP2(15);
1084         case ADIVL:     return OP2(14);
1085
1086         case ATADDCC:   return OP2(32);
1087         case ATADDCCTV: return OP2(34);
1088
1089         case ASUB:      return OP2(4);
1090         case ASUBCC:    return OP2(20);
1091         case ASUBX:     return OP2(12);
1092         case ASUBXCC:   return OP2(28);
1093
1094         case ATSUBCC:   return OP2(33);
1095         case ATSUBCCTV: return OP2(35);
1096
1097         case AMULSCC:   return OP2(36);
1098         case ASAVE:     return OP2(60);
1099         case ARESTORE:  return OP2(61);
1100
1101         case AAND:      return OP2(1);
1102         case AANDCC:    return OP2(17);
1103         case AANDN:     return OP2(5);
1104         case AANDNCC:   return OP2(21);
1105
1106         case AOR:       return OP2(2);
1107         case AORCC:     return OP2(18);
1108         case AORN:      return OP2(6);
1109         case AORNCC:    return OP2(22);
1110
1111         case AXOR:      return OP2(3);
1112         case AXORCC:    return OP2(19);
1113         case AXNOR:     return OP2(7);
1114         case AXNORCC:   return OP2(23);
1115
1116         case ASLL:      return OP2(37);
1117         case ASRL:      return OP2(38);
1118         case ASRA:      return OP2(39);
1119
1120         case AJMPL:
1121         case AJMP:      return OP2(56);
1122         case ARETT:     return OP2(57);
1123
1124         case AMOVBU:    return OP3(1);  /* ldub */
1125         case AMOVB:     return OP3(9);  /* ldsb */
1126         case AMOVHU:    return OP3(2);  /* lduh */
1127         case AMOVH:     return OP3(10); /* ldsh */
1128         case AMOVW:     return OP3(0);  /* ld */
1129         case AMOVD:     return OP3(3);  /* ldd */
1130
1131         case AMOVBU+AEND:
1132         case AMOVB+AEND:return OP3(5);  /* stb */
1133
1134         case AMOVHU+AEND:
1135         case AMOVH+AEND:return OP3(6);  /* sth */
1136
1137         case AMOVW+AEND:return OP3(4);  /* st */
1138
1139         case AMOVD+AEND:return OP3(7);  /* std */
1140
1141         case ASWAP:                     /* swap is symmetric */
1142         case ASWAP+AEND:return OP3(15);
1143
1144         case ATAS:      return OP3(13); /* tas is really ldstub */
1145
1146         case ABN:       return OPB(0);
1147         case ABE:       return OPB(1);
1148         case ABLE:      return OPB(2);
1149         case ABL:       return OPB(3);
1150         case ABLEU:     return OPB(4);
1151         case ABCS:      return OPB(5);
1152         case ABNEG:     return OPB(6);
1153         case ABVS:      return OPB(7);
1154         case ABA:       return OPB(8);
1155         case ABNE:      return OPB(9);
1156         case ABG:       return OPB(10);
1157         case ABGE:      return OPB(11);
1158         case ABGU:      return OPB(12);
1159         case ABCC:      return OPB(13);
1160         case ABPOS:     return OPB(14);
1161         case ABVC:      return OPB(15);
1162
1163         case AFBA:      return OPFB(8);
1164         case AFBE:      return OPFB(9);
1165         case AFBG:      return OPFB(6);
1166         case AFBGE:     return OPFB(11);
1167         case AFBL:      return OPFB(4);
1168         case AFBLE:     return OPFB(13);
1169         case AFBLG:     return OPFB(2);
1170         case AFBN:      return OPFB(0);
1171         case AFBNE:     return OPFB(1);
1172         case AFBO:      return OPFB(15);
1173         case AFBU:      return OPFB(7);
1174         case AFBUE:     return OPFB(10);
1175         case AFBUG:     return OPFB(5);
1176         case AFBUGE:    return OPFB(12);
1177         case AFBUL:     return OPFB(3);
1178         case AFBULE:    return OPFB(14);
1179
1180         case ATN:       return OPT(0);
1181         case ATE:       return OPT(1);
1182         case ATLE:      return OPT(2);
1183         case ATL:       return OPT(3);
1184         case ATLEU:     return OPT(4);
1185         case ATCS:      return OPT(5);
1186         case ATNEG:     return OPT(6);
1187         case ATVS:      return OPT(7);
1188         case ATA:       return OPT(8);
1189         case ATNE:      return OPT(9);
1190         case ATG:       return OPT(10);
1191         case ATGE:      return OPT(11);
1192         case ATGU:      return OPT(12);
1193         case ATCC:      return OPT(13);
1194         case ATPOS:     return OPT(14);
1195         case ATVC:      return OPT(15);
1196
1197         case AFADDF:    return OPF1(65);
1198         case AFADDD:    return OPF1(66);
1199         case AFADDX:    return OPF1(67);
1200         case AFSUBF:    return OPF1(69);
1201         case AFSUBD:    return OPF1(70);
1202         case AFSUBX:    return OPF1(71);
1203         case AFMULF:    return OPF1(73);
1204         case AFMULD:    return OPF1(74);
1205         case AFMULX:    return OPF1(75);
1206         case AFDIVF:    return OPF1(77);
1207         case AFDIVD:    return OPF1(78);
1208         case AFDIVX:    return OPF1(79);
1209
1210         case AFMOVF:    return OPF1(1);
1211         case AFNEGF:    return OPF1(5);
1212         case AFABSF:    return OPF1(9);
1213
1214         case AFSQRTF:   return OPF1(41);
1215         case AFSQRTD:   return OPF1(42);
1216         case AFSQRTX:   return OPF1(43);
1217
1218         case AFMOVWF:   return OPF1(196);
1219         case AFMOVWD:   return OPF1(200);
1220         case AFMOVWX:   return OPF1(204);
1221         case AFMOVFW:   return OPF1(209);
1222         case AFMOVDW:   return OPF1(210);
1223         case AFMOVXW:   return OPF1(211);
1224         case AFMOVFD:   return OPF1(201);
1225         case AFMOVFX:   return OPF1(205);
1226         case AFMOVDF:   return OPF1(198);
1227         case AFMOVDX:   return OPF1(206);
1228         case AFMOVXF:   return OPF1(199);
1229         case AFMOVXD:   return OPF1(203);
1230
1231         case AFCMPF:    return OPF2(81);
1232         case AFCMPD:    return OPF2(82);
1233         case AFCMPX:    return OPF2(83);
1234         case AFCMPEF:   return OPF2(85);
1235         case AFCMPED:   return OPF2(86);
1236         case AFCMPEX:   return OPF2(87);
1237
1238         case AUNIMP:    return 0;
1239         }
1240         diag("bad opcode %A", a);
1241         return 0;
1242 }