2160 lines
		
	
	
	
		
			48 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			2160 lines
		
	
	
	
		
			48 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
EM_WSIZE = 4
 | 
						|
EM_PSIZE = 4
 | 
						|
EM_BSIZE = 8    /* two words saved in call frame */
 | 
						|
 | 
						|
INT8 = 1        /* Size of values */
 | 
						|
INT16 = 2
 | 
						|
INT32 = 4
 | 
						|
INT64 = 8
 | 
						|
 | 
						|
FP_OFFSET = 0   /* Offset of saved FP relative to our FP */
 | 
						|
PC_OFFSET = 4   /* Offset of saved PC relative to our FP */
 | 
						|
 | 
						|
#define COMMENT(n) /* noop */
 | 
						|
 | 
						|
 | 
						|
#define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64)
 | 
						|
 | 
						|
#define smalls(n) sfit(n, 16)
 | 
						|
#define smallu(n) ufit(n, 16)
 | 
						|
 | 
						|
#define lo(n) (n & 0xFFFF)
 | 
						|
#define hi(n) ((n>>16) & 0xFFFF)
 | 
						|
 | 
						|
/* Use these for instructions that treat the low half as signed --- his()
 | 
						|
 * includes a modifier to produce the correct value when the low half gets
 | 
						|
 * sign extended. Er, do make sure you load the low half second. */
 | 
						|
#define los(n) (n & 0xFFFF)
 | 
						|
#define his(n) ((hi(n) - (lo(n)>>15)) & 0xFFFF)
 | 
						|
 | 
						|
#define IFFALSE {CONST, 4}
 | 
						|
#define IFTRUE {CONST, 12}
 | 
						|
#define ALWAYS {CONST, 20}
 | 
						|
#define DCTRZ {CONST, 34}
 | 
						|
 | 
						|
#define LT {CONST, 0}
 | 
						|
#define GT {CONST, 1}
 | 
						|
#define EQ {CONST, 2}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
PROPERTIES
 | 
						|
 | 
						|
	GPR             /* any GPR */
 | 
						|
	REG             /* any allocatable GPR */
 | 
						|
	FPR             /* any FPR */
 | 
						|
	FREG            /* any allocatable FPR */
 | 
						|
	SPR             /* any SPR */
 | 
						|
	CR              /* any CR */
 | 
						|
	
 | 
						|
	GPR0  GPRSP GPRFP GPR3  GPR4  GPR5  GPR6  GPR7
 | 
						|
	GPR8  GPR9  GPR10 GPR11 GPR12 GPR13 GPR14 GPR15
 | 
						|
	GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23
 | 
						|
	GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31
 | 
						|
	
 | 
						|
	CR0   CR1
 | 
						|
 | 
						|
	FPR0  FPR1  FPR2  FPR3  FPR4  FPR5  FPR6  FPR7
 | 
						|
	FPR8  FPR9  FPR10 FPR11 FPR12 FPR13 FPR14 FPR15
 | 
						|
	FPR16 FPR17 FPR18 FPR19 FPR20 FPR21 FPR22 FPR23
 | 
						|
	FPR24 FPR25 FPR26 FPR27 FPR28 FPR29 FPR30 FPR31
 | 
						|
 | 
						|
REGISTERS
 | 
						|
 | 
						|
	/* Reverse order to encourage ncg to allocate them from r31 down */
 | 
						|
	
 | 
						|
	R31("r31")         : GPR, REG, GPR31 regvar.
 | 
						|
	R30("r30")         : GPR, REG, GPR30 regvar.
 | 
						|
	R29("r29")         : GPR, REG, GPR29 regvar.
 | 
						|
	R28("r28")         : GPR, REG, GPR28 regvar.
 | 
						|
	R27("r27")         : GPR, REG, GPR27 regvar.
 | 
						|
	R26("r26")         : GPR, REG, GPR26 regvar.
 | 
						|
	R25("r25")         : GPR, REG, GPR25 regvar.
 | 
						|
	R24("r24")         : GPR, REG, GPR24 regvar.
 | 
						|
	R23("r23")         : GPR, REG, GPR23 regvar.
 | 
						|
	R22("r22")         : GPR, REG, GPR22 regvar.
 | 
						|
	R21("r21")         : GPR, REG, GPR21 regvar.
 | 
						|
	R20("r20")         : GPR, REG, GPR20 regvar.
 | 
						|
	R19("r19")         : GPR, REG, GPR19 regvar.
 | 
						|
	R18("r18")         : GPR, REG, GPR18 regvar.
 | 
						|
	R17("r17")         : GPR, REG, GPR17 regvar.
 | 
						|
	R16("r16")         : GPR, REG, GPR16 regvar.
 | 
						|
	R15("r15")         : GPR, REG, GPR15 regvar.
 | 
						|
	R14("r14")         : GPR, REG, GPR14 regvar.
 | 
						|
	R13("r13")         : GPR, REG, GPR13 regvar.
 | 
						|
	R12("r12")         : GPR, REG, GPR12.
 | 
						|
	R11("r11")         : GPR, GPR11.
 | 
						|
	R10("r10")         : GPR, REG, GPR10.
 | 
						|
	R9("r9")           : GPR, REG, GPR9.
 | 
						|
	R8("r8")           : GPR, REG, GPR8.
 | 
						|
	R7("r7")           : GPR, REG, GPR7.
 | 
						|
	R6("r6")           : GPR, REG, GPR6.
 | 
						|
	R5("r5")           : GPR, REG, GPR5.
 | 
						|
	R4("r4")           : GPR, REG, GPR4.
 | 
						|
	R3("r3")           : GPR, REG, GPR3.
 | 
						|
	FP("fp")           : GPR, GPRFP.
 | 
						|
	SP("sp")           : GPR, GPRSP.
 | 
						|
	R0("r0")           : GPR, GPR0.
 | 
						|
 | 
						|
	F31("f31")         : FPR, FREG, FPR31.
 | 
						|
	F30("f30")         : FPR, FREG, FPR30.
 | 
						|
	F29("f29")         : FPR, FREG, FPR29.
 | 
						|
	F28("f28")         : FPR, FREG, FPR28.
 | 
						|
	F27("f27")         : FPR, FREG, FPR27.
 | 
						|
	F26("f26")         : FPR, FREG, FPR26.
 | 
						|
	F25("f25")         : FPR, FREG, FPR25.
 | 
						|
	F24("f24")         : FPR, FREG, FPR24.
 | 
						|
	F23("f23")         : FPR, FREG, FPR23.
 | 
						|
	F22("f22")         : FPR, FREG, FPR22.
 | 
						|
	F21("f21")         : FPR, FREG, FPR21.
 | 
						|
	F20("f20")         : FPR, FREG, FPR20.
 | 
						|
	F19("f19")         : FPR, FREG, FPR19.
 | 
						|
	F18("f18")         : FPR, FREG, FPR18.
 | 
						|
	F17("f17")         : FPR, FREG, FPR17.
 | 
						|
	F16("f16")         : FPR, FREG, FPR16.
 | 
						|
	F15("f15")         : FPR, FREG, FPR15.
 | 
						|
	F14("f14")         : FPR, FREG, FPR14.
 | 
						|
	F13("f13")         : FPR, FREG, FPR13.
 | 
						|
	F12("f12")         : FPR, FREG, FPR12.
 | 
						|
	F11("f11")         : FPR, FREG, FPR11.
 | 
						|
	F10("f10")         : FPR, FREG, FPR10.
 | 
						|
	F9("f9")           : FPR, FREG, FPR9.
 | 
						|
	F8("f8")           : FPR, FREG, FPR8.
 | 
						|
	F7("f7")           : FPR, FREG, FPR7.
 | 
						|
	F6("f6")           : FPR, FREG, FPR6.
 | 
						|
	F5("f5")           : FPR, FREG, FPR5.
 | 
						|
	F4("f4")           : FPR, FREG, FPR4.
 | 
						|
	F3("f3")           : FPR, FREG, FPR3.
 | 
						|
	F2("f2")           : FPR, FREG, FPR2.
 | 
						|
	F1("f1")           : FPR, FREG, FPR1.
 | 
						|
	F0("f0")           : FPR, FREG, FPR0.
 | 
						|
 | 
						|
	LR("lr")           : SPR.
 | 
						|
	CTR("ctr")         : SPR.
 | 
						|
	C0("cr0")          : CR, CR0.
 | 
						|
 | 
						|
#define SCRATCH R11
 | 
						|
#define FSCRATCH F0
 | 
						|
 | 
						|
 | 
						|
TOKENS
 | 
						|
 | 
						|
/* Used only in instruction descriptions (to generate the correct syntax). */
 | 
						|
 | 
						|
	GPRINDIRECT        = { GPR reg; INT off; }    4    off "(" reg ")".
 | 
						|
	GPRINDIRECTLO      = { GPR reg; ADDR adr; }   4    ">" adr "(" reg ")". /* Warning! Do not use on labels. */
 | 
						|
	HILABEL            = { ADDR adr; }            4    "<" adr.
 | 
						|
	LOLABEL            = { ADDR adr; }            4    ">" adr.
 | 
						|
 | 
						|
/* Primitives */
 | 
						|
 | 
						|
	LABEL              = { ADDR adr; }            4    adr.
 | 
						|
	CONST              = { INT val; }             4    val.
 | 
						|
	LOCAL              = { INT off; }             4.
 | 
						|
 | 
						|
/* Allows us to use regvar() to refer to registers */
 | 
						|
 | 
						|
	GPRE               = { GPR reg; }             4    reg.
 | 
						|
 | 
						|
/* Expression partial results */
 | 
						|
	
 | 
						|
	SUM_RC             = { GPR reg; INT off; }    4.
 | 
						|
	SUM_RR             = { GPR reg1; GPR reg2; }  4.
 | 
						|
	
 | 
						|
	TRISTATE_RC_S      = { GPR reg; INT val; }    4.
 | 
						|
	TRISTATE_RC_U      = { GPR reg; INT val; }    4.
 | 
						|
	TRISTATE_RR_S      = { GPR reg1; GPR reg2; }  4.
 | 
						|
	TRISTATE_RR_U      = { GPR reg1; GPR reg2; }  4.
 | 
						|
	
 | 
						|
	TRISTATE_FF        = { FPR reg1; FPR reg2; }  4.
 | 
						|
	
 | 
						|
	SEX_B              = { GPR reg; }             4.
 | 
						|
	SEX_H              = { GPR reg; }             4.
 | 
						|
	
 | 
						|
	IND_RC_B           = { GPR reg; INT off; }    4.
 | 
						|
	IND_RC_H           = { GPR reg; INT off; }    4.
 | 
						|
	IND_RC_H_S         = { GPR reg; INT off; }    4.
 | 
						|
	IND_RC_W           = { GPR reg; INT off; }    4.
 | 
						|
	IND_RR_W           = { GPR reg1; GPR reg2; }  4.
 | 
						|
	IND_LABEL_W        = { ADDR adr; }            4.
 | 
						|
	IND_RC_D           = { GPR reg; INT off; }    8.
 | 
						|
	IND_RR_D           = { GPR reg1; GPR reg2; }  8.
 | 
						|
	IND_LABEL_D        = { ADDR adr; }            8.
 | 
						|
	
 | 
						|
	NOT_R              = { GPR reg; }             4.
 | 
						|
	
 | 
						|
	AND_RR             = { GPR reg1; GPR reg2; }  4.
 | 
						|
	AND_RC             = { GPR reg; INT val; }  4.
 | 
						|
	OR_RR              = { GPR reg1; GPR reg2; }  4.
 | 
						|
	OR_RC              = { GPR reg; INT val; }  4.
 | 
						|
	XOR_RR             = { GPR reg1; GPR reg2; }  4.
 | 
						|
	XOR_RC             = { GPR reg; INT val; }  4.
 | 
						|
 | 
						|
