


/* 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<<FLAGREG);
	if ((e&6)!=0)  instr->cdef|=(1<<FLAGREG);
	if ((e&0x10)!=0)  instr->cref|=(1<<FSTP);
	if ((e&0x20)!=0)  instr->cdef|=(1<<FSTP);
	if ((e&0x40)!=0)  instr->cref|=(1<<FCCBIT);
	if ((e&0x80)!=0)  instr->cdef|=(1<<FCCBIT);
	/**/
	/* adhocery may have to follow here                                          */
	/**/
	if (opcode==FLDCW)  instr->cdef|=((1<<FPSCR))|(1<<FCCBIT);
	if (opcode==FINIT) {
		instr->cdef|=(1<<FPSCR)|(1<<FCCBIT)|(1<<FSTP);
		instr->fdef=255;
	}
	if ((instrgroup [opcode]==SHIFTS)&&(instrform [opcode]!=SLITFORM)) {
		instr->rref|=(1<<ECX);	/* Variable shifts read ECX */
	}
}	/*p5 side effect*/
void p5specmove(int op,int rs,int rd) {
	/*************************************************************************/
	/**    Move to & from special registers and coprocessor registers            */
	/*************************************************************************/
}
/***/
void p5alterareaoffset(int newarea,int newoffset) {
	instr->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<<ECX);
		instr->rdef|=(257<<ECX);
	}
}
/***/
void p5plantnop() {
	/*************************************************************************/
	/**     Inserts a nop                                                   **/
	/*************************************************************************/

	previnstr=instr;	 
	instr=BNewInstr();
	instr->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<<rd)&RegClaimMaskA))!=0)  instr->privprops=REGVARASSN;
	instr->rref=1<<rs1;
	if (!(op==MOV))  instr->rref|=(1<<rd);	/*%or op=MOVB*/
	instr->rdef=257<<rd;
	if ((op==MOVB)||(op==CMPB)||(op==SB)) {
		instr->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<<ESP)|(1<<EBP);
	instr->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<<FPSCR;
	instr->props=DESTROYABLE;
	instr->group=group;
	if (group==FPCOMPARE)  instr->cdef=1<<FCCBIT;	/*sets the condition code*/
	instr->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<<FPSCR)|(1<<FSTP);
	newinstr->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<<rd)|(256<<ESP);
			instr->rdef=257<<ESP;
			instr->props|=STOREINSTR;
		} else if (op==POP) {
			if ((((1<<rd)&RegClaimMaskA))!=0)  instr->privprops=REGVARASSN;
			instr->rref=1<<ESP;
			instr->rdef=(257<<rd)|(257<<ESP);
			instr->props|=LOADINSTR;
		} else {
			instr->rref=1<<rd;
			instr->rdef=257<<rd;
			instr->u1.immval=1; 	/* to be like add $1 or SUB $1 */
		}

	} else if (op==BSWAP) {
		instr->csize=2;
		instr->variant=OPPLUSR;
		instr->rref=1<<rd;
		instr->rdef=257<<rd;
	} else if ((op==DIV)||(op==IDIVIDE)||(op==MUL)) {
		instr->rdef=(257<<EAX)|(257<<EDX);
		instr->rref=(instr->rdef&255)|(1<<rd);
		instr->csize=p5opcodesize(op,OPR)+1;
		instr->variant=OPR;
		instr->rmbyte=0xC0;
	} else {
		instr->rdef=257<<rd;
		instr->rref=1<<rd;
		instr->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<<ESP;
			instr->rdef=257<<ESP;
			instr->props|=LOADINSTR|STOREINSTR;
		} else if (op==POP) {
			instr->rref=256<<ESP;
			instr->rdef=257<<ESP;
			instr->props|=STOREINSTR|LOADINSTR;
		} else {
			instr->props|=STOREINSTR|LOADINSTR;
		}

	} else if ((op==DIV)||(op==IDIVIDE)||(op==MUL)) {
		instr->props|=LOADINSTR;
		instr->rdef=(257<<EAX)|(257<<EDX);
		instr->rref=instr->rdef&255;	/* Refernces alphas */
	} else Mabort(961);

	instr->rref|=(256<<base);	/* reads the Beta version AGI delay*/
	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->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<<ESP;
			instr->rdef=257<<ESP;
			instr->props|=STOREINSTR;
		} else if (op==POP) {
			instr->rref=256<<ESP;
			instr->rdef=257<<ESP;
			instr->props|=LOADINSTR;
		} else {
			instr->props|=STOREINSTR|LOADINSTR;
		}

	} else if ((op==DIV)||(op==IDIVIDE)||(op==MUL)) {
		instr->props|=LOADINSTR;
		instr->rdef=(257<<EAX)|(257<<EDX);
		instr->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<<GOTREG);	/* reads the Beta version AGI delay*/
	}
	if ((size==2)&&(instr->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<<ESP;
	instr->rdef=257<<ESP;
	p5sideeffects(PUSH);
	if (Report && !inhibitdis)  p5disasinstr(instr,&localca);
	if (Pic!=0)  Mabort(986);
}	/*p5 pushaddr*/
/***/
void p5oplitmem(int op,int lit,int base,int disp,int size) {
	/*************************************************************************/
	/**    No register literal direct to memory                             **/
	/*************************************************************************/
	int dsize;
	dsize=size;
	previnstr=instr;	 
	instr=BNewInstr();
	instr->opcode=op;
	instr->group=instrgroup [op];
	instr->rs1=base;
	instr->rref=256<<base;	/* reads the Beta version AGI delay*/
	instr->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<<ESP);
		instr->rdef=257<<ESP;
		instr->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<<GOTREG);
	}
	if ((size==2)&&(instr->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<<rd)&RegClaimMaskA)  instr->privprops=REGVARASSN;
	instr->rref=1<<rs1;
	instr->rdef=257<<rd;
	if (op==MOVB || op==CMPB) {
		instr->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<<rd;
	instr->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<<rd)&RegClaimMaskA))!=0)  instr->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<<base;
	instr->rdef=257<<rd;
	if ((instr->group!=INTLOAD)&&(op!=LEA)) {
		instr->rref|=(1<<rd);
	}
	if ((op==MOVB)||(op==CMPB)||(op==SB)) {
		instr->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<<base;
	if (instr->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<<FCCBIT;
		instr->fdef=0;
	}
	instr->cref|=(1<<FPSCR);
	if (base==ESP)  instr->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<<base)|(1<<rd);
	if (instr->group!=INTSTORE) {
		instr->rref|=(1<<rd);
		instr->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<<rd)&RegClaimMaskA))!=0)  instr->privprops|=REGVARASSN;
	instr->area=area;
	instr->domain=0;
	instr->datasize=size;
	instr->u0.offset=offset;
	instr->rdef=257<<rd;
	if ((instr->group!=INTLOAD)&&(op!=LEA)) {
		instr->rref=1<<rd;
	}
	if ((op==MOVB)||(op==CMPB)||(op==SB)) {
		instr->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<<GOTREG);
	}
	if (op==LEA) {
		instr->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<<GOTREG);
	}
	if (instr->group==FPCOMPARE) {
		instr->cdef=1<<FCCBIT;
		instr->fdef=0;
	}
	instr->cref|=(1<<FPSCR);
	p5sideeffects(op);
	if (Report && !inhibitdis)  p5disasinstr(instr,&localca);
}	/* p5 loadri                                                               */
/***/
void p5opfixmemr(int op,int area,int offset,int rd,int size) {
	/*************************************************************************/
	/** Store operations and also add to store operations                   **/
	/** Where the 32 bit disp is fixed to area & offset                     **/
	/*************************************************************************/
	previnstr=instr;	 
	instr=BNewInstr();
	instr->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<<rd;
	if (instr->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<<GOTREG);
	}
	if (size==2)  p5addprefix(osprefix,SHORTOPND);
	p5sideeffects(op);
	if (Report && !inhibitdis)  p5disasinstr(instr,&localca);
}	/* p5 opfixmemr                                                            */
/***/
static void byteswop(int reg,int op,int size) {
	/*************************************************************************/
	/** Byte swop a register after loading or before storeing               **/
	/*************************************************************************/
	if ((size==1)||(op==LEA))  return ;
	if (size==4) {
		p5opr(BSWAP,reg);
		forgetreg(reg);
		return ;
	}
	if (size==2) {
		p5opr(BSWAP,reg);
		forgetreg(reg);
		if (op==LH)  p5oplit(SAR,reg,16,reg); 
		else p5oplit(SHR,reg,16,reg);
		return ;
	}
	Mabort(923);
}
/***/
#define FIX 4
#define INDEXED 8
void p5genmemaccess(int op,int baseorarea,int offset,int index,int scale,int reg,int size,int dest,
int flags) {
	/*************************************************************************/
	/** The most general form of accessing store                            **/
	/*& Flags=Fixed&1 ! (stk_flags<<8) which hold the swopped bits          **/
	/** Fixed =1 for a Fixed up access on area & offset                     **/
	/** Fixed =0 for base displacement                                      **/
	/** scale =0,1,2,3 for indexed access -1 for no index                   **/
	/** dest  = NOREG for memory access only                                **/
	/**       = DESTREG for memory => 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<FILD)  switch (j) {

	case NOREG:
		p5opmem(op,baseorarea,offset,size);
		goto common;

	case DESTREG:
		p5oprmem(op,baseorarea,offset,reg,size);
		goto common;

	case DESTREG+STKSWOPPED:
		inhibitdis--;
		p5oprmem(op,baseorarea,offset,reg,size);
		byteswop(reg,op,size);
		return ;

	case DESTSTORE:
		p5opmemr(op,baseorarea,offset,reg,size);
		goto common;

	case DESTSTORE+STKSWOPPED:
		inhibitdis--;
		byteswop(reg,op,size);
		p5opmemr(op,baseorarea,offset,reg,size);
		return ;

	case SOURCELIT:
		p5oplitmem(op,reg,baseorarea,offset,size);
		goto common;

	case 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));
		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<<index);
		goto common;

	case INDEXED+DESTREG:
		p5oprmem(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		instr->u0.offset=-1;
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		goto common;

	case INDEXED+DESTREG+STKSWOPPED:
		inhibitdis--;
		p5oprmem(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		instr->u0.offset=-1;
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		byteswop(reg,op,size);
		return ;

	case INDEXED+DESTSTORE:
		p5opmemr(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		instr->u0.offset=-1;
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		goto common;

	case INDEXED+DESTSTORE+STKSWOPPED:
		inhibitdis--;
		byteswop(reg,op,size);
		p5opmemr(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		instr->u0.offset=-1;
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		return ;

	case INDEXED+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));

	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<<index);
		goto common;

	case INDEXED+FIX+NOREG:
		p5opfixmem(op,baseorarea,offset,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		/*      instr_offset=-1                                                      */
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		goto common;

	case INDEXED+FIX+DESTREG:
		p5oprfixmem(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		/*      instr_offset=-1                                                      */
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		goto common;

	case INDEXED+FIX+DESTREG+STKSWOPPED:
		inhibitdis--;
		p5oprfixmem(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		/*      instr_offset=-1                                                      */
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		byteswop(reg,op,size);
		return ;

	case INDEXED+FIX+DESTSTORE:
		p5opfixmemr(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		/*      instr_offset=-1                                                      */
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		goto common;

	case INDEXED+FIX+DESTSTORE+STKSWOPPED:
		inhibitdis--;
		byteswop(reg,op,size);
		p5opfixmemr(op,baseorarea,offset,reg,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		/*      instr_offset=-1                                                      */
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		return ;

	case INDEXED+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));

	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<<index);
		goto common;
	default:
		Mabort(998);
	}
	if ((swopped!=0)&&(Fstlvolswop==0)) {
		{
#if(OutputASSEMBLER==Positive) 
			char s [33] ;
			/* Obtain external ids for the swopped floating support procs */

			extern int Iextname( char * );
			strcpy(s,fstdvolname);
			Fstlvolswop=Iextname(s);
			strcpy(s,fstlname);
			Fstlswop=Iextname(s);
			strcpy(s,flddvolname);

			Fldlvolswop=Iextname(s);
			strcpy(s,fldlname);
			Fldlswop=Iextname(s);

#else
			Fstlvolswop=Mgetprockey(9,fstdvolname);
			Fstlswop=Mgetprockey(9,fstlname);
			Fldlvolswop=Mgetprockey(9,flddvolname);
			Fldlswop=Mgetprockey(9,fldlname);

#endif;
		}
	}
	if (swopped!=0 && pi->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<<EAX)|(257<<ECX)|(257<<EDX)));
		}
		unlockreg(wreg);
		return ;

	case DESTSTORE+STKSWOPPED:
	case FIX+DESTSTORE+STKSWOPPED:
	case INDEXED+FIX+DESTSTORE+STKSWOPPED:
	case INDEXED+DESTSTORE+STKSWOPPED:
		wreg=claimreg();
		inhibitdis--;
		if (size==4) {
			p5fopmem(FSTPm,EBP,pi->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<<EAX)|(257<<ECX)|(257<<EDX)));
		}
		unlockreg(wreg);
		return ;

	case FIX+NOREG:
	case FIX+DESTREG:
	case FIX+DESTSTORE:
		p5fopfixmem(op,baseorarea,offset,size);
		goto common;

	case INDEXED+NOREG:
	case INDEXED+DESTREG:
	case INDEXED+DESTSTORE:
		p5fopmem(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<<index);
		goto common;

	case INDEXED+FIX+NOREG:
	case INDEXED+FIX+DESTREG:
	case INDEXED+FIX+DESTSTORE:
		p5fopfixmem(op,baseorarea,offset,size);
		instr->privprops|=SIBREQD;
		instr->csize++;
		/*      instr_offset=-1                                                      */
		instr->sib=(scale<<6)|(5*Fixed);
		instr->rs2=index;
		instr->rref|=(256<<index);
		goto common;
	default:
		Mabort(998);
	}

