how locals and the local base are handled.
data_offset(dlabel_to_str(em.em_dlb), em.em_off, ro);
break;
+ case sof_ptyp:
+ data_offset(strdup(em.em_dnam), em.em_off, ro);
+ break;
+
case ilb_ptyp:
{
const char* label = ilabel_to_str(em.em_ilb);
data_bss(EM_bsssize, em.em_cst);
break;
+ case ico_ptyp:
+ case uco_ptyp:
+ {
+ arith val = atol(em.em_string);
+ data_int(val, em.em_size, false);
+ break;
+ }
+
+ case sof_ptyp:
+ data_offset(strdup(em.em_dnam), em.em_off, false);
+ break;
+
default:
unknown_type("bss");
}
emit "addi sp, sp, $delta"
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;
+
/* Memory operations */
+/* 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)
emit "neg %out, %left"
cost 4;
+ out:(int)reg = OR4(left:(int)reg, right:(int)reg)
+ emit "or %out, %right, %left"
+ cost 4;
+
out:(int)reg = EOR4(left:(int)reg, right:(int)reg)
emit "xor %out, %right, %left"
cost 4;
);
break;
+ case op_teq:
+ push(
+ new_ir1(
+ IR_IFEQ, EM_wordsize,
+ pop(EM_wordsize)
+ )
+ );
+ break;
+
case op_cai:
{
struct ir* dest = pop(EM_pointersize);
break;
}
+ case op_lim:
+ {
+ push(
+ new_ir1(
+ IR_LOAD, 2,
+ new_labelir(".ignmask")
+ )
+ );
+ break;
+ }
+
+ case op_sim:
+ {
+ appendir(
+ new_ir2(
+ IR_STORE, 2,
+ new_labelir(".ignmask"),
+ pop(EM_wordsize)
+ )
+ );
+ break;
+ }
+
+ case op_lni:
+ {
+ /* Increment line number --- ignore. */
+ break;
+ }
+
default:
fatal("treebuilder: unknown simple instruction '%s'",
em_mnem[opcode - sp_fmnem]);
break;
case op_cmu:
+ case op_cms:
push(
tristate_compare(value, IR_COMPAREU)
);
break;
}
+ case op_sar:
+ case op_lar:
+ case op_aar:
+ {
+ const char* helper;
+ if (value != EM_wordsize)
+ fatal("sar/lar/aar are only supported when using "
+ "word-size descriptors");
+
+ switch (opcode)
+ {
+ case op_sar: helper = ".sar4"; break;
+ case op_lar: helper = ".lar4"; break;
+ case op_aar: helper = ".aar4"; break;
+ }
+
+ materialise_stack();
+ appendir(
+ new_ir1(
+ IR_CALL, 0,
+ new_labelir(helper)
+ )
+ );
+ push(
+ new_ir0(
+ IR_GETRET, EM_wordsize
+ )
+ );
+ break;
+ }
+
+ case op_lxl:
+ {
+ struct ir* ir;
+
+ /* Walk the static chain. */
+
+ ir = new_ir0(
+ IR_GETFP, EM_pointersize
+ );
+
+ while (value--)
+ {
+ ir = new_ir1(
+ IR_CHAINFP, EM_pointersize,
+ ir
+ );
+ }
+
+ push(ir);
+ break;
+ }
+
+ case op_lxa:
+ {
+ struct ir* ir;
+
+ /* Walk the static chain. */
+
+ ir = new_ir0(
+ IR_GETFP, EM_pointersize
+ );
+
+ while (value--)
+ {
+ ir = new_ir1(
+ IR_CHAINFP, EM_pointersize,
+ ir
+ );
+ }
+
+ push(
+ new_ir1(
+ IR_FPTOARGS, EM_pointersize,
+ ir
+ )
+ );
+ break;
+ }
+
+ case op_lin:
+ {
+ /* Set line number --- ignore. */
+ break;
+ }
+
default:
fatal("treebuilder: unknown ivalue instruction '%s'",
em_mnem[opcode - sp_fmnem]);
)
);
break;
+
+ case op_fil:
+ {
+ /* Set filename --- ignore. */
+ break;
+ }
default:
fatal("treebuilder: unknown lvalue instruction '%s'",
S STACKADJUST
S GETRET
S SETRET
+S GETFP
+S CHAINFP
+S FPTOARGS