2235 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			2235 lines
		
	
	
	
		
			50 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) /* comment {LABEL, n} */
 | |
| 
 | |
| 
 | |
| #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) (lo(n) | (((0-(lo(n)>>15)) & ~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 */
 | |
| 	REG_PAIR        /* speed hack for sti 8 */
 | |
| 	FPR             /* any FPR */
 | |
| 	FREG            /* any allocatable FPR */
 | |
| 	FSREG           /* any allocatable single-precision 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.
 | |
| 
 | |
| 	/* speed hack for sti 8 */
 | |
| 	PAIR_R9_R10=R9+R10 : REG_PAIR.
 | |
| 	PAIR_R7_R8=R7+R8   : REG_PAIR.
 | |
| 	PAIR_R5_R6=R5+R6   : REG_PAIR.
 | |
| 	PAIR_R3_R4=R3+R4   : REG_PAIR.
 | |
| 
 | |
| 	/*
 | |
| 	 * F14 to F31 are reserved for regvar, if we ever implement
 | |
| 	 * it.  Don't add them to FREG; the register allocator would
 | |
| 	 * be too slow.
 | |
| 	 */
 | |
| 	F31("f31")         : FPR, FPR31.
 | |
| 	F30("f30")         : FPR, FPR30.
 | |
| 	F29("f29")         : FPR, FPR29.
 | |
| 	F28("f28")         : FPR, FPR28.
 | |
| 	F27("f27")         : FPR, FPR27.
 | |
| 	F26("f26")         : FPR, FPR26.
 | |
| 	F25("f25")         : FPR, FPR25.
 | |
| 	F24("f24")         : FPR, FPR24.
 | |
| 	F23("f23")         : FPR, FPR23.
 | |
| 	F22("f22")         : FPR, FPR22.
 | |
| 	F21("f21")         : FPR, FPR21.
 | |
| 	F20("f20")         : FPR, FPR20.
 | |
| 	F19("f19")         : FPR, FPR19.
 | |
| 	F18("f18")         : FPR, FPR18.
 | |
| 	F17("f17")         : FPR, FPR17.
 | |
| 	F16("f16")         : FPR, FPR16.
 | |
| 	F15("f15")         : FPR, FPR15.
 | |
| 	F14("f14")         : FPR, 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, FPR0.
 | |
| 
 | |
| 	FS13("f13")=F13    : FSREG.
 | |
| 	FS12("f12")=F12    : FSREG.
 | |
| 	FS11("f11")=F11    : FSREG.
 | |
| 	FS10("f10")=F10    : FSREG.
 | |
| 	FS9("f9")=F9       : FSREG.
 | |
| 	FS8("f8")=F8       : FSREG.
 | |
| 	FS7("f7")=F7       : FSREG.
 | |
| 	FS6("f6")=F6       : FSREG.
 | |
| 	FS5("f5")=F5       : FSREG.
 | |
| 	FS4("f4")=F4       : FSREG.
 | |
| 	FS3("f3")=F3       : FSREG.
 | |
| 	FS2("f2")=F2       : FSREG.
 | |
| 	FS1("f1")=F1       : FSREG.
 | |
| 
 | |
| 	LR("lr")           : SPR.
 | |
| 	CTR("ctr")         : SPR.
 | |
| 	C0("cr0")          : CR, CR0.
 | |
| 
 | |
| #define RSCRATCH R11
 | |
| #define FSCRATCH F0
 | |
| 
 | |
| 
 | |
| TOKENS
 | |
| 
 | |
| /* Used only in instruction descriptions (to generate the correct syntax). */
 | |
| 
 | |
| 	GPRINDIRECT        = { GPR reg; INT off; }    4    off "(" reg ")".
 | |
| 	CONST              = { INT val; }             4    val.
 | |
| 
 | |
| /* Primitives */
 | |
| 
 | |
| 	LABEL              = { ADDR adr; }            4    adr.
 | |
| 	LOCAL              = { INT off; }             4.
 | |
| 
 | |
| /* Allows us to use regvar() to refer to registers */
 | |
| 
 | |
| 	GPRE               = { GPR reg; }             4    reg.
 | |
| 
 | |
| /* Constants on the stack */
 | |
| 
 | |
| 	CONST_N8000        = { INT val; }             4.
 | |
| 	CONST_N7FFF_N0001  = { INT val; }             4.
 | |
| 	CONST_0000_7FFF    = { INT val; }             4.
 | |
| 	CONST_8000         = { INT val; }             4.
 | |
| 	CONST_8001_FFFF    = { INT val; }             4.
 | |
| 	CONST_HZ           = { INT val; }             4.
 | |
| 	CONST_HL           = { INT val; }             4.
 | |
| 
 | |
| /* Expression partial results */
 | |
| 
 | |
| 	SUM_RIS            = { GPR reg; INT offhi; }  4.
 | |
| 	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_RR_B           = { GPR reg1; GPR reg2; }  4.
 | |
| 	IND_RC_H           = { GPR reg; INT off; }    4.
 | |
| 	IND_RR_H           = { GPR reg1; GPR reg2; }  4.
 | |
| 	IND_RC_H_S         = { GPR reg; INT off; }    4.
 | |
| 	IND_RR_H_S         = { GPR reg1; GPR reg2; }  4.
 | |
| 	IND_RC_W           = { GPR reg; INT off; }    4.
 | |
| 	IND_RR_W           = { GPR reg1; GPR reg2; }  4.
 | |
| 	IND_RC_D           = { GPR reg; INT off; }    8.
 | |
| 	IND_RR_D           = { GPR reg1; GPR reg2; }  8.
 | |
| 
 | |
| 	NOT_R              = { GPR reg; }             4.
 | |
| 
 | |
| 	AND_RR             = { GPR reg1; GPR reg2; }  4.
 | |
| 	OR_RR              = { GPR reg1; GPR reg2; }  4.
 | |
| 	OR_RIS             = { GPR reg; INT valhi; }  4.
 | |
| 	OR_RC              = { GPR reg; INT val; }    4.
 | |
| 	XOR_RR             = { GPR reg1; GPR reg2; }  4.
 | |
| 	XOR_RIS            = { GPR reg; INT valhi; }  4.
 | |
| 	XOR_RC             = { GPR reg; INT val; }    4.
 | |
| 
 | |
| 
 | |
| SETS
 | |
| 
 | |
| 	/* signed 16-bit integer */
 | |
| 	CONST2          = CONST_N8000 + CONST_N7FFF_N0001 + CONST_0000_7FFF.
 | |
| 	/* integer that, when negated, fits signed 16-bit */
 | |
| 	CONST2_WHEN_NEG = CONST_N7FFF_N0001 + CONST_0000_7FFF + CONST_8000.
 | |
| 	/* unsigned 16-bit integer */
 | |
| 	UCONST2         = CONST_0000_7FFF + CONST_8000 + CONST_8001_FFFF.
 | |
