645 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			645 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
REGISTERS
 | 
						|
 | 
						|
    /* Registers are allocated top down; the order here is odd in order to make
 | 
						|
     * sure that non-volatile registers get allocated from r31 (or f31) down.
 | 
						|
     *
 | 
						|
     * Attributes ending in an exclamation mark must match exactly when copying
 | 
						|
     * a register into another register (e.g. for eviction).
 | 
						|
     */
 | 
						|
 | 
						|
    r12                                           bytes4! int! volatile; 
 | 
						|
    r11                                           bytes4! int! volatile; 
 | 
						|
    r10                                           bytes4! int! volatile; 
 | 
						|
    r9                                            bytes4! int! volatile;
 | 
						|
    r8                                            bytes4! int! volatile;
 | 
						|
    r7                                            bytes4! int! volatile;
 | 
						|
    r6                                            bytes4! int! volatile;
 | 
						|
    r5                                            bytes4! int! volatile;
 | 
						|
    r4                                            bytes4! int! volatile;
 | 
						|
    r3                                            bytes4! int! volatile ret;
 | 
						|
 | 
						|
    r31                                           bytes4! int!; 
 | 
						|
    r30                                           bytes4! int!; 
 | 
						|
    r29                                           bytes4! int!; 
 | 
						|
    r28                                           bytes4! int!; 
 | 
						|
    r27                                           bytes4! int!; 
 | 
						|
    r26                                           bytes4! int!; 
 | 
						|
    r25                                           bytes4! int!; 
 | 
						|
    r24                                           bytes4! int!; 
 | 
						|
    r23                                           bytes4! int!; 
 | 
						|
    r22                                           bytes4! int!; 
 | 
						|
    r21                                           bytes4! int!; 
 | 
						|
    r20                                           bytes4! int!; 
 | 
						|
    r19                                           bytes4! int!; 
 | 
						|
    r18                                           bytes4! int!; 
 | 
						|
    r17                                           bytes4! int!; 
 | 
						|
    r16                                           bytes4! int!;
 | 
						|
    r15                                           bytes4! int!;
 | 
						|
    r14                                           bytes4! int!;
 | 
						|
    r13                                           bytes4! int!;
 | 
						|
 | 
						|
    r11r12  named("r11", "r12") aliases(r11, r12) bytes8! pair! volatile;
 | 
						|
    r9r10   named("r9",  "r10") aliases(r9,  r10) bytes8! pair! volatile;
 | 
						|
    r7r8    named("r7",  "r8")  aliases(r7,  r8)  bytes8! pair! volatile;
 | 
						|
    r5r6    named("r5",  "r6")  aliases(r6,  r6)  bytes8! pair! volatile;
 | 
						|
    r3r4    named("r3",  "r4")  aliases(r3,  r4)  bytes8! pair! volatile pret;
 | 
						|
 | 
						|
    r29r30  named("r29", "r30") aliases(r29, r30) bytes8! pair!;
 | 
						|
    r27r28  named("r27", "r28") aliases(r27, r28) bytes8! pair!;
 | 
						|
    r25r26  named("r25", "r26") aliases(r25, r26) bytes8! pair!;
 | 
						|
    r23r24  named("r23", "r24") aliases(r23, r24) bytes8! pair!;
 | 
						|
    r21r22  named("r21", "r22") aliases(r21, r22) bytes8! pair!;
 | 
						|
    r19r20  named("r19", "r20") aliases(r19, r20) bytes8! pair!;
 | 
						|
    r17r18  named("r17", "r18") aliases(r17, r18) bytes8! pair!;
 | 
						|
    r15r16  named("r15", "r16") aliases(r15, r16) bytes8! pair!;
 | 
						|
    r13r14  named("r13", "r14") aliases(r13, r14) bytes8! pair!;
 | 
						|
 | 
						|
    f14                                           bytes4! float! volatile;
 | 
						|
    f13                                           bytes4! float! volatile;
 | 
						|
    f12                                           bytes4! float! volatile;
 | 
						|
    f11                                           bytes4! float! volatile;
 | 
						|
    f10                                           bytes4! float! volatile;
 | 
						|
    f9                                            bytes4! float! volatile;
 | 
						|
    f8                                            bytes4! float! volatile;
 | 
						|
    f7                                            bytes4! float! volatile;
 | 
						|
    f6                                            bytes4! float! volatile;
 | 
						|
    f5                                            bytes4! float! volatile;
 | 
						|
    f4                                            bytes4! float! volatile;
 | 
						|
    f3                                            bytes4! float! volatile fret;
 | 
						|
    f2                                            bytes4! float! volatile;
 | 
						|
    f1                                            bytes4! float! volatile;
 | 
						|
    f0                                            bytes4! float! volatile;
 | 
						|
 | 
						|
    f31                                           bytes4! float!;
 | 
						|
    f30                                           bytes4! float!;
 | 
						|
    f29                                           bytes4! float!;
 | 
						|
    f28                                           bytes4! float!;
 | 
						|
    f27                                           bytes4! float!;
 | 
						|
    f26                                           bytes4! float!;
 | 
						|
    f25                                           bytes4! float!;
 | 
						|
    f24                                           bytes4! float!;
 | 
						|
    f23                                           bytes4! float!;
 | 
						|
    f22                                           bytes4! float!;
 | 
						|
    f21                                           bytes4! float!;
 | 
						|
    f20                                           bytes4! float!;
 | 
						|
    f19                                           bytes4! float!;
 | 
						|
    f18                                           bytes4! float!;
 | 
						|
    f17                                           bytes4! float!;
 | 
						|
    f16                                           bytes4! float!;
 | 
						|
    f15                                           bytes4! float!;
 | 
						|
 | 
						|
    d14     named("f14")       aliases(f14)       bytes8! double! volatile;
 | 
						|
    d13     named("f13")       aliases(f13)       bytes8! double! volatile;
 | 
						|
    d12     named("f12")       aliases(f12)       bytes8! double! volatile;
 | 
						|
    d11     named("f11")       aliases(f11)       bytes8! double! volatile;
 | 
						|
    d10     named("f10")       aliases(f10)       bytes8! double! volatile;
 | 
						|
    d9      named("f9")        aliases(f9)        bytes8! double! volatile;
 | 
						|
    d8      named("f8")        aliases(f8)        bytes8! double! volatile;
 | 
						|
    d7      named("f7")        aliases(f7)        bytes8! double! volatile;
 | 
						|
    d6      named("f6")        aliases(f6)        bytes8! double! volatile;
 | 
						|
    d5      named("f5")        aliases(f5)        bytes8! double! volatile;
 | 
						|
    d4      named("f4")        aliases(f4)        bytes8! double! volatile;
 | 
						|
    d3      named("f3")        aliases(f3)        bytes8! double! volatile dret;
 | 
						|
    d2      named("f2")        aliases(f2)        bytes8! double! volatile;
 | 
						|
    d1      named("f1")        aliases(f1)        bytes8! double! volatile;
 | 
						|
    d0      named("f0")        aliases(f0)        bytes8! double! volatile;
 | 
						|
 | 
						|
    d31     named("f31")       aliases(f31)       bytes8! double!;
 | 
						|
    d30     named("f30")       aliases(f30)       bytes8! double!;
 | 
						|
    d29     named("f29")       aliases(f29)       bytes8! double!;
 | 
						|
    d28     named("f28")       aliases(f28)       bytes8! double!;
 | 
						|
    d27     named("f27")       aliases(f27)       bytes8! double!;
 | 
						|
    d26     named("f26")       aliases(f26)       bytes8! double!;
 | 
						|
    d25     named("f25")       aliases(f25)       bytes8! double!;
 | 
						|
    d24     named("f24")       aliases(f24)       bytes8! double!;
 | 
						|
    d23     named("f23")       aliases(f23)       bytes8! double!;
 | 
						|
    d22     named("f22")       aliases(f22)       bytes8! double!;
 | 
						|
    d21     named("f21")       aliases(f21)       bytes8! double!;
 | 
						|
    d20     named("f20")       aliases(f20)       bytes8! double!;
 | 
						|
    d19     named("f19")       aliases(f19)       bytes8! double!;
 | 
						|
    d18     named("f18")       aliases(f18)       bytes8! double!;
 | 
						|
    d17     named("f17")       aliases(f17)       bytes8! double!;
 | 
						|
    d16     named("f16")       aliases(f16)       bytes8! double!;
 | 
						|
    d15     named("f15")       aliases(f15)       bytes8! double!;
 | 
						|
 | 
						|
	cr0                                           cr!;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
