/* EPC Imp to C Translation Release 4 Version Apr 95 */ #include "imptoc.h" /** p5code05.6*/ /** 18Jly97 - Correction to adapt instructing (f90 bug from AK) */ /** also handling of i*8 litvals in oprx */ /** p5code05.5*/ /** 10Jly97 - Changes for Volatile swopped varaibles for Bloomberg */ /** p5code05.3*/ /** 25May97 - Additions to accessop to handle misaligned ints (32 & 64) */ /** 23Apr97 - Extra entries to accessop to handle 64 bit integers */ /** p5code05.2 */ /** 02Apr97 - Improvements to adapt instr */ /** p5code05.1*/ /** 29Jly96 - More care in p5 OpRX to leave original Stk record alone */ /** p5code05*/ /** 22Feb96 - Revised to use Beta registers to Model most occurrences of */ /** AGI by reading the Beta version of the register when used */ /** as a base or index(pds) */ /** Reactivated the use of Cmval in Modified Operands */ /** When TargetVariant#0 avoid partial register operns */ /** since these are very slow on P^ */ /** p5code04.3*/ /** 24Nov95 - Revised to cope with movb and cmp instructions other than */ /** as degenerate cases of cmp and mov(pds) */ /** Also correction to p5 ldfix no offsets in gotloads */ /** p5code04.2*/ /** 08Aug95 - Revised to allow quad loads & stores */ /** p5code04.1*/ /** 1Aug95 - Revisted PIC code production after problems om DGUX */ /** p5code04.i*/ /** 15June95 - Extensive changes towards handling byteswopped data */ /** p5code03.1*/ /** 31May95 - Changed to use _intvalue in estk format */ /** p5code03*/ /** 30Jun94 - Changes to restrict fast PIC method to internal area to */ /** allow for common areas in a.outs referenced from .so */ /** p5code02*/ /** 25Mar94 - Changes for new GIS bprocs(pds) */ /** p5code01 */ /** 18/10/93 - initial version */ /***/ /**************************************************************************/ /** **/ /** Module Imports **/ /** **/ /**************************************************************************/ /***/ #define MODULENAME ("code") /***/ #include "cgtarget.h" /***/ #include "cgconsts.h" /***/ #include "boconsts.h" /***/ #include "archdefs.h" /***/ /**************************************************************************/ /** **/ /** External Definitions **/ /** **/ /**************************************************************************/ /***/ #include "prototypes.h" extern int RegClaimMaskA; extern int RegClaimMaskB; extern int JumpPredictFlag; extern int Report; extern int localca; extern int cgoptions; extern int Pic; /***/ extern unsigned char paramSTflags [(((unsigned)Regparamsize>>2)-1)+1]; extern unsigned char StackSTflags [256+1]; extern int GOTareaid; /***/ /**************************************************************************/ /** **/ /** Global Definitions **/ /** **/ /**************************************************************************/ /***/ extern int currentFSP; /* Current top of FST 7-0 */ extern int currentPIaddr; #define GENGLAINDFIXUPS 0 /* generate fixups using GLA locations */ #define increports 1 /* to conditionally compile out disas */ #define STACKBASEOFFSET 0 /**/ static const unsigned char accessop [(17*17)-1+1] = { /*size 0*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 1*/ 0,LB,0,LBU,0,0,0,LB,LBU,SB,0,SB,0,0,0,SB,SB, /*size 2*/ 0,LH,0,LHU,0,0,0,LH,LHU,SH,0,SH,0,0,0,SH,SH, /*size 3*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 4*/ 0,LW,FLDm,LW,0,FLDm,0,LW,0,ST,FSTPm,ST,0,FSTPm,0,ST,0, /*size 5*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 6*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 7*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 8*/ 0,FILDd,FLDd,0,0,FLDd, 0,FILDd,0,FISTPd, FSTPd,0,0,FSTPd,0,FISTPd,0, /*size 10*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 11*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 9*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 12*/0,0,FLDq,0,0,FLDq, 0,0,0,0, FSTPq,0,0,FSTPq,0,0,0, /*size 13*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 14*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 15*/ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,0, /*size 16*/0,0,FLDq,0,0,FLDq, 0,0,0,0, FSTPq,0,0,FSTPq,0,0,0}; /***/ static struct instrfmt *instr; static struct instrfmt *previnstr; struct reckeyfmt{ int key; int offset; int adj; }; struct areakeysegfmt{ struct reckeyfmt reckeys [254+1]; int backchain; }; #if (GENGLAINDFIXUPS!=0) static struct areakeysegfmt *AreaKey; #endif #define sizeofareaseg 3072 /***/ int Maxareakey=-1; /* For repository is reset from Mprocs16 & later */ static int Fstlvolswop; static int Fstlswop; static int Fldlvolswop; static int /* ID for support RTs */ Fldlswop; static char fstdvolname [16]="_f_stdvolswop"; static char fstlname [12]="_f_stdswop"; static char flddvolname [16]="_f_lddvolswop"; static char fldlname [12]="_f_lddswop"; #define NORMALFIX 0 #define GOTRELFIX 7 #define Low16fix 9 #define dcallfix 3 #define idcallfix 5 #define GOTfix 6 #define GOTofffix 4 #define NOREG 0 /* Memory only instruction*/ #define DESTREG 1 /* Memory => reg instr */ #define DESTSTORE 2 /* Reg => store instrn */ #define SOURCELIT 3 /* Lit => Store Lit is in reg */ static int inhibitdis=0; #if(TargetEndian==BIG) #define Realoffset1 4 #define Realoffset2 0 #else #define Realoffset1 0 #define Realoffset2 4 #endif; /***/ /**************************************************************************/ /** **/ /** Peephole Support Procedures - Local Specifications **/ /** **/ /**************************************************************************/ /***/ int p5tempspace( int ,int ); void p5call( int ,int ,int ); void p5loadri( int ,int ,int ,int ); void p5floadri( int ,int ,int ,int ); void p5oplit( int ,int ,int ,int ); int AreaKeyRef( int ,int ); void p5accessindri( int ,int ,int ,int ,int ,int ); static void p5privateaccess( int ,int ,int ,int ,int ,int ,int ,int ); /***/ /**************************************************************************/ /***/ /***/ /**************************************************************************/ /** **/ /** instruction formulation procedures **/ /** **/ /**************************************************************************/ /***/ /***/ int p5opcodesize(int op,int variant) { /*************************************************************************/ /** Evaluates the size of the opcode for the relevant variant **/ /*************************************************************************/ int opcode,valbits; struct instrvariants *ivar; ivar=(struct instrvariants*)(&instrops [op*instrvarels]); valbits=ivar->valid; switch (variant) { case OPONLY: case FOPONLY: if ((valbits&oponlyval)!=0) { opcode=ivar->u0.onlyop; goto common; } else Mabort(999); case OPPLUSR: case OPPLUSRLIT: case FOPPLUSR: if ((valbits&opplusregval)!=0) { opcode=ivar->opplusreg; goto common; } else Mabort(999); case OPRR: case OPRRM: if ((valbits&oprrmval)!=0) { opcode=ivar->u0.oprrm; goto common; } else Mabort(999); case OPRSLIT: if ((valbits&oprmslitval)!=0) { opcode=ivar->oprmslit; goto common; } else Mabort(999); case OPRLIT: case OPMEMLIT: if ((valbits&oprmlitval)!=0) { opcode=ivar->oprmlit; goto common; } else Mabort(999); case OPMEM: case FOPRM: case OPR: if ((valbits&oprmval)!=0) { opcode=ivar->oprm; goto common; } else Mabort(999); case OPRMR: if ((valbits&oprmrval)!=0) { opcode=ivar->oprmr; goto common; } else Mabort(999); case OPALLIT: if ((valbits&opallitval)!=0) { opcode=ivar->allit; goto common; } else Mabort(999); case OPBRMLIT: if ((valbits&opbrlitval)!=0) { opcode=ivar->opbrmlit; goto common; } else Mabort(999); case OPEAXLIT: if ((valbits&opeaxlitval)!=0) { opcode=ivar->eaxlit; goto common; } else Mabort(999); case OPPCREL: if ((valbits&oppcrelval)!=0) { opcode=ivar->oppcrel; goto common; } else Mabort(999); case OPBMEMLIT: if ((valbits&opbrmlitval)!=0) { opcode=ivar->other; goto common; } else Mabort(999); common: if ((0<=opcode)&&(opcode<=255)) return 1; return 2; default: Mabort(998); return -1; } } /* p5 opcode size*/ /***/ static void p5sideeffects(int opcode) { /*************************************************************************/ /** Update current instr for any effects on flags regs etc **/ /*************************************************************************/ int e; e=instrsideeffects [opcode]; if (e==0) return ; if ((e&1)!=0) instr->cref|=(1<cdef|=(1<cref|=(1<cdef|=(1<cref|=(1<cdef|=(1<cdef|=((1<cdef|=(1<fdef=255; } if ((instrgroup [opcode]==SHIFTS)&&(instrform [opcode]!=SLITFORM)) { instr->rref|=(1<area=newarea; instr->u0.offset=newoffset; } /***/ void p5modinstrprops(int rem,int add,int prem,int padd) { instr->props=(instr->props&(~rem))|add; instr->privprops=(instr->privprops&(~prem))|padd; } /***/ void p5addprefix(int which,int prefixvalue) { if (instr->u2.prefixes [which]!=0) Mabort(989); instr->u2.prefixes [which]=prefixvalue; instr->csize++; if (which==iprefix) /* All repeat type prefixes alter ECX */{ instr->rref|=(1<rdef|=(257<opcode=NOP; instr->group=instrgroup [NOP]; instr->csize=1; instr->props=DESTROYABLE; if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /***/ void p5rr(int op,int rs1,int rs2,int rd) { /*************************************************************************/ /** On P5 rd is rs2 but do not shrink params or eprocs*mprocs need **/ /** a lot more conditional code **/ /*************************************************************************/ if (!((rd==rs2)||(rs2<0))) { p5rr(MOV,rs2,rd,rd); /* Simulate 3 address form by MOV */ p5rr(op,rs1,rd,rd); /* followed by 2 address form */ return ; } previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rs1=rs1; instr->rd=rd; instr->group=instrgroup [op]; instr->props=DESTROYABLE; instr->csize=p5opcodesize(op,OPRR)+1; instr->rmbyte=0xC0; instr->variant=OPRR; if ((((1<privprops=REGVARASSN; instr->rref=1<rref|=(1<rdef=257<privprops=BYTEREGOP; instr->rref=(instr->rref&15)|((unsigned)instr->rref>>4); /* Sort ah,bh,ch&dh */ instr->rdef=(instr->rdef&0xF0F)|(((unsigned)instr->rdef>>4)&0xF0F); } if ((op==CMP)||(op==TEST)||(op==CMPB)) instr->rdef=0; if (op==XCHG) instr->rdef=instr->rref|(instr->rref<<8); /* Write Betas also */ if ((op==XOR)&&(rs1==rd)) instr->rref=0; p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 rr */ /***/ void p5oponly(int op,int rdef,int rref) { /*************************************************************************/ /** Single opcode only but may change registers **/ /*************************************************************************/ int fsp; fsp=currentFSP; previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->group=instrgroup [op]; instr->props=DESTROYABLE; instr->csize=p5opcodesize(op,OPONLY); instr->variant=OPONLY; instr->rdef=rdef|((rdef&255)<<8); instr->rref=rref; if ((op>=FILD)&&(op!=FSTSW)) { if (instr->group==FPOPS2) { instr->rd=fsp+1; instr->rs1=fsp; instr->fref=3<<(fsp&7); instr->fdef=1<<((fsp+1)&7); } else { instr->rd=fsp; instr->fdef=1<<(fsp&7); if (!((FLDZ<=op)&&(op<=FLDPI))) instr->fref=instr->fdef; } } p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 opomly*/ /***/ void p5enter(int localsize,int level) { /*************************************************************************/ /** Plant the enter instruction a special with literals **/ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->opcode=ENTER; instr->group=instrgroup [ENTER]; instr->props=DESTROYABLE; instr->rref=(1<rdef=instr->rref|(instr->rref<<8); /* Write Betas also */ instr->csize=p5opcodesize(ENTER,OPONLY)+3; instr->variant=OPONLY; instr->u1.immval=(localsize<<8)|level; p5sideeffects(ENTER); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /*p5 enter*/ /***/ void p5fopr(int op,int rs1) { /*************************************************************************/ /** Perform a FP op on TOS and nominated register **/ /*************************************************************************/ int group,rd; group=instrgroup [op]; rd=currentFSP; previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rs1=rs1; instr->rd=rd; if (group==FPCOMPARE) { instr->fref=(1<<(rd&7))|(1<<(rs1&7)); } else if (op==FXCH) { instr->fref=(1<<(rd&7))|(1<<(rs1&7)); instr->fdef=instr->fref; } else { instr->fdef=1<<(rd&7); instr->fref=1<<(rs1&7); } instr->cref=1<props=DESTROYABLE; instr->group=group; if (group==FPCOMPARE) instr->cdef=1<csize=p5opcodesize(op,FOPPLUSR); instr->variant=FOPPLUSR; p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 fr */ /***/ struct instrfmt * p5appendfxch(struct fragfmt *frag,struct instrfmt * previnstr,int FSP) { /*************************************************************************/ /** Append a FXCH after previnstr and return its address **/ /*************************************************************************/ struct instrfmt *newinstr; newinstr=BInsertInstr(frag,previnstr); newinstr->opcode=FXCH; newinstr->rd=FSP; newinstr->rs1=FSP+1; newinstr->group=instrgroup [FXCH]; newinstr->props=DESTROYABLE; newinstr->variant=FOPPLUSR; newinstr->cref=(1<fref=(1<<((FSP+1)&7))|(1<<(FSP&7)); newinstr->fdef=newinstr->fref; newinstr->csize=2; return newinstr; } /***/ void p5opr(int op,int rd) { /*************************************************************************/ /** Single register involved presumed read and written **/ /*************************************************************************/ if (op>=FILD) { p5fopr(op,rd); return ; } previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rd=rd; instr->rs1=rd; instr->group=instrgroup [op]; instr->datasize=4; instr->props=DESTROYABLE; if ((op==POP)||(op==PUSH)||(op==INC)||(op==DEC)) { instr->csize=1; instr->variant=OPPLUSR; if (op==PUSH) { instr->rref=(1<rdef=257<props|=STOREINSTR; } else if (op==POP) { if ((((1<privprops=REGVARASSN; instr->rref=1<rdef=(257<props|=LOADINSTR; } else { instr->rref=1<rdef=257<u1.immval=1; /* to be like add $1 or SUB $1 */ } } else if (op==BSWAP) { instr->csize=2; instr->variant=OPPLUSR; instr->rref=1<rdef=257<rdef=(257<rref=(instr->rdef&255)|(1<csize=p5opcodesize(op,OPR)+1; instr->variant=OPR; instr->rmbyte=0xC0; } else { instr->rdef=257<rref=1<csize=p5opcodesize(op,OPR)+1; instr->variant=OPR; instr->rmbyte=0xC0; if (op>=SETO && op<=SETG) instr->privprops=BYTEREGOP; } p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /*p5 opr*/ /***/ void p5opmem(int op,int base,int disp,int size) { /*************************************************************************/ /** No register inr or dec PUSH or POP direct to memory */ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->group=instrgroup [op]; instr->rs1=base; instr->disp=disp; instr->props=DESTROYABLE; if ((op==POP)||(op==PUSH)||(op==INC)||(op==DEC)) { if (op==PUSH) { instr->rref=256<rdef=257<props|=LOADINSTR|STOREINSTR; } else if (op==POP) { instr->rref=256<rdef=257<props|=STOREINSTR|LOADINSTR; } else { instr->props|=STOREINSTR|LOADINSTR; } } else if ((op==DIV)||(op==IDIVIDE)||(op==MUL)) { instr->props|=LOADINSTR; instr->rdef=(257<rref=instr->rdef&255; /* Refernces alphas */ } else Mabort(961); instr->rref|=(256<area=-1; if (base==FRAMEPOINTER) { instr->privprops|=FRAMEACCESS; if (disp>0) { instr->area=PARAMS; instr->u0.offset=disp-PARAMBASE; } else { instr->area=STACK; instr->u0.offset=disp; } } instr->domain=0; instr->datasize=size; instr->csize=2+p5opcodesize(op,OPMEM); instr->rmbyte=0x40; /* 8 bit disp */ instr->variant=OPMEM; if ((disp==0)&&(base!=EBP)) { instr->rmbyte=0; instr->csize--; } else if ((disp>127)||(disp <-128)) { instr->csize+=3; instr->rmbyte=0x80; } if ((size==2)&&(instr->group!=INTLOAD)) p5addprefix(osprefix,SHORTOPND); if (base==ESP) instr->csize++; /*ESP need sib byte */ p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /*p5 opmem*/ /***/ void p5opfixmem(int op,int area,int offset,int size) { /*************************************************************************/ /** No register inr or dec PUSH or pop direct to memory */ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->group=instrgroup [op]; instr->props=DESTROYABLE; instr->privprops=FIXEDINSTR; if ((op==POP)||(op==PUSH)||(op==INC)||(op==DEC)) { if (op==PUSH) { instr->rref=256<rdef=257<props|=STOREINSTR; } else if (op==POP) { instr->rref=256<rdef=257<props|=LOADINSTR; } else { instr->props|=STOREINSTR|LOADINSTR; } } else if ((op==DIV)||(op==IDIVIDE)||(op==MUL)) { instr->props|=LOADINSTR; instr->rdef=(257<rref=instr->rdef&255; /* Refernces alphas */ } else if (op==JMPPTR) { instr->props|=JUMPINSTR; } else Mabort(961); instr->area=area; instr->domain=0; instr->datasize=size; instr->u0.offset=offset; instr->csize=5+p5opcodesize(op,OPMEM); instr->variant=OPMEM; instr->rmbyte=0x80; /* 32 bit disp only */ instr->fixtype=NORMALFIX; if (Pic!=0) { instr->fixtype=GOTfix; instr->rs1=GOTREG; instr->rref|=(256<group!=INTLOAD)) p5addprefix(osprefix,SHORTOPND); p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /*p5 opfixmem*/ static void p5pushaddr(int area,int offset) { /*************************************************************************/ /** Non Pic pass an address by pushing a fixed up literal **/ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->opcode=PUSH; instr->group=instrgroup [PUSH]; instr->props=DESTROYABLE|STOREINSTR; instr->privprops=FIXEDLIT; instr->area=area; instr->domain=0; instr->datasize=4; instr->u0.offset=offset; instr->variant=OPMEMLIT; instr->csize=4+p5opcodesize(PUSH,instr->variant); instr->rref=256<rdef=257<opcode=op; instr->group=instrgroup [op]; instr->rs1=base; instr->rref=256<disp=disp; instr->props=DESTROYABLE; instr->u1.immval=lit; instr->variant=OPMEMLIT; if (op==PUSH) { if ((-128<=lit)&&(lit<=127)) dsize=1; /* Push can extned short lit */ instr->csize=1+dsize; instr->rref|=(256<rdef=257<props|=STOREINSTR; } else if (op==MOV) { if (dsize==1) instr->variant=OPBMEMLIT; instr->props|=STOREINSTR; instr->csize=(p5opcodesize(op,instr->variant)+dsize)+2; if (base==ESP) instr->csize++; /*ESP need sib byte */ } else if (op==CMP) { if (dsize==1) instr->variant=OPBMEMLIT; if ((-128<=lit)&&(lit<=127)) dsize=1; /* CMP can extned short lit */ instr->csize=(p5opcodesize(op,instr->variant)+dsize)+2; if (base==ESP) instr->csize++; /*ESP need sib byte */ instr->props|=LOADINSTR; } else if (op==TEST) { if (dsize==1) instr->variant=OPBMEMLIT; instr->props|=LOADINSTR; instr->csize=(p5opcodesize(op,instr->variant)+dsize)+2; if (base==ESP) instr->csize++; /*ESP need sib byte */ } else Mabort(961); instr->area=-1; if (base==FRAMEPOINTER) { instr->privprops|=FRAMEACCESS; if (disp>0) { instr->area=PARAMS; instr->u0.offset=disp-PARAMBASE; } else { instr->area=STACK; instr->u0.offset=disp; } } instr->domain=0; instr->datasize=size; instr->rmbyte=0x40; /* 8 bit disp */ if ((disp==0)&&(base!=EBP)&&(op!=PUSH)) { instr->rmbyte=0; instr->csize--; } else if ((disp >127)||(disp<-128)) { instr->csize+=3; instr->rmbyte=0x80; } if ((size==2)&&(instr->group!=INTLOAD)) p5addprefix(osprefix,SHORTOPND); p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /*p5 oplitmem*/ /***/ void p5oplitfixmem(int op,int lit,int area,int offset,int size) { /*************************************************************************/ /** No register literal direct to memory **/ /*************************************************************************/ int dsize; dsize=size; previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->group=instrgroup [op]; instr->props=DESTROYABLE; instr->privprops=FIXEDINSTR; instr->u1.immval=lit; instr->variant=OPMEMLIT; if (dsize==1) instr->variant=OPBMEMLIT; if (op==MOV) { instr->props|=STOREINSTR; } else if (op==CMP) { if ((-128<=lit)&&(lit<=127)) dsize=1; /* CMP can extned short lit */ instr->props|=LOADINSTR; } else if (op==TEST) { instr->props|=LOADINSTR; } else Mabort(961); instr->area=area; instr->domain=0; instr->datasize=size; instr->u0.offset=offset; instr->csize=(p5opcodesize(op,instr->variant)+dsize)+5; instr->rmbyte=0x40; /* 8 bit disp */ instr->fixtype=NORMALFIX; if (Pic!=0) { instr->fixtype=GOTfix; instr->rs1=GOTREG; instr->rref|=(256<group!=INTLOAD)) p5addprefix(osprefix,SHORTOPND); p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /*p5 oplitfixmem*/ /***/ void p5rlit(int op,int rs1,int lit,int rd) { /*************************************************************************/ /** Genereral type of add lit to register **/ /** rs1 & rd should be the same except (curiously) for IMUL **/ /** However the 3 address form is maintained for the benefit of the **/ /** target independent modules eprocs,brocs&mprocs **/ /** MOV has a shortcut form which is left to Loadlit. The normal **/ /** forms will work they are just less efficient **/ /** Some operations have a special when rd is EAX these are coped with **/ /** Note: **/ /** This routine can not perform optimisations that will or may **/ /** invalidate the flags reg. For these use P5 oplit **/ /*************************************************************************/ struct instrvariants *ivar; if (!((rs1==rd)||(op==IMUL))) { p5rr(MOV,rs1,rd,rd); /* Simulate 3 address form by MOV */ p5rlit(op,rd,lit,rd); /* followed by 2 address form */ return ; } previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rs1=rs1; instr->u1.immval=lit; instr->rd=rd; instr->group=instrgroup [op]; instr->datasize=4; ivar=(struct instrvariants*)((int)&instrops [op*instrvarels]); if (instrform [op]==SLITFORM || ((ivar->valid&oprmslitval)!=0 && (-128<=lit && lit<=127) && op!=OR && op!=XOR && op!=TEST && op!=MOV)) { instr->datasize=1; instr->csize=2; instr->rmbyte=0xC0; /* rm means a register */ instr->variant=OPRSLIT; } else { instr->csize=1+p5opcodesize(op,OPRLIT); instr->variant=OPRLIT; instr->rmbyte=0xC0; /* rm means a register */ }; instr->props=DESTROYABLE; instr->csize+=instr->datasize; if ((1<privprops=REGVARASSN; instr->rref=1<rdef=257<privprops=BYTEREGOP; instr->rref=(instr->rref&15)|((unsigned)instr->rref>>4); /* Sort ah,bh,ch&dh */ instr->rdef=(instr->rdef&0xF0F)|(((unsigned)instr->rdef>>4)&0xF0F); if (op==MOVB) instr->rref|=instr->rd; /* unchanged part reffed*/ } if (op==CMP || op==TEST || op==CMPB) instr->rdef=0; p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 rlit */ /***/ /***/ void p5loadlit(int lit,int rd) { /*************************************************************************/ /** Put lit in a register Only 4 byte literals. 0 can be optimised **/ /** smaller sequence is possible for small literals but it will **/ /** be slower. However 0 & 1 are not optimises since **/ /** they are used to establish logicals. We want to protect the FLAGS **/ /** and enable improve condestablish to work. These instructions are **/ /** looked at again in clean up frag **/ /*************************************************************************/ if (lit==-1) { p5rr(XOR,rd,rd,rd); p5opr(DEC,rd); return ; } if ((targetvariant==0)&&((lit&0xFFFFFF00)==0)&&(rd<=EBX)) { if (!((0<=lit)&&(lit<=1))) { p5rr(XOR,rd,rd,rd); p5oplit(OR,rd,lit,rd); return ; } } previnstr=instr; instr=BNewInstr(); instr->opcode=MOV; instr->rd=rd; instr->rdef=257<variant=OPPLUSRLIT; instr->u1.immval=lit; instr->csize=5; instr->datasize=4; if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 loadlit */ /***/ void p5oplit(int op,int rs1,int lit,int rd) { /*************************************************************************/ /** This routine can make optimistions that are banned for p5 rlit **/ /*************************************************************************/ if (rs1==rd) { if (op==MOV) { p5loadlit(lit,rd); return ; } if ((op==ADD && lit==1)||(op==SUB && lit==-1)) { p5opr(INC,rd); return ; } if ((op==ADD && lit==-1)||(op==SUB && lit==1)) { p5opr(DEC,rd); return ; } if (op==CMP && lit==0) { p5rr(TEST,rd,rd,rd); return ; } } p5rlit(op,rs1,lit,rd); if (targetvariant==0 && (lit&0xFFFFFF00)==0 && rs1==rd && rd<=EBX) { if (instr->variant==OPEAXLIT && (op==OR || op==XOR || op==TEST)) { instr->variant=OPALLIT; instr->csize-=3; return ; } if (instr->variant==OPRLIT && (op==OR || op==XOR || op==TEST)) { instr->variant=OPBRMLIT; instr->csize-=3; return ; } } /**/ /* OR and XOR and tests of the 'AH' byte can also be optimised but */ /* because the H regs have address 4-7 the reg then does not correspond */ /* to the use bits which will upset the peepholer. This optisation, if */ /* attempted, must be left to final tidy */ /**/ } /* p5 oplit */ /***/ void p5oprmem(int op,int base,int disp,int rd,int size) { /*************************************************************************/ /** Load operations and also store & reg operations like add **/ /*************************************************************************/ if ((base<0)||(rd<0)||(rd>=FRBASE)||(base>=FRBASE)) Mabort(966); previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rs1=base; instr->disp=disp; instr->rd=rd; instr->group=instrgroup [op]; instr->props=LOADINSTR|DESTROYABLE; if ((((1<privprops|=REGVARASSN; instr->area=-1; if (base==FRAMEPOINTER) { instr->privprops|=FRAMEACCESS; if (op==LEA) { StackSTflags [0]|=4; } else { if (disp>0) { instr->area=PARAMS; instr->u0.offset=disp-PARAMBASE; } else { instr->area=STACK; instr->u0.offset=disp; } } } instr->domain=0; instr->datasize=size; instr->rref=256<rdef=257<group!=INTLOAD)&&(op!=LEA)) { instr->rref|=(1<privprops=BYTEREGOP; instr->rref=(instr->rref&0xF0F)|((unsigned)instr->rref>>4); /* Sort ah,bh,ch&dh */ instr->rdef=(instr->rdef&0xF0F)|(((unsigned)instr->rdef>>4)&0xF0F); } if ((op==CMP)||(op==CMPB)) instr->rdef=0; instr->csize=2+p5opcodesize(op,OPRRM); instr->variant=OPRRM; instr->rmbyte=0x40; /* 8 bit disp */ if ((disp==0)&&(base!=EBP)) { instr->rmbyte=0; instr->csize--; } else if ((disp>127)||(disp <-128)) { instr->csize+=3; instr->rmbyte=0x80; } if (op==LEA) { instr->datasize=0; instr->props=DESTROYABLE; } if ((instr->datasize==2)&&(instr->group!=INTLOAD)) p5addprefix(osprefix,SHORTOPND); if (base==ESP) instr->csize++; /*ESP need sib byte */ p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 loadri */ /***/ void p5fopmem(int op,int base,int disp,int size) { /*************************************************************************/ /** Load operations and also store & reg operations like add **/ /*************************************************************************/ int rd; rd=currentFSP; previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rs1=base; instr->disp=disp; instr->rd=rd; instr->group=instrgroup [op]; if (instr->group==FPSTORE) instr->props=STOREINSTR|DESTROYABLE; else instr->props=LOADINSTR|DESTROYABLE ; instr->area=-1; if (base==FRAMEPOINTER) { instr->privprops|=FRAMEACCESS; if (disp>0) { instr->area=PARAMS; instr->u0.offset=disp-PARAMBASE; } else { instr->area=STACK; instr->u0.offset=disp; } } instr->domain=0; instr->datasize=size; instr->rref=1<group!=FPSTORE) instr->fdef=1<<(rd&7); if (instr->group!=FPLOAD) { instr->fref=instr->fref|(1<<(rd&7)); } instr->csize=2+p5opcodesize(op,FOPRM); instr->variant=FOPRM; instr->rmbyte=0x40; /* 8 bit disp */ if ((disp==0)&&(base!=EBP)) { instr->rmbyte=0; instr->csize--; } else if ((disp>127)||(disp <-128)) { instr->csize+=3; instr->rmbyte=0x80; } if (instr->group==FPCOMPARE) { instr->cdef=1<fdef=0; } instr->cref|=(1<csize++; /*ESP need sib byte */ p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 loadri */ /***/ void p5opmemr(int op,int base,int disp,int rd,int size) { /*************************************************************************/ /** Store operations and also add to store operations **/ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rs1=base; instr->disp=disp; instr->rd=rd; instr->group=instrgroup [op]; instr->props=STOREINSTR|DESTROYABLE; instr->area=-1; if (base==FRAMEPOINTER) { instr->privprops|=FRAMEACCESS; if (disp>0) { instr->area=PARAMS; instr->u0.offset=disp-PARAMBASE; } else { instr->area=STACK; instr->u0.offset=disp; } } instr->domain=0; instr->datasize=size; instr->rref=(256<group!=INTSTORE) { instr->rref|=(1<props|=LOADINSTR; } if ((op==MOVB)||(op==SB)) instr->privprops=BYTEREGOP; instr->csize=2+p5opcodesize(op,OPRMR); instr->rmbyte=0x40; /* 8 bit disp */ instr->variant=OPRMR; if ((disp==0)&&(base!=EBP)) { instr->rmbyte=0; instr->csize--; } else if ((disp>127)||(disp <-128)) { instr->csize+=3; instr->rmbyte=0x80; } if ((size==2)&&(instr->group!=INTLOAD)) p5addprefix(osprefix,SHORTOPND); if (base==ESP) instr->csize++; /*ESP need sib byte */ p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 loadri */ /***/ void p5oprfixmem(int op,int area,int offset,int rd,int size) { /*************************************************************************/ /** Load operations and also store & reg operations like add where the **/ /** the address is fixed up at link time to area&offset **/ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rd=rd; instr->group=instrgroup [op]; instr->props=LOADINSTR|DESTROYABLE; instr->privprops=FIXEDINSTR; if ((((1<privprops|=REGVARASSN; instr->area=area; instr->domain=0; instr->datasize=size; instr->u0.offset=offset; instr->rdef=257<group!=INTLOAD)&&(op!=LEA)) { instr->rref=1<privprops=BYTEREGOP; instr->rref=(instr->rref&15)|(((unsigned)instr->rref>>4)&0xF0F); /* Sort ah,bh,ch&dh */ instr->rdef=(instr->rdef&0xF0F)|(((unsigned)instr->rdef>>4)&0xF0F); } if ((op==CMP)||(op==CMPB)) instr->rdef=0; instr->csize=5+p5opcodesize(op,OPRRM); instr->variant=OPRRM; instr->rmbyte=0x80; /* 32 bit disp only */ instr->fixtype=NORMALFIX; if (Pic!=0) { instr->fixtype=GOTfix; instr->rs1=GOTREG; instr->rref|=(256<props=DESTROYABLE; instr->privprops=FIXEDINSTR; instr->datasize=0; } if ((instr->datasize==2)&&(instr->group!=INTLOAD)) p5addprefix(osprefix,SHORTOPND); p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 oprfixmem */ /***/ void p5fopfixmem(int op,int area,int offset,int size) { /*************************************************************************/ /** Fload operations and also store & reg operations like add where the **/ /** the address is fixed up at link time to area&offset **/ /*************************************************************************/ int rd; rd=currentFSP; previnstr=instr; instr=BNewInstr(); instr->opcode=op; instr->rd=rd; instr->group=instrgroup [op]; if (instr->group==FPSTORE) instr->props=STOREINSTR|DESTROYABLE; else instr->props=LOADINSTR|DESTROYABLE ; instr->privprops=FIXEDINSTR; instr->area=area; instr->domain=0; instr->datasize=size; instr->u0.offset=offset; instr->fdef=1<<(rd&7); if (instr->group!=FPLOAD) { instr->fref=1<<(rd&7); } instr->csize=5+p5opcodesize(op,FOPRM); instr->variant=FOPRM; instr->rmbyte=0x80; /* 32 bit disp only */ instr->fixtype=NORMALFIX; if (Pic!=0) { instr->fixtype=GOTfix; instr->rs1=GOTREG; instr->rref|=(256<group==FPCOMPARE) { instr->cdef=1<fdef=0; } instr->cref|=(1<opcode=op; instr->rd=rd; instr->group=instrgroup [op]; instr->props=STOREINSTR|DESTROYABLE; instr->privprops=FIXEDINSTR; if ((op==MOVB)||(op==SB)) instr->privprops|=BYTEREGOP; instr->area=area; instr->u0.offset=offset; instr->domain=0; instr->datasize=size; instr->rref=1<group!=INTSTORE) { instr->props|=LOADINSTR; } instr->csize=5+p5opcodesize(op,OPRMR); instr->rmbyte=0x80; /* 32 bit disp */ instr->variant=OPRMR; instr->fixtype=NORMALFIX; if (Pic!=0) { instr->fixtype=GOTfix; instr->rs1=GOTREG; instr->rref|=(256< reg **/ /** = DESTSTORE for reg => memory **/ /*************************************************************************/ int j,i,Fixed,swopped,vol,wreg,nregs,wreg1; struct procfmt * pi; inhibitdis++; Fixed=flags&1; swopped=0; vol=0; if ((flags&(STKSWOPPED<<8))!=0) swopped=16; if ((flags&(STKVOL<<8))!=0) vol=1; j=(dest+(FIX*Fixed))+swopped; if (scale>=0) j+=INDEXED; pi=(struct procfmt *)currentPIaddr; if (op>24)|((((unsigned)reg>>16)&255)<<8))|((((unsigned)reg>>8)&255)<<16))|(reg<<24) ; /*reg is the lit */ if (size<4) reg=(unsigned)reg>>(8*(4-size)); p5oplitmem(op,reg,baseorarea,offset,size); goto common; case FIX+NOREG: p5opfixmem(op,baseorarea,offset,size); goto common; case FIX+DESTREG: p5oprfixmem(op,baseorarea,offset,reg,size); goto common; case FIX+DESTREG+STKSWOPPED: inhibitdis--; p5oprfixmem(op,baseorarea,offset,reg,size); byteswop(reg,op,size); return ; case FIX+DESTSTORE: p5opfixmemr(op,baseorarea,offset,reg,size); goto common; case FIX+DESTSTORE+STKSWOPPED: inhibitdis--; byteswop(reg,op,size); p5opfixmemr(op,baseorarea,offset,reg,size); return ; case FIX+SOURCELIT: p5oplitfixmem(op,reg,baseorarea,offset,size); goto common; case FIX+SOURCELIT+STKSWOPPED: reg=((((unsigned)reg>>24)|((((unsigned)reg>>16)&255)<<8))|((((unsigned)reg>>8)&255)<<16))|(reg<<24) ; /*reg is the lit */ if (size<4) reg=(unsigned)reg>>(8*(4-size)); p5oplitfixmem(op,reg,baseorarea,offset,size); goto common; case INDEXED+NOREG: p5opmem(op,baseorarea,offset,size); instr->privprops|=SIBREQD; instr->csize++; instr->u0.offset=-1; instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; instr->u0.offset=-1; instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; instr->u0.offset=-1; instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; instr->u0.offset=-1; instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; instr->u0.offset=-1; instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<>24)|((((unsigned)reg>>16)&255)<<8))|((((unsigned)reg>>8)&255)<<16))|(reg<<24) ; /*reg is the lit */ if (size<4) reg=(unsigned)reg>>(8*(4-size)); case INDEXED+SOURCELIT: p5oplitmem(op,reg /*really lit in this case*/,baseorarea,offset,size); instr->privprops|=SIBREQD; instr->csize++; instr->u0.offset=-1; instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; /* instr_offset=-1 */ instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; /* instr_offset=-1 */ instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; /* instr_offset=-1 */ instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; /* instr_offset=-1 */ instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; /* instr_offset=-1 */ instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<>24)|((((unsigned)reg>>16)&255)<<8))|((((unsigned)reg>>8)&255)<<16))|(reg<<24) ; /*reg is the lit */ if (size<4) reg=(unsigned)reg>>(8*(4-size)); case INDEXED+FIX+SOURCELIT: p5oplitfixmem(op,reg,baseorarea,offset,size); instr->privprops|=SIBREQD; instr->csize++; /* instr_offset=-1 */ instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<BEswopspace==0) { pi->BEswopspace=p5tempspace(8,4); if (pi->BEswopspace>=-1024) { i=((-pi->BEswopspace)>>2); StackSTflags[i]|=3; StackSTflags[i-1]|=3; } } switch (j) { case NOREG: case DESTREG: case DESTSTORE: p5fopmem(op,baseorarea,offset,size); goto common; case DESTREG+STKSWOPPED: case FIX+DESTREG+STKSWOPPED: case INDEXED+FIX+DESTREG+STKSWOPPED: case INDEXED+DESTREG+STKSWOPPED: wreg=claimreg(); inhibitdis--; if (size==4) { p5genmemaccess(LW,baseorarea,offset,index,scale,wreg,size,DESTREG,Fixed); byteswop(wreg,LW,4); p5opmemr(ST,EBP,pi->BEswopspace,wreg,4); p5fopmem(FLDm,EBP,pi->BEswopspace,4); unlockreg(wreg); return ; } /* Now for the variants of the 8 byte case which are important for Bloomberg */ nregs=countunclaimedregs(); if (vol==0 && scale<0 && nregs>0) { wreg1=claimreg(); p5genmemaccess(LW,baseorarea,offset,index,scale,wreg,4,DESTREG,Fixed); p5genmemaccess(LW,baseorarea,offset+4,index,scale,wreg1,4,DESTREG,Fixed); byteswop(wreg,LW,4); byteswop(wreg1,LW,4); p5opmemr(ST,EBP,pi->BEswopspace+4,wreg,4); p5opmemr(ST,EBP,pi->BEswopspace,wreg1,4); p5fopmem(FLDd,EBP,pi->BEswopspace,8); unlockreg(wreg1); } else if (vol==0 && scale<0) { /* above algoritim but use only wreg */ p5genmemaccess(LW,baseorarea,offset,index,scale,wreg,4,DESTREG,Fixed); byteswop(wreg,LW,4); p5opmemr(ST,EBP,pi->BEswopspace+4,wreg,4); p5genmemaccess(LW,baseorarea,offset+4,index,scale,wreg,4,DESTREG,Fixed); byteswop(wreg,LW,4); p5opmemr(ST,EBP,pi->BEswopspace,wreg,4); p5fopmem(FLDd,EBP,pi->BEswopspace,8); } else if (vol==0 && nregs>0) { wreg1=claimreg(); p5genmemaccess(LEA,baseorarea,offset,index,scale,wreg,size,DESTREG,Fixed); p5oprmem(LW,wreg,4,wreg1,4); p5oprmem(LW,wreg,0,wreg,4); byteswop(wreg,LW,4); byteswop(wreg1,LW,4); p5opmemr(ST,EBP,pi->BEswopspace+4,wreg,4); p5opmemr(ST,EBP,pi->BEswopspace,wreg1,4); p5fopmem(FLDd,EBP,pi->BEswopspace,8); unlockreg(wreg1); } else { /* Only 1 reg so call support procedure */ p5genmemaccess(LEA,baseorarea,offset,index,scale,wreg,size,DESTREG,Fixed); p5opr(PUSH,wreg); if (vol==0) p5call(Fldlswop,0,0);else p5call(Fldlvolswop,0,0); instr->rdef&=(~((257<BEswopspace,4); p5oprmem(LW,EBP,pi->BEswopspace,wreg,4); byteswop(wreg,ST,4); p5genmemaccess(ST,baseorarea,offset,index,scale,wreg,size,DESTSTORE,Fixed); unlockreg(wreg); return ; } /* Now for the variants of the 8 byte case which are important for Bloomberg */ nregs=countunclaimedregs(); if (vol==0 && scale<0 && nregs>0) { wreg1=claimreg(); p5fopmem(FSTPd,EBP,pi->BEswopspace,8); p5oprmem(LW,EBP,pi->BEswopspace+4,wreg,4); p5oprmem(LW,EBP,pi->BEswopspace,wreg1,4); byteswop(wreg,LW,4); byteswop(wreg1,LW,4); p5genmemaccess(ST,baseorarea,offset,index,scale,wreg,4,DESTSTORE,Fixed); p5genmemaccess(ST,baseorarea,offset+4,index,scale,wreg1,4,DESTSTORE,Fixed); unlockreg(wreg1); } else if (vol==0 && scale<0) { /* above algoritim but use only wreg */ p5fopmem(FSTPd,EBP,pi->BEswopspace,8); p5oprmem(LW,EBP,pi->BEswopspace+4,wreg,4); byteswop(wreg,LW,4); p5genmemaccess(ST,baseorarea,offset,index,scale,wreg,4,DESTSTORE,Fixed); p5oprmem(LW,EBP,pi->BEswopspace,wreg,4); byteswop(wreg,LW,4); p5genmemaccess(ST,baseorarea,offset+4,index,scale,wreg,4,DESTSTORE,Fixed); } else if (vol==0 && nregs>0) { wreg1=claimreg(); p5genmemaccess(LEA,baseorarea,offset,index,scale,wreg,size,DESTREG,Fixed); p5fopmem(FSTPd,EBP,pi->BEswopspace,8); p5oprmem(LW,EBP,pi->BEswopspace+4,wreg1,4); byteswop(wreg1,LW,4); p5opmemr(ST,wreg,0,wreg1,4); p5oprmem(LW,EBP,pi->BEswopspace,wreg1,4); byteswop(wreg1,LW,4); p5opmemr(ST,wreg,4,wreg1,4); unlockreg(wreg1); } else { /* Only 1 reg so call support procedure */ p5genmemaccess(LEA,baseorarea,offset,index,scale,wreg,size,DESTREG,Fixed); p5opr(PUSH,wreg); if (vol==0) p5call(Fstlswop,0,0); else p5call(Fstlvolswop,0,0); instr->rdef&=(~((257<privprops|=SIBREQD; instr->csize++; instr->u0.offset=-1; instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<privprops|=SIBREQD; instr->csize++; /* instr_offset=-1 */ instr->sib=(scale<<6)|(5*Fixed); instr->rs2=index; instr->rref|=(256<opcode=op; instr->u1.immval=lit; instr->group=instrgroup [op]; instr->props=JUMPINSTR; instr->privprops=KNOWNOFFSET; /* so immval not used as label index!*/ instr->csize=2; /* assumes known offset <127 */ p5sideeffects(op); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 jlkri */ /***/ void p5loadprocad(int rd,int id) { /*************************************************************************/ /** Load the address of proc id into reg rd. Different for Pic **/ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->rd=rd; if ((((1<privprops=REGVARASSN; instr->rdef=257<opcode=MOV; instr->domain=0; instr->u0.offset=id; /* proc id in offset */ instr->group=instrgroup [MOV]; instr->fixtype=NORMALFIX; instr->privprops|=FIXEDINSTR|PROCADFIX; instr->csize=5; instr->variant=OPPLUSRLIT; } else { Mabort(977); } p5sideeffects(instr->opcode); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /*p5 loadprocad*/ /***/ void p5callind(int reg,int parambytes,int callprops,int modemask) { /*------------------------------------------------------------ */ /* Languages that do nested calls recover stored params here. */ /* Pentium nested calls work automaically */ /*------------------------------------------------------------ */ p5opr(CALLPTR,reg); instr->rdef=(((257<rref|=(1<rref|=1<props|=ANYCALL; } /* p5 callind */ /***/ void p5call(int id,int parambytes,int callprops) { struct Exdatafmt *exdata; exdata=exrecad(id); previnstr=instr; instr=BNewInstr(); instr->opcode=CALL; instr->u1.immval=id; instr->group=instrgroup [CALL]; instr->variant=OPPCREL; instr->csize=4+p5opcodesize(CALL,OPPCREL); instr->rref=(1<rref|=1<Name,"__ashr64") == 0 || strcmp(exdata->Name,"__ashl64") ==0 || strcmp(exdata->Name,"__ushr64") ==0 || strcmp(exdata->Name,"__ush64") ==0 || strcmp(exdata->Name,"__ash64") ==0 ) instr->rref|=(1<rref|=(1<rdef=(((257<cdef=1<props=ANYCALL; instr->privprops=DIRECTCALL; if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 call */ /***/ void p5calllocal(int offset,int mode) { /*************************************************************************/ /** Call by a fixed offset (often 0) to obtain return address **/ /*************************************************************************/ previnstr=instr; instr=BNewInstr(); instr->opcode=CALL; instr->u1.immval=offset; instr->group=instrgroup [CALL]; instr->variant=OPPCREL; instr->csize=4+p5opcodesize(CALL,OPPCREL); instr->rref=1<rdef=257<cdef=1<props=JUMPINSTR; instr->privprops=KNOWNOFFSET; if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 calllocal */ /***/ void p5bcc(int cc,int labindex,int modemask) { /*************************************************************************/ /** There is no condition code on Pentium so cc is the opcode **/ /** shifted up 16 to avoid confusion with ALWAYS&NEVER **/ /** Modemask is not relevant but left for compatability **/ /*************************************************************************/ if (cc==ALWAYS) cc=JMP<<16; previnstr=instr; instr=BNewInstr(); instr->opcode=((unsigned)cc>>16)&255; instr->u1.immval=labindex; instr->group=instrgroup [instr->opcode]; instr->props=BRANCH; if (instr->opcode!=JMP) { instr->cref=1<props|=CONDITIONALBRANCH; if (JumpPredictFlag>0) { instr->props|=PREDICTED; if (JumpPredictFlag==2) instr->props|=PREDICTEDTAKEN; } } JumpPredictFlag=-1; instr->variant=OPPCREL; instr->csize=4+p5opcodesize(instr->opcode,OPPCREL); p5sideeffects(instr->opcode); if (Report && !inhibitdis) p5disasinstr(instr,&localca); } /* p5 bcc */ /***/ void p5bcctf(int cc,int labindex,int modemask) { p5bcc(cc,labindex,modemask); BTerminateFrag(labindex,0); } /***/ /***/ /***/ /***/ void p5GOTfix(int GOTreg) { /******************************************************************************/ /** Generate code to load GOTreg with the address of the GLOBAL OFFSET TABLE **/ /** **/ /** The code sequence generated is: **/ /** **/ /** call 0 **/ /** POP %GOTREG **/ /** ADD %GOTREG,__gp_disp **/ /** **/ /******************************************************************************/ struct fragfmt *frag; p5calllocal(0,0); p5opr(POP,GOTreg); previnstr=instr; instr=BNewInstr(); instr->opcode=ADD; instr->area=PLT; /* EPC's PLT corrseponds to GOT */ instr->domain=0; #if(OutputASSEMBLER==Negative) instr->u0.offset=3; /* Pos of fixup in instr */ #else instr->u0.offset=1; /* Pos on instr start AS adds 2 */ #endif; instr->rd=GOTreg; instr->group=instrgroup [ADD]; instr->rdef=257<rref=256<fixtype=GOTRELFIX; /* Type of fix to be applied */ instr->privprops=FIXEDLIT; instr->csize=6; instr->variant=OPRLIT; instr->datasize=4; if (Report && !inhibitdis) p5disasinstr(instr,&localca); frag=BCurFrag(); frag->props|=NOOPTIMFRAG; /*GOT load must not be scheduled ABI*/ } /* mips GOTfix */ /***/ static int isarealocal(int area) { /*************************************************************************/ /** If area is Known to be local returns non zero **/ /** Zero means area is or may be global **/ /*************************************************************************/ #if((Language==CCOMP)&&(LanguageVariant==USLC)) struct Exdatafmt *exdata; exdata=exrecad(area); if (PIC && (exdata->props&1)) return 0; /* local global in PIC mode can be overridden */ return exdata->flags&4; #else if (area<=CNST) return 1; return egiveareaprops(area)&INITIALISED; #endif; } /***/ void p5ldfix(int area,int offset,int rd) { /*************************************************************************/ /** Fixup register rd so that it points at area and offset **/ /*************************************************************************/ if (Pic==0) /*not Position Independent Code*/{ previnstr=instr; instr=BNewInstr(); instr->opcode=MOV; instr->area=area; instr->domain=0; instr->u0.offset=offset; instr->rd=rd; if ((((1<privprops=REGVARASSN; instr->group=instrgroup [MOV]; instr->props=DESTROYABLE; instr->fixtype=NORMALFIX; instr->rdef=257<csize=5; instr->datasize=4; instr->variant=OPPLUSRLIT; instr->privprops|=FIXEDLIT; if (Report && !inhibitdis) p5disasinstr(instr,&localca); } else { /***/ if (isarealocal(area)!=0) /* local area */{ p5oprfixmem(LEA,area,offset,rd,0) /* Pic*/; } else { previnstr=instr; instr=BNewInstr(); instr->opcode=LW; instr->rd=rd; instr->group=instrgroup [LW]; instr->props=LOADINSTR|DESTROYABLE; instr->privprops=FIXEDINSTR; if ((((1<privprops|=REGVARASSN; instr->area=area; instr->u0.offset=0; instr->domain=0; instr->datasize=4; instr->rdef=257<csize=5+p5opcodesize(LW,OPRRM); instr->variant=OPRRM; instr->rmbyte=0x80; /* 32 bit disp only */ instr->fixtype=GOTofffix; instr->rs1=GOTREG; instr->rref=256<=0)&&(reg<0)) return reg1; if (reg<0) reg=claimreg(); Toffset=Offset; reg1=checkareaaddr(area,&Toffset); if (reg1>0) { p5oprmem(LEA,reg1,Offset-Toffset,reg,0); instr->domain=domain; /* instr_privprops=instr_privprops!POINTER DOMAIN */ } else { #if(GENGLAINDFIXUPS!=0) key=AreaBaseOffset+AreaKeyRef(area,Offset); /* offset of pointer in GLA */ p5privateaccess(LW,reg,GLA,key,4,0,DESTREG,0); instr->domain=domain; /* instr_privprops=instr_privprops!POINTER DOMAIN */ instr->area=CNST; instr->u0.offset=key-AreaBaseOffset; #else p5ldfix(area,Offset+AreaBaseOffset,reg); /* instr_privprops=instr_privprops!POINTER DOMAIN */ instr->domain=domain; #endif; } setregmemory(reg,ADDROF,Offset,area,4,0); return reg; } /***/ static int adaptinstr(struct instrfmt *instr,int newdest) { /**************************************************************************/ /** Attempt to alter 'instr' so the result appears in register newdest **/ /** On a 2 address machine this is not normally possible but there **/ /** are several tricks on pentium mostly involving lea **/ /**************************************************************************/ struct instrfmt *previnstr; int op,var; op=instr->opcode; var=instr->variant; if (var==OPMEMLIT || var==OPBMEMLIT) return 0; if ((op==LEA || op==MOV || op==MOVSX || instr->group==INTLOAD) && instr->rdef!=0) { instr->rd=newdest; instr->rdef=257<rs1==newdest)&&((op==ADD)||(op==OR)||(op==XOR)||(op==AND))) { instr->rs1=instr->rd; instr->rd=newdest; instr->rdef=257<rd=newdest; instr->rdef=257<rs2=instr->rd; instr->sib=0; instr->opcode=LEA; instr->variant=OPRRM; instr->csize=3; instr->rmbyte=0; instr->rd=newdest; instr->rdef=257<rref=(256<rs1)|(256<rs2); /* LEA reads betas */ instr->privprops|=SIBREQD; return 1; } /**/ /* LEA can also handle reg plusorminus intval */ /**/ if ((var==OPRLIT || var==OPRSLIT)&&((op==ADD)||(op==SUB))&&(instr->u1.immval!=0x80000000)) /*!!*/{ instr->disp=instr->u1.immval; instr->variant=OPRRM; instr->opcode=LEA; if (op==SUB) instr->disp=-instr->disp; instr->u1.immval=0; if ((-128<=instr->disp)&&(instr->disp<=127)) instr->csize=3; else instr->csize=6; instr->rs1=instr->rd; instr->rd=newdest; instr->rdef=257<rref=256<rs1; /* LEA reads betas */ return 1; } previnstr=BMachineInstr(instr->previnstr,PREVCHAIN); if (previnstr==NULL) return 0; if (!((previnstr->rd==instr->rd) && ((var==OPRR && instr->rs1!=newdest) || var==OPRSLIT || var==OPRLIT))) return 0; if (adaptinstr(previnstr,newdest)==0) return 0; /* NO CAN DO*/ if (var==OPRR) { instr->rd=newdest; instr->rdef=257<rd; instr->rref=(1<rd)|(1<rs1); } else { instr->rd=newdest; instr->rdef=257<rd; instr->rref=1<rd; } return 1; } /* adapt instr */ /***/ void p5copyireg(int source,int dest) { /*************************************************************************/ /** Copy from 1 reg to another . Any use updating is assumed done **/ /** First investigate whether we can generate the result in the **/ /** correct registers instead of moving it. **/ /*************************************************************************/ int lca,sbit,dbit; struct fragfmt *curfrag; struct instrfmt *curinstr,*storeinstr; curfrag=BCurFrag(); if (curfrag==NULL) goto mustcopy; curinstr=curfrag->lastinstr; if (curinstr==NULL) goto mustcopy; lca=localca-curinstr->csize; if (!((0<=registerstatus(source))&&(registerstatus(source)<=1))) goto mustcopy; /**/ sbit=1<rdef==(sbit|(sbit<<8)))&&(adaptinstr(curinstr,dest)>0)) { if ((dbit&RegClaimMaskA)!=0) curinstr->privprops|=REGVARASSN; if ((increports!=0)&&(Report!=0)&&(inhibitdis==0)) { printf("Move avoided\n"); p5disasinstr(curinstr,&lca); } if (storeinstr!=NULL) { curinstr=storeinstr; curinstr->rd=dest; if ((curinstr->variant==OPRRM)&&(curinstr->rmbyte!=0x4)&&(curinstr->rs1==source)) curinstr->rs1=dest ; if (((curinstr->privprops&SIBREQD)!=0)&&(curinstr->rs2==source)) curinstr->rs2=dest; curinstr->rref=(curinstr->rref^sbit)|(dbit&255); if ((increports!=0)&&(Report!=0)&&(inhibitdis==0)) { printf("Store after move amended \n"); lca+=4; p5disasinstr(curinstr,&lca); } } forgetreg(source); return ; } if ((curinstr->rdef&dbit)!=0 || (curinstr->rref&dbit)!=0 || (curinstr->props&ANYCALL)!=0) goto mustcopy ; if ((curinstr->rref&(sbit|(sbit<<8)))!=0) { if (curinstr->group==INTSTORE && curinstr->rd==source && storeinstr==NULL && curinstr->rs1!=source && curinstr->variant==OPRMR && (curinstr->datasize>1 || dest<=3)) /*Bytes stores again!*/{ storeinstr=curinstr; } else goto mustcopy; } if ((curinstr->rdef&sbit)!=0) goto mustcopy; if (curinstr==curfrag->firstinstr) break ; curinstr=curinstr->previnstr; if (curinstr==NULL) break ; lca-=curinstr->csize; } while (1) /* FOR EVER */; mustcopy: p5rr(MOV,source,dest,dest); instr->props|=COPYINSTR; } /* p5 copy ireg */ /***/ /***/ /***/ /***/ void p5copydisplay(int levels,int *curdisplay) { /*************************************************************************/ /** Use a pair of temp regs ($24&25) to avoid any stalls when copying **/ /** as we are not yet in the procedure can omit claiming&releasing **/ /*************************************************************************/ /* all done by the enter instruction */ } /*p5 copy display*/ /***/ void p5notediagdisp(int diagdisp,int stackoffset) { /*************************************************************************/ /** Store away the diagdisp which can be amended later so discard **/ /** any regmory **/ /*************************************************************************/ int reg; reg=claimreg(); p5loadlit(diagdisp,reg); p5storeri(ST,reg,FRAMEPOINTER,stackoffset); unlockreg(reg); forgetreg(reg); } /*note diagdisp*/ /***/ void p5unassfill(int Label,int proclevel,int unassdisp /*unused on p5*/) { /*************************************************************************/ /** Plant a loop to fill the stack frame with the unassigned pattern **/ /** The first instruction must be a loadlit which will be set to **/ /** correct count (of words) at procend. **/ /*************************************************************************/ /**/ /* code planted */ /* llit ECX,count */ /* llit EAX,0x81818181 */ /* STD */ /* LEA EDI,$fp,-displaysize- */ /* REP:stosw */ /* CLD */ /**/ p5loadlit(0x1000,ECX); /* will be filled with correct cnt */ p5loadlit(UnassignedPattern,EAX); p5oponly(STD,0,0); p5oprmem(LEA,EBP,((-(4*proclevel))-4)-4,EDI,4); p5modinstrprops(0,0,0,FRAMEACCESS); p5oponly(STOSW,(257<>2; paramSTflags [i]=paramSTflags [i]|AccessType; if ((size>4)&&(i<(((unsigned)Regparamsize>>2)-1))) paramSTflags [i+1]=paramSTflags [i+1]| AccessType ; /* note that an argument within the parameter*/ /* area has been referenced - do not delete */ /* the associated STore instruction */ } Base=FRAMEPOINTER; /*Area=STACK*/ } else { if ((-1024<=Offset)&&(Offset<0)) /*set use markers*/{ i=(unsigned)((-Offset)+3)>>2; StackSTflags [i]|=AccessType; if (size>4) { StackSTflags [i-1]|=AccessType; } } Base=FRAMEPOINTER; } } else { AvailOffset=Offset; Base=checkareaaddr(Area,&AvailOffset); if (Base>=0) { ActOffset=Offset-AvailOffset; } else if ((Pic!=0)&&(isarealocal(Area)==0)) { Base=p5baseld(-1,Area,0,0); } } if (Base>=0) { p5genmemaccess(opcode,Base,ActOffset,-1,-1,rd,size,dest,flags<<8); if (Base==FRAMEPOINTER) p5modinstrprops(0,0,0,FRAMEACCESS); unlockreg(Base); } else { p5genmemaccess(opcode,Area,Offset,-1,-1,rd,size,dest,(flags<<8)|1); } /* %IF instr_opcode=BSWAP %AND previnstr_props&(LOAD INSTR!STORE INSTR)#0 %START*/ /* previnstr_area=Area */ /* previnstr_domain=0 */ /* previnstr_offset=Offset */ /* %IF volatile#0 %THEN previnstr_privprops=previnstr_privprops!VOLATILELOC*/ /* %FINISH %ELSE %IF instr_props&(LOAD INSTR!STORE INSTR)#0 %START */ if (((instr->props&(LOADINSTR|STOREINSTR))!=0)&&((flags&STKSWOPPED)==0)) { instr->area=Area; instr->domain=0; instr->u0.offset=Offset; if (Volatile!=0) p5modinstrprops(0,0,0,VOLATILELOC); } } /* p5 privateaccess */ /***/ void p5accessindri(int opclass,int rd,int base,int offset,int size,int Volatile) { /****************************************************************/ /** opclass = 1 load int 9 store int **/ /** 2 load real 10 store real **/ /** 3 load unsigned 11 store unsigned **/ /** 5 load misreal 13 store misreal **/ /** 7 load misint 15 store misint **/ /** 8 load misUint 16 store misUint **/ /****************************************************************/ int op,dest; op=accessop [(size*17)+opclass]; if (opclass>=StoreIntVal) dest=DESTSTORE; else dest=DESTREG; p5genmemaccess(op,base,offset,-1,-1,rd,size,dest,0); if (Volatile!=0) p5modinstrprops(0,0,0,VOLATILELOC); } /* p5 accessindri */ /***/ void p5accessindrr(int opclass,int rd,int base,int index,int size,int Volatile) { /****************************************************************/ /** opclass = 1 load int 5 store int **/ /** 2 load real 6 store real **/ /** 3 load unsigned 7 store unsigned **/ /****************************************************************/ int opcode,dest; opcode=accessop [(size*17)+opclass]; if (opclass>=StoreIntVal) dest=DESTSTORE; else dest=DESTREG; p5genmemaccess(opcode,base,0,index,0,rd,size,dest,0); } /* p5 accessindrr */ /***/ void p5oprx(int Opcode,int reg,struct Stkfmt *Stkin,int dest) { /*************************************************************************/ /** General operation involving an Estack item & reg (unless DEST=NOREG)**/ /** Most Eops come through here **/ /*************************************************************************/ struct procfmt *PI; int Size,i,j,AvailOffset,Form,Index,Base,Offset,Noteoffset,reg1,reg2,Flags,Area,Domain,CmValue; struct Stkfmt Modstk,Stk; Stk=*Stkin; Base=Stk.Base; Offset=Stk.Offset; Size=Stk.Size; Flags=Stk.Flags; CmValue=Stk.Cmval; /* Const modifier in Modforms only */ Stk.Cmval=0; /* In case stk modified and reused */ Area=-1; /* Not Known yet */ Domain=0; /* Not Known yet */ Form=Stk.Form&31; PI=(struct procfmt*)(currentPIaddr); switch (Form) { /***/ case RegAddr: /* (reg) is @ */ case RegVal: /* (reg) */ case Regvar: if (dest==SOURCELIT) /* Only comparisons and lit assigns to registers*/{ if (Opcode==CMP) { if (Stk.Size<4) reg1=LoadIntRO(&Stk); else reg1=Stk.Reg; p5oplit(Opcode,reg1,reg /*Lit if SOURCELIT*/,reg1); unlockreg(reg1); return ; } p5oplit(Opcode,Stk.Reg,reg /*Lit if SOURCELIT*/,Stk.Reg); } else if (dest==NOREG) { p5opr(Opcode,Stk.Reg); } else { if (!((instrgroup [Opcode]==INTLOAD)||(instrgroup [Opcode]==INTSTORE))) { if (dest==DESTREG) p5rr(Opcode,Stk.Reg,reg,reg); if (dest==DESTSTORE) p5rr(Opcode,reg,Stk.Reg,Stk.Reg); unlockreg(Stk.Reg); return ; } if (reg!=Stk.Reg) { if (dest==DESTSTORE) { p5copyireg(reg,Stk.Reg); } else { p5copyireg(Stk.Reg,reg); } } }; unlockreg(Stk.Reg); return ; /***/ case FregVal: case Fregvar: case AddrConst: /* @const */ Mabort(45); /* Bad form in StkAccess */ /***/ case Flitval: /* Floating literal */ if (Stk.Size==8) Msetconst((int)&Stk.Rlval,8,&Base,&Offset); else Msetconst((int)&Stk.Rval,4,&Base,&Offset); goto handledir; case LitVal: /* lit */ if (Stk.Size==8) { int *p = (int *)&Stk.Rlval; *p = Stk.Intvalue; /* gather the bits into one place ... */ *(p+1) = Stk.Modintval; /* ... */ Msetconst((int)&Stk.Rlval,8,&Base,&Offset); } else Msetconst((int)&Stk.Intvalue,4,&Base,&Offset); case TempAddr: /* (temp) is @*/ case TempVal: /* (temp) */ case DirAddr: /* (dir) is @ */ case DirVal: /* (dir) */ case ConstVal: /* const */ handledir: p5privateaccess(Opcode,reg,Base,Offset,Size,Flags&STKVOL,dest,Flags); return ; /***/ case IndRegVal: /* ((reg)) */ Base=Stk.Reg; Offset=0; Domain=Stk.Domain; Ind: p5genmemaccess(Opcode,Base,Offset,-1,-1,reg,Size,dest,Flags<<8); if ((Flags&(STKSWOPPED|STKVOL))==STKVOL) p5modinstrprops(0,0,0,VOLATILELOC); Stk.Size=Size; unlockreg(Base); /**/ /* for swopped items many instructions may have been issued so we cannot */ /* update instr fields safely here */ /**/ if ((Flags&STKSWOPPED)!=0) return ; instr->area=Area; instr->domain=Domain; instr->u0.offset=-1; if ((Language!=CCOMP)&&(Form==IndDirVal)&&(Stk.Base==GLA)&&(CheckFixups(GLA,Stk.Offset,&i,&Offset)>0) ) { instr->area=i; instr->u0.offset=Offset; /* pointer to known place */ } if ((Language==FORTRAN)&&((cgoptions&8)!=0)&&(Form==IndDirVal)&&(Stk.Base==PARAMS)) /*Params Independent */{ instr->area=0x7F00; /*Special pseudo area*/ instr->u0.offset=4*Stk.Offset; } return ; /***/ case IndDirVal: /* ((dir)) */ Domain=Stk.Domain; case IndTempVal: /* ((temp)) */ Stk.Form=DirVal; Stk.Size=4; Stk.Flags=(Flags&(~(STKSWOPPED|STKBSSWOPPED|STKIXSWOPPED)))|((Flags>>1)&STKSWOPPED); /* move STKBSSWOPPED -> STKSWOPPED */ Base=LoadIntRO(&Stk); Offset=0; goto Ind; /***/ case AddrDir: /* @dir */ handleAddrDir: /* addr dirs are normally loaded or pushed */ /* Use of a fixed literal is possible */ if ((dest==DESTREG)&&(instrgroup [Opcode]==INTLOAD)) reg2=reg; else reg2=claimreg(); Base=Stk.Base; Offset=Stk.Offset; if (Base==STACK) { p5oprmem(LEA,FRAMEPOINTER,Offset,reg2,0); p5modinstrprops(0,0,0,FRAMEACCESS); if ((-1024<=Offset)&&(Offset<0)) /*set addressed flag*/{ i=(unsigned)((-Offset)+3)>>2; if ((StackSTflags [i]&8)!=0) /* temp mark all of it */{ while ((StackSTflags [i]&8)!=0) { StackSTflags [i]|=7; i+=StackDirection; } } else { StackSTflags [i]|=4; PI->privprops|=FRAMEADDRTAKEN; } /* Big offsets */ } else { PI->privprops|=FRAMEADDRTAKEN; StackSTflags [0]|=4; } } else if (Base==PARAMS) { if ((0<=Offset)&&(Offset>2; paramSTflags [i]=paramSTflags [i]|4; if ((Size>4)&&(i<(((unsigned)Regparamsize>>2)-1))) paramSTflags [i+1]=paramSTflags [i+1]|4; /* Funny offsets multiplex to 0*/ } else paramSTflags [0]=paramSTflags [0]|4; Offset+=PARAMBASE; p5oprmem(LEA,FRAMEPOINTER,Offset,reg2,0); p5modinstrprops(0,0,0,FRAMEACCESS); instr->domain=Stk.Domain; /* instr_privprops=instr_privprops!POINTER DOMAIN */ } else { if ((Opcode==PUSH)&&(Pic==0)) { p5pushaddr(Base,Offset); unlockreg(reg2); return ; } reg1=CheckRegKey(ADDROF,Offset,Base,4,0); if (reg1>=0) { if (reg1!=reg2) { p5rr(MOV,reg1,reg2,reg2); instr->domain=Stk.Domain; /* instr_privprops=instr_privprops!POINTER DOMAIN */ unlockreg(reg1); } } else { AvailOffset=Offset; reg1=checkareaaddr(Base,&AvailOffset); if (reg1>=0) { p5oprmem(LEA,reg1,Offset-AvailOffset,reg2,0); instr->domain=Stk.Domain; /* instr_privprops=instr_privprops!POINTER DOMAIN */ } else { reg2=p5baseld(reg2,Base,Offset,Stk.Domain); } } }; if (dest==NOREG) { p5opr(Opcode,reg2); unlockreg(reg2); } else { if (!((instrgroup [Opcode]==INTLOAD)&&(dest==DESTREG))) { p5rr(Opcode,reg2,reg,reg); unlockreg(reg2); } } return ; /***/ case IndRegModVal: /* ((reg)+M) */ Domain=Stk.Domain; case AddrDirMod: /* @dir+M */ case RegModAddr: /* (reg)+M */ case TempModAddr: /* (temp)+M */ case DirModAddr: /* (dir)+M */ case IndTempModVal: /* ((temp)+M) */ case IndDirModVal: /* ((dir)+M) */ case AddrDirModVal: /* (dir+M) */ case IndDispModVal: /* access to global stack frame */ case AddrDispModVal: /* address in global stackfram)*/ case DispModAddr: /* address in global stackfram)*/ if ((Stk.Form==IndDispModVal)||(Stk.Form==AddrDispModVal)||(Stk.Form==DispModAddr)) { PI->privprops|=GLOBALACCESS; } if (((Stk.Form==AddrDirMod)||(Stk.Form==AddrDirModVal))&&(Stk.Base==STACK)) { { PI->privprops|=FRAMEADDRTAKEN; StackSTflags [0]|=4; } } if (Stk.Modform==LitVal) { Offset=Stk.Modintval+CmValue; Index=0; Form=LitVal; } else { memset(&Modstk,0,sizeof( struct Stkfmt)); Modstk.Form=Stk.Modform; Modstk.Base=Stk.ModBase; Modstk.Offset=Stk.Modoffset; Modstk.Reg=Stk.Modreg; Modstk.Size=4; Modstk.Flags=(Flags&(~(STKSWOPPED|STKBSSWOPPED|STKIXSWOPPED)))|(((unsigned)Flags>>2)&STKSWOPPED ); /* move STKIXSWOPPED -> STKSWOPPED */ Noteoffset=Modstk.Offset; if ((Modstk.Form&31)==RegVal) Index=Modstk.Reg; else Index=LoadIntRO(&Modstk); Modstk.Offset=0; if (Stk.Scale>3) { if (registerstatus(Index)!=1) { reg1=Index; Index=claimreg(); p5rr(MOV,reg1,Index,Index); unlockreg(reg1); } p5rlit(SHL,Index,Stk.Scale,Index); lockregister(Index,0,4); Stk.Scale=0; } Form=RegVal; Offset=Modstk.Offset; } switch (Stk.Form&31) { /***/ case AddrDirMod: /* @dir+M */ if (Form==LitVal) { Stk.Offset=Stk.Offset+Offset; goto handleAddrDir; } if (Opcode==LW) reg2=reg; else reg2=claimreg(); if ((Stk.Base==STACK)||(Stk.Base==PARAMS)) { if (Stk.Base==STACK) Offset=Stk.Offset+STACKBASEOFFSET; else Offset=Stk.Offset+PARAMBASE; p5genmemaccess(LEA,FRAMEPOINTER,Offset+CmValue,Index,Stk.Scale,reg2,Size,DESTREG,0); } else if ((Pic!=0)&&(isarealocal(Stk.Base)==0)) { Base=p5baseld(-1,Stk.Base,0,0); Offset=Stk.Offset+AreaBaseOffset; p5genmemaccess(LEA,Base,Offset+CmValue,Index,Stk.Scale,reg2,Size,DESTREG,0); unlockreg(Base); } else { p5genmemaccess(LEA,Stk.Base,Stk.Offset+CmValue,Index,Stk.Scale,reg2,Size,DESTREG,1); } unlockreg(Index); if (Opcode!=LW) { memset(&Modstk,0,sizeof( struct Stkfmt)); Modstk.Form=RegVal; Modstk.Reg=reg2; Modstk.Size=4; p5oprx(Opcode,reg,&Modstk,dest) /* Should unlock reg2 */; } return ; /***/ case RegModAddr: /* (reg)+M */ if (Opcode==LW) reg2=reg; else reg2=claimreg(); if (Form==LitVal) { p5oprmem(LEA,Stk.Reg,Offset,reg2,Size); } else { p5genmemaccess(LEA,Stk.Reg,CmValue,Index,Stk.Scale,reg2,Size,DESTREG,0); unlockreg(Index); } unlockreg(Stk.Reg); if (Opcode!=LW) { memset(&Modstk,0,sizeof( struct Stkfmt)); Modstk.Form=RegVal; Modstk.Reg=reg2; Modstk.Size=4; p5oprx(Opcode,reg,&Modstk,dest) /* Should unlock reg2 */; } return ; /***/ case TempModAddr: /* (temp)+M */ case DirModAddr: /* (dir)+M */ case DispModAddr: Stk.Form=DirVal; Stk.Size=4; Stk.Flags=(Flags&(~(STKSWOPPED|STKBSSWOPPED|STKIXSWOPPED)))|(((unsigned)Flags>>1)&STKSWOPPED); /* move STKBSSWOPPED -> STKSWOPPED */ Base=LoadIntRO(&Stk); if (Opcode==LW) reg2=reg; else reg2=claimreg(); if (Form==LitVal) { p5oprmem(LEA,Base,Offset,reg2,Size); } else { p5genmemaccess(LEA,Base,CmValue,Index,Stk.Scale,reg2,Size,DESTREG,0); unlockreg(Index); } instr->domain=Stk.Domain; /* instr_privprops=instr_privprops!POINTER DOMAIN */ unlockreg(Base); if (Opcode!=LW) { memset(&Modstk,0,sizeof( struct Stkfmt)); Modstk.Form=RegVal; Modstk.Reg=reg2; Modstk.Size=4; p5oprx(Opcode,reg,&Modstk,dest) /* Should unlock reg2 */; } return ; /***/ case IndRegModVal: /* ((reg)+M) */ if (Form==LitVal) { Base=Stk.Reg; goto Ind; } p5genmemaccess(Opcode,Stk.Reg,CmValue,Index,Stk.Scale,reg,Size,dest,Flags<<8); unlockreg(Stk.Reg); unlockreg(Index); if ((Flags&STKVOL)!=0) p5modinstrprops(0,0,0,VOLATILELOC); return ; /***/ case IndTempModVal: /* ((temp)+M) */ case IndDirModVal: /* ((dir)+M) */ case IndDispModVal: Stk.Form=DirVal; Stk.Size=4; i=CheckFixups(Stk.Base,Stk.Offset,&Area,&j /* attempt to find area of access */); Stk.Flags=(Flags&(~(STKSWOPPED|STKBSSWOPPED|STKIXSWOPPED)))|(((unsigned)Flags>>1)&STKSWOPPED); /* move STKBSSWOPPED -> STKSWOPPED */ /**/ /* we could be very short of registers here */ /**/ if ((instrgroup [Opcode]==INTLOAD)&&(countunclaimedregs()==0)&&(reg!=Index)&&(registerstatus(reg)==1) ) { unlockreg(reg); Base=LoadIntRO(&Stk); forgetreg(reg); lockregister(reg,0,4); } else Base=LoadIntRO(&Stk); Stk.Form=IndRegModVal; Stk.Reg=Base; if (Form==LitVal) goto Ind; p5genmemaccess(Opcode,Base,CmValue,Index,Stk.Scale,reg,Size,dest,Flags<<8); if ((Flags&STKSWOPPED)==0) instr->area=Area; Stk.Size=Size; unlockreg(Index); unlockreg(Base); if ((Flags&STKVOL)!=0) p5modinstrprops(0,0,0,VOLATILELOC); return ; /***/ case AddrDirModVal: /* (dir+M) */ case AddrDispModVal: Stk.Form=DirVal; if (Form==LitVal) { Stk.Intvalue=Stk.Intvalue+Offset; goto handledir; } if ((Stk.Base==STACK)||(Stk.Base==PARAMS)) { if (Stk.Base==PARAMS) Offset=Stk.Offset+PARAMBASE; else Offset=Stk.Offset+STACKBASEOFFSET; p5genmemaccess(Opcode,FRAMEPOINTER,Offset+CmValue,Index,Stk.Scale,reg,Size,dest,Flags<<8); if ((Flags&STKVOL)!=0) p5modinstrprops(0,0,0,VOLATILELOC); p5modinstrprops(0,0,0,FRAMEACCESS); if ((Flags&STKSWOPPED)==0) instr->area=Stk.Base; unlockreg(Index); return ; } Offset=(Stk.Offset+AreaBaseOffset)+CmValue; AvailOffset=Offset; Base=checkareaaddr(Stk.Base,&AvailOffset); if ((Pic!=0)&&(Base<0)&&(isarealocal(Stk.Base)==0)) { Base=p5baseld(-1,Stk.Base,0,0); AvailOffset=0; } if (Base>=0) { Offset-=AvailOffset; p5genmemaccess(Opcode,Base,Offset,Index,Stk.Scale,reg,Size,dest,Flags<<8); unlockreg(Base); } else { p5genmemaccess(Opcode,Stk.Base,Offset,Index,Stk.Scale,reg,Size,dest,(Flags<<8)|1); } unlockreg(Index); if ((Flags&STKSWOPPED)==0) instr->area=Stk.Base; if ((Flags&STKVOL)!=0) p5modinstrprops(0,0,0,VOLATILELOC); return ; default: Mabort(998); } /***/ default: Mabort(998); } } /* p5 Op RX */ /***/ void p5stkaccess(int Opclass,int reg,struct Stkfmt *Stk) { /************************************************************************/ /** Main operand-addressing function. Reg is the register to be loaded **/ /** to or stored from. Reg should be passed to the routine in a locked **/ /** state. Other registers used to access the operand are returned in **/ /** an unlocked state. Note that this routine may modify the Stk **/ /** record. If the register is being loaded to then it should have its **/ /** tracking cleared after calling this routine. **/ /** **/ /** opclass = 1 load int 9 store int **/ /** 2 load real 10 store real **/ /** 3 load unsigned 11 store unsigned **/ /** 5 load misreal 13 store misreal **/ /** 7 load misint 15 store misint **/ /** 8 load misUint 16 store misUint **/ /************************************************************************/ int Opcode,dest,Size; Size=Stk->Size; Opcode=accessop [(Size*17)+Opclass]; if (Opclass>=StoreIntVal) dest=DESTSTORE; else dest=DESTREG; if ((Opclass<=LoadMisUintVal)&&((SimpleRegForm [Stk->Form&31]==0)||(Stk->Reg!=reg))) { forgetreg(reg); } p5oprx(Opcode,reg,Stk,dest); } /*p5 stkaccess*/ /***/ #if(GENGLAINDFIXUPS!=0) static int AreaKeyRef(int area,int adjustment) { /*****************************************************************************/ /* Returns the offset of a pointer into the given data area. **/ /*****************************************************************************/ struct areakeysegfmt *CurAreaKey; int I,J,K; /* Search to see if there is already a suitable entry */ if (Maxareakey>=0) { CurAreaKey=AreaKey; K=Maxareakey&0xFF; for (I=0; I<=(unsigned)Maxareakey>>8; I++) { for (J=K; J>=0; J--) { if ((CurAreaKey->reckeys [J].key==area)&&(CurAreaKey->reckeys [J].adj==adjustment)) { return CurAreaKey->reckeys [J].offset; } } K=254; CurAreaKey=(struct areakeysegfmt*)(CurAreaKey->backchain); } } /* if we have reached the end of a segment of 255 entries then malloc */ /* another segment and generate a backward pointer to the previous */ /* segment */ if (Maxareakey==-1) { AreaKey=(struct areakeysegfmt*)(BMalloc(sizeofareaseg,1,MAAREAKEYS)); AreaKey->backchain=0; Maxareakey=0; } else { Maxareakey+=1; if ((Maxareakey&0xFF)==255) { Maxareakey+=1; CurAreaKey=AreaKey; AreaKey=(struct areakeysegfmt*)(BMalloc(sizeofareaseg,1,MAAREAKEYS)); AreaKey->backchain=(int)CurAreaKey; } } /* Generate a fixup to the area in GLA */ I=epermspace(4,4); Pd4(GLA,I,0); AreaKey->reckeys [Maxareakey&0xFF].key=area; AreaKey->reckeys [Maxareakey&0xFF].offset=I; AreaKey->reckeys [Maxareakey&0xFF].adj=adjustment; if (area>CNST) area=egiveareaid(area); pfix(GLA,I,area,adjustment); /* Base pointer can be offset */ return I; } /*AreaKeyRef*/ #endif; /***/ int p5tempspace(int bytes,int align) { /************************************************************************/ /** Interface to etempspace but recording access in StackSTflags **/ /** since temps can not be pointed at so can be freely rescheduled **/ /** Dont record access to large items(temp records) since these can be **/ /** pointed at and not noticed **/ /************************************************************************/ int offset,i; static const int stadj=0; offset=etempspace(bytes,align)+stadj; if (((-1024<=offset)&&(offset<=0))&&(bytes<=8)) { i=(unsigned)(-offset)>>2; StackSTflags [i]|=8; /* mark as temp */ if (bytes>4) StackSTflags [i-1]|=8; } return offset-stadj; } /* p5 tempspace */