| 	/* any constant on stack */
 | |
| 	CONST_ALL       = CONST_N8000 + CONST_N7FFF_N0001 + CONST_0000_7FFF +
 | |
| 	                  CONST_8000 + CONST_8001_FFFF + CONST_HZ + CONST_HL.
 | |
| 
 | |
| 	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 + OR_RR + OR_RC + XOR_RR +
 | |
| 	                     XOR_RC.
 | |
| 
 | |
| 	/* indirect 4-byte value */
 | |
| 	IND_ALL_W          = IND_RC_W + IND_RR_W.
 | |
| 	/* indirect 8-byte value */
 | |
| 	IND_ALL_D          = IND_RC_D + IND_RR_D.
 | |
| 	/* any indirect value that fits in a GPR */
 | |
| 	IND_ALL_BHW        = IND_RC_B + IND_RR_B + IND_RC_H + IND_RR_H +
 | |
| 	                     IND_RC_H_S + IND_RR_H_S + IND_ALL_W.
 | |
| 
 | |
| 	/* anything killed by sti (store indirect) */
 | |
| 	MEMORY             = IND_ALL_BHW + IND_ALL_D.
 | |
| 
 | |
| 	OP_ALL_W           = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL +
 | |
| 	                     IND_ALL_W.
 | |
| 
 | |
| 
 | |
| INSTRUCTIONS
 | |
| 
 | |
|   /* We give time as cycles of total latency from Freescale
 | |
|    * Semiconductor, MPC7450 RISC Microprocessor Family Reference
 | |
|    * Manual, Rev. 5, section 6.6.
 | |
|    *
 | |
|    * We have only 4-byte alignment for doubles; 8-byte alignment is
 | |
|    * optimal.  We guess the misalignment penalty by adding 1 cycle to
 | |
|    * the cost of loading or storing a double:
 | |
|    *   lfd lfdu lfdx: 4 -> 5
 | |
|    *   stfd stfdu stfdx: 3 -> 4
 | |
|    */
 | |
|   cost(4, 1) /* space, time */
 | |
| 
 | |
|   add             GPR:wo, GPR:ro, GPR:ro.
 | |
|   addX "add."     GPR:wo, GPR:ro, GPR:ro.
 | |
|   addi            GPR:wo, GPR:ro, CONST:ro.
 | |
|   addis           GPR:wo, GPR:ro, CONST:ro.
 | |
|   and             GPR:wo, GPR:ro, GPR:ro.
 | |
|   andc            GPR:wo, GPR:ro, GPR:ro.
 | |
|   andiX  "andi."  GPR:wo:cc, GPR:ro, CONST:ro.
 | |
|   andisX "andis." GPR:wo:cc, GPR:ro, CONST:ro.
 | |
|   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, GPR:ro, GPR:ro kills :cc.
 | |
|   cmpi            CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc.
 | |
|   cmpl            CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc.
 | |
|   cmpli           CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc.
 | |
|   divw            GPR:wo, GPR:ro, GPR:ro cost(4, 23).
 | |
|   divwu           GPR:wo, GPR:ro, GPR:ro cost(4, 23).
 | |
|   eqv             GPR:wo, GPR:ro, GPR:ro.
 | |
|   extsb           GPR:wo, GPR:ro.
 | |
|   extsh           GPR:wo, GPR:ro.
 | |
|   fadd            FREG:wo, FREG:ro, FREG:ro cost(4, 5).
 | |
|   fadds           FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5).
 | |
|   fcmpo           CR:wo, FPR:ro, FPR:ro cost(4, 5).
 | |
|   fdiv            FREG:wo, FREG:ro, FREG:ro cost(4, 35).
 | |
|   fdivs           FSREG:wo, FSREG:ro, FSREG:ro cost(4, 21).
 | |
|   fmr             FPR:wo, FPR:ro cost(4, 5).
 | |
|   fmr             FSREG:wo, FSREG:ro cost(4, 5).
 | |
|   fmul            FREG:wo, FREG:ro, FREG:ro cost(4, 5).
 | |
|   fmuls           FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5).
 | |
|   fneg            FREG:wo, FREG:ro cost(4, 5).
 | |
|   fneg            FSREG:wo, FSREG:ro cost(4, 5).
 | |
|   frsp            FSREG:wo, FREG:ro cost(4, 5).
 | |
|   fsub            FREG:wo, FREG:ro, FREG:ro cost(4, 5).
 | |
|   fsubs           FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5).
 | |
|   lbz             GPR:wo, GPRINDIRECT:ro cost(4, 3).
 | |
|   lbzx            GPR:wo, GPR:ro, GPR:ro cost(4, 3).
 | |
|   lfd             FPR:wo, GPRINDIRECT:ro cost(4, 5).
 | |
|   lfdu            FPR:wo, GPRINDIRECT:ro cost(4, 5).
 | |
|   lfdx            FPR:wo, GPR:ro, GPR:ro cost(4, 5).
 | |
|   lfs             FSREG:wo, GPRINDIRECT:ro cost(4, 4).
 | |
|   lfsu            FSREG:wo, GPRINDIRECT:rw cost(4, 4).
 | |
|   lfsx            FSREG:wo, GPR:ro, GPR:ro cost(4, 4).
 | |
|   lha             GPR:wo, GPRINDIRECT:ro cost(4, 3).
 | |
|   lhax            GPR:wo, GPR:ro, GPR:ro cost(4, 3).
 | |
|   lhz             GPR:wo, GPRINDIRECT:ro cost(4, 3).
 | |
|   lhzx            GPR:wo, GPR:ro, GPR:ro cost(4, 3).
 | |
|   li32            GPR:wo, CONST:ro cost(8, 2).
 | |
|   li32            GPR:wo, LABEL:ro cost(8, 2).
 | |
|   lwzu            GPR:wo, GPRINDIRECT:ro cost(4, 3).
 | |
|   lwzx            GPR:wo, GPR:ro, GPR:ro cost(4, 3).
 | |
|   lwz             GPR:wo, GPRINDIRECT:ro cost(4, 3).
 | |
|   nand            GPR:wo, GPR:ro, GPR:ro.
 | |
|   neg             GPR:wo, GPR:ro.
 | |
|   nor             GPR:wo, GPR:ro, GPR:ro.
 | |
|   mfcr            GPR:wo cost(4,2).
 | |
|   mullw           GPR:wo, GPR:ro, GPR:ro cost(4, 4).
 | |
|   mfspr           GPR:wo, SPR:ro cost(4, 3).
 | |
|   mtspr           SPR:wo, GPR:ro cost(4, 2).
 | |
|   or              GPR:wo, GPR:ro, GPR:ro.
 | |
|   orc             GPR:wo, GPR:ro, GPR:ro.
 | |
|   ori             GPR:wo, GPR:ro, CONST:ro.
 | |