/* Floats */
 | 
						|
 | 
						|
    FD                 = { FPR reg; }             8 reg.
 | 
						|
    FS                 = { FPR reg; }             4 reg.
 | 
						|
    
 | 
						|
/* Comments */
 | 
						|
 | 
						|
	LABELI             = { ADDR msg; INT num; }   4    msg " " num.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
SETS
 | 
						|
 | 
						|
	TOKEN              = LABEL + CONST + LOCAL.
 | 
						|
	GPRI               = GPR + GPRE.
 | 
						|
	
 | 
						|
	SUM_ALL            = SUM_RC + SUM_RR.
 | 
						|
	
 | 
						|
	TRISTATE_ALL       = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S +
 | 
						|
	                     TRISTATE_RR_U + TRISTATE_FF.
 | 
						|
	
 | 
						|
	SEX_ALL            = SEX_B + SEX_H.
 | 
						|
	
 | 
						|
	LOGICAL_ALL        = NOT_R + AND_RR + AND_RC + OR_RR + OR_RC + XOR_RR +
 | 
						|
	                     XOR_RC.
 | 
						|
	
 | 
						|
	IND_ALL_W          = IND_RC_W + IND_RR_W + IND_LABEL_W.
 | 
						|
 | 
						|
	IND_ALL_D          = IND_RC_D + IND_RR_D + IND_LABEL_D.
 | 
						|
	
 | 
						|
	OP_ALL_W           = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL +
 | 
						|
	                     IND_ALL_W.
 | 
						|
 | 
						|
 | 
						|
INSTRUCTIONS
 | 
						|
 | 
						|
  add             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  addX "add."     GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  addi            GPRI:wo, GPRI:ro, CONST:ro.
 | 
						|
  addis           GPRI:wo, GPRI:ro, CONST+HILABEL:ro.
 | 
						|
  and             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  andc            GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  andiX  "andi."  GPRI:wo, GPRI:ro, CONST:ro kills :cc.
 | 
						|
  andisX "andis." GPRI:wo, GPRI:ro, CONST:ro kills :cc.
 | 
						|
  b               LABEL:ro.
 | 
						|
  bc              CONST:ro, CONST:ro, LABEL:ro.
 | 
						|
  bcctr           CONST:ro, CONST:ro, CONST:ro.
 | 
						|
  bcctrl          CONST:ro, CONST:ro, CONST:ro.
 | 
						|
  bclr            CONST:ro, CONST:ro, CONST:ro.
 | 
						|
  bl              LABEL:ro.
 | 
						|
  cmp             CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc.
 | 
						|
  cmpi            CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc.
 | 
						|
  cmpl            CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc.
 | 
						|
  cmpli           CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc.
 | 
						|
  divw            GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  divwu           GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  eqv             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  extsb           GPRI:wo, GPRI:ro.
 | 
						|
  extsh           GPRI:wo, GPRI:ro.
 | 
						|
  fadd            FD:wo, FD:ro, FD:ro.
 | 
						|
  fadds           FS:wo, FS:ro, FS:ro.
 | 
						|
  fcmpo           CR:wo, FD:ro, FD:ro.
 | 
						|
  fdiv            FD:wo, FD:ro, FD:ro.
 | 
						|
  fdivs           FS:wo, FS:ro, FS:ro.
 | 
						|
  fneg            FS+FD:wo, FS+FD:ro.
 | 
						|
  fmul            FD:wo, FD:ro, FD:ro.
 | 
						|
  fmuls           FS:wo, FS:ro, FS:ro.
 | 
						|
  frsp            FS:wo, FD:ro.
 | 
						|
  fsub            FD:wo, FD:ro, FD:ro.
 | 
						|
  fsubs           FS:wo, FS:ro, FS:ro.
 | 
						|
  fmr             FS+FD:wo, FS+FD:ro.
 | 
						|
  lbzx            GPRI:wo, GPR:ro, GPR:ro.
 | 
						|
  lbz             GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  lfd             FD:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  lfdu            FD:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  lfdx            FD:wo, GPR:ro, GPR:ro.
 | 
						|
  lfs             FS:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  lfsu            FS:wo, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  lfsx            FS:wo, GPR:ro, GPR:ro.
 | 
						|
  lhzx            GPRI:wo, GPR:ro, GPR:ro.
 | 
						|
  lhax            GPRI:wo, GPR:ro, GPR:ro.
 | 
						|
  lha             GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  lhz             GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  lwzu            GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  lwzx            GPRI:wo, GPR:ro, GPR:ro.
 | 
						|
  lwz             GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
 | 
						|
  nand            GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  neg             GPRI:wo, GPRI:ro.
 | 
						|
  nor             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  mfcr            GPRI:wo.
 | 
						|
  mullw           GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  mfspr           GPRI:wo, SPR:ro.
 | 
						|
  mtspr           SPR:wo, GPRI:ro.
 | 
						|
  or              GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  orc             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  ori             GPRI:wo, GPRI:ro, CONST+LOLABEL:ro.
 | 
						|
  orX "or."       GPRI:wo, GPRI:ro, GPRI:ro kills :cc.
 | 
						|
  rlwinm          GPRI:wo, GPRI:ro, CONST:ro, CONST:ro, CONST:ro.
 | 
						|
  slw             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  subf            GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  sraw            GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  srawi           GPRI:wo, GPRI:ro, CONST:ro.
 | 
						|
  srw             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  stb             GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  stbx            GPRI:ro, GPR:ro, GPR:ro.
 | 
						|
  stfd            FD:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  stfdu           FD:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  stfdx           FD:ro, GPR:ro, GPR:ro.
 | 
						|
  stfs            FS:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  stfsu           FS:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  stfsx           FS:ro, GPR:ro, GPR:ro.
 | 
						|
  sth             GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  sthx            GPRI:ro, GPR:ro, GPR:ro.
 | 
						|
  stw             GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  stwx            GPRI:ro, GPR:ro, GPR:ro.
 | 
						|
  stwu            GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw.
 | 
						|
  xor             GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  xori            GPRI:wo, GPRI:ro, CONST:ro.
 | 
						|
 | 
						|
  gpr_gpr_gpr     GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  gpr_gpr_si      GPRI:wo, GPRI:ro, CONST:ro.
 | 
						|
  gpr_ro_gprindirect GPRI:ro, GPRINDIRECT:rw.
 | 
						|
  gpr_ro_gpr_gpr  GPRI:ro, GPRI:ro, GPRI:ro.
 | 
						|
  gpr_wo_gprindirect GPRI:wo, GPRINDIRECT:ro.
 | 
						|
  gpr_wo_gpr_gpr  GPRI:wo, GPRI:ro, GPRI:ro.
 | 
						|
  
 | 
						|
  invalid "invalid".
 | 
						|
  comment "!" LABEL+LABELI:ro.
 | 
						|
 | 
						|
 | 
						|
  
 | 
						|
MOVES
 | 
						|
 | 
						|
	from GPR to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->GPR")
 | 
						|
			or %2, %1, %1
 | 
						|
 | 
						|
/* GPRE exists solely to allow us to use regvar() (which can only be used in
 | 
						|
   an expression) as a register constant. */
 | 
						|
   
 | 
						|
	from GPR to GPRE
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->GPRE")
 | 
						|
			or %2, %1, %1
 | 
						|
		
 | 
						|
/* Constants */
 | 
						|
 | 
						|
	from CONST smalls(%val) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move CONST->GPRE")
 | 
						|
			addi %2, R0, {CONST, lo(%1.val)}
 | 
						|
		
 | 
						|
	from CONST to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move CONST->GPRE")
 | 
						|
			addis %2, R0, {CONST, hi(%1.val)}
 | 
						|
			ori %2, %2, {CONST, lo(%1.val)}
 | 
						|
		
 | 
						|
	from LABEL to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move LABEL->GPR")
 | 
						|
			addis %2, R0, {HILABEL, %1.adr}
 | 
						|
			ori %2, %2, {LOLABEL, %1.adr}
 | 
						|
	
 | 
						|
/* Sign extension */
 | 
						|
 | 
						|
	from SEX_B to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move SEX_B->GPR")
 | 
						|
			extsb %2, %1.reg
 | 
						|
			
 | 
						|
	from SEX_H to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move SEX_H->GPR")
 | 
						|
			extsh %2, %1.reg
 | 
						|
					
 | 
						|
/* Register + something */
 | 
						|
 | 
						|
	from SUM_RC smalls(%off) to GPR
 | 
						|
		gen	
 | 
						|
			COMMENT("move SUM_RC->GPR smalls")
 | 
						|
			addi %2, %1.reg, {CONST, lo(%1.off)}
 | 
						|
	
 | 
						|
	from SUM_RC to GPR
 | 
						|
		gen	
 | 
						|
			COMMENT("move SUM_RC->GPR large")
 | 
						|
			addi %2, %1.reg, {CONST, los(%1.off)}
 | 
						|
			addis %2, %2, {CONST, his(%1.off)}
 | 
						|
			
 | 
						|
	from SUM_RR to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move SUM_RR->GPR")
 | 
						|
			add %2, %1.reg1, %1.reg2
 | 
						|
		
 | 
						|
	from SUM_RR to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move SUM_RR->GPRE")
 | 
						|
			add %2, %1.reg1, %1.reg2
 | 
						|
		
 | 
						|
/* Read/write byte */
 | 
						|
 | 
						|
	from IND_RC_B smalls(%off) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_B->GPR small")
 | 
						|
			lbz %2, {GPRINDIRECT, %1.reg, %1.off}
 | 
						|
	
 | 
						|
	from IND_RC_B to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_B->GPR large")
 | 
						|
			addis SCRATCH, %1.reg, {CONST, his(%1.off)}
 | 
						|
			lbz %2, {GPRINDIRECT, SCRATCH, los(%1.off)}
 | 
						|
	
 | 
						|
	from GPR to IND_RC_B smalls(%off)
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_RC_B small")
 | 
						|
			stb %1, {GPRINDIRECT, %2.reg, %2.off}
 | 
						|
	
 | 
						|
	from GPR to IND_RC_B
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_RC_B large")
 | 
						|
			addis SCRATCH, %2.reg, {CONST, his(%2.off)}
 | 
						|
			stb %1, {GPRINDIRECT, SCRATCH, los(%2.off)}
 | 
						|
	
 | 
						|
