out:(int)reg = IFEQ4(in:(cr)cr)
emit "mfcr %out" /* get cr0 */
- emit "rlwinmi %out, %out, 32-2, 2, 31" /* extract just EQ */
+ emit "rlwinm %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 */
+ emit "rlwinm %out, %out, [32-5], 5, 31" /* if 32, return 1, otherwise 0 */
cost 8;
emit "subf %out, %out, %left"
cost 12;
+ out:(int)reg = MODU4(left:(int)reg, right:(int)reg)
+ emit "divwu %out, %left, %right"
+ emit "mullw %out, %out, %right"
+ emit "subf %out, %out, %left"
+ cost 12;
+
ALUR(MUL4, "mullw")
ALUCC(MUL4, "mulli")
ALUR(ASL4, "slw")
+ ALUR(LSL4, "slw")
+
out:(int)reg = NEG4(left:(int)reg)
emit "neg %out, %left"
cost 4;
+ out:(int)reg = NOT4(left:(int)reg)
+ emit "cntlzw %out, %left"
+ emit "rlwinm %out, %out, 32-5, 5, 31"
+ cost 8;
+
ALUR(AND4, "and")
ALUCC(AND4, "andi.")
return compare(left, right, size, opcode);
}
+static struct ir* tristate_compare0(int size, int opcode)
+{
+ struct ir* right = new_wordir(0);
+ struct ir* left = pop(size);
+
+ return compare(left, right, size, opcode);
+}
+
static void simple_convert(int opcode)
{
struct ir* destsize = pop(EM_wordsize);
);
}
+static void simple_branch2(int opcode, int size,
+ struct basicblock* truebb, struct basicblock* falsebb,
+ int irop)
+{
+ struct ir* right = pop(size);
+ struct ir* left = pop(size);
+
+ materialise_stack();
+ appendir(
+ new_ir2(
+ irop, 0,
+ compare(left, right, size, IR_COMPARES1),
+ new_ir2(
+ IR_PAIR, 0,
+ new_bbir(truebb),
+ new_bbir(falsebb)
+ )
+ )
+ );
+}
+
+static void compare0_branch2(int opcode,
+ struct basicblock* truebb, struct basicblock* falsebb,
+ int irop)
+{
+ push(
+ new_wordir(0)
+ );
+
+ simple_branch2(opcode, EM_wordsize, truebb, falsebb, irop);
+}
+
+static void simple_test(int size, int irop)
+{
+ push(
+ new_ir1(
+ irop, EM_wordsize,
+ tristate_compare0(size, IR_COMPARES1)
+ )
+ );
+}
+
+static void simple_test_neg(int size, int irop)
+{
+ simple_test(size, irop);
+
+ push(
+ new_ir1(
+ IR_NOT, EM_wordsize,
+ pop(EM_wordsize)
+ )
+ );
+}
+
static void insn_simple(int opcode)
{
switch (opcode)
);
break;
- case op_teq:
- push(
- new_ir1(
- IR_IFEQ, EM_wordsize,
- pop(EM_wordsize)
- )
- );
- break;
+ case op_teq: simple_test(EM_wordsize, IR_IFEQ); break;
+ case op_tne: simple_test_neg(EM_wordsize, IR_IFEQ); break;
case op_cai:
{
}
}
-static void simple_branch2(int opcode, int size,
- struct basicblock* truebb, struct basicblock* falsebb,
- int irop)
-{
- struct ir* right = pop(size);
- struct ir* left = pop(size);
-
- materialise_stack();
- appendir(
- new_ir2(
- irop, 0,
- compare(left, right, size, IR_COMPARES1),
- new_ir2(
- IR_PAIR, 0,
- new_bbir(truebb),
- new_bbir(falsebb)
- )
- )
- );
-}
-
-static void compare0_branch2(int opcode,
- struct basicblock* truebb, struct basicblock* falsebb,
- int irop)
-{
- push(
- new_wordir(0)
- );
-
- simple_branch2(opcode, EM_wordsize, truebb, falsebb, irop);
-}
-
static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock* rightbb)
{
switch (opcode)
case op_mlu: simple_alu2(opcode, value, IR_MUL); break;
case op_slu: simple_alu2(opcode, value, IR_LSL); break;
case op_sru: simple_alu2(opcode, value, IR_LSR); break;
+ case op_rmu: simple_alu2(opcode, value, IR_MODU); break;
case op_dvu: simple_alu2(opcode, value, IR_DIVU); break;
case op_and: simple_alu2(opcode, value, IR_AND); break;
);
break;
+ case op_zrf:
+ {
+ struct ir* ir = new_constir(value, 0);
+ ir->opcode = IR_CONSTF;
+ push(ir);
+ break;
+ }
+
case op_loe:
push(
new_ir1(