|   oris            GPR:wo, GPR:ro, CONST:ro.
 | |
|   orX "or."       GPR:wo:cc, GPR:ro, GPR:ro.
 | |
|   rlwinm          GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro.
 | |
|   slw             GPR:wo, GPR:ro, GPR:ro.
 | |
|   subf            GPR:wo, GPR:ro, GPR:ro.
 | |
|   sraw            GPR:wo, GPR:ro, GPR:ro cost(4, 2).
 | |
|   srawi           GPR:wo, GPR:ro, CONST:ro cost(4, 2).
 | |
|   srw             GPR:wo, GPR:ro, GPR:ro.
 | |
|   stb             GPR:ro, GPRINDIRECT:rw cost(4, 3).
 | |
|   stbx            GPR:ro, GPR:ro, GPR:ro cost(4, 3).
 | |
|   stfd            FPR:ro, GPRINDIRECT:rw cost(4, 4).
 | |
|   stfdu           FPR:ro, GPRINDIRECT:rw cost(4, 4).
 | |
|   stfdx           FPR:ro, GPR:ro, GPR:ro cost(4, 4).
 | |
|   stfs            FSREG:ro, GPRINDIRECT:rw cost(4, 3).
 | |
|   stfsu           FSREG:ro, GPRINDIRECT:rw cost(4, 3).
 | |
|   stfsx           FSREG:ro, GPR:ro, GPR:ro cost(4, 3).
 | |
|   sth             GPR:ro, GPRINDIRECT:rw cost(4, 3).
 | |
|   sthx            GPR:ro, GPR:ro, GPR:ro cost(4, 3).
 | |
|   stw             GPR:ro, GPRINDIRECT:rw cost(4, 3).
 | |
|   stwx            GPR:ro, GPR:ro, GPR:ro cost(4, 3).
 | |
|   stwu            GPR+GPRE:ro, GPRINDIRECT:rw cost(4, 3).
 | |
|   xor             GPR:wo, GPR:ro, GPR:ro.
 | |
|   xori            GPR:wo, GPR:ro, CONST:ro.
 | |
|   xoris           GPR:wo, GPR:ro, CONST:ro.
 | |
| 
 | |
|   comment "!" LABEL:ro cost(0, 0).
 | |
| 
 | |
| 
 | |
| 
 | |
| 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.reg, %1, %1
 | |
| 
 | |
| /* Constants */
 | |
| 
 | |
| 	from CONST_ALL + CONST smalls(%val) to GPR
 | |
| 		gen
 | |
| 			COMMENT("move CONST_ALL->GPR smalls")
 | |
| 			addi %2, R0, {CONST, %1.val}
 | |
| 
 | |
| 	from CONST_ALL + CONST to GPR
 | |
| 		gen
 | |
| 			COMMENT("move CONST_ALL->GPR")
 | |
| 			addis %2, R0, {CONST, hi(%1.val)}
 | |
| 			ori %2, %2, {CONST, lo(%1.val)}
 | |
| 			/* Can't use addi %2, %2, {CONST, los(%1.val)}
 | |
| 			 * because %2 might be R0. */
 | |
| 
 | |
| 	from LABEL to GPR
 | |
| 		gen
 | |
| 			COMMENT("move LABEL->GPR")
 | |