common:
	inhibitdis--;
	if (Report && !inhibitdis)  p5disasinstr(instr,&localca);
}	/*p5 genmemaccess*/
/***/
void p5loadri(int op,int rs1,int lit,int rd) {
	/*************************************************************************/
	/** For compatability with calls from mprocs                            **/
	/*************************************************************************/
	int size;
	if ((op==LB)||(op==LBU))  size=1; 
	else if ((op==LH)||(op==LHU))  size=2; 
	else size=4;

	p5oprmem(op,rs1,lit,rd,size);
}	/*p5 loadri*/
/***/
void p5floadri(int op,int rs1,int lit,int rd) {
	/*************************************************************************/
	/** For compatability with calls from mprocs                            **/
	/*************************************************************************/
	int size;
	if (op==FLDq)  size=12; 
	else if (op==FLDd)  size=8; 
	else size=4;

	p5fopmem(op,rs1,lit,size)	/* loads only to tos*/;
}
/***/
void p5storeri(int op,int rd,int rs1,int lit) {
	/*************************************************************************/
	/** For compatability with calls from mprocs                            **/
	/*************************************************************************/
	int size;
	if (op==SB)  size=1; 
	else if (op==SH)  size=2; 
	else size=4;

	p5opmemr(op,rs1,lit,rd,size);
}	/* p5 storeri                                                              */
/***/
void p5fstoreri(int op,int rd,int rs1,int lit) {
	/*************************************************************************/
	/** For compatability with calls from mprocs                            **/
	/*************************************************************************/
	int size;
	if (op==FSTPq)  size=12; 
	else if ((op==FSTd)||(op==FSTPd))  size=8; 
	else size=4;

	p5fopmem(op,rs1,lit,size);
}	/* p5 floadri                                                              */
/***/
/***/
void p5jlkri(int op,int lit) {
	/*************************************************************************/
	/** Jump by a fixed displacement. Note difference between jal           **/
	/** and B(ranches). Jal is not pc relative                              **/
	/*************************************************************************/
	previnstr=instr;	 
	instr=BNewInstr();
	instr->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<<rd)&RegClaimMaskA))!=0)  instr->privprops=REGVARASSN;
	instr->rdef=257<<rd;
	if (Pic==0) 	/*not Position Independent Code*/{
		instr->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<<ESP)|(257<<EAX))|(257<<ECX))|(257<<EDX);
	instr->rref|=(1<<EBP);	/* may have set up a frigged EBP */
				/* this makes sure Doubledefs does */
				/* not delete it!!		  */
	if (Pic) instr->rref|=1<<EBX;	/* First call goes via GOT */
	instr->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<<ESP)|(1<<EBP);
	if (Pic) instr->rref|=1<<EBX;	/* First call goes via GOT */
	/* The Intel support for long shifts break all the ruiles of the ABI by
	   passing their parameters in EAX,EDX & ECX and not on stack. It seems
	   best to do all the frigging necessary for this horror here and not
	   let it back up further into the more target independent routines    */

	if (strcmp(exdata->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<<EAX)|(1<<ECX)|(1<<EDX);

	if ((callprops&(1<<17))!=0)  instr->rref|=(1<<EDX);	/* mcount call */
	instr->rdef=(((257<<ESP)|(257<<EAX))|(257<<ECX))|(257<<EDX);
	instr->cdef=1<<FLAGREG;
	instr->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<<ESP;
	instr->rdef=257<<ESP;
	instr->cdef=1<<FLAGREG;
	instr->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<<FLAGREG;
		instr->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<<GOTreg;
	instr->rref=256<<GOTreg;
	instr->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<<rd)&RegClaimMaskA))!=0)  instr->privprops=REGVARASSN;
		instr->group=instrgroup [MOV];
		instr->props=DESTROYABLE;
		instr->fixtype=NORMALFIX;
		instr->rdef=257<<rd;
		instr->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<<rd)&RegClaimMaskA))!=0)  instr->privprops|=REGVARASSN;
			instr->area=area;
			instr->u0.offset=0;
			instr->domain=0;
			instr->datasize=4;
			instr->rdef=257<<rd;
			instr->csize=5+p5opcodesize(LW,OPRRM);
			instr->variant=OPRRM;
			instr->rmbyte=0x80;	/* 32 bit disp  only */
			instr->fixtype=GOTofffix;
			instr->rs1=GOTREG;
			instr->rref=256<<GOTREG;
			p5sideeffects(LW);
			if (Report && !inhibitdis)  p5disasinstr(instr,&localca);
			if (offset!=0)  p5oplit(ADD,rd,offset,rd);
		}
	}
}	/* p5 ldfix                                                                */

