From 367c4677fcfe42108c7938439d5760cc3c51101b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Tue, 25 Oct 2005 08:00:44 +0000 Subject: [PATCH] architecture dependent part of the codegen module --- ir/be/ia32/Makefile.in | 35 +++++ ir/be/ia32/ia32_spec.pl | 290 ++++++++++++++++++++++++++++++++++++++++ ir/be/ia32/transform.c | 117 ++++++++++++++++ ir/be/ia32/transform.h | 6 + 4 files changed, 448 insertions(+) create mode 100644 ir/be/ia32/Makefile.in create mode 100644 ir/be/ia32/ia32_spec.pl create mode 100644 ir/be/ia32/transform.c create mode 100644 ir/be/ia32/transform.h diff --git a/ir/be/ia32/Makefile.in b/ir/be/ia32/Makefile.in new file mode 100644 index 000000000..5a6141197 --- /dev/null +++ b/ir/be/ia32/Makefile.in @@ -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 index 000000000..ce2147970 --- /dev/null +++ b/ir/be/ia32/ia32_spec.pl @@ -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_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__ 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__) assert(0); +# for i = 1 to arity +# set in[i] = op_i +# done +# res = new_ir_node(dbg, irg, block, op__, 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 index 000000000..e295693b2 --- /dev/null +++ b/ir/be/ia32/transform.c @@ -0,0 +1,117 @@ +#include + +#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 index 000000000..4f129c6f8 --- /dev/null +++ b/ir/be/ia32/transform.h @@ -0,0 +1,6 @@ +#ifndef TRANSFORM_H +#define TRANSFORM_H + +void transform_node(ir_node *node, void *env); + +#endif -- 2.20.1