DECLARATIONS
 | 
						|
 | 
						|
	cr;
 | 
						|
    ubyteX;   /* bottom 8 bits valid, the rest undefined */
 | 
						|
    ubyte0;   /* bottom 8 bits valid, the rest 0 */
 | 
						|
    ushortX;  /* bottom 16 bits valid, the rest undefined */
 | 
						|
    ushort0;  /* bottom 16 bits valid, the rest 0 */
 | 
						|
 | 
						|
	address fragment;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
PATTERNS
 | 
						|
 | 
						|
/* Special */
 | 
						|
 | 
						|
	PAIR(BLOCK4, BLOCK4);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Miscellaneous special things */
 | 
						|
 | 
						|
	PUSH4(in:(int)reg)
 | 
						|
		emit "stwu %in, -4(sp)"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    PUSH8(in:(pair)reg)
 | 
						|
        emit "stwu %in.0, -4(sp)"
 | 
						|
        emit "stwu %in.1, -4(sp)"
 | 
						|
        cost 8;
 | 
						|
 | 
						|
	out:(int)reg = POP4
 | 
						|
		emit "lwz %out, 0(sp)"
 | 
						|
        emit "addi sp, sp, 4"
 | 
						|
		cost 8;
 | 
						|
 | 
						|
    out:(pair)reg = POP8
 | 
						|
        emit "lwz %out.0, 4(sp)"
 | 
						|
        emit "lwz %out.1, 0(sp)"
 | 
						|
        emit "addi sp, sp, 8"
 | 
						|
        cost 12;
 | 
						|
 | 
						|
	out:(float)reg = POPF4
 | 
						|
		emit "lfs %out, 0(sp)"
 | 
						|
		emit "addi sp, sp, 4"
 | 
						|
		cost 8;
 | 
						|
		
 | 
						|
	SETRET4(in:(ret)reg)
 | 
						|
		emit "! setret4"
 | 
						|
		cost 1;
 | 
						|
 | 
						|
    SETRET8(in:(pret)reg)
 | 
						|
        emit "! setret8"
 | 
						|
        cost 1;
 | 
						|
 | 
						|
	STACKADJUST4(delta:CONST4)
 | 
						|
        when signed_constant(%delta, 16)
 | 
						|
		emit "addi sp, sp, $delta"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	STACKADJUST4(in:(int)reg)
 | 
						|
		emit "add sp, sp, %in"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    out:(int)reg = GETFP4
 | 
						|
        emit "mr %out, fp"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)reg = FPTOARGS4(GETFP4)
 | 
						|
        emit "addi %out, fp, 8"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)reg = FPTOARGS4(in:(int)reg)
 | 
						|
        emit "addi %out, %in, 8"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)reg = GETSP4
 | 
						|
        emit "mr %out, sp"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    SETSP4(in:(int)reg)
 | 
						|
        emit "mr sp, %in"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Memory operations */
 | 
						|
 | 
						|
    /* Stores */
 | 
						|
 | 
						|
	STORE8(addr:address, value:(pair)reg)
 | 
						|
		emit "stw %value.0, 4+%addr"
 | 
						|
		emit "stw %value.1, 0+%addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	STORE4(addr:address, value:(int)reg)
 | 
						|
		emit "stw %value, %addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	STORE2(addr:address, value:(int)ushortX)
 | 
						|
		emit "sth %value, %addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    STORE2(ADD4(left:(int)reg, right:(int)reg), value:(int)ushortX)
 | 
						|
        emit "sthx %value, %left, %right"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    STORE1(addr:address, value:(int)ubyteX)
 | 
						|
		emit "stb %value, %addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    STORE1(ADD4(left:(int)reg, right:(int)reg), value:(int)ubyteX)
 | 
						|
        emit "stbx %value, %left, %right"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    /* Loads */
 | 
						|
 | 
						|
	out:(int)reg = LOAD4(addr:address)
 | 
						|
		emit "lwz %out, %addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    out:(pair)reg = LOAD8(addr:address)
 | 
						|
        emit "lwz %out.0, 4+%addr"
 | 
						|
        emit "lwz %out.1, 0+%addr"
 | 
						|
        cost 8;
 | 
						|
 | 
						|
	out:(int)ushort0 = LOAD2(addr:address)
 | 
						|
		emit "lhz %out, %addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	out:(int)ubyte0 = LOAD1(addr:address)
 | 
						|
		emit "lbz %out, %addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    /* ubyte intrinsics */
 | 
						|
 | 
						|
    out:(int)ubyteX = in:(int)ubyte0
 | 
						|
        with %out == %in
 | 
						|
        emit "! ubyte0 -> ubyteX"
 | 
						|
        cost 1;
 | 
						|
 | 
						|
    out:(int)ubyte0 = in:(int)ubyteX
 | 
						|
        emit "andi %out, %in, 0xff ! ubyteX -> ubyte0"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)reg = in:(int)ubyte0
 | 
						|
        with %out == %in
 | 
						|
        emit "! ubyte0 -> reg"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)ubyteX = in:(int)reg
 | 
						|
        with %out == %in
 | 
						|
        emit "! reg -> ubyteX"
 | 
						|
        cost 1;
 | 
						|
 | 
						|
    /* ushort intrinsics */
 | 
						|
 | 
						|
    out:(int)ushortX = in:(int)ushort0
 | 
						|
        with %out == %in
 | 
						|
        emit "! ushort0 -> ushortX"
 | 
						|
        cost 1;
 | 
						|
 | 
						|
    out:(int)ushort0 = in:(int)ushortX
 | 
						|
        emit "andi %out, %in, 0xff ! ushortX -> ushort0"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)reg = in:(int)ushort0
 | 
						|
        with %out == %in
 | 
						|
        emit "! ushort0 -> reg"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)ushortX = in:(int)reg
 | 
						|
        with %out == %in
 | 
						|
        emit "! reg -> ushortX"
 | 
						|
        cost 1;
 | 
						|
 | 
						|
	/* byte conversions */
 | 
						|
 | 
						|
    out:(int)ubyte0 = CIU14(in:(int)ubyte0)
 | 
						|
        with %out == %in
 | 
						|
        emit "! CIU14(ubyte0) -> ubyte0"
 | 
						|
        cost 1;
 | 
						|
        
 | 
						|
    out:(int)ubyte0 = CIU41(in:(int)ubyte0)
 | 
						|
        with %out == %in
 | 
						|
        emit "! CIU41(ubyte0) -> ubyte0"
 | 
						|
        cost 1;
 | 
						|
        
 | 
						|
    out:(int)ubyteX = CIU41(in:(int)ubyteX)
 | 
						|
        with %out == %in
 | 
						|
        emit "! CIU41(ubyteX) -> ubyteX"
 | 
						|
        cost 1;
 | 
						|
        
 | 
						|
    out:(int)reg = CII14(in:(int)ubyteX)
 | 
						|
        emit "extsb %out, %in ! CII14(ubyteX) -> reg"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    /* short conversions */
 | 
						|
 | 
						|
    out:(int)ushort0 = CIU24(in:(int)ushort0)
 | 
						|
        with %out == %in
 | 
						|
        emit "! CIU24(ushort0) -> ushort0"
 | 
						|
        cost 1;
 | 
						|
        
 | 
						|
    out:(int)ushort0 = CIU42(in:(int)ushort0)
 | 
						|
        with %out == %in
 | 
						|
        emit "! CIU42(ushort0) -> ushort0"
 | 
						|
        cost 1;
 | 
						|
        
 | 
						|
    out:(int)ushortX = CIU42(in:(int)ushortX)
 | 
						|
        with %out == %in
 | 
						|
        emit "! CIU42(ushortX) -> ushortX"
 | 
						|
        cost 1;
 | 
						|
        
 | 
						|
    out:(int)reg = CII24(in:(int)ushort0)
 | 
						|
        with %out == %in
 | 
						|
        emit "! CII24(ushort0) -> reg"
 | 
						|
        cost 4;
 | 
						|
        
 | 
						|
    out:(int)reg = CII24(in:(int)ushortX)
 | 
						|
        emit "extsh %out, %in"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
 | 
						|
