diff options
-rw-r--r-- | src/cmd/9g/opt.h | 10 | ||||
-rw-r--r-- | src/cmd/9g/prog.c | 162 |
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]; +} |