out:(int)reg = FPTOLB.I(in:(int)reg)
with %out == %in
cost 1;
-
+
out:(int)reg = GETSP.I
emit "mr %out, sp"
cost 4;
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 */
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"
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);
#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;
}
}
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;
}
);
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. */