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. */

    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 ret volatile;

    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;

    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;
    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;

	cr0 cr;


DECLARATIONS

	cr;

	address   fragment;


PATTERNS

/* Special */

	PAIR(BLOCK4, BLOCK4);



/* Miscellaneous special things */

	PUSH4(in:(int)reg)
		emit "stwu %in, -4(sp)"
		cost 4;

	out:(int)reg = POP4
		emit "lwz %out, 0(sp)"
        emit "addi sp, sp, 4"
		cost 8;

	out:(float)reg = POPF4
		emit "lfs %out, 0(sp)"
		emit "addi sp, sp, 4"
		cost 8;
		
	RET
		emit "ret"
		cost 4;

	SETRET4(in:(ret)reg)
		emit "mr r3, %in"
		cost 4;

    (ret)reg = GETRET4
        cost 1;

	STACKADJUST4(delta:CONST4)
        when signed_constant(%delta, 16)
		emit "addi sp, sp, $delta"
		cost 4;



/* Memory operations */

	STORE4(addr:address, value:(int)reg)
		emit "stw %value, %addr"
		cost 4;

	STORE2(addr:address, value:(int)reg)
		emit "sth %value, %addr"
		cost 4;

	STORE1(addr:address, value:(int)reg)
		emit "stb %value, %addr"
		cost 4;

	out:(int)reg = LOAD4(addr:address)
		emit "lwz %out, %addr"
		cost 4;

	out:(int)reg = LOAD2(addr:address)
		emit "lhz %out, %addr"
		cost 4;

	out:(int)reg = LOAD1(addr:address)
		emit "lbz %out, %addr"
		cost 4;

	out:(int)reg = CIU14(LOAD1(addr:address))
		emit "lbz %out, %addr"
		cost 4;

	out:(int)reg = CIU24(LOAD2(addr:address))
		emit "lhz %out, %addr"
		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 IFTRUE, EQ, $true"
		emit "b $false"
		cost 8;

	CJUMPLE(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
        emit "bc IFTRUE, LE, $true"
        emit "b $false"
		cost 8;

	CJUMPLT(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4))
        emit "bc IFTRUE, LT, $true"
        emit "b $false"
		cost 8;

	CALL(dest:LABEL4)
		emit "bl $dest"
		cost 4;

    CALL(dest:(int)reg)
        emit "mtspr ctr, %dest"
        emit "bcctrl ALWAYS, 0, 0"
        cost 8;

    JUMP(dest:LABEL4)
        emit "b $dest"
        cost 4;



/* Comparisons */

	cr:(cr)cr = COMPARES4(left:(int)reg, right:(int)reg)
        emit "cmp %cr, 0, %left, %right"
		cost 4;

	cr:(cr)cr = COMPARES4(left:(int)reg, right:CONST4)
        when signed_constant(%right, 16)
        emit "cmpi %cr, 0, %left, $right"
		cost 4;

	cr:(cr)cr = COMPAREU4(left:(int)reg, right:(int)reg)
        emit "cmpl %cr, 0, %left, %right"
		cost 4;

	cr:(cr)cr = COMPAREU4(left:(int)reg, right:CONST4)
        when signed_constant(%right, 16)
        emit "cmpli %cr, 0, %left, $right"
		cost 4;

    cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:(int)reg), result:CONST4)
        when specific_constant(%result, 0)
        emit "cmp %cr, 0, %left, %right"
        cost 4;

    cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:CONST4), result:CONST4)
        when specific_constant(%result, 0)
        when signed_constant(%right, 16)
        emit "cmpi %cr, 0, %left, $right"
        cost 4;

    cr:(cr)cr = COMPARES4(COMPAREU4(left:(int)reg, right:(int)reg), result:CONST4)
        when specific_constant(%result, 0)
        emit "cmpl %cr, 0, %left, %right"
        cost 4;



/* Conversions */

	out:(int)reg = CII14(CIU41(value:(int)reg))
		emit "extsb %out, %value"
		cost 4;

	out:(int)reg = CII24(CIU42(value:(int)reg))
		emit "extsh %out, %value"
		cost 4;

	out:(int)reg = CIU41(in:(int)reg)
		emit "andi %out, %in, 0xff"
		cost 4;

	out:(int)reg = CIU42(in:(int)reg)
		emit "andi %out, %in, 0xffff"
		cost 4;

    out:(int)reg = CIU44(in:(int)reg)
        emit "mr %out, %in"
        cost 4;



/* ALU operations */

	out:(int)reg = ADD4(left:(int)reg, right:(int)reg)
		emit "add %out, %left, %right"
		cost 4;

	out:(int)reg = ADD4(left:(int)reg, right:CONST4)
        when signed_constant(%right, 16)
		emit "addi %out, %left, $right"
		cost 4;

	out:(int)reg = SUB4(left:(int)reg, right:(int)reg)
		emit "sub %out, %right, %left"
		cost 4;

	out:(int)reg = MUL4(left:(int)reg, right:(int)reg)
		emit "mullw %out, %right, %left"
		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;

	out:(int)reg = DIV4(left:(int)reg, right:(int)reg)
		emit "divw %out, %left, %right"
		cost 4;

    out:(int)reg = ASL4(left:(int)reg, right:(int)reg)
        emit "slw %out, %left, %right"
        cost 4;

    out:(int)reg = NEG4(left:(int)reg)
        emit "neg %out, %left"
        cost 4;

	out:(int)reg = EOR4(left:(int)reg, right:(int)reg)
		emit "xor %out, %right, %left"
		cost 4;

	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 "la %out, $value"
		cost 8;


/* FPU operations */

	out:(float)reg = value:CONSTF4
		emit "lfs %out, address-containing-$value"
		cost 8;

	out:(float)reg = ADDF4(left:(float)reg, right:(float)reg)
		emit "fadds %out, %left, %right"
		cost 4;

	out:(float)reg = SUBF4(left:(float)reg, right:(float)reg)
		emit "fsubs %out, %left, %right"
		cost 4;


/* vim: set sw=4 ts=4 expandtab : */