summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/9g/opt.h10
-rw-r--r--src/cmd/9g/prog.c162
2 files changed, 172 insertions, 0 deletions
diff --git a/src/cmd/9g/opt.h b/src/cmd/9g/opt.h
index 7f15b5a69..6a07b268f 100644
--- a/src/cmd/9g/opt.h
+++ b/src/cmd/9g/opt.h
@@ -225,6 +225,16 @@ enum
void proginfo(ProgInfo*, Prog*);
+// Many Power ISA arithmetic and logical instructions come in four
+// standard variants. These bits let us map between variants.
+enum {
+ V_CC = 1<<0, // xCC (affect CR field 0 flags)
+ V_V = 1<<1, // xV (affect SO and OV flags)
+};
+
+int as2variant(int);
+int variant2as(int, int);
+
// To allow use of AJMP, ACALL, ARET in ../gc/popt.c.
enum
{
diff --git a/src/cmd/9g/prog.c b/src/cmd/9g/prog.c
index 51c132d18..7c0f0c795 100644
--- a/src/cmd/9g/prog.c
+++ b/src/cmd/9g/prog.c
@@ -101,9 +101,36 @@ static ProgInfo progtable[ALAST] = {
[ADUFFCOPY]= {Call},
};
+static void
+initproginfo(void)
+{
+ static int initialized;
+ int addvariant[] = {V_CC, V_V, V_CC|V_V};
+ int as, as2, i, variant;
+
+ if(initialized)
+ return;
+ initialized = 1;
+
+ // Perform one-time expansion of instructions in progtable to
+ // their CC, V, and VCC variants
+ for(as=0; as<nelem(progtable); as++) {
+ if(progtable[as].flags == 0)
+ continue;
+ variant = as2variant(as);
+ for(i=0; i<nelem(addvariant); i++) {
+ as2 = variant2as(as, variant | addvariant[i]);
+ if(as2 != 0 && progtable[as2].flags == 0)
+ progtable[as2] = progtable[as];
+ }
+ }
+}
+
void
proginfo(ProgInfo *info, Prog *p)
{
+ initproginfo();
+
*info = progtable[p->as];
if(info->flags == 0) {
*info = progtable[AADD];
@@ -143,3 +170,138 @@ proginfo(ProgInfo *info, Prog *p)
info->regset |= RtoB(3) | RtoB(4);
}
}
+
+// Instruction variants table. Initially this contains entries only
+// for the "base" form of each instruction. On the first call to
+// as2variant or variant2as, we'll add the variants to the table.
+static int varianttable[ALAST][4] = {
+ [AADD]= {AADD, AADDCC, AADDV, AADDVCC},
+ [AADDC]= {AADDC, AADDCCC, AADDCV, AADDCVCC},
+ [AADDE]= {AADDE, AADDECC, AADDEV, AADDEVCC},
+ [AADDME]= {AADDME, AADDMECC, AADDMEV, AADDMEVCC},
+ [AADDZE]= {AADDZE, AADDZECC, AADDZEV, AADDZEVCC},
+ [AAND]= {AAND, AANDCC, 0, 0},
+ [AANDN]= {AANDN, AANDNCC, 0, 0},
+ [ACNTLZD]= {ACNTLZD, ACNTLZDCC, 0, 0},
+ [ACNTLZW]= {ACNTLZW, ACNTLZWCC, 0, 0},
+ [ADIVD]= {ADIVD, ADIVDCC, ADIVDV, ADIVDVCC},
+ [ADIVDU]= {ADIVDU, ADIVDUCC, ADIVDUV, ADIVDUVCC},
+ [ADIVW]= {ADIVW, ADIVWCC, ADIVWV, ADIVWVCC},
+ [ADIVWU]= {ADIVWU, ADIVWUCC, ADIVWUV, ADIVWUVCC},
+ [AEQV]= {AEQV, AEQVCC, 0, 0},
+ [AEXTSB]= {AEXTSB, AEXTSBCC, 0, 0},
+ [AEXTSH]= {AEXTSH, AEXTSHCC, 0, 0},
+ [AEXTSW]= {AEXTSW, AEXTSWCC, 0, 0},
+ [AFABS]= {AFABS, AFABSCC, 0, 0},
+ [AFADD]= {AFADD, AFADDCC, 0, 0},
+ [AFADDS]= {AFADDS, AFADDSCC, 0, 0},
+ [AFCFID]= {AFCFID, AFCFIDCC, 0, 0},
+ [AFCTID]= {AFCTID, AFCTIDCC, 0, 0},
+ [AFCTIDZ]= {AFCTIDZ, AFCTIDZCC, 0, 0},
+ [AFCTIW]= {AFCTIW, AFCTIWCC, 0, 0},
+ [AFCTIWZ]= {AFCTIWZ, AFCTIWZCC, 0, 0},
+ [AFDIV]= {AFDIV, AFDIVCC, 0, 0},
+ [AFDIVS]= {AFDIVS, AFDIVSCC, 0, 0},
+ [AFMADD]= {AFMADD, AFMADDCC, 0, 0},
+ [AFMADDS]= {AFMADDS, AFMADDSCC, 0, 0},
+ [AFMOVD]= {AFMOVD, AFMOVDCC, 0, 0},
+ [AFMSUB]= {AFMSUB, AFMSUBCC, 0, 0},
+ [AFMSUBS]= {AFMSUBS, AFMSUBSCC, 0, 0},
+ [AFMUL]= {AFMUL, AFMULCC, 0, 0},
+ [AFMULS]= {AFMULS, AFMULSCC, 0, 0},
+ [AFNABS]= {AFNABS, AFNABSCC, 0, 0},
+ [AFNEG]= {AFNEG, AFNEGCC, 0, 0},
+ [AFNMADD]= {AFNMADD, AFNMADDCC, 0, 0},
+ [AFNMADDS]= {AFNMADDS, AFNMADDSCC, 0, 0},
+ [AFNMSUB]= {AFNMSUB, AFNMSUBCC, 0, 0},
+ [AFNMSUBS]= {AFNMSUBS, AFNMSUBSCC, 0, 0},
+ [AFRES]= {AFRES, AFRESCC, 0, 0},
+ [AFRSP]= {AFRSP, AFRSPCC, 0, 0},
+ [AFRSQRTE]= {AFRSQRTE, AFRSQRTECC, 0, 0},
+ [AFSEL]= {AFSEL, AFSELCC, 0, 0},
+ [AFSQRT]= {AFSQRT, AFSQRTCC, 0, 0},
+ [AFSQRTS]= {AFSQRTS, AFSQRTSCC, 0, 0},
+ [AFSUB]= {AFSUB, AFSUBCC, 0, 0},
+ [AFSUBS]= {AFSUBS, AFSUBSCC, 0, 0},
+ [AMTFSB0]= {AMTFSB0, AMTFSB0CC, 0, 0},
+ [AMTFSB1]= {AMTFSB1, AMTFSB1CC, 0, 0},
+ [AMULHD]= {AMULHD, AMULHDCC, 0, 0},
+ [AMULHDU]= {AMULHDU, AMULHDUCC, 0, 0},
+ [AMULHW]= {AMULHW, AMULHWCC, 0, 0},
+ [AMULHWU]= {AMULHWU, AMULHWUCC, 0, 0},
+ [AMULLD]= {AMULLD, AMULLDCC, AMULLDV, AMULLDVCC},
+ [AMULLW]= {AMULLW, AMULLWCC, AMULLWV, AMULLWVCC},
+ [ANAND]= {ANAND, ANANDCC, 0, 0},
+ [ANEG]= {ANEG, ANEGCC, ANEGV, ANEGVCC},
+ [ANOR]= {ANOR, ANORCC, 0, 0},
+ [AOR]= {AOR, AORCC, 0, 0},
+ [AORN]= {AORN, AORNCC, 0, 0},
+ [AREM]= {AREM, AREMCC, AREMV, AREMVCC},
+ [AREMD]= {AREMD, AREMDCC, AREMDV, AREMDVCC},
+ [AREMDU]= {AREMDU, AREMDUCC, AREMDUV, AREMDUVCC},
+ [AREMU]= {AREMU, AREMUCC, AREMUV, AREMUVCC},
+ [ARLDC]= {ARLDC, ARLDCCC, 0, 0},
+ [ARLDCL]= {ARLDCL, ARLDCLCC, 0, 0},
+ [ARLDCR]= {ARLDCR, ARLDCRCC, 0, 0},
+ [ARLDMI]= {ARLDMI, ARLDMICC, 0, 0},
+ [ARLWMI]= {ARLWMI, ARLWMICC, 0, 0},
+ [ARLWNM]= {ARLWNM, ARLWNMCC, 0, 0},
+ [ASLD]= {ASLD, ASLDCC, 0, 0},
+ [ASLW]= {ASLW, ASLWCC, 0, 0},
+ [ASRAD]= {ASRAD, ASRADCC, 0, 0},
+ [ASRAW]= {ASRAW, ASRAWCC, 0, 0},
+ [ASRD]= {ASRD, ASRDCC, 0, 0},
+ [ASRW]= {ASRW, ASRWCC, 0, 0},
+ [ASUB]= {ASUB, ASUBCC, ASUBV, ASUBVCC},
+ [ASUBC]= {ASUBC, ASUBCCC, ASUBCV, ASUBCVCC},
+ [ASUBE]= {ASUBE, ASUBECC, ASUBEV, ASUBEVCC},
+ [ASUBME]= {ASUBME, ASUBMECC, ASUBMEV, ASUBMEVCC},
+ [ASUBZE]= {ASUBZE, ASUBZECC, ASUBZEV, ASUBZEVCC},
+ [AXOR]= {AXOR, AXORCC, 0, 0},
+};
+
+static void
+initvariants(void)
+{
+ static int initialized;
+ int i, j;
+
+ if(initialized)
+ return;
+ initialized = 1;
+
+ for(i=0; i<nelem(varianttable); i++) {
+ if(varianttable[i][0] == 0) {
+ // Instruction has no variants
+ varianttable[i][0] = i;
+ continue;
+ }
+ // Copy base form to other variants
+ if(varianttable[i][0] == i) {
+ for(j=0; j<nelem(varianttable[i]); j++)
+ memmove(&varianttable[varianttable[i][j]], &varianttable[i], sizeof(varianttable[i]));
+ }
+ }
+}
+
+// as2variant returns the variant (V_*) flags of instruction as.
+int
+as2variant(int as)
+{
+ int i;
+ initvariants();
+ for(i=0; i<nelem(varianttable[as]); i++)
+ if(varianttable[as][i] == as)
+ return i;
+ fatal("as2variant: instruction %A is not a variant of itself", as);
+ return 0;
+}
+
+// variant2as returns the instruction as with the given variant (V_*) flags.
+// If no such variant exists, this returns 0.
+int
+variant2as(int as, int flags)
+{
+ initvariants();
+ return varianttable[as][flags];
+}