More opcodes.
This commit is contained in:
parent
2d52b1fdaa
commit
11b0bc1055
3 changed files with 90 additions and 43 deletions
|
@ -464,12 +464,12 @@ PATTERNS
|
||||||
|
|
||||||
out:(int)reg = IFEQ4(in:(cr)cr)
|
out:(int)reg = IFEQ4(in:(cr)cr)
|
||||||
emit "mfcr %out" /* get cr0 */
|
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;
|
cost 8;
|
||||||
|
|
||||||
out:(int)reg = IFEQ4(in:(int)reg)
|
out:(int)reg = IFEQ4(in:(int)reg)
|
||||||
emit "cntlzw %out, %in" /* returns 0..32 */
|
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;
|
cost 8;
|
||||||
|
|
||||||
|
|
||||||
|
@ -527,6 +527,12 @@ PATTERNS
|
||||||
emit "subf %out, %out, %left"
|
emit "subf %out, %out, %left"
|
||||||
cost 12;
|
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")
|
ALUR(MUL4, "mullw")
|
||||||
ALUCC(MUL4, "mulli")
|
ALUCC(MUL4, "mulli")
|
||||||
|
|
||||||
|
@ -535,10 +541,17 @@ PATTERNS
|
||||||
|
|
||||||
ALUR(ASL4, "slw")
|
ALUR(ASL4, "slw")
|
||||||
|
|
||||||
|
ALUR(LSL4, "slw")
|
||||||
|
|
||||||
out:(int)reg = NEG4(left:(int)reg)
|
out:(int)reg = NEG4(left:(int)reg)
|
||||||
emit "neg %out, %left"
|
emit "neg %out, %left"
|
||||||
cost 4;
|
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")
|
ALUR(AND4, "and")
|
||||||
ALUCC(AND4, "andi.")
|
ALUCC(AND4, "andi.")
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,14 @@ static struct ir* tristate_compare(int size, int opcode)
|
||||||
return compare(left, right, size, 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)
|
static void simple_convert(int opcode)
|
||||||
{
|
{
|
||||||
struct ir* destsize = pop(EM_wordsize);
|
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)
|
static void insn_simple(int opcode)
|
||||||
{
|
{
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
|
@ -224,14 +286,8 @@ static void insn_simple(int opcode)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case op_teq:
|
case op_teq: simple_test(EM_wordsize, IR_IFEQ); break;
|
||||||
push(
|
case op_tne: simple_test_neg(EM_wordsize, IR_IFEQ); break;
|
||||||
new_ir1(
|
|
||||||
IR_IFEQ, EM_wordsize,
|
|
||||||
pop(EM_wordsize)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case op_cai:
|
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)
|
static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock* rightbb)
|
||||||
{
|
{
|
||||||
switch (opcode)
|
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_mlu: simple_alu2(opcode, value, IR_MUL); break;
|
||||||
case op_slu: simple_alu2(opcode, value, IR_LSL); break;
|
case op_slu: simple_alu2(opcode, value, IR_LSL); break;
|
||||||
case op_sru: simple_alu2(opcode, value, IR_LSR); 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_dvu: simple_alu2(opcode, value, IR_DIVU); break;
|
||||||
|
|
||||||
case op_and: simple_alu2(opcode, value, IR_AND); break;
|
case op_and: simple_alu2(opcode, value, IR_AND); break;
|
||||||
|
@ -595,6 +620,14 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case op_zrf:
|
||||||
|
{
|
||||||
|
struct ir* ir = new_constir(value, 0);
|
||||||
|
ir->opcode = IR_CONSTF;
|
||||||
|
push(ir);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case op_loe:
|
case op_loe:
|
||||||
push(
|
push(
|
||||||
new_ir1(
|
new_ir1(
|
||||||
|
|
|
@ -32,6 +32,7 @@ S MUL
|
||||||
S DIV
|
S DIV
|
||||||
S DIVU
|
S DIVU
|
||||||
S MOD
|
S MOD
|
||||||
|
S MODU
|
||||||
S NEG
|
S NEG
|
||||||
|
|
||||||
S ADDF
|
S ADDF
|
||||||
|
@ -96,7 +97,7 @@ S COMPAREF2
|
||||||
S COMPAREF4
|
S COMPAREF4
|
||||||
S COMPAREF8
|
S COMPAREF8
|
||||||
|
|
||||||
# Boolean comparisons
|
# Tristate to boolean conversion
|
||||||
S IFEQ
|
S IFEQ
|
||||||
S IFLT
|
S IFLT
|
||||||
S IFLE
|
S IFLE
|
||||||
|
|
Loading…
Reference in a new issue