diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 3cfb1447d..366b16d14 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -229,7 +229,7 @@ PATTERNS out:(int)reg = FPTOLB.I(in:(int)reg) with %out == %in cost 1; - + out:(int)reg = GETSP.I emit "mr %out, sp" cost 4; @@ -417,6 +417,19 @@ PATTERNS emit "bl .fromui2d" cost 4; + out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg) + emit "mr %out.0, %in1" + emit "mr %out.1, %in2" + cost 8; + + out:(int)reg = FROML0.I(in:(long)reg) + emit "mr %out, %in.0" + cost 4; + + out:(int)reg = FROML1.I(in:(long)reg) + emit "mr %out, %in.1" + cost 4; + /* Locals */ @@ -448,6 +461,11 @@ PATTERNS emit "b $addr" cost 4; + JUMP(dest:(int)reg) + emit "mtspr ctr, %dest" + emit "bcctrl 20, 0, 0" + cost 8; + CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK.I, false:BLOCK.I)) emit "bc 12, 2, $true" /* IFTRUE EQ */ emit "b $false" diff --git a/mach/proto/mcg/data.c b/mach/proto/mcg/data.c index 2e6fde9b2..5eeca8fc2 100644 --- a/mach/proto/mcg/data.c +++ b/mach/proto/mcg/data.c @@ -64,7 +64,8 @@ void data_float(const char* data, size_t size, bool is_ro) emit_header(is_ro ? SECTION_ROM : SECTION_DATA); assert((size == 4) || (size == 8)); - if (float_cst(data, size, (char*) buffer)) + i = float_cst(data, size, (char*) buffer); + if ((i != 0) && (i != 2)) /* 2 == overflow */ fatal("cannot parse floating point constant %s sz %d", data, size); fprintf(outputfile, "\t!float %s sz %d\n", data, size); diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 73e454d2c..1d0c408cf 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -59,7 +59,37 @@ static struct ir* pop(int size) #endif if (ir->size != size) - fatal("expected an item on stack of size %d, but got %d\n", size, ir->size); + { + if ((size == (EM_wordsize*2)) && (ir->size == EM_wordsize)) + { + /* Tried to read a long, but we got an int. Assemble the long + * out of two ints. Note that EM doesn't specify an order. */ + return + new_ir2( + IR_FROMIPAIR, size, + ir, + pop(EM_wordsize) + ); + } + else if ((size == EM_wordsize) && (ir->size == (EM_wordsize*2))) + { + /* Tried to read an int, but we got a long. */ + push( + new_ir1( + IR_FROML1, EM_wordsize, + ir + ) + ); + + return + new_ir1( + IR_FROML0, EM_wordsize, + ir + ); + } + else + fatal("expected an item on stack of size %d, but got %d\n", size, ir->size); + } return ir; } } @@ -864,15 +894,34 @@ static void insn_ivalue(int opcode, arith value) case op_sti: { struct ir* ptr = pop(EM_pointersize); - struct ir* val = pop(value); + int offset = 0; - appendir( - store( - value, - ptr, 0, - val - ) - ); + /* FIXME: this is awful; need a better way of dealing with + * non-standard EM sizes. */ + if (value > (EM_wordsize*2)) + appendir(ptr); + + while (value > 0) + { + int s; + if (value > (EM_wordsize*2)) + s = EM_wordsize*2; + else + s = value; + + appendir( + store( + s, + ptr, offset, + pop(s) + ) + ); + + value -= s; + offset += s; + } + + assert(value == 0); break; } @@ -1483,6 +1532,31 @@ static void insn_lvalue(int opcode, const char* label, arith offset) ); break; + case op_gto: + { + struct ir* descriptor = pop(EM_pointersize); + + appendir( + new_ir1( + IR_SETSP, EM_pointersize, + load(EM_pointersize, descriptor, EM_pointersize*2) + ) + ); + appendir( + new_ir1( + IR_SETFP, EM_pointersize, + load(EM_pointersize, descriptor, EM_pointersize*1) + ) + ); + appendir( + new_ir1( + IR_JUMP, 0, + load(EM_pointersize, descriptor, EM_pointersize*0) + ) + ); + break; + } + case op_fil: { /* Set filename --- ignore. */ diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 92fb5df0d..1db593efc 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -71,6 +71,9 @@ S ?=I. FROMSI S ?=L. FROMSL S ?=F. FROMF S ?=D. FROMD +S L=II FROMIPAIR +S I=L. FROML0 +S I=L. FROML1 # The H versions are only used if wordsize > 2 S I=I. EXTENDB