/* Read/write short */
 | 
						|
 | 
						|
	from IND_RC_H smalls(%off) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_H->GPR small")
 | 
						|
			lhz %2, {GPRINDIRECT, %1.reg, %1.off}
 | 
						|
	
 | 
						|
	from IND_RC_H to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_H->GPR large")
 | 
						|
			addis SCRATCH, %1.reg, {CONST, his(%1.off)}
 | 
						|
			lhz %2, {GPRINDIRECT, SCRATCH, los(%1.off)}
 | 
						|
	
 | 
						|
	from IND_RC_H_S smalls(%off) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_H_S->GPR small")
 | 
						|
			lha %2, {GPRINDIRECT, %1.reg, %1.off}
 | 
						|
	
 | 
						|
	from IND_RC_H_S to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_H_S->GPR large")
 | 
						|
			addis SCRATCH, %1.reg, {CONST, his(%1.off)}
 | 
						|
			lha %2, {GPRINDIRECT, SCRATCH, los(%1.off)}
 | 
						|
	
 | 
						|
	from GPR to IND_RC_H smalls(%off)
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_RC_H small")
 | 
						|
			sth %1, {GPRINDIRECT, %2.reg, %2.off}
 | 
						|
	
 | 
						|
	from GPR to IND_RC_H
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_RC_H large")
 | 
						|
			addis SCRATCH, %2.reg, {CONST, his(%2.off)}
 | 
						|
			sth %1, {GPRINDIRECT, SCRATCH, los(%2.off)}
 | 
						|
	
 | 
						|
/* Read word */
 | 
						|
 | 
						|
	from IND_RC_W smalls(%off) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_W->GPR small")
 | 
						|
			lwz %2, {GPRINDIRECT, %1.reg, %1.off}
 | 
						|
	
 | 
						|
	from IND_RC_W to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_W->GPR large")
 | 
						|
			addis %2, %1.reg, {CONST, his(%1.off)}
 | 
						|
			lwz %2, {GPRINDIRECT, %2, los(%1.off)}
 | 
						|
 | 
						|
	from IND_RR_W to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RR_W->GPR")
 | 
						|
			lwzx %2, %1.reg1, %1.reg2
 | 
						|
			
 | 
						|
	from IND_LABEL_W to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_LABEL_W->GPR")
 | 
						|
			move {LABEL, %1.adr}, SCRATCH
 | 
						|
			lwz %2, {GPRINDIRECT, SCRATCH, 0}
 | 
						|
		
 | 
						|
	from IND_RC_W smalls(%off) to FS
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_W->FS small")
 | 
						|
			lfs %2, {GPRINDIRECT, %1.reg, %1.off}
 | 
						|
	
 | 
						|
	from IND_RC_W to FS
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_W->FS large")
 | 
						|
			addis SCRATCH, %1.reg, {CONST, his(%1.off)}
 | 
						|
			lfs %2, {GPRINDIRECT, SCRATCH, los(%1.off)}
 | 
						|
 | 
						|
	from IND_RR_W to FS
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RR_W->FS")
 | 
						|
			lfsx %2, %1.reg1, %1.reg2
 | 
						|
			
 | 
						|
	from IND_LABEL_W to FS
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_LABEL_W->FS")
 | 
						|
			move {LABEL, %1.adr}, SCRATCH
 | 
						|
			lfs %2, {GPRINDIRECT, SCRATCH, 0}
 | 
						|
		
 | 
						|
/* Write word */
 | 
						|
 | 
						|
	from GPR to IND_RC_W smalls(%off)
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_RC_W small")
 | 
						|
			stw %1, {GPRINDIRECT, %2.reg, %2.off}
 | 
						|
	
 | 
						|
	from GPR to IND_RC_W
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_RC_W large")
 | 
						|
			addis SCRATCH, %2.reg, {CONST, his(%2.off)}
 | 
						|
			stw %1, {GPRINDIRECT, SCRATCH, los(%2.off)}
 | 
						|
 | 
						|
	from GPR to IND_RR_W
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_RR_W")
 | 
						|
			stwx %1, %2.reg1, %2.reg2
 | 
						|
			
 | 
						|
	from GPR to IND_LABEL_W
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->IND_LABEL_D")
 | 
						|
			move {LABEL, %2.adr}, SCRATCH
 | 
						|
			stw %1, {GPRINDIRECT, SCRATCH, 0}
 | 
						|
			
 | 
						|
	from FS to IND_RC_W smalls(%off)
 | 
						|
		gen
 | 
						|
			COMMENT("move FS->IND_RC_W small")
 | 
						|
			stfs %1, {GPRINDIRECT, %2.reg, %2.off}
 | 
						|
	
 | 
						|
	from FS to IND_RC_W
 | 
						|
		gen
 | 
						|
			COMMENT("move FS->IND_RC_W large")
 | 
						|
			addis SCRATCH, %2.reg, {CONST, his(%2.off)}
 | 
						|
			stfs %1, {GPRINDIRECT, SCRATCH, los(%2.off)}
 | 
						|
 | 
						|
	from FS to IND_RR_W
 | 
						|
		gen
 | 
						|
			COMMENT("move FS->IND_RR_W")
 | 
						|
			stfsx %1, %2.reg1, %2.reg2
 | 
						|
 | 
						|
	from FS to IND_LABEL_W
 | 
						|
		gen
 | 
						|
			COMMENT("move FS->IND_LABEL_D")
 | 
						|
			move {LABEL, %2.adr}, SCRATCH
 | 
						|
			stfs %1, {GPRINDIRECT, SCRATCH, 0}
 | 
						|
			
 | 
						|
/* Read double */
 | 
						|
 | 
						|
	from IND_RC_D smalls(%off) to FD
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_D->FD small")
 | 
						|
			lfd %2, {GPRINDIRECT, %1.reg, %1.off}
 | 
						|
	
 | 
						|
	from IND_RC_D to FD
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RC_D->FD large")
 | 
						|
			addis SCRATCH, %1.reg, {CONST, his(%1.off)}
 | 
						|
			lfd %2, {GPRINDIRECT, SCRATCH, los(%1.off)}
 | 
						|
			
 | 
						|
	from IND_RR_D to FD
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_RR_D->FD")
 | 
						|
			lfdx %2, %1.reg1, %1.reg2
 | 
						|
 | 
						|
	from IND_LABEL_D to FD
 | 
						|
		gen
 | 
						|
			COMMENT("move IND_LABEL_D->FD")
 | 
						|
			move {LABEL, %1.adr}, SCRATCH
 | 
						|
			lfd %2, {GPRINDIRECT, SCRATCH, 0}
 | 
						|
		
 | 
						|
/* Write double */
 | 
						|
 | 
						|
	from FD to IND_RC_D smalls(%off)
 | 
						|
		gen
 | 
						|
			COMMENT("move FD->IND_RC_D small")
 | 
						|
			stfd %1, {GPRINDIRECT, %2.reg, %2.off}
 | 
						|
	
 | 
						|
	from FD to IND_RC_D
 | 
						|
		gen
 | 
						|
			COMMENT("move FD->IND_RC_D large")
 | 
						|
			addis SCRATCH, %2.reg, {CONST, his(%2.off)}
 | 
						|
			stfd %1, {GPRINDIRECT, SCRATCH, los(%2.off)}
 | 
						|
 | 
						|
	from FD to IND_RR_D
 | 
						|
		gen
 | 
						|
			COMMENT("move FD->IND_RR_W")
 | 
						|
			stfdx %1, %2.reg1, %2.reg2
 | 
						|
			
 | 
						|
	from FD to IND_LABEL_D
 | 
						|
		gen
 | 
						|
			COMMENT("move FD->IND_LABEL_D")
 | 
						|
			move {LABEL, %2.adr}, SCRATCH
 | 
						|
			stfd %1, {GPRINDIRECT, SCRATCH, 0}
 | 
						|
			
 | 
						|
/* Extract condition code field (actually produces (CC&3)<<2) */
 | 
						|
 | 
						|
	from CR0 to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move CR0->GPR")
 | 
						|
			mfcr %2
 | 
						|
			rlwinm %2, %2, {CONST, 4}, {CONST, 32-4}, {CONST, 31-2}
 | 
						|
 | 
						|
/* Comparisons */
 | 
						|
 | 
						|
	from TRISTATE_RR_S to CR0
 | 
						|
		gen
 | 
						|
			cmp %2, {CONST, 0}, %1.reg1, %1.reg2
 | 
						|
			
 | 
						|
	from TRISTATE_RR_U to CR0
 | 
						|
		gen
 | 
						|
			cmpl %2, {CONST, 0}, %1.reg1, %1.reg2
 | 
						|
		
 | 
						|
	from TRISTATE_RC_S to CR0
 | 
						|
		gen
 | 
						|
			COMMENT("move TRISTATE_RC_S->CR0 large")
 | 
						|
			move {CONST, %1.val}, SCRATCH
 | 
						|
			cmp %2, {CONST, 0}, %1.reg, SCRATCH
 | 
						|
			
 | 
						|
	from TRISTATE_RC_U smallu(%val) to CR0
 | 
						|
		gen
 | 
						|
			COMMENT("move TRISTATE_RC_U->CR0 small")
 | 
						|
			cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val}
 | 
						|
		
 | 
						|
	from TRISTATE_RC_U to CR0
 | 
						|
		gen
 | 
						|
			COMMENT("move TRISTATE_RC_U->CR0")
 | 
						|
			move {CONST, %1.val}, SCRATCH
 | 
						|
			cmpl %2, {CONST, 0}, %1.reg, SCRATCH
 | 
						|
		
 | 
						|
	from TRISTATE_FF to CR0
 | 
						|
		gen
 | 
						|
			COMMENT("move TRISTATE_FF->CR0")
 | 
						|
			fcmpo %2, {FD, %1.reg1}, {FD, %1.reg2}
 | 
						|
			
 | 
						|
	from GPR to CR0
 | 
						|
		gen
 | 
						|
			COMMENT("move GPR->CR0")
 | 
						|
			orX SCRATCH, %1, %1 /* alas, can't call test */
 | 
						|
			
 | 
						|
	from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move TRISTATE_R*_S->GPR")
 | 
						|
			move %1, C0
 | 
						|
			move C0, SCRATCH
 | 
						|
			move {LABEL, ".tristate_s_table"}, %2
 | 
						|
			lwzx %2, %2, SCRATCH				
 | 
						|
 | 
						|
	from TRISTATE_RR_U + TRISTATE_RC_U to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move TRISTATE_R*_U->GPR")
 | 
						|
			move %1, C0
 | 
						|
			move C0, SCRATCH
 | 
						|
			move {LABEL, ".tristate_u_table"}, %2
 | 
						|
			lwzx %2, %2, SCRATCH				
 | 
						|
 | 
						|