| 			li32 %2, {LABEL, %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_RIS to GPR
 | |
| 		gen
 | |
| 			COMMENT("move SUM_RIS->GPR")
 | |
| 			addis %2, %1.reg, {CONST, %1.offhi}
 | |
| 
 | |
| 	from SUM_RC to GPR
 | |
| 		gen
 | |
| 			COMMENT("move SUM_RC->GPR")
 | |
| 			addi %2, %1.reg, {CONST, %1.off}
 | |
| 
 | |
| 	from SUM_RR to GPR
 | |
| 		gen
 | |
| 			COMMENT("move SUM_RR->GPR")
 | |
| 			add %2, %1.reg1, %1.reg2
 | |
| 
 | |
| /* Read byte */
 | |
| 
 | |
| 	from IND_RC_B to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RC_B->GPR")
 | |
| 			lbz %2, {GPRINDIRECT, %1.reg, %1.off}
 | |
| 
 | |
| 	from IND_RR_B to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RR_B->GPR")
 | |
| 			lbzx %2, %1.reg1, %1.reg2
 | |
| 
 | |
| /* Write byte */
 | |
| 
 | |
| 	from GPR to IND_RC_B
 | |
| 		gen
 | |
| 			COMMENT("move GPR->IND_RC_B")
 | |
| 			stb %1, {GPRINDIRECT, %2.reg, %2.off}
 | |
| 
 | |
| 	from GPR to IND_RR_B
 | |
| 		gen
 | |
| 			COMMENT("move GPR->IND_RR_B")
 | |
| 			stbx %1, %2.reg1, %2.reg2
 | |
| 
 | |
| /* Read halfword (short) */
 | |
| 
 | |
| 	from IND_RC_H to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RC_H->GPR")
 | |
| 			lhz %2, {GPRINDIRECT, %1.reg, %1.off}
 | |
| 
 | |
| 	from IND_RR_H to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RR_H->GPR")
 | |
| 			lhzx %2, %1.reg1, %1.reg2
 | |
| 
 | |
| 	from IND_RC_H_S to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RC_H_S->GPR")
 | |
| 			lha %2, {GPRINDIRECT, %1.reg, %1.off}
 | |
| 
 | |
| 	from IND_RR_H_S to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RR_H_S->GPR")
 | |
| 			lhax %2, %1.reg1, %1.reg2
 | |
| 
 | |
| /* Write halfword */
 | |
| 
 | |
| 	from GPR to IND_RC_H
 | |
| 		gen
 | |
| 			COMMENT("move GPR->IND_RC_H")
 | |
| 			sth %1, {GPRINDIRECT, %2.reg, %2.off}
 | |
| 
 | |
| 	from GPR to IND_RR_H
 | |
| 		gen
 | |
| 			COMMENT("move GPR->IND_RR_H")
 | |
| 			sthx %1, %2.reg1, %2.reg2
 | |
| 
 | |
| /* Read word */
 | |
| 
 | |
| 	from IND_RC_W to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RC_W->GPR")
 | |
| 			lwz %2, {GPRINDIRECT, %1.reg, %1.off}
 | |
| 
 | |
| 	from IND_RR_W to GPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RR_W->GPR")
 | |
| 			lwzx %2, %1.reg1, %1.reg2
 | |
| 
 | |
| 	from IND_RC_W to FSREG
 | |
| 		gen
 | |
| 			COMMENT("move IND_RC_W->FSREG")
 | |
| 			lfs %2, {GPRINDIRECT, %1.reg, %1.off}
 | |
| 
 | |
| 	from IND_RR_W to FSREG
 | |
| 		gen
 | |
| 			COMMENT("move IND_RR_W->FSREG")
 | |
| 			lfsx %2, %1.reg1, %1.reg2
 | |
| 
 | |
| /* Write word */
 | |
| 
 | |
| 	from GPR to IND_RC_W
 | |
| 		gen
 | |
| 			COMMENT("move GPR->IND_RC_W")
 | |
| 			stw %1, {GPRINDIRECT, %2.reg, %2.off}
 | |
| 
 | |
| 	from GPR to IND_RR_W
 | |
| 		gen
 | |
| 			COMMENT("move GPR->IND_RR_W")
 | |
| 			stwx %1, %2.reg1, %2.reg2
 | |
| 
 | |
| 	from FSREG to IND_RC_W
 | |
| 		gen
 | |
| 			COMMENT("move FSREG->IND_RC_W")
 | |
| 			stfs %1, {GPRINDIRECT, %2.reg, %2.off}
 | |
| 
 | |
| 	from FSREG to IND_RR_W
 | |
| 		gen
 | |
| 			COMMENT("move FSREG->IND_RR_W")
 | |
| 			stfsx %1, %2.reg1, %2.reg2
 | |
| 
 | |
| /* Read double */
 | |
| 
 | |
| 	from IND_RC_D to FPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RC_D->FPR")
 | |
| 			lfd %2, {GPRINDIRECT, %1.reg, %1.off}
 | |
| 
 | |
| 	from IND_RR_D to FPR
 | |
| 		gen
 | |
| 			COMMENT("move IND_RR_D->FPR")
 | |
| 			lfdx %2, %1.reg1, %1.reg2
 | |
| 
 | |
| /* Write double */
 | |
| 
 | |
| 	from FPR to IND_RC_D
 | |
| 		gen
 | |
| 			COMMENT("move FPR->IND_RC_D")
 | |
| 			stfd %1, {GPRINDIRECT, %2.reg, %2.off}
 | |
| 
 | |
| 	from FPR to IND_RR_D
 | |
| 		gen
 | |
| 			COMMENT("move FPR->IND_RR_W")
 | |
| 			stfdx %1, %2.reg1, %2.reg2
 | |
| 
 | |
| /* 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}, RSCRATCH
 | |
| 			cmp %2, {CONST, 0}, %1.reg, RSCRATCH
 | |
| 
 | |
| 	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}, RSCRATCH
 | |
| 			cmpl %2, {CONST, 0}, %1.reg, RSCRATCH
 | |
| 
 | |
| 	from TRISTATE_FF to CR0
 | |
| 		gen
 | |
| 			COMMENT("move TRISTATE_FF->CR0")
 | |
| 			fcmpo %2, %1.reg1, %1.reg2
 | |
| 
 | |
| 	from GPR to CR0
 | |
| 		gen
 | |
| 			COMMENT("move GPR->CR0")
 | |
| 			orX RSCRATCH, %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, RSCRATCH
 | |
| 			move {LABEL, ".tristate_s_table"}, %2
 | |
| 			lwzx %2, %2, RSCRATCH
 | |
| 
 | |
| 	from TRISTATE_RR_U + TRISTATE_RC_U to GPR
 | |
| 		gen
 | |
| 			COMMENT("move TRISTATE_R*_U->GPR")
 | |
| 			move %1, C0
 | |
| 			move C0, RSCRATCH
 | |
| 			move {LABEL, ".tristate_u_table"}, %2
 | |
| 			lwzx %2, %2, RSCRATCH
 | |
| 
 | |
| /* 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 OR_RR to GPR
 | |
| 		gen
 | |
| 			COMMENT("move OR_RR->GPR")
 | |
| 			or %2, %1.reg1, %1.reg2
 | |
| 
 | |
| 	from OR_RIS to GPR
 | |
| 		gen
 | |
| 			COMMENT("move OR_RIS->GPR")
 | |
| 			oris %2, %1.reg, {CONST, %1.valhi}
 | |
| 
 | |
| 	from OR_RC to GPR
 | |
| 		gen
 | |
| 			COMMENT("move OR_RC->GPR")
 | |
| 			ori %2, %1.reg, {CONST, %1.val}
 | |
| 
 | |
| 	from XOR_RR to GPR
 | |
| 		gen
 | |
| 			COMMENT("move XOR_RR->GPR")
 | |
| 			xor %2, %1.reg1, %1.reg2
 | |
| 
 | |
| 	from XOR_RIS to GPR
 | |
| 		gen
 | |
| 			COMMENT("move XOR_RIS->GPR")
 | |
| 			xoris %2, %1.reg, {CONST, %1.valhi}
 | |
| 
 | |
| 	from XOR_RC to GPR
 | |
| 		gen
 | |
| 			COMMENT("move XOR_RC->GPR")
 | |
| 			xori %2, %1.reg, {CONST, %1.val}
 | |
| 
 | |
| /* Miscellaneous */
 | |
| 
 | |
| 	from OP_ALL_W + LABEL + CONST_ALL to GPRE
 | |
| 		gen
 | |
| 			move %1, %2.reg
 | |
| 
 | |
| 
 | |
| TESTS
 | |
| 
 | |
| 	to test GPR
 | |
| 		gen
 | |
| 			orX RSCRATCH, %1, %1
 | |
| 
 | |
| 
 | |
| 
 | |
| STACKINGRULES
 | |
| 
 | |
| 	from LOCAL to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack LOCAL")
 | |
| 			stwu {GPRE, regvar(%1.off)}, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from REG to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack REG")
 | |
| 			stwu %1, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from REG_PAIR to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack REG_PAIR")
 | |
| 			stwu %1.2, {GPRINDIRECT, SP, 0-4}
 | |
| 			stwu %1.1, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from CONST_ALL + LABEL to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack CONST_ALL + LABEL")
 | |
| 			move %1, RSCRATCH
 | |
| 			stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from SEX_B to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack SEX_B")
 | |
| 			extsb RSCRATCH, %1.reg
 | |
| 			stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from SEX_H to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack SEX_H")
 | |
| 			extsh RSCRATCH, %1.reg
 | |
| 			stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack SUM_ALL + TRISTATE_ALL + LOGICAL_ALL")
 | |
| 			move %1, RSCRATCH
 | |
| 			stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from IND_ALL_BHW to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack IND_ALL_BHW")
 | |
| 			move %1, RSCRATCH
 | |
| 			stwu RSCRATCH, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 	from IND_ALL_D to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack IND_ALL_D")
 | |
| 			move %1, FSCRATCH
 | |
| 			stfdu FSCRATCH, {GPRINDIRECT, SP, 0-8}
 | |
| 
 | |
| 	from FREG to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack FPR")
 | |
| 			stfdu %1, {GPRINDIRECT, SP, 0-8}
 | |
| 
 | |
| 	from FSREG to STACK
 | |
| 		gen
 | |
| 			COMMENT("stack FSREG")
 | |
| 			stfsu %1, {GPRINDIRECT, SP, 0-4}
 | |
| 
 | |
| 
 | |
| 
 | |
| COERCIONS
 | |
| 
 | |
| 	from REG
 | |
| 		uses REG
 | |
| 		gen
 | |
| 			COMMENT("coerce REG->REG")
 | |
| 			move %1, %a
 | |
| 		yields %a
 | |
| 
 | |
| 	from CONST_ALL
 | |
| 		uses REG
 | |
| 		gen
 | |
| 			COMMENT("coerce CONST_ALL->REG")
 | |
| 			move %1, %a
 | |
| 		yields %a
 | |
| 
 | |
| 	from LABEL
 | |
| 		uses REG
 | |
| 		gen
 | |
| 			COMMENT("coerce LABEL->REG")
 | |
| 			move %1, %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 STACK
 | |
| 		uses REG_PAIR
 | |
| 		gen
 | |
| 			COMMENT("coerce STACK->REG_PAIR")
 | |
| 			lwz %a.1, {GPRINDIRECT, SP, 0}
 | |
| 			lwz %a.2, {GPRINDIRECT, SP, 4}
 | |
| 			addi SP, SP, {CONST, 8}
 | |
| 		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, %a
 | |
| 		yields %a
 | |
| 
 | |
| 	from FSREG
 | |
| 		uses FSREG
 | |
| 		gen
 | |
| 			fmr %a, %1
 | |
| 		yields %a
 | |
| 
 | |
| 	from FREG
 | |
| 		uses FREG
 | |
| 		gen
 | |
| 			fmr %a, %1
 | |
| 		yields %a
 | |
| 
 | |
| 	from STACK
 | |
| 		uses FREG
 | |
| 		gen
 | |
| 			COMMENT("coerce STACK->FREG")
 | |
| 			lfd %a, {GPRINDIRECT, SP, 0}
 | |
| 			addi SP, SP, {CONST, 8}
 | |
| 		yields %a
 | |
| 
 | |
| 	from STACK
 | |
| 		uses FSREG
 | |
| 		gen
 | |
| 			COMMENT("coerce STACK->FSREG")
 | |
| 			lfs %a, {GPRINDIRECT, SP, 0}
 | |
| 			addi SP, SP, {CONST, 4}
 | |
| 		yields %a
 | |
| 
 | |
| 	from IND_ALL_BHW
 | |
| 		uses REG
 | |
| 		gen
 | |
| 			move %1, %a
 | |
| 		yields %a
 | |
| 
 | |
| 	from IND_ALL_W
 | |
| 		uses FSREG
 | |
| 		gen
 | |
| 			move %1, %a
 | |
| 		yields %a
 | |
| 
 | |
| 	/*
 | |
| 	 * from IND_RC_D to REG_PAIR is not possible, because
 | |
| 	 * %1.off+4 might overflow a signed 16-bit integer in
 | |
| 	 *   move {IND_RC_W, %1.val, %1.off+4}, %a.2
 | |
| 	 */
 | |
| 
 | |
| 	from IND_ALL_D
 | |
| 		uses FREG
 | |
| 		gen
 | |
| 			move %1, %a
 | |
| 		yields %a
 | |
| 
 | |
| 
 | |
| 
 | |
| PATTERNS
 | |
| 
 | |
| /* Intrinsics */
 | |
| 
 | |
| 	pat loc $1==(0-0x8000)             /* Load constant */
 | |
| 		yields {CONST_N8000, $1}
 | |
| 	pat loc $1>=(0-0x7FFF) && $1<=(0-1)
 | |
| 		yields {CONST_N7FFF_N0001, $1}
 | |
| 	pat loc $1>=0 && $1<=0x7FFF
 | |
| 		yields {CONST_0000_7FFF, $1}
 | |
| 	pat loc $1==0x8000
 | |
| 		yields {CONST_8000, $1}
 | |
| 	pat loc $1>=0x8001 && $1<=0xFFFF
 | |
| 		yields {CONST_8001_FFFF, $1}
 | |
| 	pat loc lo($1)==0
 | |
| 		yields {CONST_HZ, $1}
 | |
| 	pat loc
 | |
| 		yields {CONST_HL, $1}
 | |
| 
 | |
| 	pat dup $1==INT32                  /* Duplicate word on top of stack */
 | |
| 		with REG
 | |
| 			yields %1 %1
 | |
| 		with FSREG
 | |
| 			yields %1 %1
 | |
| 
 | |
| 	pat dup $1==INT64                  /* Duplicate double-word on top of stack */
 | |
| 		with REG REG
 | |
| 			yields %2 %1 %2 %1
 | |
| 		with FREG
 | |
| 			yields %1 %1
 | |
| 
 | |
| 	pat exg $1==INT32                  /* Exchange top two words on stack */
 | |
| 		with REG REG
 | |
| 			yields %1 %2
 | |
| 
 | |
| 	pat stl lol $1==$2                 /* Store then load local */
 | |
| 		leaving
 | |
| 			dup 4
 | |
| 			stl $1
 | |
| 
 | |
| 	pat sdl ldl $1==$2                 /* Store then load double local */
 | |
| 		leaving
 | |
| 			dup 8
 | |
| 			sdl $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 smalls($1)                 /* Load address of local */
 | |
| 		yields {SUM_RC, FP, $1}
 | |
| 
 | |
| 	pat lal                            /* Load address of local */
 | |
| 		uses REG={SUM_RIS, FP, his($1)}
 | |
| 		yields {SUM_RC, %a, los($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_ALL + 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 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 */
 | |
| 		kills MEMORY
 | |
| 		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 */
 | |
| 		kills MEMORY
 | |
| 		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
 | |
| 			yields {IND_RC_B, %1, 0}
 | |
| 		with SUM_RR
 | |
| 			yields {IND_RR_B, %1.reg1, %1.reg2}
 | |
| 		with SUM_RC
 | |
| 			yields {IND_RC_B, %1.reg, %1.off}
 | |
| 
 | |
| 	pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32
 | |
| 	/* Load half-word indirect and sign extend */
 | |
| 		with GPR
 | |
| 			yields {IND_RC_H_S, %1, 0}
 | |
| 		with SUM_RR
 | |
| 			yields {IND_RR_H_S, %1.reg1, %1.reg2}
 | |
| 		with SUM_RC
 | |
| 			yields {IND_RC_H_S, %1.reg, %1.off}
 | |
| 
 | |
| 	pat loi $1==INT16                  /* Load half-word indirect */
 | |
| 		with GPR
 | |
| 			yields {IND_RC_H, %1, 0}
 | |
| 		with SUM_RR
 | |
| 			yields {IND_RR_H, %1.reg1, %1.reg2}
 | |
| 		with SUM_RC
 | |
| 			yields {IND_RC_H, %1.reg, %1.off}
 | |
| 
 | |
| 	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}
 | |
| 
 | |
| 	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}
 | |
| 
 | |
| 	pat loi                            /* Load arbitrary size */
 | |
| 		leaving
 | |
| 			loc $1
 | |
| 			los INT32
 | |
| 
 | |
| 	pat los $1==INT32                  /* Load arbitrary size */
 | |
| 		with GPR3 GPR4 STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				bl {LABEL, ".los"}
 | |
| 
 | |
| 	pat sti $1==INT8                   /* Store byte indirect */
 | |
| 		with GPR GPR
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				stb %2, {GPRINDIRECT, %1, 0}
 | |
| 		with SUM_RR GPR
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				stbx %2, %1.reg1, %1.reg2
 | |
| 		with SUM_RC GPR
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RC_B, %1.reg, %1.off}
 | |