/* Locals */
 | 
						|
 | 
						|
	out:(int)reg = in:LOCAL4
 | 
						|
		emit "addi %out, fp, $in"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	address = in:LOCAL4
 | 
						|
		emit "$in(fp)";
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Memory addressing modes */
 | 
						|
 | 
						|
	address = ADD4(addr:(int)reg, offset:CONST4)
 | 
						|
        when signed_constant(%offset, 16)
 | 
						|
		emit "$offset(%addr)";
 | 
						|
 | 
						|
	address = addr:(int)reg
 | 
						|
		emit "0(%addr)";
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Branches */
 | 
						|
 | 
						|
	JUMP(addr:BLOCK4)
 | 
						|
		emit "b $addr"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
 | 
						|
        emit "bc 12, 2, $true" /* IFTRUE EQ */
 | 
						|
		emit "b $false"
 | 
						|
		cost 8;
 | 
						|
 | 
						|
	CJUMPLE(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
 | 
						|
        emit "bc 4, 1, $true" /* IFFALSE GT */
 | 
						|
        emit "b $false"
 | 
						|
		cost 8;
 | 
						|
 | 
						|
	CJUMPLT(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
 | 
						|
        emit "bc 12, 0, $true" /* IFTRUE LT */
 | 
						|
        emit "b $false"
 | 
						|
		cost 8;
 | 
						|
 | 
						|
	CALL1(dest:LABEL4)
 | 
						|
        with corrupted(volatile)
 | 
						|
		emit "bl $dest"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	out:(ret)reg = CALL4(dest:LABEL4)
 | 
						|
        with corrupted(volatile)
 | 
						|
		emit "bl $dest"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	out:(pret)reg = CALL8(dest:LABEL4)
 | 
						|
        with corrupted(volatile)
 | 
						|
		emit "bl $dest"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    CALL1(dest:(int)reg)
 | 
						|
        with corrupted(volatile)
 | 
						|
        emit "mtspr ctr, %dest"
 | 
						|
        emit "bcctrl 20, 0, 0"
 | 
						|
        cost 8;
 | 
						|
 | 
						|
    out:(ret)reg = CALL4(dest:(int)reg)
 | 
						|
        with corrupted(volatile)
 | 
						|
        emit "mtspr ctr, %dest"
 | 
						|
        emit "bcctrl 20, 0, 0"
 | 
						|
        cost 8;
 | 
						|
 | 
						|
    out:(pret)reg = CALL8(dest:(int)reg)
 | 
						|
        with corrupted(volatile)
 | 
						|
        emit "mtspr ctr, %dest"
 | 
						|
        emit "bcctrl 20, 0, 0"
 | 
						|
        cost 8;
 | 
						|
 | 
						|
    JUMP(dest:LABEL4)
 | 
						|
        emit "b $dest"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Comparisons */
 | 
						|
 | 
						|
	cr:(cr)cr = COMPARES44(left:(int)reg, right:(int)reg)
 | 
						|
        emit "cmp %cr, 0, %left, %right"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	cr:(cr)cr = COMPARES44(left:(int)reg, right:CONST4)
 | 
						|
        when signed_constant(%right, 16)
 | 
						|
        emit "cmpi %cr, 0, %left, $right"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	cr:(cr)cr = COMPAREU44(left:(int)reg, right:(int)reg)
 | 
						|
        emit "cmpl %cr, 0, %left, %right"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	cr:(cr)cr = COMPAREU44(left:(int)reg, right:CONST4)
 | 
						|
        when signed_constant(%right, 16)
 | 
						|
        emit "cmpli %cr, 0, %left, $right"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    out:(cr)cr = COMPARES44(in:(cr)cr, result:CONST4)
 | 
						|
        when specific_constant(%result, 0)
 | 
						|
        with %out == %in
 | 
						|
        emit "! COMPARES(cr, 0)"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Booleans */
 | 
						|
 | 
						|
    out:(int)reg = IFEQ4(in:(cr)cr)
 | 
						|
        emit "mfcr %out" /* get cr0 */
 | 
						|
        emit "rlwinmi %out, %out, 32-2, 2, 31" /* extract just EQ */
 | 
						|
        cost 8;
 | 
						|
 | 
						|
    out:(int)reg = IFEQ4(in:(int)reg)
 | 
						|
        emit "cntlzw %out, %in" /* returns 0..32 */
 | 
						|
        emit "rlwinmi %out, %out, 32-5, 5, 31" /* if 32, return 1, otherwise 0 */
 | 
						|
        cost 8;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Conversions */
 | 
						|
 | 
						|
    out:(int)reg = CIU44(in:(int)reg)
 | 
						|
        with %out == %in
 | 
						|
        emit "! ciu44"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(int)reg = CUI44(in:(int)reg)
 | 
						|
        with %out == %in
 | 
						|
        emit "! cui44"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
 | 
						|
/* ALU operations */
 | 
						|
 | 
						|
    #define ALUR(name, instr) \
 | 
						|
        out:(int)reg = name(left:(int)reg, right:(int)reg) \
 | 
						|
            emit instr " %out, %left, %right"              \
 | 
						|
            cost 4;                                        \
 | 
						|
 | 
						|
    #define ALUC(name, instr) \
 | 
						|
        out:(int)reg = name(left:(int)reg, right:CONST4)   \
 | 
						|
            when signed_constant(%right, 16)               \
 | 
						|
            emit instr " %out, %left, $right"              \
 | 
						|
            cost 4;                                        \
 | 
						|
 | 
						|
    #define ALUC_reversed(name, instr) \
 | 
						|
        out:(int)reg = name(left:CONST4, right:(int)reg)   \
 | 
						|
            when signed_constant(%left, 16)                \
 | 
						|
            emit instr " %out, %right, $left"              \
 | 
						|
            cost 4;                                        \
 | 
						|
 | 
						|
    #define ALUCC(name, instr) \
 | 
						|
        ALUC(name, instr) \
 | 
						|
        ALUC_reversed(name, instr)
 | 
						|
 | 
						|
    ALUR(ADD4, "add")
 | 
						|
    ALUCC(ADD4, "addi")
 | 
						|
 | 
						|
	out:(int)reg = SUB4(left:(int)reg, right:(int)reg)
 | 
						|
		emit "subf %out, %left, %right"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	out:(int)reg = SUB4(left:(int)reg, right:CONST4)
 | 
						|
		emit "addi %out, %left, -[$right]"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	out:(int)reg = MOD4(left:(int)reg, right:(int)reg)
 | 
						|
		emit "divw %out, %left, %right"
 | 
						|
        emit "mullw %out, %out, %right"
 | 
						|
        emit "subf %out, %out, %left"
 | 
						|
		cost 12;
 | 
						|
 | 
						|
    ALUR(MUL4, "mullw")
 | 
						|
    ALUCC(MUL4, "mulli")
 | 
						|
 | 
						|
    ALUR(DIV4, "divw")
 | 
						|
    ALUR(DIVU4, "divwu")
 | 
						|
 | 
						|
    ALUR(ASL4, "slw")
 | 
						|
 | 
						|
    out:(int)reg = NEG4(left:(int)reg)
 | 
						|
        emit "neg %out, %left"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    ALUR(AND4, "and")
 | 
						|
    ALUCC(AND4, "andi.")
 | 
						|
 | 
						|
    ALUR(OR4, "or")
 | 
						|
    ALUCC(OR4, "ori")
 | 
						|
 | 
						|
    ALUR(EOR4, "xor")
 | 
						|
    ALUCC(EOR4, "xori")
 | 
						|
 | 
						|
	out:(int)reg = value:LABEL4
 | 
						|
		emit "la %out, $value"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	out:(int)reg = value:BLOCK4
 | 
						|
		emit "la %out, $value"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	out:(int)reg = value:CONST4
 | 
						|
		emit "li %out, $value"
 | 
						|
		cost 8;
 | 
						|
 | 
						|
 | 
						|
/* FPU operations */
 | 
						|
 | 
						|
    #define FPU4R(name, instr) \
 | 
						|
        out:(float)reg = name(left:(float)reg, right:(float)reg) \
 | 
						|
            emit instr " %out, %left, %right"                    \
 | 
						|
            cost 4;                                              \
 | 
						|
 | 
						|
    #define FPU8R(name, instr) \
 | 
						|
        out:(double)reg = name(left:(double)reg, right:(double)reg) \
 | 
						|
            emit instr " %out, %left, %right"                       \
 | 
						|
            cost 4;                                                 \
 | 
						|
 | 
						|
    out:(float)reg = LOADF4(addr:address)
 | 
						|
        emit "lfs %out, %addr"
 | 
						|
        cost 4;
 | 
						|
        
 | 
						|
    out:(double)reg = LOADF8(addr:address)
 | 
						|
        emit "lfd %out, %addr"
 | 
						|
        cost 4;
 | 
						|
        
 | 
						|
	out:(float)reg = value:CONSTF4
 | 
						|
		emit "lfs %out, address-containing-$value"
 | 
						|
		cost 8;
 | 
						|
 | 
						|
    FPU4R(ADDF4, "fadds")
 | 
						|
    FPU8R(ADDF8, "fadd")
 | 
						|
 | 
						|
    FPU4R(SUBF4, "fsubs")
 | 
						|
    FPU8R(SUBF8, "fsub")
 | 
						|
 | 
						|
    FPU4R(MULF4, "fmuls")
 | 
						|
    FPU8R(MULF8, "fmul")
 | 
						|
 | 
						|
    FPU4R(DIVF4, "fdivs")
 | 
						|
    FPU8R(DIVF8, "fdiv")
 | 
						|
 | 
						|
    out:(float)reg = NEGF4(left:(float)reg)
 | 
						|
        emit "fneg %out, %left"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(double)reg = NEGF8(left:(double)reg)
 | 
						|
        emit "fneg %out, %left"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
	cr:(cr)cr = COMPAREF44(left:(float)reg, right:(float)reg)
 | 
						|
        emit "fcmpu %cr, %left, %right"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
	cr:(cr)cr = COMPAREF84(left:(double)reg, right:(double)reg)
 | 
						|
        emit "fcmpu %cr, %left, %right"
 | 
						|
		cost 4;
 | 
						|
 | 
						|
    out:(ret)reg = CFI44(val:(fret)reg)
 | 
						|
        with corrupted(volatile)
 | 
						|
        emit "bl .cfi44"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(fret)reg = CIF44(val:(ret)reg)
 | 
						|
        with corrupted(volatile)
 | 
						|
        emit "bl .cif44"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(ret)reg = CFI84(val:(dret)reg)
 | 
						|
        with corrupted(volatile)
 | 
						|
        emit "bl .cfi84"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(dret)reg = CIF48(val:(ret)reg)
 | 
						|
        with corrupted(volatile)
 | 
						|
        emit "bl .cif48"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(float)reg = CFF84(val:(double)reg)
 | 
						|
        emit "frsp %out, %val"
 | 
						|
        cost 4;
 | 
						|
 | 
						|
    out:(double)reg = CFF48(val:(float)reg)
 | 
						|
        emit "fmr %out, %val"
 | 
						|
        cost 1;
 | 
						|
 | 
						|
/* vim: set sw=4 ts=4 expandtab : */
 | 
						|
 |