/* Logicals */
 | 
						|
 | 
						|
	from NOT_R to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move NOT_R->GPR")
 | 
						|
			nor %2, %1.reg, %1.reg
 | 
						|
 | 
						|
	from AND_RR to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move AND_RR->GPR")
 | 
						|
			and %2, %1.reg1, %1.reg2
 | 
						|
 | 
						|
	from AND_RC smallu(%val) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move AND_RC->GPR small")
 | 
						|
			andiX %2, %1.reg, {CONST, %1.val}
 | 
						|
 | 
						|
	from AND_RC to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move AND_RC->GPR")
 | 
						|
			move {CONST, %1.val}, SCRATCH
 | 
						|
			and %2, %1.reg, SCRATCH
 | 
						|
 | 
						|
	from OR_RR to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move OR_RR->GPR")
 | 
						|
			or %2, %1.reg1, %1.reg2
 | 
						|
 | 
						|
	from OR_RC smallu(%val) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move OR_RC->GPR small")
 | 
						|
			ori %2, %1.reg, {CONST, %1.val}
 | 
						|
 | 
						|
	from OR_RC to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move OR_RC->GPR")
 | 
						|
			move {CONST, %1.val}, SCRATCH
 | 
						|
			or %2, %1.reg, SCRATCH
 | 
						|
 | 
						|
	from XOR_RR to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move XOR_RR->GPR")
 | 
						|
			xor %2, %1.reg1, %1.reg2
 | 
						|
 | 
						|
	from XOR_RC smallu(%val) to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move XOR_RC->GPR small")
 | 
						|
			xori %2, %1.reg, {CONST, %1.val}
 | 
						|
 | 
						|
	from XOR_RC to GPR
 | 
						|
		gen
 | 
						|
			COMMENT("move XOR_RC->GPR")
 | 
						|
			move {CONST, %1.val}, SCRATCH
 | 
						|
			xor %2, %1.reg, SCRATCH
 | 
						|
 | 
						|
/* Miscellaneous */
 | 
						|
 | 
						|
	from OP_ALL_W + LABEL + CONST to GPRE
 | 
						|
		gen
 | 
						|
			move %1, %2.reg
 | 
						|
 | 
						|
		
 | 
						|
TESTS
 | 
						|
	
 | 
						|
	to test GPR
 | 
						|
		gen
 | 
						|
			orX SCRATCH, %1, %1
 | 
						|
 | 
						|
 | 
						|
 | 
						|
STACKINGRULES
 | 
						|
	
 | 
						|
	from GPR to STACK
 | 
						|
		gen
 | 
						|
			COMMENT("stack GPR")
 | 
						|
			stwu %1, {GPRINDIRECT, SP, 0-4}
 | 
						|
	
 | 
						|
	from CONST to STACK
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("stack CONST")
 | 
						|
			move %1, %a
 | 
						|
			stwu %a, {GPRINDIRECT, SP, 0-4}
 | 
						|
			
 | 
						|
	from LABEL to STACK
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("stack LABEL")
 | 
						|
			move %1, {GPRE, %a}
 | 
						|
			stwu %a, {GPRINDIRECT, SP, 0-4}
 | 
						|
			
 | 
						|
	from SEX_B to STACK
 | 
						|
		gen
 | 
						|
			COMMENT("stack SEX_B")
 | 
						|
			extsb SCRATCH, %1.reg
 | 
						|
			stwu SCRATCH, {GPRINDIRECT, SP, 0-4}
 | 
						|
			
 | 
						|
	from SEX_H to STACK
 | 
						|
		gen
 | 
						|
			COMMENT("stack SEX_H")
 | 
						|
			extsh SCRATCH, %1.reg
 | 
						|
			stwu SCRATCH, {GPRINDIRECT, SP, 0-4}
 | 
						|
			
 | 
						|
	from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK
 | 
						|
		gen
 | 
						|
			move %1, {GPRE, SCRATCH}
 | 
						|
			stwu SCRATCH, {GPRINDIRECT, SP, 0-4}
 | 
						|
			
 | 
						|
	from IND_ALL_W to STACK
 | 
						|
		gen
 | 
						|
			move %1, SCRATCH
 | 
						|
			stwu SCRATCH, {GPRINDIRECT, SP, 0-4}
 | 
						|
			
 | 
						|
	from IND_ALL_D to STACK
 | 
						|
		gen
 | 
						|
			move %1, {FD, FSCRATCH}
 | 
						|
			stfdu {FD, FSCRATCH}, {GPRINDIRECT, SP, 0-8}
 | 
						|
			
 | 
						|
	from FD to STACK
 | 
						|
		gen
 | 
						|
			COMMENT("stack FD")
 | 
						|
			stfdu %1, {GPRINDIRECT, SP, 0-8}
 | 
						|
			
 | 
						|
	from FS to STACK
 | 
						|
		gen
 | 
						|
			COMMENT("stack FS")
 | 
						|
			stfsu %1, {GPRINDIRECT, SP, 0-4}
 | 
						|
			
 | 
						|
	from TOKEN to STACK
 | 
						|
		gen
 | 
						|
			invalid.
 | 
						|
			
 | 
						|
		
 | 
						|
		
 | 
						|
COERCIONS
 | 
						|
 | 
						|
	from REG
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce REG->REG")
 | 
						|
			move %1, %a
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	from CONST
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce CONST->REG")
 | 
						|
			move %1, %a
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	from LABEL
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce LABEL->REG")
 | 
						|
			move %1, {GPRE, %a}
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	from STACK
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce STACK->REG")
 | 
						|
			lwz %a, {GPRINDIRECT, SP, 0}
 | 
						|
			addi SP, SP, {CONST, 4}
 | 
						|
		yields %a
 | 
						|
	
 | 
						|
	from SEX_B
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce SEX_B->REG")
 | 
						|
			extsb %a, %1.reg
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	from SEX_H
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce SEX_H->REG")
 | 
						|
			extsh %a, %1.reg
 | 
						|
		yields %a
 | 
						|
	
 | 
						|
	from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			move %1, {GPRE, %a}
 | 
						|
		yields %a
 | 
						|
	
 | 
						|
	from FS
 | 
						|
		uses FREG
 | 
						|
		gen
 | 
						|
			fmr {FS, %a}, %1
 | 
						|
		yields {FS, %a}
 | 
						|
		
 | 
						|
	from FD
 | 
						|
		uses FREG
 | 
						|
		gen
 | 
						|
			fmr {FD, %a}, %1
 | 
						|
		yields {FD, %a}
 | 
						|
		
 | 
						|
	from STACK
 | 
						|
		uses FREG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce STACK->FD")
 | 
						|
			lfd {FD, %a}, {GPRINDIRECT, SP, 0}
 | 
						|
			addi SP, SP, {CONST, 8}
 | 
						|
		yields {FD, %a}
 | 
						|
 | 
						|
	from STACK
 | 
						|
		uses FREG
 | 
						|
		gen
 | 
						|
			COMMENT("coerce STACK->FS")
 | 
						|
			lfs {FS, %a}, {GPRINDIRECT, SP, 0}
 | 
						|
			addi SP, SP, {CONST, 4}
 | 
						|
		yields {FS, %a}
 | 
						|
		
 | 
						|
	from IND_ALL_W
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			move %1, %a
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	from IND_ALL_W
 | 
						|
		uses FREG
 | 
						|
		gen
 | 
						|
			move %1, {FS, %a}
 | 
						|
		yields {FS, %a}
 | 
						|
		
 | 
						|
	from IND_ALL_D
 | 
						|
		uses FREG
 | 
						|
		gen
 | 
						|
			move %1, {FD, %a}
 | 
						|
		yields {FD, %a}
 | 
						|
		
 | 
						|
	
 | 
						|
 | 
						|
 | 
						|
PATTERNS
 | 
						|
 | 
						|
/* Intrinsics */
 | 
						|
 | 
						|
	pat loc                            /* Load constant */
 | 
						|
		yields {CONST, $1}
 | 
						|
 | 
						|
	pat dup $1==INT32                  /* Duplicate word on top of stack */
 | 
						|
		with GPR
 | 
						|
			yields %1 %1
 | 
						|
								
 | 
						|
	pat dup $1==INT64                  /* Duplicate double-word on top of stack */
 | 
						|
		with GPR GPR
 | 
						|
			yields %2 %1 %2 %1
 | 
						|
								
 | 
						|
	pat exg $1==INT32                  /* Exchange top two words on stack */
 | 
						|
		with GPR GPR
 | 
						|
			yields %1 %2
 | 
						|
		
 | 
						|
	pat stl lol $1==$2                 /* Store then load local */
 | 
						|
		leaving
 | 
						|
			dup 4
 | 
						|
			stl $1
 | 
						|
			
 | 
						|
	pat lal sti lal loi $1==$3 && $2==$4 /* Store then load local, of a different size */
 | 
						|
		leaving
 | 
						|
			dup INT32
 | 
						|
			lal $1
 | 
						|
			sti $2
 | 
						|
			
 | 
						|
	pat ste loe $1==$2                 /* Store then load external */
 | 
						|
		leaving
 | 
						|
			dup 4
 | 
						|
			ste $1
 | 
						|
		
 | 
						|
		
 | 
						|
/* Type conversions */
 | 
						|
 | 
						|
	pat loc loc cii loc loc cii $1==$4 && $2==$5 /* madness, generated by the C compiler */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			loc $2
 | 
						|
			cii
 | 
						|
			
 | 
						|
	pat loc loc cii loc loc cii $2==INT32 && $5==INT32 && $4<$2 /* madness, generated by the C compiler */
 | 
						|
		leaving
 | 
						|
			loc $4
 | 
						|
			loc $5
 | 
						|
			cii
 | 
						|
			
 | 
						|
	pat loc loc ciu                    /* signed X -> unsigned X */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			loc $2
 | 
						|
			cuu
 | 
						|
			
 | 
						|
	pat loc loc cuu $1==$2             /* unsigned X -> unsigned X */
 | 
						|
		/* nop */
 | 
						|
 | 
						|
	pat loc loc cii $1==$2             /* signed X -> signed X */
 | 
						|
		/* nop */
 | 
						|
 | 
						|
	pat loc loc cui $1==$2             /* unsigned X -> signed X */
 | 
						|
		/* nop */
 | 
						|
		
 | 
						|
	pat loc loc cui $1==INT8 && $2==INT32 /* unsigned char -> signed int */
 | 
						|
		/* nop */
 | 
						|
	
 | 
						|
	pat loc loc cui $1==INT16 && $2==INT32 /* unsigned short -> signed int */
 | 
						|
		/* nop */
 | 
						|
	
 | 
						|
	pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */
 | 
						|
		with GPR
 | 
						|
			yields {SEX_B, %1}
 | 
						|
	
 | 
						|
	pat loc loc cii $1==2 && $2==4     /* signed char -> signed short */
 | 
						|
		with GPR
 | 
						|
			yields {SEX_H, %1}
 | 
						|
	
 | 
						|
 | 
						|
		
 | 
						|
	
 | 
						|
		
 | 
						|