| 		with GPR SEX_B
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				stb %2.reg, {GPRINDIRECT, %1, 0}
 | |
| 		with SUM_RR SEX_B
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				stbx %2.reg, %1.reg1, %1.reg2
 | |
| 		with SUM_RC SEX_B
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2.reg, {IND_RC_B, %1.reg, %1.off}
 | |
| 
 | |
| 	pat sti $1==INT16                  /* Store half-word indirect */
 | |
| 		with GPR GPR
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				sth %2, {GPRINDIRECT, %1, 0}
 | |
| 		with SUM_RR GPR
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				sthx %2, %1.reg1, %1.reg2
 | |
| 		with SUM_RC GPR
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RC_H, %1.reg, %1.off}
 | |
| 		with GPR SEX_H
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				sth %2.reg, {GPRINDIRECT, %1, 0}
 | |
| 		with SUM_RR SEX_H
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				sthx %2.reg, %1.reg1, %1.reg2
 | |
| 		with SUM_RC SEX_H
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2.reg, {IND_RC_H, %1.reg, %1.off}
 | |
| 
 | |
| 	pat sti $1==INT32                  /* Store word indirect */
 | |
| 		with GPR GPR+FSREG
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RC_W, %1, 0}
 | |
| 		with SUM_RR GPR+FSREG
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RR_W, %1.reg1, %1.reg2}
 | |
