architecture dependent part of the codegen module
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Tue, 25 Oct 2005 08:00:44 +0000 (08:00 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Tue, 25 Oct 2005 08:00:44 +0000 (08:00 +0000)
ir/be/ia32/Makefile.in [new file with mode: 0644]
ir/be/ia32/ia32_spec.pl [new file with mode: 0644]
ir/be/ia32/transform.c [new file with mode: 0644]
ir/be/ia32/transform.h [new file with mode: 0644]

diff --git a/ir/be/ia32/Makefile.in b/ir/be/ia32/Makefile.in
new file mode 100644 (file)
index 0000000..5a61411
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Project:     libFIRM
+# File name:   ir/be/ia32/Makefile.in
+# Purpose:
+# Author:      Boris Boesler, Till Riedel
+# Modified by:
+# Created:
+# CVS-ID:      $Id$
+# Copyright:   (c) 1999-2005 Universitaet Karlsruhe
+# Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+#
+
+top_srcdir := @top_srcdir@
+srcdir = @srcdir@
+topdir = ../../..
+subdir := ir/be/ia32
+full_dir = $(top_srcdir)/ir/be
+full_dirbe = $(full_dir)/$(FIRMBE_ARCH)
+
+SOURCES = Makefile.in new_nodes.c new_nodes.h transform.c transform.h
+
+include $(topdir)/MakeRules
+
+CPPFLAGS +=    -I$(top_srcdir)/ir/adt   -I$(top_srcdir)/ir/ir  -I$(top_srcdir)/ir/common  \
+               -I$(top_srcdir)/ir/ident -I$(top_srcdir)/ir/tr  -I$(top_srcdir)/ir/tv \
+               -I$(top_srcdir)/ir/debug -I$(top_srcdir)/ir/ana -I$(top_srcdir)/ir/st \
+               -I$(top_srcdir)/ir/stat -I$(top_srcdir)/ir/external -I$(top_srcdir)/ir/ana2 \
+               -I$(topdir)/ir/config
+
+include $(top_srcdir)/MakeTargets
+
+subdir_depend depend:
+       $(full_dir)/scripts/generate_new_opcodes.pl $(full_dirbe)/$(FIRMBE_ARCH)_spec.pl $(full_dirbe)
+
+all: subdir.o
diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl
new file mode 100644 (file)
index 0000000..ce21479
--- /dev/null
@@ -0,0 +1,290 @@
+# 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
diff --git a/ir/be/ia32/transform.c b/ir/be/ia32/transform.c
new file mode 100644 (file)
index 0000000..e295693
--- /dev/null
@@ -0,0 +1,117 @@
+#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;
+  }
+}
diff --git a/ir/be/ia32/transform.h b/ir/be/ia32/transform.h
new file mode 100644 (file)
index 0000000..4f129c6
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+void transform_node(ir_node *node, void *env);
+
+#endif