/* Local variables */
 | 
						|
 | 
						|
	pat lal                            /* Load address of local */
 | 
						|
		yields {SUM_RC, FP, $1}
 | 
						|
 | 
						|
	pat lol inreg($1)>0                /* Load from local */
 | 
						|
		yields {LOCAL, $1}
 | 
						|
		
 | 
						|
	pat lol                            /* Load from local */
 | 
						|
		leaving
 | 
						|
			lal $1
 | 
						|
			loi INT32
 | 
						|
 | 
						|
	pat ldl                            /* Load double-word from local */
 | 
						|
		leaving
 | 
						|
			lal $1
 | 
						|
			loi INT32*2
 | 
						|
			
 | 
						|
	pat stl inreg($1)>0                /* Store to local */
 | 
						|
		with CONST + LABEL + GPR + OP_ALL_W
 | 
						|
			kills regvar($1), LOCAL %off==$1
 | 
						|
			gen
 | 
						|
				move %1, {GPRE, regvar($1)}
 | 
						|
		
 | 
						|
	pat stl                            /* Store to local */
 | 
						|
		leaving
 | 
						|
			lal $1
 | 
						|
			sti INT32
 | 
						|
		
 | 
						|
	pat sdl                            /* Store double-word to local */
 | 
						|
		leaving
 | 
						|
			lal $1
 | 
						|
			sti INT32*2
 | 
						|
			
 | 
						|
	pat lil inreg($1)>0                /* Load from indirected local */
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			lwz %a, {GPRINDIRECT, regvar($1), 0}
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	pat lil                            /* Load from indirected local */
 | 
						|
		leaving
 | 
						|
			lol $1
 | 
						|
			loi INT32
 | 
						|
			
 | 
						|
	pat sil                            /* Save to indirected local */
 | 
						|
		leaving
 | 
						|
			lol $1
 | 
						|
			sti INT32
 | 
						|
			
 | 
						|
	pat stl lol $1==$2                 /* Save then load (generated by C compiler) */
 | 
						|
		leaving
 | 
						|
			dup 4
 | 
						|
			stl $1
 | 
						|
			
 | 
						|
	pat zrl                             /* Zero local */
 | 
						|
		leaving
 | 
						|
			loc 0
 | 
						|
			stl $1
 | 
						|
	
 | 
						|
	pat inl                             /* Increment local */
 | 
						|
		leaving
 | 
						|
			lol $1
 | 
						|
			loc 1
 | 
						|
			adi 4
 | 
						|
			stl $1
 | 
						|
					
 | 
						|
	pat del                             /* Decrement local */
 | 
						|
		leaving
 | 
						|
			lol $1
 | 
						|
			loc 1
 | 
						|
			sbi 4
 | 
						|
			stl $1
 | 
						|
 | 
						|
 | 
						|
/* Global variables */
 | 
						|
		
 | 
						|
	pat lpi                            /* Load address of external function */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
				
 | 
						|
	pat lae                            /* Load address of external */
 | 
						|
		yields {LABEL, $1}
 | 
						|
		
 | 
						|
	pat loe                            /* Load word external */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
			loi INT32
 | 
						|
 | 
						|
	pat ste                            /* Store word external */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
			sti INT32
 | 
						|
			
 | 
						|
	pat lde                            /* Load double-word external */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
			loi INT64
 | 
						|
			
 | 
						|
	pat sde                            /* Store double-word external */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
			sti INT64
 | 
						|
			
 | 
						|
	pat zre                             /* Zero external */
 | 
						|
		leaving
 | 
						|
			loc 0
 | 
						|
			ste $1
 | 
						|
	
 | 
						|
	pat ine                             /* Increment external */
 | 
						|
		uses REG={LABEL, $1}, REG
 | 
						|
			gen
 | 
						|
				lwz %b, {GPRINDIRECT, %a, 0}
 | 
						|
				addi %b, %b, {CONST, 1}
 | 
						|
				stw %b, {GPRINDIRECT, %a, 0}
 | 
						|
					
 | 
						|
	pat dee                             /* Decrement external */
 | 
						|
		uses REG={LABEL, $1}, REG
 | 
						|
			gen
 | 
						|
				lwz %b, {GPRINDIRECT, %a, 0}
 | 
						|
				addi %b, %b, {CONST, 0-1}
 | 
						|
				stw %b, {GPRINDIRECT, %a, 0}
 | 
						|
					
 | 
						|
 | 
						|
 | 
						|
/* Structures */
 | 
						|
 | 
						|
	pat lof                            /* Load word offsetted */
 | 
						|
		leaving
 | 
						|
			adp $1
 | 
						|
			loi INT32
 | 
						|
			
 | 
						|
	pat ldf                            /* Load double-word offsetted */
 | 
						|
		leaving
 | 
						|
			adp $1
 | 
						|
			loi INT64
 | 
						|
			
 | 
						|
	pat stf                            /* Store word offsetted */
 | 
						|
		leaving
 | 
						|
			adp $1
 | 
						|
			sti INT32
 | 
						|
			
 | 
						|
	pat sdf                            /* Store double-word offsetted */
 | 
						|
		leaving
 | 
						|
			adp $1
 | 
						|
			sti INT64
 | 
						|
			
 | 
						|
 | 
						|
 | 
						|
/* Loads and stores */
 | 
						|
 | 
						|
	pat loi $1==INT8                   /* Load byte indirect */
 | 
						|
		with GPR
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				lbz %a, {GPRINDIRECT, %1, 0}
 | 
						|
			yields %a
 | 
						|
		with SUM_RR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				lbzx %a, %1.reg1, %1.reg2
 | 
						|
			yields %a
 | 
						|
		with SUM_RC
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				move {IND_RC_B, %1.reg, %1.off}, %a
 | 
						|
			yields %a
 | 
						|
		
 | 
						|
	pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32 /* Load half-word indirect and sign extend */
 | 
						|
		with GPR
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				lha %a, {GPRINDIRECT, %1, 0}
 | 
						|
			yields %a
 | 
						|
		with SUM_RR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				lhax %a, %1.reg1, %1.reg2
 | 
						|
			yields %a
 | 
						|
		with SUM_RC
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				move {IND_RC_H_S, %1.reg, %1.off}, %a
 | 
						|
			yields %a
 | 
						|
		
 | 
						|
	pat loi $1==INT16                  /* Load half-word indirect */
 | 
						|
		with GPR
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				lhz %a, {GPRINDIRECT, %1, 0}
 | 
						|
			yields %a
 | 
						|
		with SUM_RR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				lhzx %a, %1.reg1, %1.reg2
 | 
						|
			yields %a
 | 
						|
		with SUM_RC
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				move {IND_RC_H, %1.reg, %1.off}, %a
 | 
						|
			yields %a
 | 
						|
		
 | 
						|
	pat loi $1==INT32                  /* Load word indirect */
 | 
						|
		with GPR
 | 
						|
			yields {IND_RC_W, %1, 0}
 | 
						|
		with SUM_RC
 | 
						|
			yields {IND_RC_W, %1.reg, %1.off}
 | 
						|
		with SUM_RR
 | 
						|
			yields {IND_RR_W, %1.reg1, %1.reg2}
 | 
						|
		with LABEL
 | 
						|
			yields {IND_LABEL_W, %1.adr}
 | 
						|
 | 
						|
	pat loi $1==INT64                  /* Load double-word indirect */
 | 
						|
		with GPR
 | 
						|
			yields {IND_RC_D, %1, 0}
 | 
						|
		with SUM_RC
 | 
						|
			yields {IND_RC_D, %1.reg, %1.off}
 | 
						|
		with SUM_RR
 | 
						|
			yields {IND_RR_D, %1.reg1, %1.reg2}
 | 
						|
		with LABEL
 | 
						|
			yields {IND_LABEL_D, %1.adr}
 | 
						|
 | 
						|
	pat loi                            /* Load arbitrary size */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			los INT32
 | 
						|
					
 | 
						|
	pat los                            /* Load arbitrary size */
 | 
						|
		with GPR3 GPR4 STACK
 | 
						|
			kills ALL
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".los"}
 | 
						|
				
 | 
						|
	pat sti $1==INT8                   /* Store byte indirect */
 | 
						|
		with GPR GPR
 | 
						|
			gen
 | 
						|
				stb %2, {GPRINDIRECT, %1, 0}
 | 
						|
		with SUM_RR GPR
 | 
						|
			gen
 | 
						|
				stbx %2, %1.reg1, %1.reg2
 | 
						|
		with SUM_RC GPR
 | 
						|
			gen
 | 
						|
				move %2, {IND_RC_B, %1.reg, %1.off}
 | 
						|
		with GPR SEX_B
 | 
						|
			gen
 | 
						|
				stb %2.reg, {GPRINDIRECT, %1, 0}
 | 
						|
		with SUM_RR SEX_B
 | 
						|
			gen
 | 
						|
				stbx %2.reg, %1.reg1, %1.reg2
 | 
						|
		with SUM_RC SEX_B
 | 
						|
			gen
 | 
						|
				move %2.reg, {IND_RC_B, %1.reg, %1.off}
 | 
						|
 | 
						|
	pat sti $1==INT16                  /* Store half-word indirect */
 | 
						|
		with GPR GPR
 | 
						|
			gen
 | 
						|
				sth %2, {GPRINDIRECT, %1, 0}
 | 
						|
		with SUM_RR GPR
 | 
						|
			gen
 | 
						|
				sthx %2, %1.reg1, %1.reg2
 | 
						|
		with SUM_RC GPR
 | 
						|
			gen
 | 
						|
				move %2, {IND_RC_H, %1.reg, %1.off}
 | 
						|
		with GPR SEX_H
 | 
						|
			gen
 | 
						|
				sth %2.reg, {GPRINDIRECT, %1, 0}
 | 
						|
		with SUM_RR SEX_H
 | 
						|
			gen
 | 
						|
				sthx %2.reg, %1.reg1, %1.reg2
 | 
						|
		with SUM_RC SEX_H
 | 
						|
			gen
 | 
						|
				move %2.reg, {IND_RC_H, %1.reg, %1.off}
 | 
						|
 | 
						|
	pat sti $1==INT32                  /* Store word indirect */
 | 
						|
		with GPR GPR+FS
 | 
						|
			gen
 | 
						|
				move %2, {IND_RC_W, %1, 0}
 | 
						|
		with SUM_RR GPR+FS
 | 
						|
			gen
 | 
						|
				move %2, {IND_RR_W, %1.reg1, %1.reg2}
 | 
						|
		with SUM_RC GPR+FS
 | 
						|
			gen
 | 
						|
				move %2, {IND_RC_W, %1.reg, %1.off}
 | 
						|
		with LABEL GPR+FS
 | 
						|
			gen
 | 
						|
				move %2, {IND_LABEL_W, %1.adr}
 | 
						|
 | 
						|
	pat sti $1==INT64                  /* Store double-word indirect */
 | 
						|
		with GPR FD
 | 
						|
			gen
 | 
						|
				move %2, {IND_RC_D, %1, 0}
 | 
						|
		with SUM_RR FD
 | 
						|
			gen
 | 
						|
				move %2, {IND_RR_D, %1.reg1, %1.reg2}
 | 
						|
		with SUM_RC FD
 | 
						|
			gen
 | 
						|
				move %2, {IND_RC_D, %1.reg, %1.off}
 | 
						|
		with GPR GPR GPR
 | 
						|
			gen
 | 
						|
				stw %2, {GPRINDIRECT, %1, 0}
 | 
						|
				stw %3, {GPRINDIRECT, %1, 4}
 | 
						|
		with SUM_RC GPR GPR
 | 
						|
			gen
 | 
						|
				move %2, {IND_RC_W, %1.reg, %1.off}
 | 
						|
				move %3, {IND_RC_W, %1.reg, %1.off+4}
 | 
						|
		with LABEL FD
 | 
						|
			gen
 | 
						|
				move %2, {IND_LABEL_D, %1.adr}
 | 
						|
				
 | 
						|
 | 
						|
	pat sti                            /* Store arbitrary size */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			sts INT32
 | 
						|
					
 | 
						|
	pat sts                            /* Load arbitrary size */
 | 
						|
		with GPR3 GPR4 STACK
 | 
						|
			kills ALL
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".sts"}
 | 
						|
				
 | 
						|
 | 
						|
 | 
						|