| 		with SUM_RC GPR+FSREG
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RC_W, %1.reg, %1.off}
 | |
| 
 | |
| 	pat sti $1==INT64                  /* Store double-word indirect */
 | |
| 		with REG FREG
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RC_D, %1, 0}
 | |
| 		with SUM_RR FREG
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RR_D, %1.reg1, %1.reg2}
 | |
| 		with SUM_RC FREG
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2, {IND_RC_D, %1.reg, %1.off}
 | |
| 		/*
 | |
| 		 * This pattern would be too slow:
 | |
| 		 *   with REG REG REG
 | |
| 		 * ncg can't handle that many registers, and would
 | |
| 		 * take about 2 seconds on each sti 8.  So we use
 | |
| 		 * REG_PAIR as a speed hack for sti 8.
 | |
| 		 */
 | |
| 		with REG REG_PAIR
 | |
| 			kills MEMORY
 | |
| 			gen
 | |
| 				move %2.1, {IND_RC_W, %1, 0}
 | |
| 				move %2.2, {IND_RC_W, %1, 4}
 | |
| 		/*
 | |
| 		 * Next 2 patterns exist because there is no coercion
 | |
| 		 * from IND_ALL_D to REG_PAIR.
 | |
| 		 */
 | |
| 		with REG IND_RC_D
 | |
| 			kills MEMORY
 | |
| 			uses REG={SUM_RC, %2.reg, %2.off}, REG_PAIR
 | |
| 			gen
 | |
| 				move {IND_RC_W, %a, 0}, %b.1
 | |
| 				move {IND_RC_W, %a, 4}, %b.2
 | |
| 				move %b.1, {IND_RC_W, %1, 0}
 | |
| 				move %b.2, {IND_RC_W, %1, 4}
 | |
| 		with REG IND_RR_D
 | |
| 			kills MEMORY
 | |
| 			uses REG={SUM_RR, %2.reg1, %2.reg2}, REG_PAIR
 | |
| 			gen
 | |
| 				move {IND_RC_W, %a, 0}, %b.1
 | |
| 				move {IND_RC_W, %a, 4}, %b.2
 | |
| 				move %b.1, {IND_RC_W, %1, 0}
 | |
| 				move %b.2, {IND_RC_W, %1, 4}
 | |
| 
 | |
| 	pat sti                            /* Store arbitrary size */
 | |
| 		leaving
 | |
| 			loc $1
 | |
| 			sts INT32
 | |
| 
 | |
| 	pat sts $1==INT32                  /* Store 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 CONST2 REG
 | |
| 			yields {SUM_RC, %2, %1.val}
 | |
| 		with REG CONST2
 | |
| 			yields {SUM_RC, %1, %2.val}
 | |
| 		with CONST_HZ REG
 | |
| 			uses reusing %2, REG={SUM_RIS, %2, his(%1.val)}
 | |
| 			yields %a
 | |
| 		with REG CONST_HZ
 | |
| 			uses reusing %1, REG={SUM_RIS, %1, his(%2.val)}
 | |
| 			yields %a
 | |
| 		with CONST_ALL-CONST2-CONST_HZ REG
 | |
| 			uses reusing %2, REG={SUM_RIS, %2, his(%1.val)}
 | |
| 			yields {SUM_RC, %a, los(%1.val)}
 | |
| 		with REG CONST_ALL-CONST2-CONST_HZ
 | |
| 			uses reusing %1, REG={SUM_RIS, %1, his(%2.val)}
 | |
| 			yields {SUM_RC, %a, los(%2.val)}
 | |
| 		with CONST_ALL 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 CONST2_WHEN_NEG REG
 | |
| 			yields {SUM_RC, %2, 0-%1.val}
 | |
| 		with CONST_HZ REG
 | |
| 			uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)}
 | |
| 			yields %a
 | |
| 		with CONST_ALL-CONST2_WHEN_NEG-CONST_HZ REG
 | |
| 			uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)}
 | |
| 			yields {SUM_RC, %a, los(0-%1.val)}
 | |
| 		with CONST_ALL 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 UCONST2
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				andiX %a, %1, {CONST, %2.val}
 | |
| 			yields %a
 | |
| 		with UCONST2 GPR
 | |
| 			uses reusing %2, REG
 | |
| 			gen
 | |
| 				andiX %a, %2, {CONST, %1.val}
 | |
| 			yields %a
 | |
| 		with GPR CONST_HZ
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				andisX %a, %1, {CONST, hi(%2.val)}
 | |
| 			yields %a
 | |
| 		with CONST_HZ GPR
 | |
| 			uses reusing %2, REG
 | |
| 			gen
 | |
| 				andisX %a, %2, {CONST, hi(%1.val)}
 | |
| 			yields %a
 | |
| 
 | |
| 	pat and defined($1)                /* AND set */
 | |
