diff options
Diffstat (limited to 'src/liblink/asm9.c')
| -rw-r--r-- | src/liblink/asm9.c | 226 |
1 files changed, 146 insertions, 80 deletions
diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 64fc651207..f604395a7a 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -454,7 +454,7 @@ static int isint32(vlong); static int isuint32(uvlong); static int aclass(Link*, Addr*); static Optab* oplook(Link*, Prog*); -static void asmout(Link*, Prog*, Optab*, int32*); +static void asmout(Link*, Prog*, Optab*, uint32*); static vlong vregoff(Link*, Addr*); static int32 regoff(Link*, Addr*); static int32 oprrr(Link*, int); @@ -468,13 +468,16 @@ static void maskgen(Link*, Prog*, uchar*, uint32); static int getmask64(uchar*, uvlong); static void maskgen64(Link*, Prog*, uchar*, uvlong); static uint32 loadu32(int, vlong); -static void addaddrreloc(Link*, LSym*, int*, int*); +static void addaddrreloc(Link*, LSym*, uint32*, uint32*); -static struct +typedef struct Oprang Oprang; +struct Oprang { Optab* start; Optab* stop; -} oprange[ALAST]; +}; + +static Oprang oprange[ALAST]; static uchar xcmp[C_NCLASS][C_NCLASS]; @@ -486,7 +489,8 @@ span9(Link *ctxt, LSym *cursym) Optab *o; int m, bflag; vlong c, otxt; - int32 out[6], i, j; + uint32 out[6]; + int32 i, j; uchar *bp, *cast; p = cursym->text; @@ -687,27 +691,7 @@ aclass(Link *ctxt, Addr *a) return C_LACON; return C_DACON; } - consize: - if(ctxt->instoffset >= 0) { - if(ctxt->instoffset == 0) - return C_ZCON; - if(ctxt->instoffset <= 0x7fff) - return C_SCON; - if(ctxt->instoffset <= 0xffff) - return C_ANDCON; - if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset)) /* && (instoffset & (1<<31)) == 0) */ - return C_UCON; - if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset)) - return C_LCON; - return C_DCON; - } - if(ctxt->instoffset >= -0x8000) - return C_ADDCON; - if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset)) - return C_UCON; - if(isint32(ctxt->instoffset)) - return C_LCON; - return C_DCON; + goto consize; case D_EXTERN: case D_STATIC: @@ -736,6 +720,28 @@ aclass(Link *ctxt, Addr *a) } return C_GOK; + consize: + if(ctxt->instoffset >= 0) { + if(ctxt->instoffset == 0) + return C_ZCON; + if(ctxt->instoffset <= 0x7fff) + return C_SCON; + if(ctxt->instoffset <= 0xffff) + return C_ANDCON; + if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset)) /* && (instoffset & (1<<31)) == 0) */ + return C_UCON; + if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset)) + return C_LCON; + return C_DCON; + } + if(ctxt->instoffset >= -0x8000) + return C_ADDCON; + if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset)) + return C_UCON; + if(isint32(ctxt->instoffset)) + return C_LCON; + return C_DCON; + case D_BRANCH: return C_SBRA; } @@ -1271,61 +1277,120 @@ buildop(Link *ctxt) } } -#define OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1)) -#define OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc)) -#define OP(o,xo) OPVCC((o),(xo),0,0) +uint32 +OPVCC(uint32 o, uint32 xo, uint32 oe, uint32 rc) +{ + return o<<26 | xo<<1 | oe<<10 | rc&1; +} + +uint32 +OPCC(uint32 o, uint32 xo, uint32 rc) +{ + return OPVCC(o, xo, 0, rc); +} + +uint32 +OP(uint32 o, uint32 xo) +{ + return OPVCC(o, xo, 0, 0); +} /* the order is dest, a/s, b/imm for both arithmetic and logical operations */ -#define AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11)) -#define AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF)) -#define LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11)) -#define LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF)) -#define OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1)) -#define OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1)) -#define OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)) -#define OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\ - (((mb)&31L)<<6)|(((me)&31L)<<1)) +uint32 +AOP_RRR(uint32 op, uint32 d, uint32 a, uint32 b) +{ + return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11; +} + +uint32 +AOP_IRR(uint32 op, uint32 d, uint32 a, uint32 simm) +{ + return op | (d&31)<<21 | (a&31)<<16 | (simm&0xFFFF); +} + +uint32 +LOP_RRR(uint32 op, uint32 a, uint32 s, uint32 b) +{ + return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11; +} + +uint32 +LOP_IRR(uint32 op, uint32 a, uint32 s, uint32 uimm) +{ + return op | (s&31)<<21 | (a&31)<<16 | (uimm&0xFFFF); +} + +uint32 +OP_BR(uint32 op, uint32 li, uint32 aa) +{ + return op | li&0x03FFFFFC | aa<<1; +} + +uint32 +OP_BC(uint32 op, uint32 bo, uint32 bi, uint32 bd, uint32 aa) +{ + return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 | bd&0xFFFC | aa<<1; +} + +uint32 +OP_BCR(uint32 op, uint32 bo, uint32 bi) +{ + return op | (bo&0x1F)<<21 | (bi&0x1F)<<16; +} + +uint32 +OP_RLW(uint32 op, uint32 a, uint32 s, uint32 sh, uint32 mb, uint32 me) +{ + return op | (s&31)<<21 | (a&31)<<16 | (sh&31)<<11 | (mb&31)<<6 | (me&31)<<1; +} -#define OP_ADD OPVCC(31,266,0,0) -#define OP_ADDI OPVCC(14,0,0,0) -#define OP_ADDIS OPVCC(15,0,0,0) -#define OP_ANDI OPVCC(28,0,0,0) -#define OP_EXTSB OPVCC(31,954,0,0) -#define OP_EXTSH OPVCC(31,922,0,0) -#define OP_EXTSW OPVCC(31,986,0,0) -#define OP_MCRF OPVCC(19,0,0,0) -#define OP_MCRFS OPVCC(63,64,0,0) -#define OP_MCRXR OPVCC(31,512,0,0) -#define OP_MFCR OPVCC(31,19,0,0) -#define OP_MFFS OPVCC(63,583,0,0) -#define OP_MFMSR OPVCC(31,83,0,0) -#define OP_MFSPR OPVCC(31,339,0,0) -#define OP_MFSR OPVCC(31,595,0,0) -#define OP_MFSRIN OPVCC(31,659,0,0) -#define OP_MTCRF OPVCC(31,144,0,0) -#define OP_MTFSF OPVCC(63,711,0,0) -#define OP_MTFSFI OPVCC(63,134,0,0) -#define OP_MTMSR OPVCC(31,146,0,0) -#define OP_MTMSRD OPVCC(31,178,0,0) -#define OP_MTSPR OPVCC(31,467,0,0) -#define OP_MTSR OPVCC(31,210,0,0) -#define OP_MTSRIN OPVCC(31,242,0,0) -#define OP_MULLW OPVCC(31,235,0,0) -#define OP_MULLD OPVCC(31,233,0,0) -#define OP_OR OPVCC(31,444,0,0) -#define OP_ORI OPVCC(24,0,0,0) -#define OP_ORIS OPVCC(25,0,0,0) -#define OP_RLWINM OPVCC(21,0,0,0) -#define OP_SUBF OPVCC(31,40,0,0) -#define OP_RLDIC OPVCC(30,4,0,0) -#define OP_RLDICR OPVCC(30,2,0,0) -#define OP_RLDICL OPVCC(30,0,0,0) +enum { + /* each rhs is OPVCC(_, _, _, _) */ + OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0, + OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0, + OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0, + OP_ANDI = 28<<26 | 0<<1 | 0<<10 | 0, + OP_EXTSB = 31<<26 | 954<<1 | 0<<10 | 0, + OP_EXTSH = 31<<26 | 922<<1 | 0<<10 | 0, + OP_EXTSW = 31<<26 | 986<<1 | 0<<10 | 0, + OP_MCRF = 19<<26 | 0<<1 | 0<<10 | 0, + OP_MCRFS = 63<<26 | 64<<1 | 0<<10 | 0, + OP_MCRXR = 31<<26 | 512<<1 | 0<<10 | 0, + OP_MFCR = 31<<26 | 19<<1 | 0<<10 | 0, + OP_MFFS = 63<<26 | 583<<1 | 0<<10 | 0, + OP_MFMSR = 31<<26 | 83<<1 | 0<<10 | 0, + OP_MFSPR = 31<<26 | 339<<1 | 0<<10 | 0, + OP_MFSR = 31<<26 | 595<<1 | 0<<10 | 0, + OP_MFSRIN = 31<<26 | 659<<1 | 0<<10 | 0, + OP_MTCRF = 31<<26 | 144<<1 | 0<<10 | 0, + OP_MTFSF = 63<<26 | 711<<1 | 0<<10 | 0, + OP_MTFSFI = 63<<26 | 134<<1 | 0<<10 | 0, + OP_MTMSR = 31<<26 | 146<<1 | 0<<10 | 0, + OP_MTMSRD = 31<<26 | 178<<1 | 0<<10 | 0, + OP_MTSPR = 31<<26 | 467<<1 | 0<<10 | 0, + OP_MTSR = 31<<26 | 210<<1 | 0<<10 | 0, + OP_MTSRIN = 31<<26 | 242<<1 | 0<<10 | 0, + OP_MULLW = 31<<26 | 235<<1 | 0<<10 | 0, + OP_MULLD = 31<<26 | 233<<1 | 0<<10 | 0, + OP_OR = 31<<26 | 444<<1 | 0<<10 | 0, + OP_ORI = 24<<26 | 0<<1 | 0<<10 | 0, + OP_ORIS = 25<<26 | 0<<1 | 0<<10 | 0, + OP_RLWINM = 21<<26 | 0<<1 | 0<<10 | 0, + OP_SUBF = 31<<26 | 40<<1 | 0<<10 | 0, + OP_RLDIC = 30<<26 | 4<<1 | 0<<10 | 0, + OP_RLDICR = 30<<26 | 2<<1 | 0<<10 | 0, + OP_RLDICL = 30<<26 | 0<<1 | 0<<10 | 0, +}; -#define oclass(v) ((v).class-1) +int +oclass(Addr *a) +{ + return a->class - 1; +} // add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2. static void -addaddrreloc(Link *ctxt, LSym *s, int *o1, int *o2) +addaddrreloc(Link *ctxt, LSym *s, uint32 *o1, uint32 *o2) { Reloc *rel; @@ -1346,7 +1411,7 @@ getmask(uchar *m, uint32 v) int i; m[0] = m[1] = 0; - if(v != ~0U && v & (1<<31) && v & 1){ /* MB > ME */ + if(v != ~(uint32)0 && v & (1<<31) && v & 1){ /* MB > ME */ if(getmask(m, ~v)){ i = m[0]; m[0] = m[1]+1; m[1] = i-1; return 1; @@ -1424,9 +1489,10 @@ high16adjusted(int32 d) } static void -asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) +asmout(Link *ctxt, Prog *p, Optab *o, uint32 *out) { - int32 o1, o2, o3, o4, o5, v, t; + uint32 o1, o2, o3, o4, o5; + int32 v, t; vlong d; int r, a; uchar mask[2]; @@ -1694,7 +1760,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) r = p->reg; if(r == NREG) r = 0; - switch(oclass(p->to)) { + switch(oclass(&p->to)) { case C_CTR: o1 = OPVCC(19, 528, 0, 0); break; @@ -1902,7 +1968,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) case 33: /* fabs [frb,]frd; fmr. frb,frd */ r = p->from.reg; - if(oclass(p->from) == C_NONE) + if(oclass(&p->from) == C_NONE) r = p->to.reg; o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, r); break; @@ -2034,7 +2100,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) break; case 54: /* mov msr,r1; mov r1, msr*/ - if(oclass(p->from) == C_REG){ + if(oclass(&p->from) == C_REG){ if(p->as == AMOVD) o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0); else |