/* Arithmetic wrappers */
 | 
						|
 | 
						|
	pat ads $1==4                      /* Add var to pointer */
 | 
						|
		leaving adi $1
 | 
						|
	
 | 
						|
	pat sbs $1==4                      /* Subtract var from pointer */
 | 
						|
		leaving sbi $1
 | 
						|
		
 | 
						|
	pat adp                            /* Add constant to pointer */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			adi 4
 | 
						|
 | 
						|
	pat adu                            /* Add unsigned */
 | 
						|
		leaving
 | 
						|
			adi $1
 | 
						|
			
 | 
						|
	pat sbu                            /* Subtract unsigned */
 | 
						|
		leaving
 | 
						|
			sbi $1
 | 
						|
			
 | 
						|
	pat inc                            /* Add 1 */
 | 
						|
		leaving
 | 
						|
			loc 1
 | 
						|
			adi 4
 | 
						|
			
 | 
						|
	pat dec                            /* Subtract 1 */
 | 
						|
		leaving
 | 
						|
			loc 1
 | 
						|
			sbi 4
 | 
						|
	
 | 
						|
	pat loc mlu $2==2                  /* Unsigned multiply by constant */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			mli 4
 | 
						|
			
 | 
						|
	pat mlu                            /* Unsigned multiply by var */
 | 
						|
		leaving
 | 
						|
			mli $1
 | 
						|
			
 | 
						|
	pat loc slu                        /* Shift left unsigned by constant amount */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			sli $2
 | 
						|
			
 | 
						|
	pat slu                            /* Shift left unsigned by variable amount */
 | 
						|
		leaving
 | 
						|
			sli $1
 | 
						|
 | 
						|
			
 | 
						|
			
 | 
						|
/* Word arithmetic */
 | 
						|
 | 
						|
	pat adi $1==4                      /* Add word (second + top) */
 | 
						|
		with REG REG
 | 
						|
			yields {SUM_RR, %1, %2}
 | 
						|
		with CONST REG
 | 
						|
			yields {SUM_RC, %2, %1.val}
 | 
						|
		with REG CONST
 | 
						|
			yields {SUM_RC, %1, %2.val}
 | 
						|
		with CONST SUM_RC
 | 
						|
			yields {SUM_RC, %2.reg, %2.off+%1.val}
 | 
						|
		with CONST LABEL
 | 
						|
			yields {LABEL, %2.adr+%1.val}
 | 
						|
			
 | 
						|
	pat sbi $1==4                      /* Subtract word (second - top) */
 | 
						|
		with REG REG
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				subf %a, %1, %2
 | 
						|
			yields %a
 | 
						|
		with CONST REG
 | 
						|
			yields {SUM_RC, %2, 0-%1.val}
 | 
						|
		with CONST SUM_RC
 | 
						|
			yields {SUM_RC, %2.reg, %2.off-%1.val}
 | 
						|
		with CONST LABEL
 | 
						|
			yields {LABEL, %2.adr+(0-%1.val)}
 | 
						|
				
 | 
						|
	pat ngi $1==4                      /* Negate word */
 | 
						|
		with REG
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				neg %a, %1
 | 
						|
			yields %a
 | 
						|
		
 | 
						|
	pat mli $1==4                      /* Multiply word (second * top) */
 | 
						|
		with REG REG
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				mullw %a, %2, %1
 | 
						|
			yields %a
 | 
						|
		
 | 
						|
	pat dvi $1==4                      /* Divide word (second / top) */
 | 
						|
		with REG REG
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				divw %a, %2, %1
 | 
						|
			yields %a
 | 
						|
					
 | 
						|
	pat dvu $1==4                      /* Divide unsigned word (second / top) */
 | 
						|
		with REG REG
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				divwu %a, %2, %1
 | 
						|
			yields %a
 | 
						|
 | 
						|
	pat rmi $1==4                      /* Remainder word (second % top) */
 | 
						|
		with REG REG
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				divw %a, %2, %1
 | 
						|
				mullw %a, %a, %1
 | 
						|
				subf %a, %a, %2
 | 
						|
			yields %a
 | 
						|
								
 | 
						|
	pat rmu $1==4                      /* Remainder unsigned word (second % top) */
 | 
						|
		with REG REG
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				divwu %a, %2, %1
 | 
						|
				mullw %a, %a, %1
 | 
						|
				subf %a, %a, %2
 | 
						|
			yields %a
 | 
						|
 | 
						|
	pat and $1==4                      /* AND word */
 | 
						|
		with GPR NOT_R
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				andc %a, %1, %2.reg
 | 
						|
			yields %a
 | 
						|
		with NOT_R GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				andc %a, %2, %1.reg
 | 
						|
			yields %a
 | 
						|
		with GPR GPR
 | 
						|
			yields {AND_RR, %1, %2}
 | 
						|
		with GPR CONST
 | 
						|
			yields {AND_RC, %1, %2.val}
 | 
						|
		with CONST GPR
 | 
						|
			yields {AND_RC, %2, %1.val}
 | 
						|
		
 | 
						|
	pat and !defined($1)               /* AND set */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".and"}
 | 
						|
				
 | 
						|
	pat ior $1==4                      /* OR word */
 | 
						|
		with GPR NOT_R
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				orc %a, %1, %2.reg
 | 
						|
			yields %a
 | 
						|
		with NOT_R GPR
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				orc %a, %2, %1.reg
 | 
						|
			yields %a
 | 
						|
		with GPR GPR
 | 
						|
			yields {OR_RR, %1, %2}
 | 
						|
		with GPR CONST
 | 
						|
			yields {OR_RC, %1, %2.val}
 | 
						|
		with CONST GPR
 | 
						|
			yields {OR_RC, %2, %1.val}
 | 
						|
		
 | 
						|
	pat ior !defined($1)               /* OR set */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".ior"}
 | 
						|
				
 | 
						|
	pat xor $1==4                      /* XOR word */
 | 
						|
		with GPR GPR
 | 
						|
			yields {XOR_RR, %1, %2}
 | 
						|
		with GPR CONST
 | 
						|
			yields {XOR_RC, %1, %2.val}
 | 
						|
		with CONST GPR
 | 
						|
			yields {XOR_RC, %2, %1.val}
 | 
						|
	
 | 
						|
	pat xor !defined($1)               /* XOR set */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".xor"}
 | 
						|
				
 | 
						|
	pat com $1==INT32                  /* NOT word */
 | 
						|
		with AND_RR
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				nand %a, %1.reg1, %1.reg2
 | 
						|
			yields %a
 | 
						|
		with OR_RR
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				nor %a, %1.reg1, %1.reg2
 | 
						|
			yields %a
 | 
						|
		with XOR_RR
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				eqv %a, %1.reg1, %1.reg2
 | 
						|
			yields %a
 | 
						|
		with GPR
 | 
						|
			yields {NOT_R, %1}
 | 
						|
				
 | 
						|
	pat com !defined($1)               /* NOT set */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".com"}
 | 
						|
				
 | 
						|
	pat sli $1==4                      /* Shift left (second << top) */
 | 
						|
		with CONST GPR
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				rlwinm %a, %2, {CONST, (%1.val & 0x1F)}, {CONST, 0}, {CONST, 31-(%1.val & 0x1F)}
 | 
						|
			yields %a
 | 
						|
		with GPR GPR
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				slw %a, %2, %1
 | 
						|
			yields %a
 | 
						|
			
 | 
						|
	pat sri $1==4                      /* Shift right signed (second >> top) */
 | 
						|
		with CONST GPR
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				srawi %a, %2, {CONST, %1.val & 0x1F}
 | 
						|
			yields %a
 | 
						|
		with GPR GPR
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				sraw %a, %2, %1
 | 
						|
			yields %a
 | 
						|
 | 
						|
	pat sru $1==4                      /* Shift right unsigned (second >> top) */
 | 
						|
		with CONST GPR
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				rlwinm %a, %2, {CONST, 32-(%1.val & 0x1F)}, {CONST, (%1.val & 0x1F)}, {CONST, 31}
 | 
						|
			yields %a
 | 
						|
		with GPR GPR
 | 
						|
			uses reusing %2, REG
 | 
						|
			gen
 | 
						|
				srw %a, %2, %1
 | 
						|
			yields %a
 | 
						|
			
 | 
						|
 | 
						|
 | 
						|
/* Arrays */
 | 
						|
 | 
						|
	pat aar $1==INT32                  /* Index array */
 | 
						|
		with GPR3 GPR4 GPR5
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".aar4"}
 | 
						|
			yields R3
 | 
						|
			
 | 
						|
	pat lae lar $2==INT32 && nicesize(rom($1, 3)) /* Load array */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
			aar INT32
 | 
						|
			loi rom($1, 3)
 | 
						|
			
 | 
						|
	pat lar $1==INT32                  /* Load array */
 | 
						|
		with GPR3 GPR4 GPR5 STACK
 | 
						|
			kills ALL
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".lar4"}
 | 
						|
			
 | 
						|
	pat lae sar $2==INT32 && nicesize(rom($1, 3)) /* Store array */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
			aar INT32
 | 
						|
			sti rom($1, 3)
 | 
						|
 | 
						|
	pat sar $1==INT32                  /* Store array */
 | 
						|
		with GPR3 GPR4 GPR5 STACK
 | 
						|
			kills ALL
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".sar4"}
 | 
						|
			
 | 
						|
 | 
						|
 | 
						|
			
 | 
						|