| 		with STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				move {CONST, $1}, R3
 | |
| 				bl {LABEL, ".and"}
 | |
| 
 | |
| 	pat ior $1==4                      /* OR word */
 | |
| 		with REG NOT_R
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				orc %a, %1, %2.reg
 | |
| 			yields %a
 | |
| 		with NOT_R REG
 | |
| 			uses reusing %2, REG
 | |
| 			gen
 | |
| 				orc %a, %2, %1.reg
 | |
| 			yields %a
 | |
| 		with REG REG
 | |
| 			yields {OR_RR, %1, %2}
 | |
| 		with REG UCONST2
 | |
| 			yields {OR_RC, %1, %2.val}
 | |
| 		with UCONST2 REG
 | |
| 			yields {OR_RC, %2, %1.val}
 | |
| 		with REG CONST_HZ
 | |
| 			uses reusing %1, REG={OR_RIS, %1, hi(%2.val)}
 | |
| 			yields %a
 | |
| 		with CONST_HZ REG
 | |
| 			uses reusing %2, REG={OR_RIS, %2, hi(%1.val)}
 | |
| 			yields %a
 | |
| 		with REG CONST_ALL-UCONST2-CONST_HZ
 | |
| 			uses reusing %1, REG={OR_RIS, %1, hi(%2.val)}
 | |
| 			yields {OR_RC, %1, lo(%2.val)}
 | |
| 		with CONST_ALL-UCONST2-CONST_HZ REG
 | |
| 			uses reusing %2, REG={OR_RIS, %2, hi(%1.val)}
 | |
| 			yields {OR_RC, %2, lo(%1.val)}
 | |
| 
 | |
| 	pat ior defined($1)                /* OR set */
 | |
| 		with STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				move {CONST, $1}, R3
 | |
| 				bl {LABEL, ".ior"}
 | |
| 
 | |
| 	/* OR set (variable), used in lang/m2/libm2/LtoUset.e */
 | |
| 	pat ior !defined($1)
 | |
| 		with GPR3 STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				bl {LABEL, ".ior"}
 | |
| 
 | |
| 	pat xor $1==4                      /* XOR word */
 | |
| 		with REG REG
 | |
| 			yields {XOR_RR, %1, %2}
 | |
| 		with REG UCONST2
 | |
| 			yields {XOR_RC, %1, %2.val}
 | |
| 		with UCONST2 REG
 | |
| 			yields {XOR_RC, %2, %1.val}
 | |
| 		with REG CONST_HZ
 | |
| 			uses reusing %1, REG={XOR_RIS, %1, hi(%2.val)}
 | |
| 			yields %a
 | |
| 		with CONST_HZ REG
 | |
| 			uses reusing %2, REG={XOR_RIS, %2, hi(%1.val)}
 | |
| 			yields %a
 | |
| 		with REG CONST_ALL-UCONST2-CONST_HZ
 | |
| 			uses reusing %1, REG={XOR_RIS, %1, hi(%2.val)}
 | |
| 			yields {XOR_RC, %1, lo(%2.val)}
 | |
| 		with CONST_ALL-UCONST2-CONST_HZ REG
 | |
| 			uses reusing %2, REG={XOR_RIS, %2, hi(%1.val)}
 | |
| 			yields {XOR_RC, %2, lo(%1.val)}
 | |
| 
 | |
| 	pat xor defined($1)                /* XOR set */
 | |
| 		with STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				move {CONST, $1}, R3
 | |
| 				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
 | |
| 				move {CONST, $1}, R3
 | |
| 				bl {LABEL, ".com"}
 | |
| 
 | |
| 	pat zer $1==4                      /* Push zero */
 | |
| 		leaving
 | |
| 			loc 0
 | |
| 
 | |
| 	pat zer defined($1)	   	   /* Create empty set */
 | |
| 		with STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				move {CONST, $1}, R3
 | |
| 				bl {LABEL, ".zer"}
 | |
| 
 | |
| 	pat sli $1==4                      /* Shift left (second << top) */
 | |
| 		with CONST_ALL 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_ALL 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_ALL 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
 | |
| 			kills ALL
 | |
| 			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 singleton set */
 | |
| 		with GPR4 STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				move {CONST, $1}, R3
 | |
| 				bl {LABEL, ".set"}
 | |
| 
 | |
| 	/* Create set (variable), used in lang/m2/libm2/LtoUset.e */
 | |
| 	pat set !defined($1)
 | |
| 		with GPR3 GPR4 STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				bl {LABEL, ".set"}
 | |
| 
 | |
| 	pat inn defined($1)                /* Test for set bit */
 | |
| 		with STACK
 | |
| 			kills ALL
 | |
| 			uses REG
 | |
| 			gen
 | |
| 				li32 %a, {CONST, $1}
 | |
| 				stwu %a, {GPRINDIRECT, SP, 0-4}
 | |
| 				bl {LABEL, ".inn"}
 | |
| 
 | |
| 
 | |
| /* Boolean resolutions */
 | |
| 
 | |
| 	pat teq                            /* top = (top == 0) */
 | |
| 		with TRISTATE_ALL + GPR
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				move %1, C0
 | |
| 				move C0, RSCRATCH
 | |
| 				move {LABEL, ".teq_table"}, %a
 | |
| 				lwzx %a, %a, RSCRATCH
 | |
| 			yields %a
 | |
| 
 | |
| 	pat tne                            /* top = (top != 0) */
 | |
| 		with TRISTATE_ALL + GPR
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				move %1, C0
 | |
| 				move C0, RSCRATCH
 | |
| 				move {LABEL, ".tne_table"}, %a
 | |
| 				lwzx %a, %a, RSCRATCH
 | |
| 			yields %a
 | |
| 
 | |
| 	pat tlt                            /* top = (top < 0) */
 | |
| 		with TRISTATE_ALL + GPR
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				move %1, C0
 | |
| 				move C0, RSCRATCH
 | |
| 				move {LABEL, ".tlt_table"}, %a
 | |
| 				lwzx %a, %a, RSCRATCH
 | |
| 			yields %a
 | |
| 
 | |
| 	pat tle                            /* top = (top <= 0) */
 | |
| 		with TRISTATE_ALL + GPR
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				move %1, C0
 | |
| 				move C0, RSCRATCH
 | |
| 				move {LABEL, ".tle_table"}, %a
 | |
| 				lwzx %a, %a, RSCRATCH
 | |
| 			yields %a
 | |
| 
 | |
| 	pat tgt                            /* top = (top > 0) */
 | |
| 		with TRISTATE_ALL + GPR
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				move %1, C0
 | |
| 				move C0, RSCRATCH
 | |
| 				move {LABEL, ".tgt_table"}, %a
 | |
| 				lwzx %a, %a, RSCRATCH
 | |
| 			yields %a
 | |
| 
 | |
| 	pat tge                            /* top = (top >= 0) */
 | |
