From 11b0bc1055d1e089608a1f29be84c41938b8d670 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 22 Oct 2016 20:32:51 +0200 Subject: [PATCH] More opcodes. --- mach/powerpc/mcg/table | 17 +++++- mach/proto/mcg/treebuilder.c | 113 ++++++++++++++++++++++------------- util/mcgg/ir.dat | 3 +- 3 files changed, 90 insertions(+), 43 deletions(-) diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 240086b0c..8a87e079d 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -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.") diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 91a082655..4ec1b46e0 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -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( diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 6b3c3755e..5c47c6639 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -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