ref: 4e4bd869e97fecee8921ecd8d135de061e73f372
parent: 01e7d784df2e35dc030b8435654d1454687371e5
author: Jacob Moody <moody@posixcafe.org>
date: Sat Jun 1 13:53:20 EDT 2024
9[cl]: correct previous changes 37e65b331bdf98f409be1bd2fbb55aec158c7877 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. 539013042677ddd193cf6c37a53e4f64ed33649a 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. 0c6fd079ce51181e32e6625fdc85d07567991f37 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;