/* Sets */
 | 
						|
 | 
						|
	pat set defined($1)                /* Create word with set bit */
 | 
						|
		leaving
 | 
						|
			loc 1
 | 
						|
			exg INT32
 | 
						|
			sli INT32
 | 
						|
			
 | 
						|
	pat set !defined($1)               /* Create structure with set bit (variable) */
 | 
						|
		with GPR3 GPR4 STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".set"}
 | 
						|
			
 | 
						|
	pat inn defined($1)                /* Test for set bit */
 | 
						|
		leaving
 | 
						|
			set INT32
 | 
						|
			and INT32
 | 
						|
			
 | 
						|
	pat inn !defined($1)               /* Test for set bit (variable) */
 | 
						|
		with GPR3 STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".inn"}
 | 
						|
			
 | 
						|
			
 | 
						|
			
 | 
						|
/* Boolean resolutions */
 | 
						|
 | 
						|
	pat teq                            /* top = (top == 0) */
 | 
						|
		with TRISTATE_ALL + GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				move C0, SCRATCH
 | 
						|
				move {LABEL, ".teq_table"}, %a
 | 
						|
				lwzx %a, %a, SCRATCH
 | 
						|
			yields %a
 | 
						|
				
 | 
						|
	pat tne                            /* top = (top != 0) */
 | 
						|
		with TRISTATE_ALL + GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				move C0, SCRATCH
 | 
						|
				move {LABEL, ".tne_table"}, %a
 | 
						|
				lwzx %a, %a, SCRATCH
 | 
						|
			yields %a
 | 
						|
				
 | 
						|
	pat tlt                            /* top = (top < 0) */
 | 
						|
		with TRISTATE_ALL + GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				move C0, SCRATCH
 | 
						|
				move {LABEL, ".tlt_table"}, %a
 | 
						|
				lwzx %a, %a, SCRATCH
 | 
						|
			yields %a
 | 
						|
				
 | 
						|
	pat tle                            /* top = (top <= 0) */
 | 
						|
		with TRISTATE_ALL + GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				move C0, SCRATCH
 | 
						|
				move {LABEL, ".tle_table"}, %a
 | 
						|
				lwzx %a, %a, SCRATCH
 | 
						|
			yields %a
 | 
						|
				
 | 
						|
	pat tgt                            /* top = (top > 0) */
 | 
						|
		with TRISTATE_ALL + GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				move C0, SCRATCH
 | 
						|
				move {LABEL, ".tgt_table"}, %a
 | 
						|
				lwzx %a, %a, SCRATCH
 | 
						|
			yields %a
 | 
						|
 | 
						|
	pat tge                            /* top = (top >= 0) */
 | 
						|
		with TRISTATE_ALL + GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				move C0, SCRATCH
 | 
						|
				move {LABEL, ".tge_table"}, %a
 | 
						|
				lwzx %a, %a, SCRATCH
 | 
						|
			yields %a
 | 
						|
				
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Simple branches */
 | 
						|
 | 
						|
	pat zeq                            /* Branch if signed top == 0 */
 | 
						|
		with TRISTATE_ALL+GPR STACK
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				bc IFTRUE, EQ, {LABEL, $1}
 | 
						|
 | 
						|
	pat beq
 | 
						|
		leaving
 | 
						|
			cmi INT32
 | 
						|
			zeq $1
 | 
						|
			
 | 
						|
	pat zne                            /* Branch if signed top != 0 */
 | 
						|
		with TRISTATE_ALL+GPR STACK
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				bc IFFALSE, EQ, {LABEL, $1}
 | 
						|
 | 
						|
	pat bne
 | 
						|
		leaving
 | 
						|
			cmi INT32
 | 
						|
			zne $1
 | 
						|
			
 | 
						|
	pat zgt                            /* Branch if signed top > 0 */
 | 
						|
		with TRISTATE_ALL+GPR STACK
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				bc IFTRUE, GT, {LABEL, $1}
 | 
						|
 | 
						|
	pat bgt
 | 
						|
		leaving
 | 
						|
			cmi INT32
 | 
						|
			zgt $1
 | 
						|
			
 | 
						|
	pat zge                            /* Branch if signed top >= 0 */
 | 
						|
		with TRISTATE_ALL+GPR STACK
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				bc IFFALSE, LT, {LABEL, $1}
 | 
						|
 | 
						|
	pat bge
 | 
						|
		leaving
 | 
						|
			cmi INT32
 | 
						|
			zge $1
 | 
						|
			
 | 
						|
	pat zlt                            /* Branch if signed top < 0 */
 | 
						|
		with TRISTATE_ALL+GPR STACK
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				bc IFTRUE, LT, {LABEL, $1}
 | 
						|
 | 
						|
	pat blt
 | 
						|
		leaving
 | 
						|
			cmi INT32
 | 
						|
			zlt $1
 | 
						|
			
 | 
						|
	pat zle                            /* Branch if signed top >= 0 */
 | 
						|
		with TRISTATE_ALL+GPR STACK
 | 
						|
			gen
 | 
						|
				move %1, C0
 | 
						|
				bc IFFALSE, GT, {LABEL, $1}
 | 
						|
 | 
						|
	pat ble
 | 
						|
		leaving
 | 
						|
			cmi INT32
 | 
						|
			zle $1
 | 
						|
			
 | 
						|
 | 
						|
/* Compare and jump */
 | 
						|
 | 
						|
	pat cmi                            /* Signed tristate compare */
 | 
						|
		with CONST GPR
 | 
						|
			yields {TRISTATE_RC_S, %2, %1.val}
 | 
						|
		with GPR GPR
 | 
						|
			yields {TRISTATE_RR_S, %2, %1}
 | 
						|
			
 | 
						|
	pat cmu                            /* Unsigned tristate compare */
 | 
						|
		with CONST GPR
 | 
						|
			yields {TRISTATE_RC_U, %2, %1.val}
 | 
						|
		with GPR GPR
 | 
						|
			yields {TRISTATE_RR_U, %2, %1}
 | 
						|
						
 | 
						|
	pat cmp                            /* Compare pointers */
 | 
						|
		leaving
 | 
						|
			cmu INT32
 | 
						|
			
 | 
						|
	pat cms $1==INT32                  /* Compare blocks (word sized) */
 | 
						|
		leaving
 | 
						|
			cmi INT32
 | 
						|
			
 | 
						|
			
 | 
						|
			
 | 
						|
 | 
						|
/* Other branching and labelling */
 | 
						|
 | 
						|
	pat lab topeltsize($1)==4 && !fallthrough($1)
 | 
						|
		gen
 | 
						|
			labeldef $1
 | 
						|
			yields R3
 | 
						|
			
 | 
						|
	pat lab topeltsize($1)==4 && fallthrough($1)
 | 
						|
		with GPR3
 | 
						|
		gen
 | 
						|
			labeldef $1
 | 
						|
		yields %1
 | 
						|
			
 | 
						|
	pat lab topeltsize($1)!=4
 | 
						|
		with STACK
 | 
						|
		kills ALL
 | 
						|
		gen
 | 
						|
			labeldef $1
 | 
						|
			
 | 
						|
	pat bra topeltsize($1)==4          /* Unconditional jump with TOS GPRister */
 | 
						|
		with GPR3 STACK
 | 
						|
		gen
 | 
						|
			b {LABEL, $1}
 | 
						|
			
 | 
						|
	pat bra topeltsize($1)!=4          /* Unconditional jump without TOS GPRister */
 | 
						|
		with STACK
 | 
						|
		gen
 | 
						|
			b {LABEL, $1}
 | 
						|
			
 | 
						|
				
 | 
						|
						
 | 
						|
/* Miscellaneous */
 | 
						|
 | 
						|
	pat cal                            /* Call procedure */
 | 
						|
		with STACK
 | 
						|
			kills ALL
 | 
						|
			gen
 | 
						|
				bl {LABEL, $1}
 | 
						|
 | 
						|
	pat cai                            /* Call procedure indirect */
 | 
						|
		with GPR STACK
 | 
						|
			kills ALL
 | 
						|
			gen
 | 
						|
				mtspr CTR, %1
 | 
						|
				bcctrl ALWAYS, {CONST, 0}, {CONST, 0}
 | 
						|
				
 | 
						|
	pat lfr $1==INT32                  /* Load function result, word */
 | 
						|
		yields R3
 | 
						|
		
 | 
						|
	pat lfr $1==INT64                  /* Load function result, double-word */
 | 
						|
		yields R4 R3
 | 
						|
		
 | 
						|
	pat ret $1==0                      /* Return from procedure */
 | 
						|
		gen
 | 
						|
			return
 | 
						|
			b {LABEL, ".ret"}
 | 
						|
			
 | 
						|
	pat ret $1==INT32                  /* Return from procedure, word */
 | 
						|
		with GPR3
 | 
						|
		gen
 | 
						|
			return
 | 
						|
			b {LABEL, ".ret"}
 | 
						|
 | 
						|
	pat ret $1==INT64                  /* Return from procedure, double-word */
 | 
						|
		with GPR3 GPR4
 | 
						|
		gen
 | 
						|
			return
 | 
						|
			b {LABEL, ".ret"}
 | 
						|
 | 
						|
	pat blm                            /* Block move constant length */
 | 
						|
		with GPR GPR STACK
 | 
						|
			uses REG
 | 
						|
			gen
 | 
						|
				move {CONST, $1}, %a
 | 
						|
				stwu %a, {GPRINDIRECT, SP, 0-4}
 | 
						|
				stwu %2, {GPRINDIRECT, SP, 0-4}
 | 
						|
				stwu %1, {GPRINDIRECT, SP, 0-4}
 | 
						|
				bl {LABEL, "_memmove"}
 | 
						|
				addi SP, SP, {CONST, 12}
 | 
						|
				
 | 
						|
	pat bls                            /* Block move variable length */
 | 
						|
		with GPR GPR GPR STACK
 | 
						|
			gen
 | 
						|
				stwu %1, {GPRINDIRECT, SP, 0-4}
 | 
						|
				stwu %3, {GPRINDIRECT, SP, 0-4}
 | 
						|
				stwu %2, {GPRINDIRECT, SP, 0-4}
 | 
						|
				bl {LABEL, "_memmove"}
 | 
						|
				addi SP, SP, {CONST, 12}
 | 
						|
				
 | 
						|
	pat csa                            /* Array-lookup switch */
 | 
						|
		with GPR3 GPR4 STACK
 | 
						|
			gen
 | 
						|
				b {LABEL, ".csa"}
 | 
						|
				
 | 
						|
	pat csb                            /* Table-lookup switch */
 | 
						|
		with GPR3 GPR4 STACK
 | 
						|
			gen
 | 
						|
				b {LABEL, ".csb"}
 | 
						|
 | 
						|
				
 | 
						|
 | 
						|
