changeset 7169: | 94fca26a23d8 |
parent: | 4e09a9199097 |
child: | 8eca5306b6d9 |
author: | cinap_lenrek@felloff.net |
date: | Wed, 17 Apr 2019 23:38:00 +0200 |
permissions: | -rw-r--r-- |
description: | 7c: fix long to vlong/pointer conversion, avoid negative immediate offsets we have to explicitely convert to vlong by sign or zero extending as not every operation leaves a proper zero/sign extended result in the register. for example NEGW will zero extend, breaking negative int offsets on pointers. we explicitely insert SXTW or MOVWU instructions which the peephole optimizer takes out again when it is safe todo so. when promoting constant offsets to immediate offsets, make sure the offset will be in range. otherwise the linker will produce not so optimal pointer arithmetic instructions to calculate the offset. |
1 #include "gc.h"3 static char resvreg[nelem(reg)];5 #define isv(et) ((et) == TVLONG || (et) == TUVLONG || (et) == TIND)7 void8 ginit(void)9 {10 Type *t;12 thechar = '7';13 thestring = "arm64";14 exregoffset = REGEXT;15 exfregoffset = FREGEXT;16 newvlongcode = 1;17 listinit();18 nstring = 0;19 mnstring = 0;20 nrathole = 0;21 pc = 0;22 breakpc = -1;23 continpc = -1;24 cases = C;25 firstp = P;26 lastp = P;27 tfield = types[TLONG];29 typeswitch = typechlv;30 typeword = typechlvp;31 typecmplx = typesu;32 /* TO DO */33 memmove(typechlpv, typechlp, sizeof(typechlpv));34 typechlpv[TVLONG] = 1;35 typechlpv[TUVLONG] = 1;37 zprog.link = P;38 zprog.as = AGOK;39 zprog.reg = NREG;40 zprog.from.type = D_NONE;41 zprog.from.name = D_NONE;42 zprog.from.reg = NREG;43 zprog.to = zprog.from;45 regnode.op = OREGISTER;46 regnode.class = CEXREG;47 regnode.reg = REGTMP;48 regnode.complex = 0;49 regnode.addable = 11;50 regnode.type = types[TLONG];52 qregnode = regnode;53 qregnode.type = types[TVLONG];55 constnode.op = OCONST;56 constnode.class = CXXX;57 constnode.complex = 0;58 constnode.addable = 20;59 constnode.type = types[TLONG];61 vconstnode = constnode;62 vconstnode.type = types[TVLONG];64 fconstnode.op = OCONST;65 fconstnode.class = CXXX;66 fconstnode.complex = 0;67 fconstnode.addable = 20;68 fconstnode.type = types[TDOUBLE];70 nodsafe = new(ONAME, Z, Z);71 nodsafe->sym = slookup(".safe");72 nodsafe->type = types[TINT];73 nodsafe->etype = types[TINT]->etype;74 nodsafe->class = CAUTO;75 complex(nodsafe);77 t = typ(TARRAY, types[TCHAR]);78 symrathole = slookup(".rathole");79 symrathole->class = CGLOBL;80 symrathole->type = t;82 nodrat = new(ONAME, Z, Z);83 nodrat->sym = symrathole;84 nodrat->type = types[TIND];85 nodrat->etype = TVOID;86 nodrat->class = CGLOBL;87 complex(nodrat);88 nodrat->type = t;90 nodret = new(ONAME, Z, Z);91 nodret->sym = slookup(".ret");92 nodret->type = types[TIND];93 nodret->etype = TIND;94 nodret->class = CPARAM;95 nodret = new(OIND, nodret, Z);96 complex(nodret);98 com64init();100 memset(reg, 0, sizeof(reg));101 /* don't allocate */102 reg[REGTMP] = 1;103 reg[REGSB] = 1;104 reg[REGSP] = 1;105 reg[REGZERO] = 1;106 /* keep two external registers */107 reg[REGEXT] = 1;108 reg[REGEXT-1] = 1;109 memmove(resvreg, reg, sizeof(reg));110 }112 void113 gclean(void)114 {115 int i;116 Sym *s;118 for(i=0; i<NREG; i++)119 if(reg[i] && !resvreg[i])120 diag(Z, "reg %d left allocated", i);121 for(i=NREG; i<NREG+NFREG; i++)122 if(reg[i] && !resvreg[i])123 diag(Z, "freg %d left allocated", i-NREG);124 while(mnstring)125 outstring("", 1L);126 symstring->type->width = nstring;127 symrathole->type->width = nrathole;128 for(i=0; i<NHASH; i++)129 for(s = hash[i]; s != S; s = s->link) {130 if(s->type == T)131 continue;132 if(s->type->width == 0)133 continue;134 if(s->class != CGLOBL && s->class != CSTATIC)135 continue;136 if(s->type == types[TENUM])137 continue;138 gpseudo(AGLOBL, s, nodconst(s->type->width));139 }140 nextpc();141 p->as = AEND;142 outcode();143 }145 void146 nextpc(void)147 {149 p = alloc(sizeof(*p));150 *p = zprog;151 p->lineno = nearln;152 pc++;153 if(firstp == P) {154 firstp = p;155 lastp = p;156 return;157 }158 lastp->link = p;159 lastp = p;160 }162 void163 gargs(Node *n, Node *tn1, Node *tn2)164 {165 long regs;166 Node fnxargs[20], *fnxp;168 regs = cursafe;170 fnxp = fnxargs;171 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */173 curarg = 0;174 fnxp = fnxargs;175 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */177 cursafe = regs;178 }180 void181 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)182 {183 Node nod;185 if(n == Z)186 return;187 if(n->op == OLIST) {188 garg1(n->left, tn1, tn2, f, fnxp);189 garg1(n->right, tn1, tn2, f, fnxp);190 return;191 }192 if(f == 0) {193 if(n->complex >= FNX) {194 regsalloc(*fnxp, n);195 nod = znode;196 nod.op = OAS;197 nod.left = *fnxp;198 nod.right = n;199 nod.type = n->type;200 cgen(&nod, Z);201 (*fnxp)++;202 }203 return;204 }205 if(typesu[n->type->etype]) {206 regaalloc(tn2, n);207 if(n->complex >= FNX) {208 sugen(*fnxp, tn2, n->type->width);209 (*fnxp)++;210 } else211 sugen(n, tn2, n->type->width);212 return;213 }214 if(REGARG >= 0 && curarg == 0 && typechlpv[n->type->etype]) {215 regaalloc1(tn1, n);216 if(n->complex >= FNX) {217 cgen(*fnxp, tn1);218 (*fnxp)++;219 } else220 cgen(n, tn1);221 return;222 }223 if(vconst(n) == 0) {224 regaalloc(tn2, n);225 gopcode(OAS, n, Z, tn2);226 return;227 }228 regalloc(tn1, n, Z);229 if(n->complex >= FNX) {230 cgen(*fnxp, tn1);231 (*fnxp)++;232 } else233 cgen(n, tn1);234 regaalloc(tn2, n);235 gopcode(OAS, tn1, Z, tn2);236 regfree(tn1);237 }239 Node*240 nodgconst(vlong v, Type *t)241 {242 if(!typev[t->etype])243 return nodconst((long)v);244 vconstnode.vconst = v;245 return &vconstnode;246 }248 Node*249 nodconst(long v)250 {251 constnode.vconst = v;252 return &constnode;253 }255 Node*256 nod32const(vlong v)257 {258 constnode.vconst = v & MASK(32);259 return &constnode;260 }262 Node*263 nodfconst(double d)264 {265 fconstnode.fconst = d;266 return &fconstnode;267 }269 void270 nodreg(Node *n, Node *nn, int reg)271 {272 *n = qregnode;273 n->reg = reg;274 n->type = nn->type;275 n->lineno = nn->lineno;276 }278 void279 regret(Node *n, Node *nn)280 {281 int r;283 r = REGRET;284 if(typefd[nn->type->etype])285 r = FREGRET+NREG;286 nodreg(n, nn, r);287 reg[r]++;288 }290 void291 regalloc(Node *n, Node *tn, Node *o)292 {293 int i, j;294 static int lasti;296 switch(tn->type->etype) {297 case TCHAR:298 case TUCHAR:299 case TSHORT:300 case TUSHORT:301 case TINT:302 case TUINT:303 case TLONG:304 case TULONG:305 case TVLONG:306 case TUVLONG:307 case TIND:308 if(o != Z && o->op == OREGISTER) {309 i = o->reg;310 if(i >= 0 && i < NREG)311 goto out;312 }313 j = lasti + REGRET+1;314 for(i=REGRET+1; i<NREG; i++) {315 if(j >= NREG)316 j = REGRET+1;317 if(reg[j] == 0 && resvreg[j] == 0) {318 i = j;319 goto out;320 }321 j++;322 }323 diag(tn, "out of fixed registers");324 goto err;326 case TFLOAT:327 case TDOUBLE:328 if(o != Z && o->op == OREGISTER) {329 i = o->reg;330 if(i >= NREG && i < NREG+NFREG)331 goto out;332 }333 j = lasti + NREG;334 for(i=NREG; i<NREG+NFREG; i++) {335 if(j >= NREG+NFREG)336 j = NREG;337 if(reg[j] == 0) {338 i = j;339 goto out;340 }341 j++;342 }343 diag(tn, "out of float registers");344 goto err;345 }346 diag(tn, "unknown type in regalloc: %T", tn->type);347 err:348 nodreg(n, tn, 0);349 return;350 out:351 reg[i]++;352 lasti++;353 if(lasti >= 5)354 lasti = 0;355 nodreg(n, tn, i);356 }358 void359 regialloc(Node *n, Node *tn, Node *o)360 {361 Node nod;363 nod = *tn;364 nod.type = types[TIND];365 regalloc(n, &nod, o);366 }368 void369 regfree(Node *n)370 {371 int i;373 i = 0;374 if(n->op != OREGISTER && n->op != OINDREG)375 goto err;376 i = n->reg;377 if(i < 0 || i >= sizeof(reg))378 goto err;379 if(reg[i] <= 0)380 goto err;381 reg[i]--;382 return;383 err:384 diag(n, "error in regfree: %d", i);385 }387 void388 regsalloc(Node *n, Node *nn)389 {390 cursafe = align(cursafe, nn->type, Aaut3);391 maxargsafe = maxround(maxargsafe, cursafe+curarg);392 *n = *nodsafe;393 n->xoffset = -(stkoff + cursafe);394 n->type = nn->type;395 n->etype = nn->type->etype;396 n->lineno = nn->lineno;397 }399 void400 regaalloc1(Node *n, Node *nn)401 {402 nodreg(n, nn, REGARG);403 reg[REGARG]++;404 curarg = align(curarg, nn->type, Aarg1);405 curarg = align(curarg, nn->type, Aarg2);406 maxargsafe = maxround(maxargsafe, cursafe+curarg);407 }409 void410 regaalloc(Node *n, Node *nn)411 {412 curarg = align(curarg, nn->type, Aarg1);413 *n = *nn;414 n->op = OINDREG;415 n->reg = REGSP;416 n->xoffset = curarg + SZ_VLONG;417 n->complex = 0;418 n->addable = 20;419 curarg = align(curarg, nn->type, Aarg2);420 maxargsafe = maxround(maxargsafe, cursafe+curarg);421 }423 void424 regind(Node *n, Node *nn)425 {427 if(n->op != OREGISTER) {428 diag(n, "regind not OREGISTER");429 return;430 }431 n->op = OINDREG;432 n->type = nn->type;433 }435 void436 raddr(Node *n, Prog *p)437 {438 Adr a;440 naddr(n, &a);441 if(a.type == D_CONST && a.offset == 0) {442 a.type = D_REG;443 a.reg = REGZERO;444 }445 if(a.type != D_REG && a.type != D_FREG) {446 if(n)447 diag(n, "bad in raddr: %O", n->op);448 else449 diag(n, "bad in raddr: <null>");450 p->reg = NREG;451 } else452 p->reg = a.reg;453 }455 void456 naddr(Node *n, Adr *a)457 {458 long v;460 a->type = D_NONE;461 if(n == Z)462 return;463 switch(n->op) {464 default:465 bad:466 diag(n, "bad in naddr: %O", n->op);467 break;469 case OREGISTER:470 a->type = D_REG;471 a->sym = S;472 a->reg = n->reg;473 if(a->reg >= NREG) {474 a->type = D_FREG;475 a->reg -= NREG;476 }477 break;479 case OIND:480 naddr(n->left, a);481 if(a->type == D_REG) {482 a->type = D_OREG;483 break;484 }485 if(a->type == D_CONST) {486 a->type = D_OREG;487 break;488 }489 goto bad;491 case OINDREG:492 a->type = D_OREG;493 a->sym = S;494 a->offset = n->xoffset;495 a->reg = n->reg;496 break;498 case ONAME:499 a->etype = n->etype;500 a->type = D_OREG;501 a->name = D_STATIC;502 a->sym = n->sym;503 a->offset = n->xoffset;504 if(n->class == CSTATIC)505 break;506 if(n->class == CEXTERN || n->class == CGLOBL) {507 a->name = D_EXTERN;508 break;509 }510 if(n->class == CAUTO) {511 a->name = D_AUTO;512 break;513 }514 if(n->class == CPARAM) {515 a->name = D_PARAM;516 break;517 }518 goto bad;520 case OCONST:521 a->sym = S;522 a->reg = NREG;523 if(typefd[n->type->etype]) {524 a->type = D_FCONST;525 a->dval = n->fconst;526 } else {527 a->type = D_CONST;528 a->offset = n->vconst;529 }530 break;532 case OADDR:533 naddr(n->left, a);534 if(a->type == D_OREG) {535 a->type = D_CONST;536 break;537 }538 print("bad addr %D\n", a);539 goto bad;541 case OADD:542 if(n->left->op == OCONST) {543 naddr(n->left, a);544 v = a->offset;545 naddr(n->right, a);546 } else {547 naddr(n->right, a);548 v = a->offset;549 naddr(n->left, a);550 }551 a->offset += v;552 break;554 }555 }557 void558 fop(int as, int f1, int f2, Node *t)559 {560 Node nod1, nod2, nod3;562 nodreg(&nod1, t, NREG+f1);563 nodreg(&nod2, t, NREG+f2);564 regalloc(&nod3, t, t);565 gopcode(as, &nod1, &nod2, &nod3);566 gmove(&nod3, t);567 regfree(&nod3);568 }570 void571 gmove(Node *f, Node *t)572 {573 int ft, tt, a;574 Node nod;576 ft = f->type->etype;577 tt = t->type->etype;579 if(ft == TDOUBLE && f->op == OCONST) {580 }581 if(ft == TFLOAT && f->op == OCONST) {582 }584 /*585 * a load --586 * put it into a register then587 * worry what to do with it.588 */589 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {590 switch(ft) {591 default:592 if(ewidth[ft] == 4){593 if(typeu[ft])594 a = AMOVWU;595 else596 a = AMOVW;597 }else598 a = AMOV;599 break;600 case TINT:601 a = AMOVW;602 break;603 case TUINT:604 a = AMOVWU;605 break;606 case TFLOAT:607 a = AFMOVS;608 break;609 case TDOUBLE:610 a = AFMOVD;611 break;612 case TCHAR:613 a = AMOVB;614 break;615 case TUCHAR:616 a = AMOVBU;617 break;618 case TSHORT:619 a = AMOVH;620 break;621 case TUSHORT:622 a = AMOVHU;623 break;624 }625 regalloc(&nod, f, t);626 gins(a, f, &nod);627 gmove(&nod, t);628 regfree(&nod);629 return;630 }632 /*633 * a store --634 * put it into a register then635 * store it.636 */637 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {638 switch(tt) {639 default:640 if(ewidth[tt] == 4)641 a = AMOVW;642 else643 a = AMOV;644 break;645 case TINT:646 a = AMOVW;647 break;648 case TUINT:649 a = AMOVWU;650 break;651 case TUCHAR:652 a = AMOVBU;653 break;654 case TCHAR:655 a = AMOVB;656 break;657 case TUSHORT:658 a = AMOVHU;659 break;660 case TSHORT:661 a = AMOVH;662 break;663 case TFLOAT:664 a = AFMOVS;665 break;666 case TDOUBLE:667 a = AFMOVD;668 break;669 }670 if(!typefd[ft] && vconst(f) == 0) {671 gins(a, f, t);672 return;673 }674 if(ft == tt)675 regalloc(&nod, t, f);676 else677 regalloc(&nod, t, Z);678 gmove(f, &nod);679 gins(a, &nod, t);680 regfree(&nod);681 return;682 }684 /*685 * type x type cross table686 */687 a = AGOK;688 switch(ft) {689 case TDOUBLE:690 case TFLOAT:691 switch(tt) {692 case TDOUBLE:693 a = AFMOVD;694 if(ft == TFLOAT)695 a = AFCVTSD;696 break;697 case TFLOAT:698 a = AFMOVS;699 if(ft == TDOUBLE)700 a = AFCVTDS;701 break;702 case TCHAR:703 case TSHORT:704 case TINT:705 case TLONG:706 a = AFCVTZSDW;707 if(ft == TFLOAT)708 a = AFCVTZSSW;709 break;710 case TUCHAR:711 case TUSHORT:712 case TUINT:713 case TULONG:714 a = AFCVTZUDW;715 if(ft == TFLOAT)716 a = AFCVTZUSW;717 break;718 case TVLONG:719 a = AFCVTZSD;720 if(ft == TFLOAT)721 a = AFCVTZSS;722 break;723 case TUVLONG:724 case TIND:725 a = AFCVTZUD;726 if(ft == TFLOAT)727 a = AFCVTZUS;728 break;729 }730 break;731 case TUINT:732 case TULONG:733 case TINT:734 case TLONG:735 switch(tt) {736 case TDOUBLE:737 if(ft == TUINT || ft == TULONG)738 gins(AUCVTFWD, f, t);739 else740 gins(ASCVTFWD, f, t);741 return;742 case TFLOAT:743 if(ft == TUINT || ft == TULONG)744 gins(AUCVTFWS, f, t);745 else746 gins(ASCVTFWS, f, t);747 return;748 case TINT:749 case TUINT:750 case TLONG:751 case TULONG:752 case TSHORT:753 case TUSHORT:754 case TCHAR:755 case TUCHAR:756 if(typeu[tt])757 a = AMOVWU;758 else759 a = AMOVW;760 break;761 case TVLONG:762 case TUVLONG:763 case TIND:764 if(typeu[ft])765 a = AMOVWU;766 else767 a = ASXTW;768 break;769 }770 break;771 case TVLONG:772 case TUVLONG:773 case TIND:774 switch(tt) {775 case TDOUBLE:776 if(ft == TVLONG)777 gins(ASCVTFD, f, t);778 else779 gins(AUCVTFD, f, t);780 return;781 case TFLOAT:782 if(ft == TVLONG)783 gins(ASCVTFS, f, t);784 else785 gins(AUCVTFS, f, t);786 return;787 case TINT:788 case TUINT:789 case TLONG:790 case TULONG:791 case TSHORT:792 case TUSHORT:793 case TCHAR:794 case TUCHAR:795 a = AMOVWU;796 break;797 case TVLONG:798 case TUVLONG:799 case TIND:800 a = AMOV;801 break;802 }803 break;804 case TSHORT:805 switch(tt) {806 case TDOUBLE:807 regalloc(&nod, f, Z);808 gins(AMOVH, f, &nod);809 gins(ASCVTFWD, &nod, t);810 regfree(&nod);811 return;812 case TFLOAT:813 regalloc(&nod, f, Z);814 gins(AMOVH, f, &nod);815 gins(ASCVTFWS, &nod, t);816 regfree(&nod);817 return;818 case TINT:819 case TUINT:820 case TLONG:821 case TULONG:822 case TVLONG:823 case TUVLONG:824 case TIND:825 a = AMOVH;826 break;827 case TSHORT:828 case TUSHORT:829 case TCHAR:830 case TUCHAR:831 a = AMOV;832 break;833 }834 break;835 case TUSHORT:836 switch(tt) {837 case TDOUBLE:838 regalloc(&nod, f, Z);839 gins(AMOVHU, f, &nod);840 gins(AUCVTFWD, &nod, t);841 regfree(&nod);842 return;843 case TFLOAT:844 regalloc(&nod, f, Z);845 gins(AMOVHU, f, &nod);846 gins(AUCVTFWS, &nod, t);847 regfree(&nod);848 return;849 case TINT:850 case TUINT:851 case TLONG:852 case TULONG:853 case TVLONG:854 case TUVLONG:855 case TIND:856 a = AMOVHU;857 break;858 case TSHORT:859 case TUSHORT:860 case TCHAR:861 case TUCHAR:862 a = AMOV;863 break;864 }865 break;866 case TCHAR:867 switch(tt) {868 case TDOUBLE:869 regalloc(&nod, f, Z);870 gins(AMOVB, f, &nod);871 gins(ASCVTFWD, &nod, t);872 regfree(&nod);873 return;874 case TFLOAT:875 regalloc(&nod, f, Z);876 gins(AMOVB, f, &nod);877 gins(ASCVTFWS, &nod, t);878 regfree(&nod);879 return;880 case TINT:881 case TUINT:882 case TLONG:883 case TULONG:884 case TIND:885 case TSHORT:886 case TUSHORT:887 case TVLONG:888 case TUVLONG:889 a = AMOVB;890 break;891 case TCHAR:892 case TUCHAR:893 a = AMOV;894 break;895 }896 break;897 case TUCHAR:898 switch(tt) {899 case TDOUBLE:900 regalloc(&nod, f, Z);901 gins(AMOVBU, f, &nod);902 gins(AUCVTFWD, &nod, t);903 regfree(&nod);904 return;905 case TFLOAT:906 regalloc(&nod, f, Z);907 gins(AMOVBU, f, &nod);908 gins(AUCVTFWS, &nod, t);909 regfree(&nod);910 return;911 case TINT:912 case TUINT:913 case TLONG:914 case TULONG:915 case TIND:916 case TSHORT:917 case TUSHORT:918 case TVLONG:919 case TUVLONG:920 a = AMOVBU;921 break;922 case TCHAR:923 case TUCHAR:924 a = AMOV;925 break;926 }927 break;928 }929 if(a == AGOK)930 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);931 if(a == AMOV || (a == AMOVW || a == AMOVWU) && ewidth[ft] == ewidth[tt] || a == AFMOVS || a == AFMOVD)932 if(samaddr(f, t))933 return;934 gins(a, f, t);935 }937 void938 gmover(Node *f, Node *t)939 {940 int ft, tt, a;942 ft = f->type->etype;943 tt = t->type->etype;944 a = AGOK;945 if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){946 switch(tt){947 case TSHORT:948 a = AMOVH;949 break;950 case TUSHORT:951 a = AMOVHU;952 break;953 case TCHAR:954 a = AMOVB;955 break;956 case TUCHAR:957 a = AMOVBU;958 break;959 case TINT:960 a = AMOVW;961 break;962 case TUINT:963 a = AMOVWU;964 break;965 }966 }967 if(a == AGOK)968 gmove(f, t);969 else970 gins(a, f, t);971 }973 void974 gins(int a, Node *f, Node *t)975 {977 nextpc();978 p->as = a;979 if(f != Z)980 naddr(f, &p->from);981 if(t != Z)982 naddr(t, &p->to);983 if(debug['g'])984 print("%P\n", p);985 }987 void988 gopcode(int o, Node *f1, Node *f2, Node *t)989 {990 int a, et, true;991 Adr ta;993 et = TLONG;994 if(f1 != Z && f1->type != T) {995 et = f1->type->etype;996 if(f1->op == OCONST){997 if(t != Z && t->type != T)998 et = t->type->etype;999 else if(f2 != Z && f2->type != T && ewidth[f2->type->etype] > ewidth[et])1000 et = f2->type->etype;1001 }1002 }1003 true = o & BTRUE;1004 o &= ~BTRUE;1005 a = AGOK;1006 switch(o) {1007 case OAS:1008 gmove(f1, t);1009 return;1011 case OASADD:1012 case OADD:1013 a = AADDW;1014 if(isv(et))1015 a = AADD;1016 else if(et == TFLOAT)1017 a = AFADDS;1018 else if(et == TDOUBLE)1019 a = AFADDD;1020 break;1022 case OASSUB:1023 case OSUB:1024 a = ASUBW;1025 if(isv(et))1026 a = ASUB;1027 else if(et == TFLOAT)1028 a = AFSUBS;1029 else if(et == TDOUBLE)1030 a = AFSUBD;1031 break;1033 case OASOR:1034 case OOR:1035 a = AORRW;1036 if(isv(et))1037 a = AORR;1038 break;1040 case OASAND:1041 case OAND:1042 a = AANDW;1043 if(isv(et))1044 a = AAND;1045 break;1047 case OASXOR:1048 case OXOR:1049 a = AEORW;1050 if(isv(et))1051 a = AEOR;1052 break;1054 case OASLSHR:1055 case OLSHR:1056 a = ALSRW;1057 if(isv(et))1058 a = ALSR;1059 break;1061 case OASASHR:1062 case OASHR:1063 a = AASRW;1064 if(isv(et))1065 a = AASR;1066 break;1068 case OASASHL:1069 case OASHL:1070 a = ALSLW;1071 if(isv(et))1072 a = ALSL;1073 break;1075 case OFUNC:1076 a = ABL;1077 break;1079 case OASMUL:1080 case OMUL:1081 a = AMULW;1082 if(isv(et))1083 a = AMUL;1084 else if(et == TFLOAT)1085 a = AFMULS;1086 else if(et == TDOUBLE)1087 a = AFMULD;1088 break;1090 case OASDIV:1091 case ODIV:1092 a = ASDIVW;1093 if(isv(et))1094 a = ASDIV;1095 else if(et == TFLOAT)1096 a = AFDIVS;1097 else if(et == TDOUBLE)1098 a = AFDIVD;1099 break;1101 case OASMOD:1102 case OMOD:1103 a = AREMW;1104 if(isv(et))1105 a = AREM;1106 break;1108 case OASLMUL:1109 case OLMUL:1110 a = AUMULL;1111 if(isv(et))1112 a = AMUL;1113 break;1115 case OASLMOD:1116 case OLMOD:1117 a = AUREMW;1118 if(isv(et))1119 a = AUREM;1120 break;1122 case OASLDIV:1123 case OLDIV:1124 a = AUDIVW;1125 if(isv(et))1126 a = AUDIV;1127 break;1129 case OCOM:1130 a = AMVNW;1131 if(isv(et))1132 a = AMVN;1133 break;1135 case ONEG:1136 a = ANEGW;1137 if(isv(et))1138 a = ANEG;1139 break;1141 case OCASE:1142 a = ACASE; /* ACASEW? */1143 break;1145 case OEQ:1146 case ONE:1147 case OLT:1148 case OLE:1149 case OGE:1150 case OGT:1151 case OLO:1152 case OLS:1153 case OHS:1154 case OHI:1155 a = ACMPW;1156 if(isv(et))1157 a = ACMP;1158 if(et == TFLOAT)1159 a = AFCMPS;1160 else if(et == TDOUBLE)1161 a = AFCMPD;1162 nextpc();1163 p->as = a;1164 naddr(f1, &p->from);1165 if(f1->op == OCONST && p->from.offset < 0){1166 if(a == ACMPW && (ulong)p->from.offset != 0x80000000UL) {1167 p->as = ACMNW;1168 p->from.offset = -p->from.offset;1169 }else if(a == ACMP && p->from.offset != 0x8000000000000000LL){1170 p->as = ACMN;1171 p->from.offset = -p->from.offset;1172 }1173 }1174 raddr(f2, p);1175 switch(o) {1176 case OEQ:1177 a = ABEQ;1178 break;1179 case ONE:1180 a = ABNE;1181 break;1182 case OLT:1183 a = ABLT;1184 /* ensure NaN comparison is always false */1185 if(typefd[et] && !true)1186 a = ABMI;1187 break;1188 case OLE:1189 a = ABLE;1190 if(typefd[et] && !true)1191 a = ABLS;1192 break;1193 case OGE:1194 a = ABGE;1195 if(typefd[et] && true)1196 a = ABPL;1197 break;1198 case OGT:1199 a = ABGT;1200 if(typefd[et] && true)1201 a = ABHI;1202 break;1203 case OLO:1204 a = ABLO;1205 break;1206 case OLS:1207 a = ABLS;1208 break;1209 case OHS:1210 a = ABHS;1211 break;1212 case OHI:1213 a = ABHI;1214 break;1215 }1216 f1 = Z;1217 f2 = Z;1218 break;1219 }1220 if(a == AGOK)1221 diag(Z, "bad in gopcode %O", o);1222 nextpc();1223 p->as = a;1224 if(f1 != Z)1225 naddr(f1, &p->from);1226 if(f2 != Z) {1227 naddr(f2, &ta);1228 p->reg = ta.reg;1229 }1230 if(t != Z)1231 naddr(t, &p->to);1232 if(debug['g'])1233 print("%P\n", p);1234 }1236 int1237 samaddr(Node *f, Node *t)1238 {1239 return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;1240 }1242 void1243 gbranch(int o)1244 {1245 int a;1247 a = AGOK;1248 switch(o) {1249 case ORETURN:1250 a = ARETURN;1251 break;1252 case OGOTO:1253 a = AB;1254 break;1255 }1256 nextpc();1257 if(a == AGOK) {1258 diag(Z, "bad in gbranch %O", o);1259 nextpc();1260 }1261 p->as = a;1262 }1264 void1265 patch(Prog *op, long pc)1266 {1268 op->to.offset = pc;1269 op->to.type = D_BRANCH;1270 }1272 void1273 gpseudo(int a, Sym *s, Node *n)1274 {1276 nextpc();1277 p->as = a;1278 p->from.type = D_OREG;1279 p->from.sym = s;1280 p->from.name = D_EXTERN;1281 if(a == ATEXT)1282 p->reg = (profileflg ? 0 : NOPROF);1283 if(s->class == CSTATIC)1284 p->from.name = D_STATIC;1285 naddr(n, &p->to);1286 if(a == ADATA || a == AGLOBL)1287 pc--;1288 }1290 int1291 sconst(Node *n)1292 {1293 vlong vv;1295 if(n->op == OCONST) {1296 if(!typefd[n->type->etype]) {1297 vv = n->vconst;1298 if(vv >= (vlong)(-32766) && vv < (vlong)32766)1299 return 1;1300 /*1301 * should be specialised for constant values which will1302 * fit in different instructionsl; for now, let 5l1303 * sort it out1304 */1305 return 1;1306 }1307 }1308 return 0;1309 }1311 static int1312 isaddcon(vlong v)1313 {1314 /* uimm12 or uimm24? */1315 if(v < 0)1316 return 0;1317 if((v & 0xFFF) == 0)1318 v >>= 12;1319 return v <= 0xFFF;1320 }1322 int1323 sval(vlong v)1324 {1325 return isaddcon(v) || isaddcon(-v);1326 }1328 int1329 usableoffset(Node *n, vlong o, Node *v)1330 {1331 int s;1333 if(v != nil){1334 if(v->op != OCONST || typefd[v->type->etype])1335 return 0;1336 o += v->vconst;1337 }1338 s = n->type->width;1339 if(s > 16)1340 s = 16;1341 if((o % s) != 0)1342 return 0;1343 return o >= -256 && o < 4096*s;1344 }1346 long1347 exreg(Type *t)1348 {1349 long o;1351 if(typechlpv[t->etype]) {1352 if(exregoffset <= REGEXT-2)1353 return 0;1354 o = exregoffset;1355 if(reg[o] && !resvreg[o])1356 return 0;1357 resvreg[o] = reg[o] = 1;1358 exregoffset--;1359 return o;1360 }1361 if(typefd[t->etype]) {1362 if(exfregoffset <= NFREG-1)1363 return 0;1364 o = exfregoffset + NREG;1365 if(reg[o] && !resvreg[o])1366 return 0;1367 resvreg[o] = reg[o] = 1;1368 exfregoffset--;1369 return o;1370 }1371 return 0;1372 }1374 schar ewidth[NTYPE] =1375 {1376 -1, /* [TXXX] */1377 SZ_CHAR, /* [TCHAR] */1378 SZ_CHAR, /* [TUCHAR] */1379 SZ_SHORT, /* [TSHORT] */1380 SZ_SHORT, /* [TUSHORT] */1381 SZ_INT, /* [TINT] */1382 SZ_INT, /* [TUINT] */1383 SZ_LONG, /* [TLONG] */1384 SZ_LONG, /* [TULONG] */1385 SZ_VLONG, /* [TVLONG] */1386 SZ_VLONG, /* [TUVLONG] */1387 SZ_FLOAT, /* [TFLOAT] */1388 SZ_DOUBLE, /* [TDOUBLE] */1389 SZ_IND, /* [TIND] */1390 0, /* [TFUNC] */1391 -1, /* [TARRAY] */1392 0, /* [TVOID] */1393 -1, /* [TSTRUCT] */1394 -1, /* [TUNION] */1395 SZ_INT, /* [TENUM] */1396 };1398 long ncast[NTYPE] =1399 {1400 0, /* [TXXX] */1401 BCHAR|BUCHAR, /* [TCHAR] */1402 BCHAR|BUCHAR, /* [TUCHAR] */1403 BSHORT|BUSHORT, /* [TSHORT] */1404 BSHORT|BUSHORT, /* [TUSHORT] */1405 BINT|BUINT|BLONG|BULONG, /* [TINT] */1406 BINT|BUINT|BLONG|BULONG, /* [TUINT] */1407 BINT|BUINT|BLONG|BULONG, /* [TLONG] */1408 BINT|BUINT|BLONG|BULONG, /* [TULONG] */1409 BVLONG|BUVLONG|BIND, /* [TVLONG] */1410 BVLONG|BUVLONG|BIND, /* [TUVLONG] */1411 BFLOAT, /* [TFLOAT] */1412 BDOUBLE, /* [TDOUBLE] */1413 BVLONG|BUVLONG|BIND, /* [TIND] */1414 0, /* [TFUNC] */1415 0, /* [TARRAY] */1416 0, /* [TVOID] */1417 BSTRUCT, /* [TSTRUCT] */1418 BUNION, /* [TUNION] */1419 0, /* [TENUM] */1420 };