--- /dev/null
+# Creation: 2005/10/19
+# $Id$
+# This is the specification for the ia32 assembler Firm-operations
+
+# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
+
+$arch = "ia32";
+
+# The node description is done as a perl hash initializer with the
+# following structure:
+#
+# %nodes = (
+#
+# <op-name> => {
+# "op_flags" => "N|L|C|X|I|F|Y|H|c",
+# "arity" => "0|1|2|3|variable|dynamic|all",
+# "state" => "floats|pinned",
+# "args" => "DEFAULT"
+# or
+# [
+# { "type" => "type 1", "name" => "name 1" },
+# { "type" => "type 2", "name" => "name 2" },
+# ...
+# ],
+# "comment" => "any comment for constructor",
+# "rd_constructor" => "DEFAULT"
+# or
+# "c source code which constructs an ir_node"
+# },
+#
+# ... # (all nodes you need to describe)
+#
+# ); # close the %nodes initializer
+
+# the op_flags correspond to the firm irop_flags:
+# N irop_flag_none
+# L irop_flag_labeled
+# C irop_flag_commutative
+# X irop_flag_cfopcode
+# I irop_flag_ip_cfopcode
+# F irop_flag_fragile
+# Y irop_flag_forking
+# H irop_flag_highlevel
+# c irop_flag_constlike
+#
+# arity: arity of the operation
+# args: the arguments of the node constructor (debug, irg and block
+# are always the first 3 arguments and are always autmatically
+# created)
+# or DEFAULT
+# DEFAULT will create the following arguments:
+# for i = 1 .. arity: ir_node *op_i
+# ir_mode *mode
+# comment: optional comment for the node constructor
+# rd_constructor: for every operation there will be a
+# new_rd_<arch>_<op-name> function with the arguments from above
+# which creates the ir_node corresponding to the defined operation
+# you can either put the complete source code of this function here
+# or use DEFAULT
+# DEFAULT creates the following constructor:
+#
+# if (!op_<arch>_<op-name>) assert(0);
+# for i = 1 to arity
+# set in[i] = op_i
+# done
+# res = new_ir_node(dbg, irg, block, op_<arch>_<op-name>, mode, in)
+# res = optimize_node(res)
+# IRN_VRFY_IRG(res, irg)
+# return res
+#
+# NOTE: You can use DEFAULT if and only if arity is 0,1,2 or 3
+
+#--------------------------------------------------#
+# _ #
+# (_) #
+# _ __ _____ __ _ _ __ ___ _ __ ___ #
+# | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
+# | | | | __/\ V V / | | | | (_) | |_) \__ \ #
+# |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
+# | | #
+# |_| #
+#--------------------------------------------------#
+
+# arithmetic operations
+
+%nodes = (
+
+# commutative operations
+
+"Add" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Add_i" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Add: Add(a, const) = Add(const, a) = a + const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Mul" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Mul_i" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"And" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct And: And(a, b) = And(b, a) = a AND b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"And_i" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct And: And(a, const) = And(const, a) = a AND const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Or" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Or_i" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Or: Or(a, const) = Or(const, a) = a OR const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Eor" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Eor_i" => {
+ "op_flags" => "C",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
+ "rd_constructor" => "DEFAULT"
+},
+
+# not commutative operations
+
+"Sub" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Sub: Sub(a, b) = a - b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Sub_i" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Sub: Sub(a, const) = a - const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Mod" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Mod: Mod(a, b) = a % b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Mod_i" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Mod: Mod(a, const) = a % const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Shl" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Shl: Shl(a, b) = a << b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Shl_i" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Shl: Shl(a, const) = a << const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Shr" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Shr: Shr(a, b) = a >> b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Shr_i" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Shr: Shr(a, const) = a >> const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Shrs" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Shrs: Shrs(a, b) = a >> b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Shrs_i" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Shrs: Shrs(a, const) = a >> const",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Rot" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 2,
+ "args" => "DEFAULT",
+ "comment" => "construct Rot: Rot(a, b) = a ROT b",
+ "rd_constructor" => "DEFAULT"
+},
+
+"Rot_i" => {
+ "op_flags" => "N",
+ "state" => "floats",
+ "arity" => 1,
+ "args" => "DEFAULT",
+ "comment" => "construct Rot: Rot(a, const) = a ROT const",
+ "rd_constructor" => "DEFAULT"
+}
+
+); # end of %nodes
--- /dev/null
+#include <libfirm/firm.h>
+
+#include "../firm2arch_nodes_attr.h"
+#include "transform.h"
+#include "new_nodes.h"
+
+void transform_node(ir_node *node, void *env) {
+ ir_mode *mode = get_irn_mode(node);
+ opcode code = get_irn_opcode(node);
+ ir_node *op1 = NULL;
+ ir_node *op2 = NULL;
+ ir_node *asm_op = NULL;
+ ir_node *const_op = NULL;
+ ir_node *expr_op = NULL;
+ opcode code_op1, code_op2;
+
+ /* TODO: maybe one can transform
+ "Const -- Sub -- Exp" into "Exp -- Minus -- Add -- Const"
+ to save a register
+ but I'm not sure about side effects */
+
+#define GEN(a) case iro_##a: asm_op = new_ia32_##a(op1, op2, mode); break
+#define GENI(a) case iro_##a: asm_op = new_ia32_##a##_i(expr_op, mode); break
+
+ switch (code) {
+ /* commutative arith ops */
+ case iro_Add:
+ case iro_Mul:
+ case iro_And:
+ case iro_Or:
+ case iro_Eor:
+ op1 = get_irn_n(node, 0);
+ op2 = get_irn_n(node, 1);
+ code_op1 = get_irn_opcode(op1);
+ code_op2 = get_irn_opcode(op2);
+
+ /* determine if one operator is a Const */
+ const_op = code_op1 == iro_Const ? op1 : (code_op2 == iro_Const ? op2 : NULL);
+ expr_op = code_op1 != iro_Const ? op1 : (code_op2 != iro_Const ? op2 : NULL);
+
+ goto gen_asm_node;
+
+ /* not commutative arith ops: only construct the immediate nodes
+ when the right operand is a Const */
+ case iro_Sub:
+ case iro_DivMod:
+ case iro_Mod:
+ case iro_Shl:
+ case iro_Shr:
+ case iro_Shrs:
+ case iro_Rot:
+ op1 = get_irn_n(node, 0);
+ op2 = get_irn_n(node, 1);
+ code_op1 = get_irn_opcode(op1);
+ code_op2 = get_irn_opcode(op2);
+
+ /* determine if the right operator is a Const */
+ const_op = code_op2 == iro_Const ? op2 : NULL;
+ expr_op = op1;
+
+gen_asm_node:
+ assert(code_op1 != iro_Const && code_op2 != iro_Const && "Op(Const, Const) not expected!");
+ if ((code_op1 == iro_Const) && (code_op2 == iro_Const)) {
+ printf("Ignoring %s(Const, Const)\n", get_irn_opname(node));
+ return;
+ }
+
+ if (const_op) { /* one of the operators is a Const */
+ switch (code) {
+ GENI(Add);
+ GENI(Mul);
+ GENI(And);
+ GENI(Or);
+ GENI(Eor);
+ GENI(Sub);
+// GENI(DivMod);
+ GENI(Mod);
+ GENI(Shl);
+ GENI(Shr);
+ GENI(Shrs);
+ GENI(Rot);
+ default:
+ /* ignore */
+ break;
+ }
+ /* make the Const an attribute */
+ asmop_attr *attr = (asmop_attr *)get_irn_generic_attr(const_op);
+ attr->tv = get_Const_tarval(const_op);
+ }
+ else { /* both operators need to be computed */
+ switch (code) {
+ GEN(Add);
+ GEN(Mul);
+ GEN(And);
+ GEN(Or);
+ GEN(Eor);
+ GEN(Sub);
+// GEN(DivMod);
+ GEN(Mod);
+ GEN(Shl);
+ GEN(Shr);
+ GEN(Shrs);
+ GEN(Rot);
+ default:
+ /* ignore */
+ break;
+ }
+ }
+
+ /* exchange the old firm node with the new assembler node */
+ exchange(node, asm_op);
+ break;
+ default:
+ fprintf(stderr, "Ignoring node: %s\n", get_irn_opname(node));
+ break;
+ }
+}