More opcodes.
This commit is contained in:
parent
2d52b1fdaa
commit
11b0bc1055
|
@ -464,12 +464,12 @@ PATTERNS
|
|||
|
||||
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;
|
||||
|
||||
|
||||
|
@ -527,6 +527,12 @@ PATTERNS
|
|||
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")
|
||||
|
||||
|
@ -535,10 +541,17 @@ PATTERNS
|
|||
|
||||
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.")
|
||||
|
||||
|
|
|
@ -178,6 +178,14 @@ static struct ir* tristate_compare(int size, int opcode)
|
|||
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);
|
||||
|
@ -193,6 +201,60 @@ static void simple_convert(int opcode)
|
|||
);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -224,14 +286,8 @@ static void insn_simple(int 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:
|
||||
{
|
||||
|
@ -318,38 +374,6 @@ static void insn_simple(int opcode)
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -490,6 +514,7 @@ static void insn_ivalue(int opcode, arith value)
|
|||
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;
|
||||
|
@ -595,6 +620,14 @@ static void insn_ivalue(int opcode, arith value)
|
|||
);
|
||||
break;
|
||||
|
||||
case op_zrf:
|
||||
{
|
||||
struct ir* ir = new_constir(value, 0);
|
||||
ir->opcode = IR_CONSTF;
|
||||
push(ir);
|
||||
break;
|
||||
}
|
||||
|
||||
case op_loe:
|
||||
push(
|
||||
new_ir1(
|
||||
|
|
|
@ -32,6 +32,7 @@ S MUL
|
|||
S DIV
|
||||
S DIVU
|
||||
S MOD
|
||||
S MODU
|
||||
S NEG
|
||||
|
||||
S ADDF
|
||||
|
@ -96,7 +97,7 @@ S COMPAREF2
|
|||
S COMPAREF4
|
||||
S COMPAREF8
|
||||
|
||||
# Boolean comparisons
|
||||
# Tristate to boolean conversion
|
||||
S IFEQ
|
||||
S IFLT
|
||||
S IFLE
|
||||
|
|
Loading…
Reference in a new issue