/***/
void p5codefix(int labindex,int offset,int rd) {
	/***********************************************************************/
	/** generate a sethi/or sequence which loads rd with the address of   **/
	/** the label identified by labindex and adjust the address by offset **/
	/***********************************************************************/

	Mabort(79);	/*%if rd=rZERO*/
	/**/
	/* This will not work but is not called                                      */
	/**/
}	/* p5 codefix                                                              */
/***/
static int p5baseld(int reg,int area,int Offset,int domain) {
	/*************************************************************************/
	/**    Sets a register to 'offset' from the start of 'area'.            **/
	/**    If domain is non-zero then the loaded address is in the given    **/
	/**    domain.                                                          **/
	/*************************************************************************/
	int reg1,Toffset;
#if(GENGLAINDFIXUPS!=0)
	int key;
#endif

	reg1=CheckRegKey(ADDROF,Offset,area,4,0);
	if ((reg1>=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<<newdest;
		return 1;
	}
	/**/
	/*  op r1,r2 can be rewritten op r2,r1 if op commutable                      */
	/**/
	if ((var==OPRR)&&(instr->rs1==newdest)&&((op==ADD)||(op==OR)||(op==XOR)||(op==AND))) {
		instr->rs1=instr->rd;
		instr->rd=newdest;
		instr->rdef=257<<newdest;
		return 1;
	}
	/**/
	/* imul by lit has sepearate source & dest registers                         */
	/**/
	if (op==IMUL && (var==OPRLIT || var==OPRSLIT)) {
		instr->rd=newdest;
		instr->rdef=257<<newdest;
		return 1;
	}
	/**/
	/* LEA can be used to give a 3 address form of add r1,r2                     */
	/**/
	if ((op==ADD)&&(var==OPRR)) {
		instr->rs2=instr->rd;
		instr->sib=0;
		instr->opcode=LEA;
		instr->variant=OPRRM;
		instr->csize=3;
		instr->rmbyte=0;
		instr->rd=newdest;
		instr->rdef=257<<newdest;
		instr->rref=(256<<instr->rs1)|(256<<instr->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<<newdest;
		instr->rref=256<<instr->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<<instr->rd;
		instr->rref=(1<<instr->rd)|(1<<instr->rs1);
	} else {
		instr->rd=newdest;
		instr->rdef=257<<instr->rd;
		instr->rref=1<<instr->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<<source;
	dbit=257<<dest;
	storeinstr=NULL;
	do {
		if ((curinstr->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<<ECX)|(257<<EDI),((1<<ECX)|(1<<EDI))|(1<<EAX));
	p5addprefix(iprefix,REP);
	p5oponly(CLD,0,0);
}	/*p5 unass fill*/
/***/
void p5FSRaccess(int op,int area,int offset) {
	/****************************************************************/
	/** op = LDFSR/STFSR                                           **/
	/****************************************************************/
}	/* mips FSRaccess                                                          */
/***/
/***/
static void p5privateaccess(int opcode,int rd,int Area,int Offset,int size,int Volatile,int dest,int flags
) {
	/****************************************************************/
	/**  Designed for private access only Public access                     **/
	/** should go via p5 stkaccess                                          **/
	/** dest can be NOREG,DESTREG or DESTSTORE                              **/
	/****************************************************************/
	int Base,index,i,AccessType,ActOffset;
	int AvailOffset,Origoffset;

	if (Area==PARAMS)  ActOffset=Offset+PARAMBASE; 
	else if (Area==STACK)  ActOffset=Offset+STACKBASEOFFSET
	; 
	else ActOffset=Offset+AreaBaseOffset;

	Origoffset=Offset;
	index=0;
	Base=-1;
	if ((Area==STACK)||(Area==PARAMS)) {
		if ((dest==DESTSTORE)||(opcode==POP))  AccessType=1; 
		else AccessType=2;	/*store*/
		/*load*/
		if (Area==PARAMS) {
			if (Offset<Regparamsize) {
				i=(unsigned)Offset>>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<Regparamsize)) 	/*set addressed flag*/{
				i=(unsigned)(Offset&(-4))>>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                                                            */
