ref: d37701e87284d9c0258349c359a4dc275ee26a59
parent: 0c3e5940527272770e2f87127bf76b5dbae7a8bd
author: Jacob Moody <moody@posixcafe.org>
date: Sat Jun 1 13:53:20 EDT 2024
9[cl]: correct previous changes 1f83b100a345e2573db8173a16235d94ba4fc82c Was to adjust the compiler to better match the ISA w.r.t. subtraction, but was overzelous and rewrote all additions instead of just those with constants. 8f2658dda5cae63ee65c21b81cdad9f104c807b4 Intended to restrict compiler generated immediate operations to only those of which can be encodable by the ISA. However the check for signed constants was incorrect and resulted in constants that do not properly encode. 0ef486b8fa59bb0aa15d74fbe817c158cf844a41 Attempted to classify address literals to save on instruction encoding, but this is actually not possible. We have to walk the program first to derive some of the constants (INITDAT depends on etext) so we can not classify them here. Instead we should just limit address literals to 32 bits (with sign extension) as a worst case. It would be possible in the future to do a pass over to program later and find address literals that only need one instruction instead of two but this works for now.
--- a/sys/src/cmd/9c/cgen.c
+++ b/sys/src/cmd/9c/cgen.c
@@ -1,34 +1,25 @@
#include "gc.h"
-/*
- * POWER only gives us 16 bit immediates and shifted 16 bit immediate with optional sign extension
- */
-
static int
issim16(vlong v)
{
+ /* addi */
if((short)v == v)
return 1;
-
- 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;
+ /* addis */
+ if(v == (long)(v & 0xFFFF0000))
+ return 1;
+ return 0;
}
-
static int
-isuim16(vlong v)
+isuim16(uvlong v)
{
+ /* andi */
if((ushort)v == v)
return 1;
- if((v & 0xFFFFFFFFULL<<32) != 0)
- return 0;
- if((v & 0xFFFF) == 0)
+ /* andis */
+ if(v == (ulong)(v & 0xFFFF0000))
return 1;
return 0;
}
@@ -192,8 +183,11 @@
goto usereg;
case OSUB:
- r->vconst = -r->vconst;
- o = n->op = OADD;
+ if(r->op == OCONST)
+ if(!typefd[n->type->etype]) {
+ r->vconst = -r->vconst;
+ o = n->op = OADD;
+ }
case OADD:
/*
@@ -274,8 +268,11 @@
goto useregas;
case OASSUB:
- r->vconst = -r->vconst;
- o = n->op = OASADD;
+ if(r->op == OCONST)
+ if(!typefd[n->type->etype]) {
+ r->vconst = -r->vconst;
+ o = n->op = OADD;
+ }
case OASADD:
if(l->op == OBIT)
--- a/sys/src/cmd/9l/span.c
+++ b/sys/src/cmd/9l/span.c
@@ -307,7 +307,7 @@
}
if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) {
instoffset = s->value + a->offset;
- goto consize;
+ return C_LCON;
}
if(s->type == SCONST) {
instoffset = s->value + a->offset;
@@ -321,9 +321,7 @@
return C_SECON;
}
instoffset = s->value + a->offset + INITDAT;
- if(dlm)
- return C_LCON;
- goto consize;
+ return C_LCON;
case D_AUTO:
instoffset = autosize + a->offset;
--
⑨