5 #define Rm(X) (((X)&31)<<16)
6 #define Rn(X) (((X)&31)<<5)
7 #define Rd(X) (((X)&31)<<0)
10 #define OPDP2(x) (0<<30 | 0 << 29 | 0xd6<<21 | (x)<<10)
11 #define OPDP3(sf,op54,op31,o0) ((sf)<<31 | (op54)<<29 | 0x1B<<24 | (op31)<<21 | (o0)<<15)
12 #define OPBcc(x) (0x2A<<25 | 0<<24 | 0<<4 | ((x)&15))
13 #define OPBLR(x) (0x6B<<25 | 0<<23 | (x)<<21 | 0x1F<<16 | 0<<10) /* x=0, JMP; 1, CALL; 2, RET */
14 #define SYSOP(l,op0,op1,crn,crm,op2,rt) (0x354<<22 | (l)<<21 | (op0)<<19 | (op1)<<16 | (crn)<<12 | (crm)<<8 | (op2)<<5 | (rt))
15 #define SYSHINT(x) SYSOP(0,0,3,2,0,(x),0x1F)
17 #define LDSTR12U(sz,v,opc) ((sz)<<30 | 7<<27 | (v)<<26 | 1<<24 | (opc)<<22)
18 #define LDSTR9S(sz,v,opc) ((sz)<<30 | 7<<27 | (v)<<26 | 0<<24 | (opc)<<22)
19 #define LD2STR(o) ((o) & ~(3<<22))
21 #define LDSTX(sz,o2,l,o1,o0) ((sz)<<30 | 0x8<<24 | (o2)<<23 | (l)<<22 | (o1)<<21 | (o0)<<15)
23 #define FPCMP(m,s,type,op,op2) ((m)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | (op)<<14 | 8<<10 | (op2))
24 #define FPCCMP(m,s,type,op) ((m)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | 1<<10 | (op)<<4)
25 #define FPOP1S(m,s,type,op) ((m)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | (op)<<15 | 0x10<<10)
26 #define FPOP2S(m,s,type,op) ((m)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | (op)<<12 | 2<<10)
27 #define FPCVTI(sf,s,type,rmode,op) ((sf)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | (rmode)<<19 | (op)<<16 | 0<<10)
28 #define FPCVTF(sf,s,type,rmode,op,scale) ((sf)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 0<<21 | (rmode)<<19 | (op)<<16 | (scale)<<10)
29 #define ADR(p,o,rt) ((p)<<31 | ((o)&3)<<29 | (0x10<<24) | (((o>>2)&0x7FFFF)<<5) | (rt))
31 #define LSL0_32 (2<<13)
32 #define LSL0_64 (3<<13)
34 static long opbrr(int);
35 static long opbra(int);
36 static long oshrr(int, int, int);
37 static long olhrr(int, int, int);
38 static long olsr12u(long, long, int, int);
39 static long olsr9s(long, long, int, int);
40 static long opimm(int);
41 static vlong brdist(Prog*, int, int, int);
42 static long opbfm(int, int, int, int, int);
43 static long opextr(int, long, int, int, int);
44 static long opbit(int);
46 static long opstr12(int);
47 static long opstr9(int);
48 static long opldr9(int);
49 static long opxrrr(int);
50 static long olsxrr(int, int, int, int);
51 static long oprrr(int);
52 static long opirr(int);
53 static long opldr12(int);
54 static long opldrpp(int);
55 static long opload(int);
56 static long opstore(int);
57 static long omovlit(int, Prog*, Adr*, int);
58 static int movesize(int);
59 static long oaddi(long, long, int, int);
62 * valid pstate field values, and value to use in instruction
68 D_SPSel, (0<<16) | (4<<12) | (5<<5),
69 D_DAIFSet, (3<<16) | (4<<12) | (6<<5),
70 D_DAIFClr, (3<<16) | (4<<12) | (7<<5),
74 asmout(Prog *p, Optab *o)
76 long o1, o2, o3, o4, o5, v, hi;
78 int r, s, rf, rt, ra, nzcv, cond, i, as;
80 static Prog *lastcase;
89 diag("unknown asm %d", o->type);
93 case 0: /* pseudo ops */
96 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
101 if(p->to.type == D_NONE)
105 o1 |= (rf<<16) | (r<<5) | rt;
108 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
111 if(p->to.type == D_NONE){
113 diag("ineffective ZR destination\n%P", p);
119 v = regoff(&p->from);
120 o1 = oaddi(o1, v, r, rt);
123 case 3: /* op R<<n[,R],R (shifted register) */
125 o1 |= p->from.offset; /* includes reg, op, etc */
127 if(p->to.type == D_NONE)
130 if(p->as == AMVN || p->as == AMVNW)
137 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */
143 v = regoff(&p->from);
144 if((v & 0xFFF000) != 0){
146 o1 |= 1<<22; /* shift, by 12 */
148 o1 |= ((v& 0xFFF) << 10) | (r<<5) | rt;
151 case 5: /* b s; bl s */
153 o1 |= brdist(p, 0, 26, 2);
156 case 6: /* b ,O(R); bl ,O(R) */
158 o1 |= p->to.reg << 5;
163 o1 |= brdist(p, 0, 19, 2)<<5;
166 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
173 case AASR: o1 = opbfm(ASBFM, v, 63, rf, rt); break;
174 case AASRW: o1 = opbfm(ASBFMW, v, 31, rf, rt); break;
175 case ALSL: o1 = opbfm(AUBFM, (64-v)&63, 63-v, rf, rt); break;
176 case ALSLW: o1 = opbfm(AUBFMW, (32-v)&31, 31-v, rf, rt); break;
177 case ALSR: o1 = opbfm(AUBFM, v, 63, rf, rt); break;
178 case ALSRW: o1 = opbfm(AUBFMW, v, 31, rf, rt); break;
179 case AROR: o1 = opextr(AEXTR, v, rf, rf, rt); break;
180 case ARORW: o1 = opextr(AEXTRW, v, rf, rf, rt); break;
182 diag("bad shift $con\n%P", curp);
187 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
192 o1 |= (p->from.reg << 16) | (r<<5) | p->to.reg;
195 case 10: /* brk/hvc/.../svc [$con] */
197 if(p->to.type != D_NONE)
198 o1 |= (p->to.offset & 0xffff)<<5;
202 switch(aclass(&p->to)) {
208 if(p->to.name != D_EXTERN && p->to.name != D_STATIC)
211 if(p->to.sym->type == SUNDEF)
212 ckoff(p->to.sym, p->to.offset);
213 dynreloc(p->to.sym, p->pc, 1);
216 o2 = instoffset >> 32;
219 case 12: /* movT $lcon, reg */
220 o1 = omovlit(p->as, p, &p->from, p->to.reg);
223 case 13: /* addop $lcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
224 o1 = omovlit(AMOV, p, &p->from, REGTMP);
226 if(p->to.type == D_NONE)
231 if(p->to.type != D_NONE && (p->to.reg == REGSP || r == REGSP)){
237 o2 |= REGTMP << 16; /* shift is 0 */
244 if(aclass(&p->to) == C_ADDR)
245 diag("address constant needs DWORD\n%P", p);
249 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Rn,Ra,Rd */
253 if(p->from3.type == D_REG){
264 o1 |= (rf<<16) | (ra<<10) | (r<<5) | rt;
267 case 16: /* XremY R[,R],R -> XdivY; XmsubY */
274 o1 |= (rf<<16) | (r<<5) | REGTMP;
276 o2 |= o1 & (1<<31); /* same size */
277 o2 |= (rf<<16) | (r<<10) | (REGTMP<<5) | rt;
280 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
285 if(p->to.type == D_NONE)
289 o1 |= (rf<<16) | (r<<5) | rt;
292 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
297 if(p->from3.type == D_NONE){
302 rf = p->from3.reg; /* CSEL */
305 if(p->from3.type != D_NONE)
306 diag("invalid combination\n%P", p);
311 o1 |= (r<<16) | (cond<<12) | (rf<<5) | rt;
314 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
317 if(p->from3.type == D_REG){
319 rf = p->from3.reg; /* Rm */
322 rf = p->from3.offset & 0x1F;
324 o1 |= (rf<<16) | (cond<<12) | (p->reg<<5) | nzcv;
327 case 20: /* movT R,O(R) -> strT */
332 if(v < 0){ /* unscaled 9-bit signed */
333 o1 = olsr9s(opstr9(p->as), v, r, p->from.reg);
335 v = offsetshift(v, o->a3);
336 o1 = olsr12u(opstr12(p->as), v, r, p->from.reg);
340 case 21: /* movT O(R),R -> ldrT */
341 v = regoff(&p->from);
345 if(v < 0){ /* unscaled 9-bit signed */
346 o1 = olsr9s(opldr9(p->as), v, r, p->to.reg);
348 v = offsetshift(v, o->a1);
349 //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
350 o1 = olsr12u(opldr12(p->as), v, r, p->to.reg);
354 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
356 if(v < -256 || v > 255)
357 diag("offset out of range\n%P", p);
359 if(p->from.type == D_XPOST)
363 o1 |= ((v&0x1FF)<<12) | (p->from.reg<<5) | p->to.reg;
366 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
368 if(v < -256 || v > 255)
369 diag("offset out of range\n%P", p);
370 o1 = LD2STR(opldrpp(p->as));
371 if(p->to.type == D_XPOST)
375 o1 |= ((v&0x1FF)<<12) | (p->to.reg<<5) | p->from.reg;
378 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
381 s = rf == REGSP || rt == REGSP;
382 if(p->as == AMVN || p->as == AMVNW){
384 diag("illegal SP reference\n%P", p);
386 o1 |= (rf<<16) | (REGZERO<<5) | rt;
392 o1 |= (rf<<16) | (REGZERO<<5) | rt;
396 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
400 o1 |= (rf<<16) | (REGZERO<<5) | rt;
403 case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */
405 o1 |= p->from.offset; /* includes reg, op, etc */
407 o1 |= (REGZERO<<5) | rt;
410 case 27: /* op Rm<<n[,Rn],Rd (extended register) */
412 if(p->from.type == D_EXTREG)
413 o1 |= p->from.offset; /* includes reg, op, etc */
415 o1 |= p->from.reg << 16;
417 if(p->to.type == D_NONE)
425 case 28: /* logop $lcon, [R], R (64 bit literal) */
426 o1 = omovlit(AMOV, p, &p->from, REGTMP);
431 o2 |= REGTMP << 16; /* shift is 0 */
436 case 29: /* op Rn, Rd */
438 o1 |= p->from.reg<<5 | p->to.reg;
441 case 30: /* movT R,L(R) -> strT */
444 diag("unexpected long move, op %A tab %A\n%P", p->as, o->as, p);
446 if((v & ((1<<s)-1)) != 0)
447 diag("misaligned offset\n%P", p);
448 if(v < 0 || (v>>s) >= (1<<24))
450 hi = v - (v & (0xFFF<<s));
451 if((hi & 0xFFF) != 0)
452 diag("internal: miscalculated offset %ld [%d]\n%P", v, s, p);
453 //fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF);
457 o1 = oaddi(opirr(AADD), hi, r, REGTMP);
458 o2 = olsr12u(opstr12(p->as), ((v-hi)>>s)&0xFFF, REGTMP, p->from.reg);
461 case 31: /* movT L(R), R -> ldrT */
464 diag("unexpected long move, op %A tab %A\n%P", p->as, o->as, p);
465 v = regoff(&p->from);
466 if((v & ((1<<s)-1)) != 0)
467 diag("misaligned offset\n%P", p);
468 if(v < 0 || (v>>s) >= (1<<24))
470 hi = v - (v & (0xFFF<<s));
471 if((hi & 0xFFF) != 0)
472 diag("internal: miscalculated offset %ld [%d]\n%P", v, s, p);
473 //fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF);
477 o1 = oaddi(opirr(AADD), hi, r, REGTMP);
478 o2 = olsr12u(opldr12(p->as), ((v-hi)>>s)&0xFFF, REGTMP, p->to.reg);
481 case 32: /* mov $con, R -> movz/movn */
491 diag("impossible move wide: %#llux\n%P", p->from.offset, p);
503 o1 |= (((d>>(s*16))& 0xFFFF) << 5) | ((s&3)<<21) | rt;
506 case 33: /* movk $uimm16 << pos */
510 diag("requires uimm16\n%P", p);
512 if(p->from3.type != D_NONE){
513 if(p->from3.type != D_CONST)
514 diag("missing bit position\n%P", p);
516 if((s&0xF) != 0 || (s /= 16) >= 4 || (o1&S64) == 0 && s >= 2)
517 diag("illegal bit position\n%P", p);
520 o1 |= ((d & 0xFFFF) << 5) | ((s&3)<<21) | rt;
523 case 34: /* mov $lacon,R */
524 o1 = omovlit(AMOV, p, &p->from, REGTMP);
538 case 35: /* mov SPR,R -> mrs */
541 if((o1 & (v & ~(3<<19))) != 0)
542 diag("MRS register value overlap\n%P", p);
547 case 36: /* mov R,SPR */
550 if((o1 & (v & ~(3<<19))) != 0)
551 diag("MSR register value overlap\n%P", p);
556 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
557 if((p->from.offset&~(uvlong)0xF) != 0)
558 diag("illegal immediate for PSTATE field\n%P", p);
560 o1 |= (p->from.offset&0xF) << 8; /* Crm */
562 for(i = 0; i < nelem(pstatefield); i++)
563 if(pstatefield[i].a == p->to.offset){
564 v = pstatefield[i].b;
568 diag("illegal PSTATE field for immediate move\n%P", p);
572 case 38: /* clrex [$imm] */
574 if(p->to.type == D_NONE)
577 o1 |= (p->to.offset & 0xF)<<8;
580 case 39: /* cbz R, rel */
583 o1 |= brdist(p, 0, 19, 2) << 5;
590 diag("illegal bit number\n%P", p);
591 o1 |= ((v&0x20)<<(31-5)) | ((v&0x1F)<<19);
592 o1 |= brdist(p, 0, 14, 2)<<5;
596 case 41: /* eret, nop, others with no operands */
600 case 42: /* bfm R,r,s,R */
601 o1 = opbfm(p->as, p->from.offset, p->from3.offset, p->reg, p->to.reg);
604 case 43: /* bfm aliases */
612 case ABFI: o1 = opbfm(ABFM, 64-r, s-1, rf, rt); break;
613 case ABFIW: o1 = opbfm(ABFMW, 32-r, s-1, rf, rt); break;
614 case ABFXIL: o1 = opbfm(ABFM, r, r+s-1, rf, rt); break;
615 case ABFXILW: o1 = opbfm(ABFMW, r, r+s-1, rf, rt); break;
616 case ASBFIZ: o1 = opbfm(ASBFM, 64-r, s-1, rf, rt); break;
617 case ASBFIZW: o1 = opbfm(ASBFMW, 32-r, s-1, rf, rt); break;
618 case ASBFX: o1 = opbfm(ASBFM, r, r+s-1, rf, rt); break;
619 case ASBFXW: o1 = opbfm(ASBFMW, r, r+s-1, rf, rt); break;
620 case AUBFIZ: o1 = opbfm(AUBFM, 64-r, s-1, rf, rt); break;
621 case AUBFIZW: o1 = opbfm(AUBFMW, 32-r, s-1, rf, rt); break;
622 case AUBFX: o1 = opbfm(AUBFM, r, r+s-1, rf, rt); break;
623 case AUBFXW: o1 = opbfm(AUBFMW, r, r+s-1, rf, rt); break;
625 diag("bad bfm alias\n%P", curp);
630 case 44: /* extr $b, Rn, Rm, Rd */
631 o1 = opextr(p->as, p->from.offset, p->from3.reg, p->reg, p->to.reg);
634 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
639 as = AMOVWU; /* clearer in disassembly */
642 case ASXTB: o1 = opbfm(ASBFM, 0, 7, rf, rt); break;
644 case ASXTH: o1 = opbfm(ASBFM, 0, 15, rf, rt); break;
646 case ASXTW: o1 = opbfm(ASBFM, 0, 31, rf, rt); break;
648 case AUXTB: o1 = opbfm(AUBFM, 0, 7, rf, rt); break;
650 case AUXTH: o1 = opbfm(AUBFM, 0, 15, rf, rt); break;
651 case AMOVWU: o1 = oprrr(as) | (rf<<16) | (REGZERO<<5) | rt; break;
652 case AUXTW: o1 = opbfm(AUBFM, 0, 31, rf, rt); break;
653 case ASXTBW: o1 = opbfm(ASBFMW, 0, 7, rf, rt); break;
654 case ASXTHW: o1 = opbfm(ASBFMW, 0, 15, rf, rt); break;
655 case AUXTBW: o1 = opbfm(AUBFMW, 0, 7, rf, rt); break;
656 case AUXTHW: o1 = opbfm(AUBFMW, 0, 15, rf, rt); break;
657 default: diag("bad sxt %A", as); break;
663 o1 |= p->from.reg<<5;
667 case 47: /* movT R,V(R) -> strT (huge offset) */
669 o1 = omovlit(AMOV, p, &p->to, REGTMP);
673 o2 = LD2STR(olsxrr(p->as, REGTMP, r, p->from.reg));
674 o2 |= 7<<13; // REGTMP.SX
677 case 48: /* movT V(R), R -> ldrT (huge offset) */
679 o1 = omovlit(AMOV, p, &p->from, REGTMP);
683 o2 = olsxrr(p->as, REGTMP, r, p->to.reg);
684 o2 |= 7<<13; // REGTMP.SX
687 case 50: /* sys/sysl */
689 if((p->from.offset & ~SYSARG4(0x7, 0xF, 0xF, 0x7)) != 0)
690 diag("illegal SYS argument\n%P", p);
691 o1 |= p->from.offset;
692 if(p->to.type == D_REG)
694 else if(p->reg != NREG)
702 if(p->from.type == D_CONST)
703 o1 |= (p->from.offset&0xF)<<8;
708 o1 |= (p->from.offset&0x7F)<<5;
711 case 53: /* and/or/eor... $bimmN, Rn, Rd -> op (N,r,s), Rn, Rd */
720 }else if(as == AMOVW || as == AMOVWU){
725 mask = findmask(p->from.offset);
727 mask = findmask(p->from.offset | p->from.offset<<32);
729 diag("invalid mask %#llux\n%P", p->from.offset, p);
731 case 2: o1 |= 0xF000; break;
732 case 4: o1 |= 0xE000; break;
733 case 8: o1 |= 0xC000; break;
734 case 16: o1 |= 0x8000; break;
735 case 64: o1 |= ((o1&S64)!=0)<<22; break;
737 o1 |= (mask->r<<16) | ((mask->s-1)<<10);
741 case 54: /* floating point arith */
743 if(p->from.type == D_FCONST) {
744 rf = chipfloat(p->from.ieee);
746 diag("invalid floating-point immediate\n%P", p);
754 if((o1 & (0x1F<<24)) == (0x1E<<24) && (o1 & (1<<11)) == 0){ /* monadic */
759 o1 |= (rf << 16) | (r<<5) | rt;
762 case 56: /* floating point compare */
764 if(p->from.type == D_FCONST) {
765 if(p->from.ieee->h != 0 || p->from.ieee->l != 0)
766 diag("invalid floating-point immediate\n%P", p);
772 o1 |= rf<<16 | rt<<5;
775 case 57: /* floating point conditional compare */
780 diag("implausible condition\n%P", p);
782 if(p->from3.type != D_FREG)
783 diag("illegal FCCMP\n%P", p);
785 o1 |= rf<<16 | cond<<12 | rt<<5 | nzcv;
791 o1 |= p->from.reg<<5;
802 if(p->from3.type != D_NONE)
803 o1 |= p->from3.reg<<10;
810 case 60: /* adrp label,r */
811 d = brdist(p, 12, 21, 0);
812 o1 = ADR(1, d, p->to.reg);
815 case 61: /* adr label, r */
816 d = brdist(p, 0, 21, 0);
817 o1 = ADR(0, d, p->to.reg);
820 case 62: /* case Rv, Rt -> adr tab, Rt; movw Rt[R<<2], Rl; add Rt, Rl; br (Rl) */
821 o1 = ADR(0, 4*4, p->to.reg); /* adr 4(pc), Rt */
822 o2 = (2<<30)|(7<<27)|(2<<22)|(1<<21)|(3<<13)|(1<<12)|(2<<10)|(p->from.reg<<16)|(p->to.reg<<5)|REGTMP; /* movw Rt[Rv<<2], REGTMP */
823 o3 = oprrr(AADD) | (p->to.reg<<16) | (REGTMP<<5) | REGTMP; /* add Rt, REGTMP */
824 o4 = (0x6b<<25)|(0x1F<<16)|(REGTMP<<5); /* br (REGTMP) */
830 diag("missing CASE\n%P", p);
834 o1 = p->cond->pc - (lastcase->pc + 4*4);
836 dynreloc(S, p->pc, 1);
841 case 64: /* movT R,addr */
842 o1 = omovlit(AMOV, p, &p->to, REGTMP);
843 o2 = olsr12u(opstr12(p->as), 0, REGTMP, p->from.reg);
846 case 65: /* movT addr,R */
847 o1 = omovlit(AMOV, p, &p->from, REGTMP);
848 o2 = olsr12u(opldr12(p->as), 0, REGTMP, p->to.reg);
851 case 66: /* movpT (R)O!,R; movpT O(R)!, R -> ldrT */
853 v = p->from.offset >> 2 + ((o1 & S64) != 0);
854 if(v < -128 || v > 127)
855 diag("offset out of range\n%P", p);
856 if(p->from.type == D_XPOST)
858 else if(p->from.type == D_XPRE)
862 o1 |= ((v&0x7F)<<15) | (p->from.reg<<5) | p->reg | (p->to.reg<<10);
865 case 67: /* movpT R,(R)O!; movpT O(R)!, R -> strT */
866 o1 = LD2STR(opldrpp(p->as));
867 v = p->to.offset >> 2 + ((o1 & S64) != 0);
868 if(v < -128 || v > 127)
869 diag("offset out of range\n%P", p);
870 if(p->to.type == D_XPOST)
872 else if(p->to.type == D_XPRE)
876 o1 |= ((v&0x7F)<<15) | (p->to.reg<<5) | p->from.reg | (p->reg<<10);
881 Bprint(&bso, "%2d ", o->type);
887 Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
891 Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
896 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
902 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
909 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
910 v, o1, o2, o3, o4, p);
918 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
919 v, o1, o2, o3, o4, o5, p);
930 * basic Rm op Rn -> Rd (using shifted register with 0)
932 * also Rm*Rn op Ra -> Rd
938 case AADC: return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10;
939 case AADCW: return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10;
940 case AADCS: return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10;
941 case AADCSW: return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10;
944 case ASBC: return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10;
946 case ASBCS: return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10;
948 case ASBCW: return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10;
950 case ASBCSW: return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10;
952 case AADD: return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
953 case AADDW: return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
955 case AADDS: return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
957 case AADDSW: return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
959 case ASUB: return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
960 case ASUBW: return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
962 case ASUBS: return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
964 case ASUBSW: return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10;
966 case AAND: return S64 | 0<<29 | 0xA<<24;
967 case AANDW: return S32 | 0<<29 | 0xA<<24;
969 case AORR: return S64 | 1<<29 | 0xA<<24;
972 case AORRW: return S32 | 1<<29 | 0xA<<24;
973 case AEOR: return S64 | 2<<29 | 0xA<<24;
974 case AEORW: return S32 | 2<<29 | 0xA<<24;
975 case AANDS: return S64 | 3<<29 | 0xA<<24;
976 case AANDSW: return S32 | 3<<29 | 0xA<<24;
978 case ABIC: return S64 | 0<<29 | 0xA<<24 | 1<<21;
979 case ABICW: return S32 | 0<<29 | 0xA<<24 | 1<<21;
980 case ABICS: return S64 | 3<<29 | 0xA<<24 | 1<<21;
981 case ABICSW: return S32 | 3<<29 | 0xA<<24 | 1<<21;
982 case AEON: return S64 | 2<<29 | 0xA<<24 | 1<<21;
983 case AEONW: return S32 | 2<<29 | 0xA<<24 | 1<<21;
985 case AORN: return S64 | 1<<29 | 0xA<<24 | 1<<21;
987 case AORNW: return S32 | 1<<29 | 0xA<<24 | 1<<21;
989 case AASR: return S64 | OPDP2(10); /* also ASRV */
990 case AASRW: return S32 | OPDP2(10);
991 case ALSL: return S64 | OPDP2(8);
992 case ALSLW: return S32 | OPDP2(8);
993 case ALSR: return S64 | OPDP2(9);
994 case ALSRW: return S32 | OPDP2(9);
995 case AROR: return S64 | OPDP2(11);
996 case ARORW: return S32 | OPDP2(11);
998 case ACCMN: return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4; /* cond<<12 | nzcv<<0 */
999 case ACCMNW: return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4;
1000 case ACCMP: return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4; /* imm5<<16 | cond<<12 | nzcv<<0 */
1001 case ACCMPW: return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4;
1003 case ACRC32B: return S32 | OPDP2(16);
1004 case ACRC32H: return S32 | OPDP2(17);
1005 case ACRC32W: return S32 | OPDP2(18);
1006 case ACRC32X: return S64 | OPDP2(19);
1007 case ACRC32CB: return S32 | OPDP2(20);
1008 case ACRC32CH: return S32 | OPDP2(21);
1009 case ACRC32CW: return S32 | OPDP2(22);
1010 case ACRC32CX: return S64 | OPDP2(23);
1012 case ACSEL: return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10;
1013 case ACSELW: return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10;
1014 case ACSET: return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10;
1015 case ACSETW: return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10;
1016 case ACSETM: return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10;
1017 case ACSETMW: return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10;
1019 case ACSINC: return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10;
1021 case ACSINCW: return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10;
1023 case ACSINV: return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10;
1025 case ACSINVW: return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10;
1027 case ACSNEG: return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10;
1029 case ACSNEGW: return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10;
1032 case AMADD: return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15;
1034 case AMADDW: return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15;
1036 case AMSUB: return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15;
1038 case AMSUBW: return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15;
1040 case AMRS: return SYSOP(1,2,0,0,0,0,0);
1041 case AMSR: return SYSOP(0,2,0,0,0,0,0);
1043 case ANEG: return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21;
1044 case ANEGW: return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21;
1045 case ANEGS: return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21;
1046 case ANEGSW: return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21;
1049 case ASDIV: return S64 | OPDP2(3);
1051 case ASDIVW: return S32 | OPDP2(3);
1054 case ASMADDL: return OPDP3(1, 0, 1, 0);
1056 case ASMSUBL: return OPDP3(1, 0, 1, 1);
1057 case ASMULH: return OPDP3(1, 0, 2, 0);
1059 case AUMADDL: return OPDP3(1, 0, 5, 0);
1061 case AUMSUBL: return OPDP3(1, 0, 5, 1);
1062 case AUMULH: return OPDP3(1, 0, 6, 0);
1065 case AUDIV: return S64 | OPDP2(2);
1067 case AUDIVW: return S32 | OPDP2(2);
1069 case AAESE: return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10;
1070 case AAESD: return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10;
1071 case AAESMC: return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10;
1072 case AAESIMC: return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10;
1074 case ASHA1C: return 0x5E<<24 | 0<<12;
1075 case ASHA1P: return 0x5E<<24 | 1<<12;
1076 case ASHA1M: return 0x5E<<24 | 2<<12;
1077 case ASHA1SU0: return 0x5E<<24 | 3<<12;
1078 case ASHA256H: return 0x5E<<24 | 4<<12;
1079 case ASHA256H2: return 0x5E<<24 | 5<<12;
1080 case ASHA256SU1: return 0x5E<<24 | 6<<12;
1082 case ASHA1H: return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10;
1083 case ASHA1SU1: return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10;
1084 case ASHA256SU0: return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10;
1086 case AFCVTZSD: return FPCVTI(1, 0, 1, 3, 0);
1087 case AFCVTZSDW: return FPCVTI(0, 0, 1, 3, 0);
1088 case AFCVTZSS: return FPCVTI(1, 0, 0, 3, 0);
1089 case AFCVTZSSW: return FPCVTI(0, 0, 0, 3, 0);
1091 case AFCVTZUD: return FPCVTI(1, 0, 1, 3, 1);
1092 case AFCVTZUDW: return FPCVTI(0, 0, 1, 3, 1);
1093 case AFCVTZUS: return FPCVTI(1, 0, 0, 3, 1);
1094 case AFCVTZUSW: return FPCVTI(0, 0, 0, 3, 1);
1096 case ASCVTFD: return FPCVTI(1, 0, 1, 0, 2);
1097 case ASCVTFS: return FPCVTI(1, 0, 0, 0, 2);
1098 case ASCVTFWD: return FPCVTI(0, 0, 1, 0, 2);
1099 case ASCVTFWS: return FPCVTI(0, 0, 0, 0, 2);
1101 case AUCVTFD: return FPCVTI(1, 0, 1, 0, 3);
1102 case AUCVTFS: return FPCVTI(1, 0, 0, 0, 3);
1103 case AUCVTFWD: return FPCVTI(0, 0, 1, 0, 3);
1104 case AUCVTFWS: return FPCVTI(0, 0, 0, 0, 3);
1106 case AFADDS: return FPOP2S(0, 0, 0, 2);
1107 case AFADDD: return FPOP2S(0, 0, 1, 2);
1108 case AFSUBS: return FPOP2S(0, 0, 0, 3);
1109 case AFSUBD: return FPOP2S(0, 0, 1, 3);
1110 case AFMULS: return FPOP2S(0, 0, 0, 0);
1111 case AFMULD: return FPOP2S(0, 0, 1, 0);
1112 case AFDIVS: return FPOP2S(0, 0, 0, 1);
1113 case AFDIVD: return FPOP2S(0, 0, 1, 1);
1114 case AFMAXS: return FPOP2S(0, 0, 0, 4);
1115 case AFMINS: return FPOP2S(0, 0, 0, 5);
1116 case AFMAXD: return FPOP2S(0, 0, 1, 4);
1117 case AFMIND: return FPOP2S(0, 0, 1, 5);
1118 case AFMAXNMS: return FPOP2S(0, 0, 0, 6);
1119 case AFMAXNMD: return FPOP2S(0, 0, 1, 6);
1120 case AFMINNMS: return FPOP2S(0, 0, 0, 7);
1121 case AFMINNMD: return FPOP2S(0, 0, 1, 7);
1122 case AFNMULS: return FPOP2S(0, 0, 0, 8);
1123 case AFNMULD: return FPOP2S(0, 0, 1, 8);
1125 case AFCMPS: return FPCMP(0, 0, 0, 0, 0);
1126 case AFCMPD: return FPCMP(0, 0, 1, 0, 0);
1127 case AFCMPES: return FPCMP(0, 0, 0, 0, 16);
1128 case AFCMPED: return FPCMP(0, 0, 1, 0, 16);
1130 case AFCCMPS: return FPCCMP(0, 0, 0, 0);
1131 case AFCCMPD: return FPCCMP(0, 0, 1, 0);
1132 case AFCCMPES: return FPCCMP(0, 0, 0, 1);
1133 case AFCCMPED: return FPCCMP(0, 0, 1, 1);
1135 case AFCSELS: return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10;
1136 case AFCSELD: return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10;
1138 case AFMOVS: return FPOP1S(0, 0, 0, 0);
1139 case AFABSS: return FPOP1S(0, 0, 0, 1);
1140 case AFNEGS: return FPOP1S(0, 0, 0, 2);
1141 case AFSQRTS: return FPOP1S(0, 0, 0, 3);
1142 case AFCVTSD: return FPOP1S(0, 0, 0, 5);
1143 case AFCVTSH: return FPOP1S(0, 0, 0, 7);
1144 case AFRINTNS: return FPOP1S(0, 0, 0, 8);
1145 case AFRINTPS: return FPOP1S(0, 0, 0, 9);
1146 case AFRINTMS: return FPOP1S(0, 0, 0, 10);
1147 case AFRINTZS: return FPOP1S(0, 0, 0, 11);
1148 case AFRINTAS: return FPOP1S(0, 0, 0, 12);
1149 case AFRINTXS: return FPOP1S(0, 0, 0, 14);
1150 case AFRINTIS: return FPOP1S(0, 0, 0, 15);
1152 case AFMOVD: return FPOP1S(0, 0, 1, 0);
1153 case AFABSD: return FPOP1S(0, 0, 1, 1);
1154 case AFNEGD: return FPOP1S(0, 0, 1, 2);
1155 case AFSQRTD: return FPOP1S(0, 0, 1, 3);
1156 case AFCVTDS: return FPOP1S(0, 0, 1, 4);
1157 case AFCVTDH: return FPOP1S(0, 0, 1, 7);
1158 case AFRINTND: return FPOP1S(0, 0, 1, 8);
1159 case AFRINTPD: return FPOP1S(0, 0, 1, 9);
1160 case AFRINTMD: return FPOP1S(0, 0, 1, 10);
1161 case AFRINTZD: return FPOP1S(0, 0, 1, 11);
1162 case AFRINTAD: return FPOP1S(0, 0, 1, 12);
1163 case AFRINTXD: return FPOP1S(0, 0, 1, 14);
1164 case AFRINTID: return FPOP1S(0, 0, 1, 15);
1165 case AFCVTHS: return FPOP1S(0, 0, 3, 4);
1166 case AFCVTHD: return FPOP1S(0, 0, 3, 5);
1169 diag("bad rrr %d %A", a, a);
1183 /* op $addcon, Rn, Rd */
1185 case AADD: return S64 | 0<<30 | 0<<29 | 0x11<<24;
1187 case AADDS: return S64 | 0<<30 | 1<<29 | 0x11<<24;
1189 case AADDW: return S32 | 0<<30 | 0<<29 | 0x11<<24;
1191 case AADDSW: return S32 | 0<<30 | 1<<29 | 0x11<<24;
1192 case ASUB: return S64 | 1<<30 | 0<<29 | 0x11<<24;
1194 case ASUBS: return S64 | 1<<30 | 1<<29 | 0x11<<24;
1195 case ASUBW: return S32 | 1<<30 | 0<<29 | 0x11<<24;
1197 case ASUBSW: return S32 | 1<<30 | 1<<29 | 0x11<<24;
1199 /* op $imm(SB), Rd; op label, Rd */
1200 case AADR: return 0<<31 | 0x10<<24;
1201 case AADRP: return 1<<31 | 0x10<<24;
1203 /* op $bimm, Rn, Rd */
1204 case AAND: return S64 | 0<<29 | 0x24<<23;
1205 case AANDW: return S32 | 0<<29 | 0x24<<23 | 0<<22;
1206 case AORR: return S64 | 1<<29 | 0x24<<23;
1207 case AORRW: return S32 | 1<<29 | 0x24<<23 | 0<<22;
1208 case AEOR: return S64 | 2<<29 | 0x24<<23;
1209 case AEORW: return S32 | 2<<29 | 0x24<<23 | 0<<22;
1210 case AANDS: return S64 | 3<<29 | 0x24<<23;
1211 case AANDSW: return S32 | 3<<29 | 0x24<<23 | 0<<22;
1213 case AASR: return S64 | 0<<29 | 0x26<<23; /* alias of SBFM */
1214 case AASRW: return S32 | 0<<29 | 0x26<<23 | 0<<22;
1216 /* op $width, $lsb, Rn, Rd */
1217 case ABFI: return S64 | 2<<29 | 0x26<<23 | 1<<22; /* alias of BFM */
1218 case ABFIW: return S32 | 2<<29 | 0x26<<23 | 0<<22;
1220 /* op $imms, $immr, Rn, Rd */
1221 case ABFM: return S64 | 1<<29 | 0x26<<23 | 1<<22;
1222 case ABFMW: return S32 | 1<<29 | 0x26<<23 | 0<<22;
1223 case ASBFM: return S64 | 0<<29 | 0x26<<23 | 1<<22;
1224 case ASBFMW: return S32 | 0<<29 | 0x26<<23 | 0<<22;
1225 case AUBFM: return S64 | 2<<29 | 0x26<<23 | 1<<22;
1226 case AUBFMW: return S32 | 2<<29 | 0x26<<23 | 0<<22;
1228 case ABFXIL: return S64 | 1<<29 | 0x26<<23 | 1<<22; /* alias of BFM */
1229 case ABFXILW: return S32 | 1<<29 | 0x26<<23 | 0<<22;
1231 case AEXTR: return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21;
1232 case AEXTRW: return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21;
1234 case ACBNZ: return S64 | 0x1A<<25 | 1<<24;
1235 case ACBNZW: return S32 | 0x1A<<25 | 1<<24;
1236 case ACBZ: return S64 | 0x1A<<25 | 0<<24;
1237 case ACBZW: return S32 | 0x1A<<25 | 0<<24;
1239 case ACCMN: return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4; /* imm5<<16 | cond<<12 | nzcv<<0 */
1240 case ACCMNW: return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4;
1241 case ACCMP: return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4; /* imm5<<16 | cond<<12 | nzcv<<0 */
1242 case ACCMPW: return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4;
1244 case AMOVK: return S64 | 3<<29 | 0x25<<23;
1245 case AMOVKW: return S32 | 3<<29 | 0x25<<23;
1247 case AMOVN: return S64 | 0<<29 | 0x25<<23;
1248 case AMOVNW: return S32 | 0<<29 | 0x25<<23;
1249 case AMOVZ: return S64 | 2<<29 | 0x25<<23;
1250 case AMOVZW: return S32 | 2<<29 | 0x25<<23;
1252 case AMSR: return SYSOP(0,0,0,4,0,0,0x1F); /* MSR (immediate) */
1258 case ASYS: return SYSOP(0,1,0,0,0,0,0);
1259 case ASYSL: return SYSOP(1,1,0,0,0,0,0);
1261 case ATBZ: return 0x36<<24;
1262 case ATBNZ: return 0x37<<24;
1264 case ADSB: return SYSOP(0,0,3,3,0,4,0x1F);
1265 case ADMB: return SYSOP(0,0,3,3,0,5,0x1F);
1266 case AISB: return SYSOP(0,0,3,3,0,6,0x1F);
1267 case AHINT: return SYSOP(0,0,3,2,0,0,0x1F);
1270 diag("bad irr %A", a);
1278 #define OPBIT(x) (1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | (x)<<10)
1284 case ACLS: return S64 | OPBIT(5);
1285 case ACLSW: return S32 | OPBIT(5);
1286 case ACLZ: return S64 | OPBIT(4);
1287 case ACLZW: return S32 | OPBIT(4);
1288 case ARBIT: return S64 | OPBIT(0);
1289 case ARBITW: return S32 | OPBIT(0);
1290 case AREV: return S64 | OPBIT(3);
1291 case AREVW: return S32 | OPBIT(2);
1292 case AREV16: return S64 | OPBIT(1);
1293 case AREV16W: return S32 | OPBIT(1);
1294 case AREV32: return S64 | OPBIT(2);
1296 diag("bad bit op\n%P", curp);
1302 * add/subtract extended register
1308 case AADD: return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64;
1309 case AADDW: return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32;
1311 case AADDS: return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64;
1313 case AADDSW: return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32;
1315 case ASUB: return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64;
1316 case ASUBW: return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32;
1318 case ASUBS: return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64;
1320 case ASUBSW: return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32;
1323 diag("bad opxrrr %A\n%P", a, curp);
1331 case ASVC: return 0xD4<<24 | 0<<21 | 1; /* imm16<<5 */
1332 case AHVC: return 0xD4<<24 | 0<<21 | 2;
1333 case ASMC: return 0xD4<<24 | 0<<21 | 3;
1334 case ABRK: return 0xD4<<24 | 1<<21 | 0;
1335 case AHLT: return 0xD4<<24 | 2<<21 | 0;
1336 case ADCPS1: return 0xD4<<24 | 5<<21 | 1;
1337 case ADCPS2: return 0xD4<<24 | 5<<21 | 2;
1338 case ADCPS3: return 0xD4<<24 | 5<<21 | 3;
1340 case ACLREX: return SYSOP(0,0,3,3,0,2,0x1F);
1342 diag("bad imm %A", a);
1348 brdist(Prog *p, int preshift, int flen, int shift)
1356 if(s->type != SUNDEF)
1357 diag("bad branch sym type");
1358 v = (uvlong)s->value >> (Roffset-2);
1359 dynreloc(s, p->pc, 0); /* TO DO */
1361 else if(p->cond != P)
1362 v = (p->cond->pc>>preshift) - (pc>>preshift);
1363 if((v & ((1<<shift)-1)) != 0)
1364 diag("misaligned label\n%P", p);
1366 t = (vlong)1 << (flen-1);
1367 if(v < -t || v >= t)
1368 diag("branch too far\n%P", p);
1369 return v & ((t<<1)-1);
1373 * pc-relative branches
1379 case ABEQ: return OPBcc(0x0);
1380 case ABNE: return OPBcc(0x1);
1381 case ABCS: return OPBcc(0x2);
1382 case ABHS: return OPBcc(0x2);
1383 case ABCC: return OPBcc(0x3);
1384 case ABLO: return OPBcc(0x3);
1385 case ABMI: return OPBcc(0x4);
1386 case ABPL: return OPBcc(0x5);
1387 case ABVS: return OPBcc(0x6);
1388 case ABVC: return OPBcc(0x7);
1389 case ABHI: return OPBcc(0x8);
1390 case ABLS: return OPBcc(0x9);
1391 case ABGE: return OPBcc(0xa);
1392 case ABLT: return OPBcc(0xb);
1393 case ABGT: return OPBcc(0xc);
1394 case ABLE: return OPBcc(0xd); /* imm19<<5 | cond */
1395 case AB: return 0<<31 | 5<<26; /* imm26 */
1396 case ABL: return 1<<31 | 5<<26;
1398 diag("bad bra %A", a);
1407 case ABL: return OPBLR(1); /* BLR */
1408 case AB: return OPBLR(0); /* BR */
1409 case ARET: return OPBLR(2); /* RET */
1411 diag("bad brr %A", a);
1420 case ADRPS: return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5;
1421 case AERET: return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5;
1422 case ANOP: return SYSHINT(0);
1423 case AYIELD: return SYSHINT(1);
1424 case AWFE: return SYSHINT(2);
1425 case AWFI: return SYSHINT(3);
1426 case ASEV: return SYSHINT(4);
1427 case ASEVL: return SYSHINT(5);
1429 diag("bad op0 %A", a);
1441 case ALDAR: return LDSTX(3,1,1,0,1) | 0x1F<<10;
1442 case ALDARW: return LDSTX(2,1,1,0,1) | 0x1F<<10;
1443 case ALDARB: return LDSTX(0,1,1,0,1) | 0x1F<<10;
1444 case ALDARH: return LDSTX(1,1,1,0,1) | 0x1F<<10;
1445 case ALDAXP: return LDSTX(3,0,1,1,1);
1446 case ALDAXPW: return LDSTX(2,0,1,1,1);
1447 case ALDAXR: return LDSTX(3,0,1,0,1) | 0x1F<<10;
1448 case ALDAXRW: return LDSTX(2,1,1,0,1) | 0x1F<<10;
1449 case ALDAXRB: return LDSTX(0,0,1,0,1) | 0x1F<<10;
1450 case ALDAXRH: return LDSTX(1,0,1,0,1) | 0x1F<<10;
1451 case ALDXR: return LDSTX(3,0,1,0,0) | 0x1F<<10;
1452 case ALDXRB: return LDSTX(0,0,1,0,0) | 0x1F<<10;
1453 case ALDXRH: return LDSTX(1,0,1,0,0) | 0x1F<<10;
1454 case ALDXRW: return LDSTX(2,0,1,0,0) | 0x1F<<10;
1455 case ALDXP: return LDSTX(3,0,1,1,0);
1456 case ALDXPW: return LDSTX(2,0,1,1,0);
1457 case AMOVNP: return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22;
1458 case AMOVNPW: return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22;
1460 diag("bad opload %A\n%P", a, curp);
1468 case ASTLR: return LDSTX(3,1,0,0,1) | 0x1F<<10;
1469 case ASTLRB: return LDSTX(0,1,0,0,1) | 0x1F<<10;
1470 case ASTLRH: return LDSTX(1,1,0,0,1) | 0x1F<<10;
1471 case ASTLP: return LDSTX(3,0,0,1,1);
1472 case ASTLPW: return LDSTX(2,0,0,1,1);
1473 case ASTLRW: return LDSTX(2,1,0,0,1) | 0x1F<<10;
1474 case ASTLXP: return LDSTX(2,0,0,1,1);
1475 case ASTLXPW: return LDSTX(3,0,0,1,1);
1476 case ASTLXR: return LDSTX(3,0,0,0,1) | 0x1F<<10;
1477 case ASTLXRB: return LDSTX(0,0,0,0,1) | 0x1F<<10;
1478 case ASTLXRH: return LDSTX(1,0,0,0,1) | 0x1F<<10;
1479 case ASTLXRW: return LDSTX(2,0,0,0,1) | 0x1F<<10;
1480 case ASTXR: return LDSTX(3,0,0,0,0) | 0x1F<<10;
1481 case ASTXRB: return LDSTX(0,0,0,0,0) | 0x1F<<10;
1482 case ASTXRH: return LDSTX(1,0,0,0,0) | 0x1F<<10;
1483 case ASTXP: return LDSTX(3,0,0,1,0);
1484 case ASTXPW: return LDSTX(2,0,0,1,0);
1485 case ASTXRW: return LDSTX(2,0,0,0,0) | 0x1F<<10;
1486 case AMOVNP: return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22;
1487 case AMOVNPW: return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22;
1489 diag("bad opstore %A\n%P", a, curp);
1494 * load/store register (unsigned immediate) C3.3.13
1495 * these produce 64-bit values (when there's an option)
1499 olsr12u(long o, long v, int b, int r)
1501 if(v < 0 || v >= (1<<12))
1502 diag("offset out of range: %ld\n%P", v, curp);
1513 case AMOV: return LDSTR12U(3, 0, 1); /* imm12<<10 | Rn<<5 | Rt */
1514 case AMOVW: return LDSTR12U(2, 0, 2);
1515 case AMOVWU: return LDSTR12U(2, 0, 1);
1516 case AMOVH: return LDSTR12U(1, 0, 2);
1517 case AMOVHU: return LDSTR12U(1, 0, 1);
1518 case AMOVB: return LDSTR12U(0, 0, 2);
1519 case AMOVBU: return LDSTR12U(0, 0, 1);
1520 case AFMOVS: return LDSTR12U(2, 1, 1);
1521 case AFMOVD: return LDSTR12U(3, 1, 1);
1523 diag("bad opldr12 %A\n%P", a, curp);
1530 return LD2STR(opldr12(a));
1534 * load/store register (unscaled immediate) C3.3.12
1538 olsr9s(long o, long v, int b, int r)
1540 if(v < -256 || v > 255)
1541 diag("offset out of range: %ld\n%P", v, curp);
1552 case AMOV: return LDSTR9S(3, 0, 1); /* simm9<<12 | Rn<<5 | Rt */
1553 case AMOVW: return LDSTR9S(2, 0, 2);
1554 case AMOVWU: return LDSTR9S(2, 0, 1);
1555 case AMOVH: return LDSTR9S(1, 0, 2);
1556 case AMOVHU: return LDSTR9S(1, 0, 1);
1557 case AMOVB: return LDSTR9S(0, 0, 2);
1558 case AMOVBU: return LDSTR9S(0, 0, 1);
1559 case AFMOVS: return LDSTR9S(2, 1, 1);
1560 case AFMOVD: return LDSTR9S(3, 1, 1);
1562 diag("bad opldr9 %A\n%P", a, curp);
1569 return LD2STR(opldr9(a));
1576 case AMOV: return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22; /* simm9<<12 | Rn<<5 | Rt */
1577 case AMOVW: return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22;
1578 case AMOVWU: return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22;
1579 case AMOVH: return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22;
1580 case AMOVHU: return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22;
1581 case AMOVB: return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22;
1582 case AMOVBU: return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22;
1583 case AMOVPW: return 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22;
1584 case AMOVPSW: return 1<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22;
1585 case AMOVP: return 2<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22;
1587 diag("bad opldr %A\n%P", a, curp);
1592 * load/store register (extended register)
1595 olsxrr(int a, int b, int c, int d)
1597 return opldrpp(a) | 1<<21 | b<<16 | 2<<10 | c<<5 | d;
1601 oaddi(long o1, long v, int r, int rt)
1603 if((v & 0xFFF000) != 0){
1607 o1 |= ((v & 0xFFF) << 10) | (r<<5) | rt;
1612 * load a literal value into dr
1615 omovlit(int as, Prog *p, Adr *a, int dr)
1620 if(p->cond == nil){ /* not in literal pool */
1622 /* TO DO: could be clever, and use general constant builder */
1625 if(v != 0 && (v & 0xFFF) == 0){
1627 o1 |= 1<<22; /* shift, by 12 */
1629 if(v < 0 || v > 0xFFF)
1630 diag("literal out of range\n%P", p);
1631 o1 |= ((v& 0xFFF) << 10) | (REGZERO<<5) | dr;
1634 w = 0; /* default: 32 bit, unsigned */
1641 w = 1; /* 64 bit simd&fp */
1644 if(p->cond->as == ADWORD)
1646 else if(p->cond->to.offset < 0)
1647 w = 2; /* sign extend */
1652 w = 2; /* 32 bit, sign-extended to 64 */
1655 v = brdist(p, 0, 19, 2);
1656 o1 = (w<<30)|(fp<<26)|(3<<27);
1657 o1 |= (v&0x7FFFF)<<5;
1664 opbfm(int a, int r, int s, int rf, int rt)
1669 if((o & (1<<31)) == 0)
1674 diag("illegal bit number\n%P", curp);
1677 diag("illegal bit number\n%P", curp);
1684 opextr(int a, long v, int rn, int rm, int rt)
1689 c = (o & (1<<31)) != 0? 63: 31;
1691 diag("illegal bit number\n%P", curp);
1700 * size in log2(bytes)