/* EM specials */
 | 
						|
 | 
						|
	pat fil                            /* Set current filename */
 | 
						|
		leaving
 | 
						|
			lae $1
 | 
						|
			ste ".filename"
 | 
						|
			
 | 
						|
	pat lin                            /* Set current line number */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			ste ".linenumber"
 | 
						|
 | 
						|
	pat lni                            /* Increment line number */
 | 
						|
		leaving
 | 
						|
			ine ".linenumber"			
 | 
						|
			
 | 
						|
	pat lim                            /* Load EM trap ignore mask */
 | 
						|
		leaving
 | 
						|
			lde ".ignmask"
 | 
						|
			
 | 
						|
	pat sim                            /* Store EM trap ignore mask */
 | 
						|
		leaving
 | 
						|
			ste ".ignmask"
 | 
						|
			
 | 
						|
	pat trp                            /* Raise EM trap */
 | 
						|
		with GPR3
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".trap"}
 | 
						|
				
 | 
						|
	pat sig                            /* Set trap handler */
 | 
						|
		leaving
 | 
						|
			ste ".trppc"
 | 
						|
			
 | 
						|
	pat rtt                            /* Return from trap */
 | 
						|
		leaving
 | 
						|
			ret 0
 | 
						|
			
 | 
						|
	pat lxl $1==0                      /* Load FP */
 | 
						|
		leaving
 | 
						|
			lor 0
 | 
						|
		
 | 
						|
	pat lxl $1==1                      /* Load caller's FP */
 | 
						|
		leaving
 | 
						|
			lxl 0
 | 
						|
			dch
 | 
						|
			
 | 
						|
	pat dch                            /* FP -> caller FP */
 | 
						|
		with GPR
 | 
						|
			uses reusing %1, REG
 | 
						|
			gen
 | 
						|
				lwz %a, {GPRINDIRECT, %1, FP_OFFSET}
 | 
						|
			yields %a
 | 
						|
 | 
						|
	pat lpb                            /* Convert FP to argument address */
 | 
						|
		leaving
 | 
						|
			adp EM_BSIZE
 | 
						|
			
 | 
						|
	pat lxa                            /* Load caller's SP */
 | 
						|
		leaving
 | 
						|
			lxl $1
 | 
						|
			lpb
 | 
						|
			
 | 
						|
	pat gto                            /* longjmp */
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			move {LABEL, $1}, %a
 | 
						|
			move {IND_RC_W, %a, 8}, FP
 | 
						|
			move {IND_RC_W, %a, 4}, SP
 | 
						|
			move {IND_RC_W, %a, 0}, %a
 | 
						|
			mtspr CTR, %a
 | 
						|
			bcctr ALWAYS, {CONST, 0}, {CONST, 0}
 | 
						|
				
 | 
						|
#if 0
 | 
						|
			
 | 
						|
	pat gto                            /* longjmp */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				ld {LABEL, $1+2}
 | 
						|
				wspec {CONST, 1}
 | 
						|
				ld {LABEL, $1+4}
 | 
						|
				wspec {CONST, 0}
 | 
						|
				ld {LABEL, $1+0}
 | 
						|
				wspec {CONST, 2}
 | 
						|
			
 | 
						|
	pat str $1==1                      /* Store special GPRister */
 | 
						|
		with GPR0
 | 
						|
			gen
 | 
						|
				wspec {CONST, $1}
 | 
						|
				
 | 
						|
#endif
 | 
						|
 | 
						|
	pat lor $1==0                      /* Load FP */
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			move FP, %a
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	pat lor $1==1                      /* Load SP */
 | 
						|
		uses REG
 | 
						|
		gen
 | 
						|
			move SP, %a
 | 
						|
		yields %a
 | 
						|
		
 | 
						|
	pat lor $1==2                      /* Load HP */
 | 
						|
		leaving
 | 
						|
			loe ".reghp"
 | 
						|
			
 | 
						|
	pat str $1==0                      /* Store FP */
 | 
						|
		with GPR
 | 
						|
			gen
 | 
						|
				move %1, FP
 | 
						|
				
 | 
						|
	pat str $1==1                      /* Store SP */
 | 
						|
		with GPR
 | 
						|
			gen
 | 
						|
				move %1, SP
 | 
						|
			
 | 
						|
	pat str $1==2                      /* Store HP */
 | 
						|
		leaving
 | 
						|
			ste ".reghp"
 | 
						|
				
 | 
						|
	pat ass                            /* Adjust stack by variable amount */
 | 
						|
		with CONST
 | 
						|
			gen
 | 
						|
				move {SUM_RC, SP, %1.val}, {GPRE, SP}
 | 
						|
		with GPR
 | 
						|
			gen
 | 
						|
				move {SUM_RR, SP, %1}, {GPRE, SP}
 | 
						|
				
 | 
						|
	pat asp                            /* Adjust stack by constant amount */
 | 
						|
		leaving
 | 
						|
			loc $1
 | 
						|
			ass
 | 
						|
			
 | 
						|
			
 | 
						|
			
 | 
						|
/* Floating point support */
 | 
						|
 | 
						|
	/* All very cheap and nasty --- this needs to be properly integrated into
 | 
						|
	 * the code generator. ncg doesn't like having separate FPU registers. */
 | 
						|
 | 
						|
	/* Single-precision */
 | 
						|
	
 | 
						|
	pat zrf $1==INT32                  /* Push zero */
 | 
						|
		leaving
 | 
						|
			loe ".fs_00000000"
 | 
						|
		
 | 
						|
	pat adf $1==INT32                  /* Add single */
 | 
						|
		with FS FS
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fadds {FS, %a}, %2, %1
 | 
						|
			yields {FS, %a}
 | 
						|
				
 | 
						|
	pat sbf $1==INT32                  /* Subtract single */
 | 
						|
		with FS FS
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fsubs {FS, %a}, %2, %1
 | 
						|
			yields {FS, %a}
 | 
						|
				
 | 
						|
	pat mlf $1==INT32                  /* Multiply single */
 | 
						|
		with FS FS
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fmuls {FS, %a}, %2, %1
 | 
						|
			yields {FS, %a}
 | 
						|
 | 
						|
	pat dvf $1==INT32                  /* Divide single */
 | 
						|
		with FS FS
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fdivs {FS, %a}, %2, %1
 | 
						|
			yields {FS, %a}
 | 
						|
 | 
						|
	pat ngf $1==INT32                  /* Negate single */
 | 
						|
		with FS
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fneg {FS, %a}, %1
 | 
						|
			yields {FS, %a}
 | 
						|
 | 
						|
	pat cmf $1==INT32                  /* Compare single */
 | 
						|
		with FS FS
 | 
						|
			yields {TRISTATE_FF, %2.reg, %1.reg}
 | 
						|
			
 | 
						|
	pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */
 | 
						|
		with FS
 | 
						|
			yields {FD, %1.reg}
 | 
						|
					
 | 
						|
	pat loc loc cfu $1==INT32 && $2==INT32 /* Convert single to unsigned int */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cfu4"}
 | 
						|
				
 | 
						|
	pat loc loc cfi $1==INT32 && $2==INT32 /* Convert single to signed int */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cfi4"}
 | 
						|
				
 | 
						|
	pat loc loc cif $1==INT32 && $2==INT32 /* Convert integer to single */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cif4"}
 | 
						|
				
 | 
						|
	pat loc loc cuf $1==INT32 && $2==INT32 /* Convert unsigned int to single */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cuf4"}
 | 
						|
				
 | 
						|
	pat fef $1==INT32                  /* Split single */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".fef4"}
 | 
						|
				
 | 
						|
	/* Double-precision */
 | 
						|
	
 | 
						|
	pat zrf $1==INT64                  /* Push zero */
 | 
						|
		leaving
 | 
						|
			lde ".fd_00000000"
 | 
						|
		
 | 
						|
	pat adf $1==INT64                  /* Add double */
 | 
						|
		with FD FD
 | 
						|
			uses FREG
 | 
						|
			gen
 | 
						|
				fadd {FD, %a}, %2, %1
 | 
						|
			yields {FD, %a}
 | 
						|
				
 | 
						|
	pat sbf $1==INT64                  /* Subtract double */
 | 
						|
		with FD FD
 | 
						|
			uses FREG
 | 
						|
			gen
 | 
						|
				fsub {FD, %a}, %2, %1
 | 
						|
			yields {FD, %a}
 | 
						|
				
 | 
						|
	pat mlf $1==INT64                  /* Multiply double */
 | 
						|
		with FD FD
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fmul {FD, %a}, %2, %1
 | 
						|
			yields {FD, %a}
 | 
						|
 | 
						|
	pat dvf $1==INT64                  /* Divide double */
 | 
						|
		with FD FD
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fdiv {FD, %a}, %2, %1
 | 
						|
			yields {FD, %a}
 | 
						|
 | 
						|
	pat ngf $1==INT64                  /* Negate double */
 | 
						|
		with FD
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				fneg {FD, %a}, %1
 | 
						|
			yields {FD, %a}
 | 
						|
 | 
						|
	pat cmf $1==INT64                  /* Compare double */
 | 
						|
		with FD FD
 | 
						|
			yields {TRISTATE_FF, %2.reg, %1.reg}
 | 
						|
				
 | 
						|
	pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */
 | 
						|
		with FD
 | 
						|
			uses reusing %1, FREG
 | 
						|
			gen
 | 
						|
				frsp {FS, %a}, %1
 | 
						|
			yields {FS, %a}
 | 
						|
					
 | 
						|
	pat loc loc cfu $1==INT64 && $2==INT32 /* Convert double to unsigned int */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cfu8"}
 | 
						|
				
 | 
						|
	pat loc loc cfi $1==INT64 && $2==INT32 /* Convert double to signed int */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cfi8"}
 | 
						|
				
 | 
						|
	pat loc loc cif $1==INT32 && $2==INT64 /* Convert integer to double */
 | 
						|
		with STACK
 | 
						|
			kills ALL
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cif8"}
 | 
						|
		
 | 
						|
	pat loc loc cuf $1==INT32 && $2==INT64 /* Convert unsigned int to double */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".cuf8"}
 | 
						|
				
 | 
						|
	pat fef $1==INT64                  /* Split double */
 | 
						|
		with FD
 | 
						|
			gen
 | 
						|
				addi SP, SP, {CONST, 0-8}
 | 
						|
				stfd %1, {GPRINDIRECT, SP, 0}
 | 
						|
				stwu SP, {GPRINDIRECT, SP, 0-4}
 | 
						|
				bl {LABEL, "___fef8"}
 | 
						|
				stw R3, {GPRINDIRECT, SP, 0}
 | 
						|
				
 | 
						|
	pat fif $1==INT64                  /* Multiply and split double (?) */
 | 
						|
		with STACK
 | 
						|
			gen
 | 
						|
				bl {LABEL, ".fif8"}
 | 
						|
				
 |