| 		with TRISTATE_ALL + GPR
 | |
| 			uses reusing %1, REG
 | |
| 			gen
 | |
| 				move %1, C0
 | |
| 				move C0, RSCRATCH
 | |
| 				move {LABEL, ".tge_table"}, %a
 | |
| 				lwzx %a, %a, RSCRATCH
 | |
| 			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 $1==INT32                  /* Signed tristate compare */
 | |
| 		with CONST_ALL GPR
 | |
| 			yields {TRISTATE_RC_S, %2, %1.val}
 | |
| 		with GPR GPR
 | |
| 			yields {TRISTATE_RR_S, %2, %1}
 | |
| 
 | |
| 	pat cmu $1==INT32                  /* Unsigned tristate compare */
 | |
| 		with CONST_ALL 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
 | |
| 
 | |
| 	pat cms defined($1)
 | |
| 		with STACK
 | |
| 			kills ALL
 | |
| 			gen
 | |
| 				move {CONST, $1}, R3
 | |
| 				bl {LABEL, ".cms"}
 | |
| 			yields R3
 | |
| 
 | |
| 
 | |
| 
 | |
| /* 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 STACK
 | |
| 			gen
 | |
| 				b {LABEL, ".csa"}
 | |
| 
 | |
| 	pat csb                            /* Table-lookup switch */
 | |
| 		with STACK
 | |
| 			gen
 | |
| 				b {LABEL, ".csb"}
 | |
| 
 | |
| 
 | |
| 
 | |
| /* EM specials */
 | |
| 
 | |
| 	pat fil                            /* Set current filename */
 | |
| 		leaving
 | |
| 			lae $1
 | |
| 			ste "hol0+4"
 | |
| 
 | |
| 	pat lin                            /* Set current line number */
 | |
| 		leaving
 | |
| 			loc $1
 | |
| 			ste "hol0"
 | |
| 
 | |
| 	pat lni                            /* Increment line number */
 | |
| 		leaving
 | |
| 			ine "hol0"
 | |
| 
 | |
| 	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}
 | |
| 
 | |
| 	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 str $1==0                      /* Store FP */
 | |
| 		with GPR
 | |
| 			gen
 | |
| 				move %1, FP
 | |
| 
 | |
| 	pat str $1==1                      /* Store SP */
 | |
| 		with GPR
 | |
| 			gen
 | |
| 				move %1, SP
 | |
| 
 | |
| 	pat loc ass $1==4 && $2==4         /* Drop 4 bytes from stack */
 | |
| 		with exact GPR
 | |
| 			/* nop */
 | |
| 		with STACK
 | |
| 			gen
 | |
| 				addi SP, SP, {CONST, 4}
 | |
| 
 | |
| 	pat ass $1==4                      /* Adjust stack by variable amount */
 | |
| 		with CONST2 STACK
 | |
| 			gen
 | |
| 				move {SUM_RC, SP, %1.val}, SP
 | |
| 		with CONST_HZ STACK
 | |
| 			gen
 | |
| 				move {SUM_RC, SP, his(%1.val)}, SP
 | |
| 		with CONST_ALL-CONST2-CONST_HZ STACK
 | |
| 			gen
 | |
| 				move {SUM_RC, SP, his(%1.val)}, SP
 | |
| 				move {SUM_RC, SP, los(%1.val)}, SP
 | |
| 		with GPR STACK
 | |
| 			gen
 | |
| 				move {SUM_RR, SP, %1}, SP
 | |
| 
 | |
| 	pat asp                            /* Adjust stack by constant amount */
 | |
| 		leaving
 | |
| 			loc $1
 | |
| 			ass 4
 | |
| 
 | |
| 
 | |
| 
 | |
| /* 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 FSREG FSREG
 | |
| 			uses reusing %1, FSREG
 | |
| 			gen
 | |
| 				fadds %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat sbf $1==INT32                  /* Subtract single */
 | |
| 		with FSREG FSREG
 | |
| 			uses reusing %1, FSREG
 | |
| 			gen
 | |
| 				fsubs %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat mlf $1==INT32                  /* Multiply single */
 | |
| 		with FSREG FSREG
 | |
| 			uses reusing %1, FSREG
 | |
| 			gen
 | |
| 				fmuls %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat dvf $1==INT32                  /* Divide single */
 | |
| 		with FSREG FSREG
 | |
| 			uses reusing %1, FSREG
 | |
| 			gen
 | |
| 				fdivs %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat ngf $1==INT32                  /* Negate single */
 | |
| 		with FSREG
 | |
| 			uses reusing %1, FSREG
 | |
| 			gen
 | |
| 				fneg %a, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat cmf $1==INT32                  /* Compare single */
 | |
| 		with FSREG FSREG
 | |
| 			yields {TRISTATE_FF, %2.1, %1.1}
 | |
| 
 | |
| 	pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */
 | |
| 		with FSREG
 | |
| 			yields %1.1
 | |
| 
 | |
| 	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 FREG FREG
 | |
| 			uses FREG
 | |
| 			gen
 | |
| 				fadd %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat sbf $1==INT64                  /* Subtract double */
 | |
| 		with FREG FREG
 | |
| 			uses FREG
 | |
| 			gen
 | |
| 				fsub %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat mlf $1==INT64                  /* Multiply double */
 | |
| 		with FREG FREG
 | |
| 			uses reusing %1, FREG
 | |
| 			gen
 | |
| 				fmul %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat dvf $1==INT64                  /* Divide double */
 | |
| 		with FREG FREG
 | |
| 			uses reusing %1, FREG
 | |
| 			gen
 | |
| 				fdiv %a, %2, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat ngf $1==INT64                  /* Negate double */
 | |
| 		with FREG
 | |
| 			uses reusing %1, FREG
 | |
| 			gen
 | |
| 				fneg %a, %1
 | |
| 			yields %a
 | |
| 
 | |
| 	pat cmf $1==INT64                  /* Compare double */
 | |
| 		with FREG FREG
 | |
| 			yields {TRISTATE_FF, %2, %1}
 | |
| 
 | |
| 	pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */
 | |
| 		with FREG
 | |
| 			uses reusing %1, FSREG
 | |
| 			gen
 | |
| 				frsp %a, %1
 | |
| 			yields %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 exponent, fraction */
 | |
| 		with GPR3 GPR4
 | |
| 			kills FPR0, FPR1, GPR6, GPR7
 | |
| 			gen
 | |
| 				bl {LABEL, ".fef8"}
 | |
| 			yields R4 R3 R5
 | |
| 
 | |
| 	pat fif $1==INT64                  /* Multiply then split integer, fraction */
 | |
| 		with FPR1 FPR2
 | |
| 			kills FPR1, FPR2, GPR3, GPR4, GPR5, GPR6
 | |
| 			gen
 | |
| 				bl {LABEL, ".fif8"}
 | |
| 			yields F1 F2
 |