ref: 539013042677ddd193cf6c37a53e4f64ed33649a
parent: 8483799d4a0f80e38edfb83f1772af840cafe637
author: Jacob Moody <moody@posixcafe.org>
date: Sat Apr 6 18:13:54 EDT 2024
9c: avoid generating immediates that make the linker use REGTMP
--- a/sys/src/cmd/9c/cgen.c
+++ b/sys/src/cmd/9c/cgen.c
@@ -1,13 +1,36 @@
#include "gc.h"
+/*
+ * POWER only gives us 16 bit immediates and shifted 16 bit immediate with optional sign extension
+ */
+
static int
-isim32(vlong v)
+issim16(vlong v)
{
- if((v & 0xffffffff80000000) == 0xffffffff80000000) // 32-bit negative
+ if((short)v == v)
return 1;
- if((v & 0xffffffff00000000) == 0) // 32-bit positive
+
+ if(v < 0 && (v & 0xFFFFFFFFULL<<32) != 0xFFFFFFFFULL<<32)
+ return 0;
+ else if((v & 0xFFFFFFFFULL<<32) != 0)
+ return 0;
+
+ if((v & 0xFFFF) != 0)
+ return 0;
+ return 1;
+}
+
+
+static int
+isuim16(vlong v)
+{
+ if((ushort)v == v)
return 1;
- return 0;
+ if((v & 0xFFFFFFFFULL<<32) != 0)
+ return 0;
+ if((v & 0xFFFF) == 0)
+ return 1;
+ return 0;
}
void
@@ -147,8 +170,6 @@
break;
}
- case OADD:
- case OSUB:
case OAND:
case OOR:
case OLSHR:
@@ -155,10 +176,10 @@
case OASHL:
case OASHR:
/*
- * immediate operands
+ * unsigned immediate operands
*/
if(nn != Z)
- if(r->op == OCONST && isim32(r->vconst))
+ if(r->op == OCONST && isuim16(r->vconst))
if(!typefd[n->type->etype]) {
cgen(l, nn);
if(r->vconst == 0)
@@ -168,7 +189,25 @@
gopcode(o, r, Z, nn);
break;
}
+ goto usereg;
+ case OADD:
+ case OSUB:
+ /*
+ * signed immediate operands
+ */
+ if(nn != Z)
+ if(r->op == OCONST && issim16(r->vconst))
+ if(!typefd[n->type->etype]) {
+ cgen(l, nn);
+ if(r->vconst == 0)
+ if(o != OAND)
+ break;
+ if(nn != Z)
+ gopcode(o, r, Z, nn);
+ break;
+ }
+
case OMUL:
case OLMUL:
case OLDIV:
@@ -175,6 +214,7 @@
case OLMOD:
case ODIV:
case OMOD:
+ usereg:
if(nn == Z) {
nullwarn(l, r);
break;
@@ -207,13 +247,11 @@
case OASASHL:
case OASASHR:
case OASAND:
- case OASADD:
- case OASSUB:
case OASXOR:
case OASOR:
if(l->op == OBIT)
goto asbitop;
- if(r->op == OCONST && isim32(r->vconst))
+ if(r->op == OCONST && isuim16(r->vconst))
if(!typefd[r->type->etype])
if(!typefd[n->type->etype]) {
if(l->addable < INDEXED)
@@ -230,7 +268,30 @@
regfree(&nod2);
break;
}
+ goto useregas;
+ case OASADD:
+ case OASSUB:
+ if(l->op == OBIT)
+ goto asbitop;
+ if(r->op == OCONST && issim16(r->vconst))
+ if(!typefd[r->type->etype])
+ if(!typefd[n->type->etype]) {
+ if(l->addable < INDEXED)
+ reglcgen(&nod2, l, Z);
+ else
+ nod2 = *l;
+ regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */
+ gopcode(OAS, &nod2, Z, &nod);
+ gopcode(o, r, Z, &nod);
+ gopcode(OAS, &nod, Z, &nod2);
+
+ regfree(&nod);
+ if(l->addable < INDEXED)
+ regfree(&nod2);
+ break;
+ }
+
case OASLMUL:
case OASLDIV:
case OASLMOD:
@@ -237,6 +298,7 @@
case OASMUL:
case OASDIV:
case OASMOD:
+ useregas:
if(l->op == OBIT)
goto asbitop;
if(l->complex >= r->complex) {