#undef is_Start
#define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
+extern ir_node *be_new_NoReg(ir_graph *irg);
+
/**************************************************
* _ _ _ __
* | | | (_)/ _|
assert(irn_req && "missing requirement for regparam");
memcpy(req, &(irn_req->req), sizeof(*req));
return req;
+ //return NULL;
}
else if (is_Proj(irn)) {
if (pos == -1) {
if (is_Phi(irn)) {
DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
if (mode_is_float(mode))
- memcpy(req, &(ia32_default_req_ia32_floating_point.req), sizeof(*req));
+ memcpy(req, &(ia32_default_req_ia32_fp.req), sizeof(*req));
else if (mode_is_int(mode) || mode_is_reference(mode))
- memcpy(req, &(ia32_default_req_ia32_general_purpose.req), sizeof(*req));
+ memcpy(req, &(ia32_default_req_ia32_gp.req), sizeof(*req));
else if (mode == mode_T || mode == mode_M) {
DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
return NULL;
}
else if (get_irn_op(irn) == op_Return && pos > 0) {
DB((mod, LEVEL_1, "returning reqs EAX for %+F\n", irn));
- memcpy(req, &(ia32_default_req_ia32_general_purpose_eax.req), sizeof(*req));
+ memcpy(req, &(ia32_default_req_ia32_gp_eax.req), sizeof(*req));
}
else {
DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
if (is_ia32_irn(irn))
return get_ia32_flags(irn);
else {
- if (is_Start_Proj(irn) || is_Unknown(irn))
+ if (is_Start_Proj(irn))
return arch_irn_flags_ignore;
return 0;
irg_walk_blkwise_graph(cg->irg, check_for_alloca, NULL, &(cg->has_alloca));
if (cg->has_alloca) {
- ia32_general_purpose_regs[REG_EBP].type = arch_register_type_ignore;
+ ia32_gp_regs[REG_EBP].type = arch_register_type_ignore;
}
irg_walk_blkwise_graph(cg->irg, ia32_place_consts, ia32_transform_node, cg);
* Stack reservation and StackParam lowering.
*/
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
+#if 0
firm_dbg_module_t *mod = cg->mod;
ir_node *frame = get_irg_frame(irg);
ir_node *end_block = get_irg_end_block(irg);
/* Determine stack register */
if (cg->has_alloca) {
- stack_reg = &ia32_general_purpose_regs[REG_EBP];
+ stack_reg = &ia32_gp_regs[REG_EBP];
}
else {
- stack_reg = &ia32_general_purpose_regs[REG_ESP];
+ stack_reg = &ia32_gp_regs[REG_ESP];
}
/* If frame is used, then we need to reserve some stackspace. */
sched_add_after(sched_point, stack_free);
}
}
+#endif
}
ir_node *ptr = get_irg_frame(cg->irg);
ir_node *val = be_get_Spill_context(spill);
ir_node *mem = new_rd_NoMem(cg->irg);
+ ir_node *noreg = be_new_NoReg(cg->irg);
ir_mode *mode = get_irn_mode(spill);
ir_node *res;
entity *ent = be_get_spill_entity(spill);
unsigned offs = get_entity_offset_bytes(ent);
+ char buf[64];
DB((cg->mod, LEVEL_1, "lower_spill: got offset %d for %+F\n", offs, ent));
- res = new_rd_ia32_Store(dbg, cg->irg, block, ptr, val, mem, mode);
- set_ia32_am_offs(res, new_tarval_from_long(offs, mode_Iu));
+ res = new_rd_ia32_Store(dbg, cg->irg, block, ptr, noreg, val, mem, mode);
+ snprintf(buf, sizeof(buf), "%d", offs);
+ add_ia32_am_offs(res, buf);
return res;
}
ir_node *ptr = get_irg_frame(cg->irg);
ir_mode *mode = get_irn_mode(reload);
ir_node *pred = get_irn_n(reload, 0);
- tarval *tv;
+ ir_node *noreg = be_new_NoReg(cg->irg);
+ char buf[64];
+ char *ofs;
ir_node *res;
if (be_is_Spill(pred)) {
entity *ent = be_get_spill_entity(pred);
unsigned offs = get_entity_offset_bytes(ent);
DB((cg->mod, LEVEL_1, "lower_reload: got offset %d for %+F\n", offs, ent));
- tv = new_tarval_from_long(offs, mode_Iu);
+
+ snprintf(buf, sizeof(buf), "%d", offs);
}
else if (is_ia32_Store(pred)) {
- tv = get_ia32_am_offs(pred);
+ ofs = get_ia32_am_offs(pred);
+ strncpy(buf, ofs, sizeof(buf));
+ free(ofs);
}
else {
assert(0 && "unsupported Reload predecessor");
}
- res = new_rd_ia32_Load(dbg, cg->irg, block, ptr, pred, mode);
- set_ia32_am_offs(res, tv);
+ res = new_rd_ia32_Load(dbg, cg->irg, block, ptr, noreg, pred, mode);
+ add_ia32_am_offs(res, buf);
return res;
}
ia32_code_gen_t *cg = self;
if (cg->has_alloca) {
- return &ia32_general_purpose_regs[REG_EBP];
+ return &ia32_gp_regs[REG_EBP];
}
- return &ia32_general_purpose_regs[REG_ESP];
+ return &ia32_gp_regs[REG_ESP];
}
/**
}
ia32_finish_irg(irg, cg);
- dump_ir_block_graph_sched(irg, "-finished");
+ //dump_ir_block_graph_sched(irg, "-finished");
ia32_gen_routine(out, irg, cg);
cur_reg_set = NULL;
assert(pn == 0 && "only one floating point result supported");
/* Get the proj number for the floating point result */
- pn = ia32_get_reg_projnum(&ia32_floating_point_regs[REG_XMM0], isa->reg_projnum_map);
+ pn = ia32_get_reg_projnum(&ia32_fp_regs[REG_XMM0], isa->reg_projnum_map);
}
else {
/* In case of 64bit return value, the result is */
/* in EDX:EAX and we have two result projs. */
switch (pn) {
case 0:
- pn = ia32_get_reg_projnum(&ia32_general_purpose_regs[REG_EAX], isa->reg_projnum_map);
+ pn = ia32_get_reg_projnum(&ia32_gp_regs[REG_EAX], isa->reg_projnum_map);
break;
case 1:
- pn = ia32_get_reg_projnum(&ia32_general_purpose_regs[REG_EDX], isa->reg_projnum_map);
+ pn = ia32_get_reg_projnum(&ia32_gp_regs[REG_EDX], isa->reg_projnum_map);
break;
default:
assert(0 && "only two int results supported");
}
else {
/* Set mode to floating point if required */
- if (!strcmp(ia32_reg_classes[CLASS_ia32_floating_point].name,
+ if (!strcmp(ia32_reg_classes[CLASS_ia32_fp].name,
ia32_projnum_reg_req_map[pn]->req.cls->name)) {
set_irn_mode(proj, mode_F);
}
* Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
*/
static const list_sched_selector_t *ia32_get_list_sched_selector(const void *self) {
- memcpy(&ia32_sched_selector, reg_pressure_selector, sizeof(list_sched_selector_t));
+ memcpy(&ia32_sched_selector, trivial_selector, sizeof(list_sched_selector_t));
ia32_sched_selector.to_appear_in_schedule = ia32_to_appear_in_schedule;
return &ia32_sched_selector;
}
static const arch_env_t *arch_env = NULL;
+char *ia32_emit_binop(ir_node *irn) {
+ return "R1, R2";
+}
+
+char *ia32_emit_unop(ir_node *irn) {
+ return "R";
+}
+
+char *ia32_emit_am(ir_node *irn) {
+ return "AM";
+}
/*************************************************************
* _ _ __ _ _
* Return node's tarval as string.
*/
const char *node_const_to_str(ir_node *n) {
- char *buf;
- tarval *tv = get_ia32_Immop_tarval(n);
+ char *s = get_ia32_cnst(n);
- if (tv) {
- buf = xmalloc(SNPRINTF_BUF_LEN);
- tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
- return buf;
- }
- else if (get_ia32_old_ir(n)) {
- return get_sc_name(get_ia32_old_ir(n));
- }
- else
- return "0";
+ if (!s)
+ s = "NULL";
+
+ return s;
}
/**
* Returns node's offset as string.
*/
char *node_offset_to_str(ir_node *n) {
- char *buf;
- tarval *tv = get_ia32_am_offs(n);
+ char *s = get_ia32_am_offs(n);
- if (tv) {
- buf = xmalloc(SNPRINTF_BUF_LEN);
- tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
- return buf;
- }
- else
- return "";
+ if (!s)
+ s = "";
+
+ return s;
}
/* We always pass the ir_node which is a pointer. */
#define EMIT(a) if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; }
/* generated int emitter functions */
- IA32_EMIT(Copy);
- IA32_EMIT(Perm);
-
IA32_EMIT(Const);
IA32_EMIT(Add);
- IA32_EMIT(Add_i);
IA32_EMIT(Sub);
- IA32_EMIT(Sub_i);
IA32_EMIT(Minus);
IA32_EMIT(Inc);
IA32_EMIT(Dec);
IA32_EMIT(Min);
IA32_EMIT(And);
- IA32_EMIT(And_i);
IA32_EMIT(Or);
- IA32_EMIT(Or_i);
IA32_EMIT(Eor);
- IA32_EMIT(Eor_i);
IA32_EMIT(Not);
IA32_EMIT(Shl);
- IA32_EMIT(Shl_i);
IA32_EMIT(Shr);
- IA32_EMIT(Shr_i);
IA32_EMIT(Shrs);
- IA32_EMIT(Shrs_i);
IA32_EMIT(RotL);
- IA32_EMIT(RotL_i);
IA32_EMIT(RotR);
IA32_EMIT(Lea);
- IA32_EMIT(Lea_i);
IA32_EMIT(Mul);
- IA32_EMIT(Mul_i);
- IA32_EMIT(Cltd);
+ IA32_EMIT(Cdq);
IA32_EMIT(DivMod);
IA32_EMIT(Store);
IA32_EMIT(fAdd);
IA32_EMIT(fSub);
- IA32_EMIT(fMinus);
IA32_EMIT(fMul);
IA32_EMIT(fDiv);
/* other emitter functions */
IA32_EMIT(CondJmp);
- IA32_EMIT(CondJmp_i);
IA32_EMIT(SwitchJmp);
IA32_EMIT(Call);
- IA32_EMIT(Alloca);
- IA32_EMIT(Alloca_i);
EMIT(Jmp);
EMIT(Proj);
const lc_arg_env_t *ia32_get_arg_env(void);
-void equalize_dest_src(FILE *F, ir_node *n);
+char *ia32_emit_binop(ir_node *irn);
+char *ia32_emit_unop(ir_node *irn);
+char *ia32_emit_am(ir_node *irn);
int get_ia32_reg_nr(ir_node *irn, int posi, int in_out);
const char *get_ia32_in_reg_name(ir_node *irn, int pos);
/* this is the order of the assigned registers usesd for parameter passing */
const ia32_register_req_t *gpreg_param_req_std[] = {
- &ia32_default_req_ia32_general_purpose_eax,
- &ia32_default_req_ia32_general_purpose_ecx,
- &ia32_default_req_ia32_general_purpose_edx,
- &ia32_default_req_ia32_general_purpose_ebx,
- &ia32_default_req_ia32_general_purpose_edi,
- &ia32_default_req_ia32_general_purpose_esi
+ &ia32_default_req_ia32_gp_eax,
+ &ia32_default_req_ia32_gp_ecx,
+ &ia32_default_req_ia32_gp_edx,
+ &ia32_default_req_ia32_gp_ebx,
+ &ia32_default_req_ia32_gp_edi,
+ &ia32_default_req_ia32_gp_esi
};
const ia32_register_req_t *gpreg_param_req_this[] = {
- &ia32_default_req_ia32_general_purpose_ecx,
- &ia32_default_req_ia32_general_purpose_eax,
- &ia32_default_req_ia32_general_purpose_edx,
- &ia32_default_req_ia32_general_purpose_ebx,
- &ia32_default_req_ia32_general_purpose_edi,
- &ia32_default_req_ia32_general_purpose_esi
+ &ia32_default_req_ia32_gp_ecx,
+ &ia32_default_req_ia32_gp_eax,
+ &ia32_default_req_ia32_gp_edx,
+ &ia32_default_req_ia32_gp_ebx,
+ &ia32_default_req_ia32_gp_edi,
+ &ia32_default_req_ia32_gp_esi
};
const ia32_register_req_t *fpreg_param_req_std[] = {
- &ia32_default_req_ia32_floating_point_xmm0,
- &ia32_default_req_ia32_floating_point_xmm1,
- &ia32_default_req_ia32_floating_point_xmm2,
- &ia32_default_req_ia32_floating_point_xmm3,
- &ia32_default_req_ia32_floating_point_xmm4,
- &ia32_default_req_ia32_floating_point_xmm5,
- &ia32_default_req_ia32_floating_point_xmm6,
- &ia32_default_req_ia32_floating_point_xmm7
+ &ia32_default_req_ia32_fp_xmm0,
+ &ia32_default_req_ia32_fp_xmm1,
+ &ia32_default_req_ia32_fp_xmm2,
+ &ia32_default_req_ia32_fp_xmm3,
+ &ia32_default_req_ia32_fp_xmm4,
+ &ia32_default_req_ia32_fp_xmm5,
+ &ia32_default_req_ia32_fp_xmm6,
+ &ia32_default_req_ia32_fp_xmm7
};
const ia32_register_req_t *fpreg_param_req_this[] = {
NULL, /* in case of a "this" pointer, the first parameter must not be a float */
- &ia32_default_req_ia32_floating_point_xmm0,
- &ia32_default_req_ia32_floating_point_xmm1,
- &ia32_default_req_ia32_floating_point_xmm2,
- &ia32_default_req_ia32_floating_point_xmm3,
- &ia32_default_req_ia32_floating_point_xmm4,
- &ia32_default_req_ia32_floating_point_xmm5,
- &ia32_default_req_ia32_floating_point_xmm6,
- &ia32_default_req_ia32_floating_point_xmm7
+ &ia32_default_req_ia32_fp_xmm0,
+ &ia32_default_req_ia32_fp_xmm1,
+ &ia32_default_req_ia32_fp_xmm2,
+ &ia32_default_req_ia32_fp_xmm3,
+ &ia32_default_req_ia32_fp_xmm4,
+ &ia32_default_req_ia32_fp_xmm5,
+ &ia32_default_req_ia32_fp_xmm6,
+ &ia32_default_req_ia32_fp_xmm7
};
else if (is_ia32_Store(pred)) {
return 0;
}
- else if (is_ia32_CondJmp(pred) || is_ia32_CondJmp_i(pred)) {
+ else if (is_ia32_CondJmp(pred)) {
return 0;
}
else if (is_ia32_SwitchJmp(pred)) {
return 0;
}
- else if (is_ia32_Cltd(pred) || is_ia32_Mul(pred)) {
+ else if (is_ia32_Cdq(pred) || is_ia32_Mulh(pred)) {
if (nr == pn_EAX)
return 0;
if (nr == pn_EDX)
if (nr == pn_DivMod_res_mod || pn_Mod_res)
return 1;
}
+ else if (is_ia32_fDiv(pred)) {
+ if (nr == pn_Quot_res)
+ return 0;
+ else
+ assert(0 && "there should be no more Projs for a fDiv");
+ }
else if (is_ia32_Call(pred)) {
return 0;
}
#include "config.h"
#endif
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <alloc.h>
+#endif
+
#include <stdlib.h>
#include "irprog_t.h"
#include "irop.h"
#include "firm_common_t.h"
#include "irvrfy_t.h"
+#include "irprintf.h"
#include "../bearch.h"
#include "ia32_new_nodes.h"
#include "gen_ia32_regalloc_if.h"
-
+#ifdef obstack_chunk_alloc
+# undef obstack_chunk_alloc
+# define obstack_chunk_alloc xmalloc
+#else
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free free
+#endif
/***********************************************************************************
* _ _ _ __
return NULL;
}
+/**
+ * Returns a string containing the names of all registers within the limited bitset
+ */
+static char *get_limited_regs(const arch_register_req_t *req, char *buf, int max) {
+ bitset_t *bs = bitset_alloca(req->cls->n_regs);
+ char *p = buf;
+ int size = 0;
+ int i, cnt;
+
+ req->limited(NULL, bs);
+
+ for (i = 0; i < req->cls->n_regs; i++) {
+ if (bitset_is_set(bs, i)) {
+ cnt = snprintf(p, max - size, " %s", req->cls->regs[i].name);
+ if (cnt < 0) {
+ fprintf(stderr, "dumper problem, exiting\n");
+ exit(1);
+ }
+
+ p += cnt;
+ size += cnt;
+
+ if (size >= max)
+ break;
+ }
+ }
+
+ return buf;
+}
+
+/**
+ * Dumps the register requirements for either in or out.
+ */
+static void dump_reg_req(FILE *F, ir_node *n, const ia32_register_req_t **reqs, int inout) {
+ char *dir = inout ? "out" : "in";
+ int max = inout ? get_ia32_n_res(n) : get_irn_arity(n);
+ char *buf = alloca(1024);
+ int i;
+
+ memset(buf, 0, 1024);
+
+ if (reqs) {
+ for (i = 0; i < max; i++) {
+ fprintf(F, "%sreq #%d =", dir, i);
+
+ if (reqs[i]->req.type == arch_register_req_type_none) {
+ fprintf(F, " n/a");
+ }
+
+ if (reqs[i]->req.type & arch_register_req_type_normal) {
+ fprintf(F, " %s", reqs[i]->req.cls->name);
+ }
+
+ if (reqs[i]->req.type & arch_register_req_type_limited) {
+ fprintf(F, " %s", get_limited_regs(&reqs[i]->req, buf, 1024));
+ }
+
+ if (reqs[i]->req.type & arch_register_req_type_should_be_same) {
+ ir_fprintf(F, " same as %+F", get_irn_n(n, reqs[i]->pos));
+ }
+
+ if (reqs[i]->req.type & arch_register_req_type_should_be_different) {
+ ir_fprintf(F, " different from %+F", get_irn_n(n, reqs[i]->pos));
+ }
+
+ fprintf(F, "\n");
+ }
+
+ fprintf(F, "\n");
+ }
+ else {
+ fprintf(F, "%sreq = N/A\n", dir);
+ }
+}
+
/**
* Dumper interface for dumping ia32 nodes in vcg.
* @param n the node to dump
* @return 0 on success or != 0 on failure
*/
static int dump_node_ia32(ir_node *n, FILE *F, dump_reason_t reason) {
- const char *name, *p;
- ir_mode *mode = NULL;
- int bad = 0;
- asmop_attr *attr;
- int i;
+ ir_mode *mode = NULL;
+ int bad = 0;
+ int i;
+ ia32_attr_t *attr;
const ia32_register_req_t **reqs;
const arch_register_t **slots;
switch (reason) {
case dump_node_opcode_txt:
- name = get_irn_opname(n);
- fprintf(F, "%s", name);
+ fprintf(F, "%s", get_irn_opname(n));
break;
case dump_node_mode_txt:
mode = NULL;
}
else if (is_ia32_Load(n)) {
- mode = get_irn_mode(get_irn_n(n, 1));
+ mode = get_irn_mode(get_irn_n(n, 0));
}
else if (is_ia32_Store(n)) {
mode = get_irn_mode(get_irn_n(n, 2));
break;
case dump_node_nodeattr_txt:
- name = get_irn_opname(n);
- p = name + strlen(name) - 2;
- if ((p[0] == '_' && p[1] == 'i') || is_ia32_Const(n) || is_ia32_fConst(n)) {
- tarval *tv = get_ia32_Immop_tarval(n);
- if (tv) {
- fprintf_tv(F, tv, 1);
- }
- else {
- fprintf(F, "[SymC &%s]", get_sc_name(get_ia32_old_ir(n)));
- }
+ if (is_ia32_Call(n)) {
+ fprintf(F, "&%s ", get_ia32_sc(n));
}
- else if (is_ia32_Call(n)) {
- ir_node *sc = get_ia32_old_ir(n);
+ else if (get_ia32_cnst(n)) {
+ char *pref = "";
- fprintf(F, "&%s ", get_sc_name(sc));
+ if (get_ia32_sc(n)) {
+ pref = "SymC ";
+ }
+
+ fprintf(F, "[%s%s]", pref, get_ia32_cnst(n));
}
- if (is_ia32_AddrMode(n)) {
- fprintf(F, "[AddrMode] ");
+ if (is_ia32_AddrModeS(n) || is_ia32_AddrModeD(n)) {
+ fprintf(F, "[AM] ");
}
break;
case dump_node_info_txt:
attr = get_ia32_attr(n);
+ fprintf(F, "=== IA32 attr begin ===\n");
/* dump IN requirements */
if (get_irn_arity(n) > 0) {
reqs = get_ia32_in_req_all(n);
-
- if (reqs) {
- for (i = 0; i < get_irn_arity(n); i++) {
- if (reqs[i]->req.type != arch_register_req_type_none) {
- fprintf(F, "inreq[%d]=[%s]\n", i, reqs[i]->req.cls->name);
- }
- else {
- fprintf(F, "inreq[%d]=[none]\n", i);
- }
- }
-
- fprintf(F, "\n");
- }
- else {
- fprintf(F, "NO IN REQS\n");
- }
+ dump_reg_req(F, n, reqs, 0);
}
/* dump OUT requirements */
if (attr->n_res > 0) {
reqs = get_ia32_out_req_all(n);
-
- if (reqs) {
- for (i = 0; i < attr->n_res; i++) {
- if (reqs[i]->req.type != arch_register_req_type_none) {
- fprintf(F, "outreq[%d]=[%s]\n", i, reqs[i]->req.cls->name);
- }
- else {
- fprintf(F, "outreq[%d]=[none]\n", i);
- }
- }
- }
- else {
- fprintf(F, "NO OUT REQS\n");
- }
+ dump_reg_req(F, n, reqs, 1);
}
/* dump assigned registers */
}
}
}
+ fprintf(F, "\n");
+
+ /* dump op type */
+ fprintf(F, "op = ");
+ switch (attr->tp) {
+ case ia32_Normal:
+ fprintf(F, "Normal");
+ break;
+ case ia32_Const:
+ fprintf(F, "Const");
+ break;
+ case ia32_SymConst:
+ fprintf(F, "SymConst");
+ break;
+ case ia32_AddrModeD:
+ fprintf(F, "AM Dest (Load+Store)");
+ break;
+ case ia32_AddrModeS:
+ fprintf(F, "AM Source (Load)");
+ break;
+ }
+ fprintf(F, "\n");
+
+
+ /* dump supported am */
+ fprintf(F, "AM support = ");
+ switch (attr->am_support) {
+ case ia32_am_None:
+ fprintf(F, "none");
+ break;
+ case ia32_am_Source:
+ fprintf(F, "source only (Load)");
+ break;
+ case ia32_am_Dest:
+ fprintf(F, "dest only (Load+Store)");
+ break;
+ case ia32_am_Full:
+ fprintf(F, "full");
+ break;
+ }
+ fprintf(F, "\n");
- /* special for LEA */
- if (is_ia32_Lea(n) || is_ia32_Lea_i(n)) {
- tarval *o = get_ia32_am_offs(n);
- tarval *tv = get_ia32_Immop_tarval(n);
+ /* dump AM offset */
+ fprintf(F, "AM offset = ");
+ if (attr->am_offs) {
+ fprintf(F, "%s", get_ia32_am_offs(n));
+ }
+ else {
+ fprintf(F, "n/a");
+ }
+ fprintf(F, "\n");
- fprintf(F, "LEA ");
- if (o) {
- fprintf_tv(F, o, 0);
- }
+ /* dump AM scale */
+ fprintf(F, "AM scale = %d\n", get_ia32_am_scale(n));
- fprintf(F, "(%s", get_irn_opname(get_irn_n(n, 0)));
+ /* dump pn code */
+ fprintf(F, "pn_code = %d\n", get_ia32_pncode(n));
- if (is_ia32_Lea(n)) {
- fprintf(F, ", %s", get_irn_opname(get_irn_n(n, 1)));
- }
+ /* dump n_res */
+ fprintf(F, "n_res = %d\n", get_ia32_n_res(n));
- if (tv) {
- fprintf(F, ", ");
- fprintf_tv(F, tv, 0);
- }
- fprintf(F, ")\n");
+ /* dump flags */
+ fprintf(F, "flags =");
+ if (attr->flags & arch_irn_flags_dont_spill) {
+ fprintf(F, " unspillable");
+ }
+ if (attr->flags & arch_irn_flags_rematerializable) {
+ fprintf(F, " remat");
+ }
+ if (attr->flags & arch_irn_flags_ignore) {
+ fprintf(F, " ignore");
}
+ fprintf(F, "\n");
+
+ fprintf(F, "=== IA32 attr end ===\n");
+ /* end of: case dump_node_info_txt */
break;
}
* |___/
***************************************************************************************************/
+ static char *copy_str(char *dst, const char *src) {
+ dst = xcalloc(1, strlen(src) + 1);
+ strncpy(dst, src, strlen(src) + 1);
+ return dst;
+ }
+
+ static char *set_cnst_from_tv(char *cnst, tarval *tv) {
+ if (cnst) {
+ free(cnst);
+ }
+
+ cnst = xcalloc(1, 64);
+ assert(tarval_snprintf(cnst, 63, tv));
+ return cnst;
+ }
+
/**
* Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
* Firm was made by people hating const :-(
*/
-asmop_attr *get_ia32_attr(const ir_node *node) {
+ia32_attr_t *get_ia32_attr(const ir_node *node) {
assert(is_ia32_irn(node) && "need ia32 node to get ia32 attributes");
- return (asmop_attr *)get_irn_generic_attr((ir_node *)node);
+ return (ia32_attr_t *)get_irn_generic_attr((ir_node *)node);
}
/**
* Gets the type of an ia32 node.
*/
-asmop_type_t get_ia32_op_type(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ia32_op_type_t get_ia32_op_type(const ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->tp;
}
/**
* Sets the type of an ia32 node.
*/
-void set_ia32_op_type(const ir_node *node, asmop_type_t tp) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->tp = tp;
+void set_ia32_op_type(ir_node *node, ia32_op_type_t tp) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->tp = tp;
}
/**
- * Gets the addr mode type of an ia32 node
+ * Gets the supported addrmode of an ia32 node
*/
-addrmode_type_t get_ia32_am_type(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
- return attr->am_tp;
+ia32_am_type_t get_ia32_am_support(const ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ return attr->am_support;
}
/**
- * Sets the addr mode type of an ia32 node
+ * Sets the supported addrmode of an ia32 node
*/
-void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->am_tp = am_tp;
+void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->am_support = am_tp;
}
/**
- * Gets the addr mode offset.
+ * Joins all offsets to one string with adds.
*/
-tarval *get_ia32_am_offs(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
- return attr->am_offs;
+char *get_ia32_am_offs(const ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ char *res = NULL;
+ int size;
+
+ size = obstack_object_size(attr->am_offs);
+ if (size > 0) {
+ res = xcalloc(1, size + 1);
+ memcpy(res, obstack_base(attr->am_offs), size);
+ }
+
+ res[size] = '\0';
+ return res;
}
/**
- * Sets the offset for addr mode.
+ * Add an offset for addrmode.
*/
-void set_ia32_am_offs(ir_node *node, tarval *am_offs) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->am_offs = am_offs;
+static void extend_ia32_am_offs(ir_node *node, char *offset, char op) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+
+ if (!attr->am_offs) {
+ /* obstack is not initialized */
+ attr->am_offs = xcalloc(1, sizeof(*(attr->am_offs)));
+ obstack_init(attr->am_offs);
+ }
+ else {
+ /* obstack is initialized -> there is already one offset */
+ /* present -> connect the offsets with an add */
+ obstack_printf(attr->am_offs, " %c ", op);
+ }
+
+ obstack_printf(attr->am_offs, "%s", offset);
+}
+
+/**
+ * Add an offset for addrmode.
+ */
+void add_ia32_am_offs(ir_node *node, char *offset) {
+ extend_ia32_am_offs(node, offset, '+');
+}
+
+/**
+ * Sub an offset for addrmode.
+ */
+void sub_ia32_am_offs(ir_node *node, char *offset) {
+ extend_ia32_am_offs(node, offset, '-');
}
/**
* Gets the addr mode const.
*/
-tarval *get_ia32_am_const(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
- return attr->am_const;
+int get_ia32_am_scale(const ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ return attr->am_scale;
}
/**
- * Sets the const for addr mode.
+ * Sets the index register scale for addrmode.
*/
-void set_ia32_am_const(ir_node *node, tarval *am_const) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->am_const = am_const;
+void set_ia32_am_scale(ir_node *node, int scale) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->am_scale = scale;
}
/**
* Return the tarval of an immediate operation or NULL in case of SymConst
*/
tarval *get_ia32_Immop_tarval(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->tv;
}
* Sets the attributes of an immediate operation to the specified tarval
*/
void set_ia32_Immop_tarval(ir_node *node, tarval *tv) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->tv = tv;
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->tv = tv;
+ attr->cnst = set_cnst_from_tv(attr->cnst, attr->tv);
+}
+
+/**
+ * Return the sc attribute.
+ */
+char *get_ia32_sc(const ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ return attr->sc;
}
/**
- * Return the old_ir attribute.
+ * Sets the sc attribute.
*/
-ir_node *get_ia32_old_ir(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
- return attr->old_ir;
+void set_ia32_sc(ir_node *node, char *sc) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->sc = copy_str(attr->sc, sc);
+
+ if (attr->cnst) {
+ free(attr->cnst);
+ }
+ attr->cnst = attr->sc;
}
/**
- * Sets the old_ir attribute.
+ * Gets the string representation of the internal const (tv or symconst)
*/
-void set_ia32_old_ir(ir_node *node, ir_node *old_ir) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->old_ir = old_ir;
+char *get_ia32_cnst(ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ return attr->cnst;
}
/**
* Returns the argument register requirements of an ia32 node.
*/
const ia32_register_req_t **get_ia32_in_req_all(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->in_req;
}
* Returns the result register requirements of an ia32 node.
*/
const ia32_register_req_t **get_ia32_out_req_all(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->out_req;
}
* Returns the argument register requirement at position pos of an ia32 node.
*/
const ia32_register_req_t *get_ia32_in_req(const ir_node *node, int pos) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->in_req[pos];
}
* Returns the result register requirement at position pos of an ia32 node.
*/
const ia32_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->out_req[pos];
}
* Sets the OUT register requirements at position pos.
*/
void set_ia32_req_out(ir_node *node, const ia32_register_req_t *req, int pos) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
attr->out_req[pos] = req;
}
* Sets the IN register requirements at position pos.
*/
void set_ia32_req_in(ir_node *node, const ia32_register_req_t *req, int pos) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
attr->in_req[pos] = req;
}
* Returns the register flag of an ia32 node.
*/
arch_irn_flags_t get_ia32_flags(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->flags;
}
* Sets the register flag of an ia32 node.
*/
void set_ia32_flags(const ir_node *node, arch_irn_flags_t flags) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->flags = flags;
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->flags = flags;
}
/**
* Returns the result register slots of an ia32 node.
*/
const arch_register_t **get_ia32_slots(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->slots;
}
* Returns the name of the OUT register at position pos.
*/
const char *get_ia32_out_reg_name(const ir_node *node, int pos) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
assert(is_ia32_irn(node) && "Not an ia32 node.");
assert(pos < attr->n_res && "Invalid OUT position.");
* Returns the index of the OUT register at position pos within its register class.
*/
int get_ia32_out_regnr(const ir_node *node, int pos) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
assert(is_ia32_irn(node) && "Not an ia32 node.");
assert(pos < attr->n_res && "Invalid OUT position.");
* Returns the OUT register at position pos.
*/
const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
assert(is_ia32_irn(node) && "Not an ia32 node.");
assert(pos < attr->n_res && "Invalid OUT position.");
* Sets the number of results.
*/
void set_ia32_n_res(ir_node *node, int n_res) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->n_res = n_res;
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->n_res = n_res;
}
/**
* Returns the number of results.
*/
int get_ia32_n_res(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->n_res;
}
/**
* Returns the flavour of an ia32 node,
*/
-op_flavour_t get_ia32_flavour(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ia32_op_flavour_t get_ia32_flavour(const ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->op_flav;
}
/**
* Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh.
*/
-void set_ia32_flavour(ir_node *node, op_flavour_t op_flav) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->op_flav = op_flav;
+void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->op_flav = op_flav;
}
/**
* Returns the projnum code.
*/
long get_ia32_pncode(const ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
return attr->pn_code;
}
* Sets the projnum code
*/
void set_ia32_pncode(ir_node *node, long code) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->pn_code = code;
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->pn_code = code;
}
* Gets the type of an ia32_Const.
*/
unsigned get_ia32_Const_type(ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to get type");
* Sets the type of an ia32_Const.
*/
void set_ia32_Const_type(ir_node *node, int type) {
- asmop_attr *attr = get_ia32_attr(node);
+ ia32_attr_t *attr = get_ia32_attr(node);
assert((is_ia32_Const(node) || is_ia32_fConst(node)) && "Need ia32_Const to set type");
- assert((type == asmop_Const || type == asmop_SymConst) && "Unsupported ia32_Const type");
+ assert((type == ia32_Const || type == ia32_SymConst) && "Unsupported ia32_Const type");
attr->tp = type;
}
* Copy the attributes from an ia32_Const to an Immop (Add_i, Sub_i, ...) node
*/
void set_ia32_Immop_attr(ir_node *node, ir_node *cnst) {
- asmop_attr *na = get_ia32_attr(node);
- asmop_attr *ca = get_ia32_attr(cnst);
+ ia32_attr_t *na = get_ia32_attr(node);
+ ia32_attr_t *ca = get_ia32_attr(cnst);
assert((is_ia32_Const(cnst) || is_ia32_fConst(cnst)) && "Need ia32_Const to set Immop attr");
na->tp = ca->tp;
na->tv = ca->tv;
- if (ca->old_ir) {
- na->old_ir = xcalloc(1, sizeof(*(ca->old_ir)));
- memcpy(na->old_ir, ca->old_ir, sizeof(*(ca->old_ir)));
+ if (ca->sc) {
+ na->sc = copy_str(na->sc, ca->sc);
}
else {
- na->old_ir = NULL;
+ na->sc = NULL;
}
}
* Copy the attributes from a Const to an ia32_Const
*/
void set_ia32_Const_attr(ir_node *ia32_cnst, ir_node *cnst) {
- asmop_attr *attr = get_ia32_attr(ia32_cnst);
+ ia32_attr_t *attr = get_ia32_attr(ia32_cnst);
assert((is_ia32_Const(ia32_cnst) || is_ia32_fConst(ia32_cnst)) && "Need ia32_Const to set Const attr");
switch (get_irn_opcode(cnst)) {
case iro_Const:
- attr->tp = asmop_Const;
- attr->tv = get_Const_tarval(cnst);
+ attr->tp = ia32_Const;
+ attr->tv = get_Const_tarval(cnst);
+ attr->cnst = set_cnst_from_tv(attr->cnst, attr->tv);
break;
case iro_SymConst:
- attr->tp = asmop_SymConst;
- attr->tv = NULL;
- attr->old_ir = xcalloc(1, sizeof(*cnst));
- memcpy(attr->old_ir, cnst, sizeof(*cnst));
+ attr->tp = ia32_SymConst;
+ attr->tv = NULL;
+ attr->sc = copy_str(attr->sc, get_sc_name(cnst));
+ attr->cnst = attr->sc;
break;
case iro_Unknown:
assert(0 && "Unknown Const NYI");
}
/**
- * Sets the AddrMode attribute
+ * Sets the AddrMode(S|D) attribute
+ */
+void set_ia32_AddrMode(ir_node *node, char direction) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+
+ switch (direction) {
+ case 'D':
+ attr->tp = ia32_AddrModeD;
+ break;
+ case 'S':
+ attr->tp = ia32_AddrModeS;
+ break;
+ default:
+ assert(0 && "wrong AM type");
+ }
+}
+
+/**
+ * Returns whether or not the node is an AddrModeS node.
*/
-void set_ia32_AddrMode(ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
- attr->tp = asmop_AddrMode;
+int is_ia32_AddrModeS(ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ return (attr->tp == ia32_AddrModeS);
}
/**
- * Returns whether or not the node is an AddrMode node.
+ * Returns whether or not the node is an AddrModeD node.
*/
-int is_ia32_AddrMode(ir_node *node) {
- asmop_attr *attr = get_ia32_attr(node);
- return (attr->tp == asmop_AddrMode);
+int is_ia32_AddrModeD(ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ return (attr->tp == ia32_AddrModeD);
}
/**
* Returns the attributes of an ia32 node.
*/
-asmop_attr *get_ia32_attr(const ir_node *node);
+ia32_attr_t *get_ia32_attr(const ir_node *node);
/**
* Gets the type of an ia32 node.
*/
-asmop_type_t get_ia32_op_type(const ir_node *node);
+ia32_op_type_t get_ia32_op_type(const ir_node *node);
/**
* Sets the type of an ia32 node.
*/
-void set_ia32_op_type(const ir_node *node, asmop_type_t tp);
+void set_ia32_op_type(ir_node *node, ia32_op_type_t tp);
/**
- * Gets the addr mode type of an ia32 node
+ * Gets the supported addrmode of an ia32 node
*/
-addrmode_type_t get_ia32_am_type(const ir_node *node);
+ia32_am_type_t get_ia32_am_support(const ir_node *node);
/**
- * Sets the addr mode type of an ia32 node
+ * Sets the supported addrmode of an ia32 node
*/
-void set_ia32_am_type(const ir_node *node, addrmode_type_t am_tp);
+void set_ia32_am_support(ir_node *node, ia32_am_type_t am_tp);
/**
- * Gets the addr mode offset.
+ * Gets the joined addrmode offset.
*/
-tarval *get_ia32_am_offs(const ir_node *node);
+char *get_ia32_am_offs(const ir_node *node);
/**
- * Sets the offset for addr mode.
+ * Adds an offset for addrmode.
*/
-void set_ia32_am_offs(ir_node *node, tarval *am_offs);
+void add_ia32_am_offs(ir_node *node, char *offset);
+
+/**
+ * Subs an offset for addrmode.
+ */
+void sub_ia32_am_offs(ir_node *node, char *offset);
/**
* Gets the addr mode const.
*/
-tarval *get_ia32_am_const(const ir_node *node);
+int get_ia32_am_scale(const ir_node *node);
/**
* Sets the const for addr mode.
*/
-void set_ia32_am_const(ir_node *node, tarval *am_const);
+void set_ia32_am_scale(ir_node *node, int scale);
/**
* Return the tarval of an immediate operation or NULL in case of SymConst
void set_ia32_Immop_tarval(ir_node *node, tarval *tv);
/**
- * Return the old_ir attribute.
+ * Return the sc attribute.
+ */
+char *get_ia32_sc(const ir_node *node);
+
+/**
+ * Sets the sc attribute.
*/
-ir_node *get_ia32_old_ir(const ir_node *node);
+void set_ia32_sc(ir_node *node, char *sc);
/**
- * Sets the old_ir attribute.
+ * Gets the string representation of the internal const (tv or symconst)
*/
-void set_ia32_old_ir(ir_node *node, ir_node *old_ir);
+char *get_ia32_cnst(ir_node *node);
/**
* Returns the argument register requirements of an ia32 node.
/**
* Returns the flavour of an ia32 node,
*/
-op_flavour_t get_ia32_flavour(const ir_node *node);
+ia32_op_flavour_t get_ia32_flavour(const ir_node *node);
/**
* Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh.
*/
-void set_ia32_flavour(ir_node *node, op_flavour_t op_flav);
+void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav);
/**
* Returns the projnum code.
/**
* Sets the AddrMode attribute
+ * @param direction The "direction" of AM ('S' source or 'D' destination)
*/
-void set_ia32_AddrMode(ir_node *node);
+void set_ia32_AddrMode(ir_node *node, char direction);
/**
- * Returns whether or not the node is an AddrMode node.
+ * Returns whether or not the node is an AddrModeS node.
*/
-int is_ia32_AddrMode(ir_node *node);
+int is_ia32_AddrModeS(ir_node *node);
/**
- * Checks whether or not an ir_node is an ia32 node
+ * Returns whether or not the node is an AddrModeD node.
*/
-int is_ia32_irn(const ir_node *node);
+int is_ia32_AddrModeD(ir_node *node);
/* Include the generated headers */
#include "gen_ia32_new_nodes.h"
#ifndef _IA32_NODES_ATTR_H_
#define _IA32_NODES_ATTR_H_
+#include <obstack.h>
+
#include "firm_types.h"
#include "../bearch.h"
-typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod, flavour_Mul, flavour_Mulh } op_flavour_t;
+typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod, flavour_Mul, flavour_Mulh } ia32_op_flavour_t;
typedef enum { pn_EAX, pn_EDX } pn_ia32_Register;
-typedef enum { asmop_Normal, asmop_Const, asmop_SymConst, asmop_AddrMode } asmop_type_t;
+typedef enum { ia32_Normal, ia32_Const, ia32_SymConst, ia32_AddrModeD, ia32_AddrModeS } ia32_op_type_t;
typedef enum {
- am_Reg = 1, /**<< (%reg) */
- am_OffsReg, /**<< o(%reg) */
- am_RegReg, /**<< (%reg, %reg) */
- am_RegConst, /**<< ( , %reg, const) */
- am_OffsRegConst, /**<< o( , %reg, const) */
- am_OffsRegReg, /**<< o(%reg, %reg) */
- am_RegRegConst, /**<< (%reg, %reg, const) */
- am_OffsRegRegConst /**<< o(%reg, %reg, const) */
-} addrmode_type_t;
+ ia32_am_None = 0, /**<< no addrmode support */
+ ia32_am_Dest = 1, /**<< addrmode for destination only */
+ ia32_am_Source = 2, /**<< addrmode for source only */
+ ia32_am_Full = 3 /**<< full addmode support */
+} ia32_am_type_t;
typedef struct _ia32_register_req_t {
const arch_register_req_t req;
int pos; /**<< in case of "should be same/different" we need to remember the pos to get the irn */
} ia32_register_req_t;
-typedef struct _ia32_asmop_attr {
- asmop_type_t tp; /**<< ia32 node type */
- addrmode_type_t am_tp; /**<< addr mode type */
+typedef struct _ia32_attr_t {
+ ia32_op_type_t tp; /**<< ia32 node type */
+ ia32_am_type_t am_support; /**<< indicates addrmode type supported by this node */
- tarval *am_offs; /**<< offset for AddrMode */
- tarval *am_const; /**<< shift const for AddrMode */
+ struct obstack *am_offs; /**<< offsets for AddrMode */
+ int am_scale; /**<< addrmode scale for index register */
- tarval *tv; /**<< tarval for immediate operations */
- ir_node *old_ir; /**<< old ir node to avoid duplicating information (symconst in case of asmop_SymConst) */
+ tarval *tv; /**<< tarval for immediate operations */
+ char *sc; /**<< symconst name */
+ char *cnst; /**<< points to the string representation of the constant value (either tv or sc) */
- op_flavour_t op_flav; /**<< flavour of an op (flavour_Div/Mod/DivMod/Mul/Mulh) */
- long pn_code; /**<< projnum "types" (e.g. indicate compare operators and argument numbers) */
- long n_res; /**<< number of results */
- arch_irn_flags_t flags; /**<< indicating if spillable and/or rematerializeable */
+ ia32_op_flavour_t op_flav; /**<< flavour of an op (flavour_Div/Mod/DivMod/Mul/Mulh) */
+ long pn_code; /**<< projnum "types" (e.g. indicate compare operators and argument numbers) */
+ long n_res; /**<< number of results */
+ arch_irn_flags_t flags; /**<< indicating if spillable and/or rematerializeable */
const ia32_register_req_t **in_req; /**<< register requirements for arguments */
const ia32_register_req_t **out_req; /**<< register requirements for results */
const arch_register_t **slots; /**<< register slots for assigned registers */
-} asmop_attr;
+} ia32_attr_t;
#endif /* _IA32_NODES_ATTR_H_ */
# %nodes = (
#
# <op-name> => {
-# "op_flags" => "N|L|C|X|I|F|Y|H|c|K",
-# "arity" => "0|1|2|3|variable|dynamic|all",
-# "state" => "floats|pinned",
-# "args" => [
-# { "type" => "type 1", "name" => "name 1" },
-# { "type" => "type 2", "name" => "name 2" },
-# ...
-# ],
-# "comment" => "any comment for constructor",
+# "op_flags" => "N|L|C|X|I|F|Y|H|c|K",
+# "irn_flags" => "R|N|I"
+# "arity" => "0|1|2|3 ... |variable|dynamic|all",
+# "state" => "floats|pinned",
+# "args" => [
+# { "type" => "type 1", "name" => "name 1" },
+# { "type" => "type 2", "name" => "name 2" },
+# ...
+# ],
+# "comment" => "any comment for constructor",
+# "emit" => "emit code with templates",
# "rd_constructor" => "c source code which constructs an ir_node"
# },
#
#
# ); # close the %nodes initializer
+# op_flags: flags for the operation, OPTIONAL (default is "N")
# the op_flags correspond to the firm irop_flags:
# N irop_flag_none
# L irop_flag_labeled
# c irop_flag_constlike
# K irop_flag_keep
#
-# op_flags: flags for the operation, OPTIONAL (default is "N")
+# irn_flags: special node flags, OPTIONAL (default is 0)
+# following irn_flags are supported:
+# R rematerializeable
+# N not spillable
+# I ignore for register allocation
#
# state: state of the operation, OPTIONAL (default is "pinned")
#
# caller save registers and in the correct order, otherwise it will break
# the magic!
%reg_classes = (
- "general_purpose" => [
- { "name" => "eax", "type" => 2 },
- { "name" => "edx", "type" => 2 },
- { "name" => "ebx", "type" => 3 },
- { "name" => "ecx", "type" => 2 },
- { "name" => "esi", "type" => 3 },
- { "name" => "edi", "type" => 3 },
- { "name" => "ebp", "type" => 3 },
- { "name" => "esp", "type" => 4 } # we don't want esp to be assigned
- ],
- "floating_point" => [
- { "name" => "xmm0", "type" => 2 },
- { "name" => "xmm1", "type" => 2 },
- { "name" => "xmm2", "type" => 2 },
- { "name" => "xmm3", "type" => 2 },
- { "name" => "xmm4", "type" => 2 },
- { "name" => "xmm5", "type" => 2 },
- { "name" => "xmm6", "type" => 2 },
- { "name" => "xmm7", "type" => 2 },
- ]
+ "gp" => [
+ { "name" => "eax", "type" => 2 },
+ { "name" => "edx", "type" => 2 },
+ { "name" => "ebx", "type" => 3 },
+ { "name" => "ecx", "type" => 2 },
+ { "name" => "esi", "type" => 3 },
+ { "name" => "edi", "type" => 3 },
+ { "name" => "ebp", "type" => 3 },
+ { "name" => "esp", "type" => 4 }, # we don't want esp to be assigned
+ { "name" => "xxx", "type" => 4 } # we need a dummy register for NoReg and Unknown nodes
+ ],
+ "fp" => [
+ { "name" => "xmm0", "type" => 2 },
+ { "name" => "xmm1", "type" => 2 },
+ { "name" => "xmm2", "type" => 2 },
+ { "name" => "xmm3", "type" => 2 },
+ { "name" => "xmm4", "type" => 2 },
+ { "name" => "xmm5", "type" => 2 },
+ { "name" => "xmm6", "type" => 2 },
+ { "name" => "xmm7", "type" => 2 }
+ ]
); # %reg_classes
#--------------------------------------------------#
# commutative operations
-"Add" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. addl %S2, %D1\t\t\t/* Add(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
+# NOTE:
+# All nodes supporting Addressmode have 5 INs:
+# 1 - base r1 == NoReg in case of no AM or no base
+# 2 - index r2 == NoReg in case of no AM or no index
+# 3 - op1 r3 == always present
+# 4 - op2 r4 == NoReg in case of immediate operation
+# 5 - mem NoMem in case of no AM otherwise it takes the mem from the Load
-"Add_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Add: Add(a, const) = Add(const, a) = a + const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. addl %C, %D1\t\t\t/* Add(%C, %S1) -> %D1, (%A1, const) */'
+"Add" => {
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. add %ia32_emit_binop\t\t\t/* Add(%A1, %A2) -> %D1 */'
},
"Mul" => {
- "op_flags" => "C",
- "arity" => 2,
- "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "eax in_r1", "edx in_r2" ] },
- "emit" =>
-' if (mode_is_signed(get_irn_mode(n))) {
-4. imull %S2\t\t\t/* signed Mul(%S1, %S2) -> %D1, (%A1, %A2) */
- }
- else {
-4. mull %S2\t\t\t/* unsigned Mul(%S1, %S2) -> %D1, (%A1, %A2) */
- }
-'
+ "op_flags" => "C",
+ "irn_flags" => "A",
+ "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. imul %ia32_emit_binop\t\t\t/* Mul(%A1, %A2) -> %D1 */'
},
-"Mul_i" => {
- "state" => "pinned",
- "arity" => 1,
- "comment" => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "eax in_r1", "edx" ] },
- "emit" =>
-' if (mode_is_signed(get_irn_mode(n))) {
-4. imull %C\t\t\t/* signed Mul(%C, %S1) -> %D1, (%A1, const) */
- }
- else {
-4. mull %C\t\t\t/* unsigned Mul(%C, %S1) -> %D1, (%A1, const) */
- }
-'
+# Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX
+"Mulh" => {
+ "op_flags" => "C",
+ "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r2" ] },
+ "emit" => '. imul %ia32_emit_unop\t\t\t/* Mulh(%A1, %A2) -> %D1 */ '
},
"And" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct And: And(a, b) = And(b, a) = a AND b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. andl %S2, %D1\t\t\t/* And(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"And_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct And: And(a, const) = And(const, a) = a AND const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. andl %C, %D1\t\t\t/* And(%C, %S1) -> %D1, (%A1, const) */'
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct And: And(a, b) = And(b, a) = a AND b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. and %ia32_emit_binop\t\t\t/* And(%A1, %A2) -> %D1 */'
},
"Or" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. orl %S2, %D1\t\t\t/* Or(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Or_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Or: Or(a, const) = Or(const, a) = a OR const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. orl %C, %D1\t\t\t/* Or(%C, %S1) -> %D1, (%A1, const) */'
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. or %ia32_emit_binop\t\t\t/* Or(%A1, %A2) -> %D1 */'
},
"Eor" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. xorl %S2, %D1\t\t\t/* Xor(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Eor_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. xorl %C, %D1\t\t\t/* Xor(%C, %S1) -> %D1, (%A1, const) */'
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. xor %ia32_emit_binop\t\t\t/* Xor(%A1, %A2) -> %D1 */'
},
"Max" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" =>
-'2. cmpl %S2, %S1\t\t\t/* prepare Max (%S1 should be %D1), (%A1, %A2) */
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
+ "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
+ "emit" =>
+'2. cmp %S1, %S2\t\t\t/* prepare Max (%S1 - %S2), (%A1, %A2) */
if (mode_is_signed(get_irn_mode(n))) {
-4. cmovl %S2, %D1\t\t\t/* %S1 is less %S2 */
+4. cmovl %D1, %S2\t\t\t/* %S1 is less %S2 */
}
else {
-4. cmovb %S2, %D1\t\t\t/* %S1 is below %S2 */
+4. cmovb %D1, %S2\t\t\t/* %S1 is below %S2 */
}
'
},
"Min" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" =>
-'2. cmpl %S2, %S1\t\t\t/* prepare Min (%S1 should be %D1), (%A1, %A2) */
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b",
+ "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
+ "emit" =>
+'2. cmp %S1, %S2\t\t\t/* prepare Min (%S1 - %S2), (%A1, %A2) */
if (mode_is_signed(get_irn_mode(n))) {
-2. cmovg %S2, %D1\t\t\t/* %S1 is greater %S2 */
+2. cmovg %D1, %S2\t\t\t/* %S1 is greater %S2 */
}
else {
-2. cmova %S2, %D1\t\t\t/* %S1 is above %S2 */
+2. cmova %D1, %S2, %D1\t\t\t/* %S1 is above %S2 */
}
'
},
# not commutative operations
"Sub" => {
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Sub: Sub(a, b) = a - b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. subl %S2, %D1\t\t\t/* Sub(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Sub_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Sub: Sub(a, const) = a - const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. subl %C, %D1\t\t\t/* Sub(%S1, %C) -> %D1, (%A1, const) */'
+ "irn_flags" => "R",
+ "comment" => "construct Sub: Sub(a, b) = a - b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. sub %ia32_emit_binop\t\t\t/* Sub(%A1, %A2) -> %D1 */'
},
"DivMod" => {
- "op_flags" => "F|L",
- "state" => "exc_pinned",
- "arity" => 4,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose", "general_purpose", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
- "emit" =>
+ "op_flags" => "F|L",
+ "state" => "exc_pinned",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
+ "emit" =>
' if (mode_is_signed(get_irn_mode(n))) {
-4. idivl %S2\t\t\t/* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
+4. idiv %S2\t\t\t/* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
}
else {
-4. divl %S2\t\t\t/* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
+4. div %S2\t\t\t/* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
}
'
},
"Shl" => {
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Shl: Shl(a, b) = a << b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. shll %S2, %D1\t\t\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Shl_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Shl: Shl(a, const) = a << const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. shll %C, %D1\t\t\t/* Shl(%S1, %C) -> %D1, (%A1, const) */'
+ "irn_flags" => "R",
+ "comment" => "construct Shl: Shl(a, b) = a << b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. shl %ia32_emit_binop\t\t\t/* Shl(%A1, %A2) -> %D1 */'
},
"Shr" => {
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Shr: Shr(a, b) = a >> b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. shrl %S2, %D1\t\t\t/* Shr(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Shr_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Shr: Shr(a, const) = a >> const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. shrl %C, %D1\t\t\t/* Shr(%S1, %C) -> %D1, (%A1, const) */'
+ "irn_flags" => "R",
+ "comment" => "construct Shr: Shr(a, b) = a >> b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. shr %ia32_emit_binop\t\t\t/* Shr(%A1, %A2) -> %D1 */'
},
"Shrs" => {
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Shrs: Shrs(a, b) = a >> b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. sarl %S2, %D1\t\t\t/* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */'
-},
-
-"Shrs_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Shrs: Shrs(a, const) = a >> const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. sarl %C, %D1\t\t\t/* Shrs(%S1, %C) -> %D1, (%A1, const) */'
+ "irn_flags" => "R",
+ "comment" => "construct Shrs: Shrs(a, b) = a >> b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. sar %ia32_emit_binop\t\t\t/* Shrs(%A1, %A2) -> %D1 */'
},
"RotR" => {
- "arity" => 2,
- "remat" => 1,
+ "irn_flags" => "R",
"comment" => "construct RotR: RotR(a, b) = a ROTR b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. rorl %S2, %D1\t\t\t/* RotR(%S1, %S2) -> %D1, (%A1, %A2) */'
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. ror %ia32_emit_binop\t\t\t/* RotR(%A1, %A2) -> %D1 */'
},
"RotL" => {
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct RotL: RotL(a, b) = a ROTL b",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. roll %S2, %D1\t\t\t/* RotL(%S1, %S2) -> %D1, (%A1, %A2) */'
+ "irn_flags" => "R",
+ "comment" => "construct RotL: RotL(a, b) = a ROTL b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. rol %ia32_emit_binop\t\t\t/* RotL(%A1, %A2) -> %D1 */'
},
-"RotL_i" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct RotL: RotL(a, const) = a ROTL const",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. roll %C, %D1\t\t\t/* RotL(%S1, %C) -> %D1, (%A1, const) */'
-},
+# unary operations
"Minus" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Minus: Minus(a) = -a",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. negl %D1\t\t\t/* Neg(%S1) -> %D1, (%A1) */'
+ "irn_flags" => "R",
+ "comment" => "construct Minus: Minus(a) = -a",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. neg %ia32_emit_unop\t\t\t/* Neg(%A1) -> %D1, (%A1) */'
},
"Inc" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Increment: Inc(a) = a++",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. incl %D1\t\t\t/* Inc(%S1) -> %D1, (%A1) */'
+ "irn_flags" => "R",
+ "comment" => "construct Increment: Inc(a) = a++",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. inc %ia32_emit_unop\t\t\t/* Inc(%S1) -> %D1, (%A1) */'
},
"Dec" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Decrement: Dec(a) = a--",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. decl %D1\t\t\t/* Dec(%S1) -> %D1, (%A1) */'
+ "irn_flags" => "R",
+ "comment" => "construct Decrement: Dec(a) = a--",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. dec %ia32_emit_unop\t\t\t/* Dec(%S1) -> %D1, (%A1) */'
},
"Not" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Not: Not(a) = !a",
- "check_inout" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
- "emit" => '. notl %D1\t\t\t/* Not(%S1) -> %D1, (%A1) */'
+ "irn_flags" => "R",
+ "comment" => "construct Not: Not(a) = !a",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. not %ia32_emit_unop\t\t\t/* Not(%S1) -> %D1, (%A1) */'
},
# other operations
"Conv" => {
"arity" => 1,
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "in_r1" ] },
+ "reg_req" => { "in" => [ "gp" ], "out" => [ "in_r1" ] },
"comment" => "construct Conv: Conv(a) = (conv)a"
},
"CondJmp" => {
- "op_flags" => "C|L|X|Y",
- "arity" => 2,
- "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "none" ] },
-},
-
-"CondJmp_i" => {
- "op_flags" => "L|X|Y",
- "arity" => 1,
- "comment" => "construct conditional jump: CMP A, const && JMPxx LABEL",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "none", "none" ] },
+ "op_flags" => "C|L|X|Y",
+ "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "none", "none" ] },
},
"SwitchJmp" => {
- "op_flags" => "L|X|Y",
- "arity" => 1,
- "comment" => "construct switch",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "none" ] },
+ "op_flags" => "L|X|Y",
+ "comment" => "construct switch",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
},
"Const" => {
- "op_flags" => "c",
- "arity" => "0",
- "remat" => 1,
- "comment" => "represents an integer constant",
- "reg_req" => { "out" => [ "general_purpose" ] },
- "emit" => '. movl %C, %D1\t\t\t/* Mov Const into register */',
- "cmp_attr" =>
+ "op_flags" => "c",
+ "irn_flags" => "R",
+ "comment" => "represents an integer constant",
+ "reg_req" => { "out" => [ "gp" ] },
+ "emit" => '. mov %D1, %C\t\t\t/* Mov Const into register */',
+ "cmp_attr" =>
'
if (attr_a->tp == attr_b->tp) {
- if (attr_a->tp == asmop_SymConst) {
- if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+ if (attr_a->tp == ia32_SymConst) {
+ if (attr_a->sc == NULL || attr_b->sc == NULL)
return 1;
else
- return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
+ return strcmp(attr_a->sc, attr_b->sc);
}
else {
- if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+ if (attr_a->tv == NULL || attr_b->tv == NULL)
return 1;
if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
'
},
-"Cltd" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "construct Cltd: sign extend EAX -> EDX:EAX",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "eax in_r1", "edx" ] },
- "emit" => '. cltd\t\t\t/* sign extend EAX -> EDX:EAX, (%A1) */'
+"Cdq" => {
+ "irn_flags" => "R",
+ "comment" => "construct CDQ: sign extend EAX -> EDX:EAX",
+ "reg_req" => { "in" => [ "gp" ], "out" => [ "eax in_r1", "edx" ] },
+ "emit" => '. cdq\t\t\t/* sign extend EAX -> EDX:EAX, (%A1) */'
},
# Load / Store
"Load" => {
- "op_flags" => "L|F",
- "state" => "exc_pinned",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
- "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] },
- "emit" => '. movl %O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1, (%A1) */'
+ "op_flags" => "L|F",
+ "irn_flags" => "R",
+ "state" => "exc_pinned",
+ "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+ "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp" ] },
+ "emit" => '. mov %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */'
},
"Store" => {
- "op_flags" => "L|F",
- "state" => "exc_pinned",
- "arity" => 3,
- "remat" => 1,
- "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] },
- "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */'
+ "op_flags" => "L|F",
+ "state" => "exc_pinned",
+ "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ] },
+ "emit" => '. mov %ia32_emit_am, %S3\t\t\t/* Store(%A2) -> (%A1) */'
},
"Lea" => {
- "arity" => 2,
- "comment" => "construct Lea: Lea(a,b) = lea offs(a,b,const) | res = a + b * const + offs with const = 0,1,2,4,8",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. leal %O(%S1, %S2, %C), %D1\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */'
-},
-
-"Lea_i" => {
- "arity" => 1,
- "comment" => "construct Lea: Lea(a) = lea offs(a) | res = a + offs",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
- "emit" => '. leal %C(%S1), %D1\t\t\t/* %D1 = %S1 + %C, (%A1)*/'
+ "irn_flags" => "R",
+ "comment" => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8",
+ "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
+ "emit" => '. lea %D1, %ia32_emit_am\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */'
},
"StackParam" => {
"arity" => 1,
"remat" => 1,
"comment" => "constructs a Stack Parameter to retrieve a parameter from Stack",
- "reg_req" => { "in" => [ "none" ], "out" => [ "general_purpose" ] },
+ "reg_req" => { "in" => [ "none" ], "out" => [ "gp" ] },
"cmp_attr" =>
'
return (attr_a->pn_code != attr_b->pn_code);
"StackArg" => {
"arity" => 2,
"comment" => "constructs a Stack Argument to pass an argument on Stack",
- "reg_req" => { "in" => [ "none", "general_purpose" ], "out" => [ "none" ] },
+ "reg_req" => { "in" => [ "none", "gp" ], "out" => [ "none" ] },
"cmp_attr" =>
'
return (attr_a->pn_code != attr_b->pn_code);
# commutative operations
"fAdd" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "check_inout" => 1,
- "comment" => "construct SSE Add: Add(a, b) = Add(b, a) = a + b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
- "emit" => '. add%M %S2, %D1\t\t\t/* SSE Add(%S1, %S2) -> %D1 */'
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct SSE Add: Add(a, b) = Add(b, a) = a + b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. adds%M %ia32_emit_binop\t\t\t/* SSE Add(%A1, %A2) -> %D1 */'
},
"fMul" => {
- "op_flags" => "C",
- "arity" => 2,
- "check_inout" => 1,
- "comment" => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
- "emit" =>'. muls%M %S2, %D1\t\t\t/* SSE Mul(%S1, %S2) -> %D1 */'
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. muls%M %ia32_emit_binop\t\t\t/* SSE Mul(%A1, %A2) -> %D1 */'
},
"fMax" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "check_inout" => 1,
- "comment" => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
- "emit" =>'. maxs%M %S2, %D1\t\t\t/* SSE Max(%S1, %S2) -> %D1 */'
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. maxs%M %ia32_emit_binop\t\t\t/* SSE Max(%A1, %A2) -> %D1 */'
},
"fMin" => {
- "op_flags" => "C",
- "arity" => 2,
- "remat" => 1,
- "check_inout" => 1,
- "comment" => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
- "emit" =>'. mins%M %S2, %D1\t\t\t/* SSE Min(%S1, %S2) -> %D1 */'
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. mins%M %ia32_emit_binop\t\t\t/* SSE Min(%A1, %A2) -> %D1 */'
+},
+
+"fAnd" => {
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct SSE And: And(a, b) = a AND b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. andp%M %ia32_emit_binop\t\t\t/* SSE And(%A3, %A4) -> %D1 */'
+},
+
+"fOr" => {
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct SSE Or: Or(a, b) = a OR b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. orp%M %ia32_emit_binop\t\t\t/* SSE Or(%A3, %A4) -> %D1 */'
+},
+
+"fEor" => {
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "comment" => "construct SSE Eor: Eor(a, b) = a XOR b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. xorp%M %ia32_emit_binop\t\t\t/* SSE Xor(%A3, %A4) -> %D1 */'
},
# not commutative operations
"fSub" => {
- "arity" => 2,
- "remat" => 1,
- "check_inout" => 1,
- "comment" => "construct SSE Sub: Sub(a, b) = a - b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
- "emit" => '. subs%M %S2, %D1\t\t\t/* SSE Sub(%S1, %S2) -> %D1 */'
+ "irn_flags" => "R",
+ "comment" => "construct SSE Sub: Sub(a, b) = a - b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. subs%M %ia32_emit_binop\t\t\t/* SSE Sub(%A1, %A2) -> %D1 */'
},
"fDiv" => {
- "arity" => 2,
- "remat" => 1,
- "check_inout" => 1,
- "comment" => "construct SSE Div: Div(a, b) = a / b",
- "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_r1" ] },
- "emit" => '. divs%M %S2, %D1\t\t\t/* SSE Div(%S1, %S2) -> %D1 */'
-},
-
-"fMinus" => {
- "arity" => 1,
- "remat" => 1,
- "check_inout" => 1,
- "comment" => "construct SSE Minus: Minus(a) = -a",
- "reg_req" => { "in" => [ "floating_point" ], "out" => [ "in_r1" ] },
- "emit" => '. xorp%M c %D1\t\t\t/* SSE Minus(%S1) -> %D1 */'
+ "irn_flags" => "R",
+ "comment" => "construct SSE Div: Div(a, b) = a / b",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "in_r1" ] },
+ "emit" => '. divs%M %ia32_emit_binop\t\t\t/* SSE Div(%A1, %A2) -> %D1 */'
},
# other operations
"fConv" => {
"arity" => 1,
- "reg_req" => { "in" => [ "floating_point" ], "out" => [ "general_purpose" ] },
+ "reg_req" => { "in" => [ "fp" ], "out" => [ "gp" ] },
"comment" => "construct Conv: Conv(a) = (conv)a"
},
"fCondJmp" => {
- "op_flags" => "C|L|X|Y",
- "arity" => 2,
- "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL",
- "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "none" ] },
+ "op_flags" => "C|L|X|Y",
+ "comment" => "construct conditional jump: UCOMIS A, B && JMPxx LABEL",
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "fp", "none" ], "out" => [ "none", "none" ] },
},
"fConst" => {
- "op_flags" => "c",
- "arity" => "0",
- "remat" => 1,
- "comment" => "represents a SSE constant",
- "reg_req" => { "out" => [ "floating_point" ] },
- "emit" => '. mov%M %C, %D1\t\t\t/* Mov fConst into register */',
- "cmp_attr" =>
+ "op_flags" => "c",
+ "irn_flags" => "R",
+ "comment" => "represents a SSE constant",
+ "reg_req" => { "out" => [ "fp" ] },
+ "emit" => '. mov%M %D1, %C\t\t\t/* Load fConst into register */',
+ "cmp_attr" =>
'
if (attr_a->tp == attr_b->tp) {
- if (attr_a->tp == asmop_SymConst) {
- if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+ if (attr_a->tp == ia32_SymConst) {
+ if (attr_a->sc == NULL || attr_b->sc == NULL)
return 1;
else
- return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
+ return strcmp(attr_a->sc, attr_b->sc);
}
else {
- if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
+ if (attr_a->tv == NULL || attr_b->tv == NULL)
return 1;
if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
# Load / Store
"fLoad" => {
- "op_flags" => "L|F",
- "state" => "exc_pinned",
- "arity" => 2,
- "remat" => 1,
- "comment" => "construct SSE Load: Load(ptr, mem) = LD ptr",
- "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "floating_point" ] },
- "emit" => '. movl O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1 */'
+ "op_flags" => "L|F",
+ "irn_flags" => "R",
+ "state" => "exc_pinned",
+ "comment" => "construct SSE Load: Load(ptr, mem) = LD ptr",
+ "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "fp" ] },
+ "emit" => '. movs%M %D1, %ia32_emit_am\t\t\t/* Load((%A1)) -> %D1 */'
},
"fStore" => {
"op_flags" => "L|F",
"state" => "exc_pinned",
- "arity" => 3,
- "remat" => 1,
"comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val",
- "reg_req" => { "in" => [ "general_purpose", "floating_point", "none" ] },
- "emit" => '. movl %S2, O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */'
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ] },
+ "emit" => '. movs%M %ia32_emit_am, %S3\t\t\t/* Store(%S3) -> (%A1) */'
},
"fStackParam" => {
"arity" => 1,
"remat" => 1,
"comment" => "constructs a Stack Parameter to retrieve a SSE parameter from Stack",
- "reg_req" => { "in" => [ "none" ], "out" => [ "floating_point" ] },
+ "reg_req" => { "in" => [ "none" ], "out" => [ "fp" ] },
"cmp_attr" =>
'
return (attr_a->pn_code != attr_b->pn_code);
"fStackArg" => {
"arity" => 2,
"comment" => "constructs a Stack Argument to pass an argument on Stack",
- "reg_req" => { "in" => [ "none", "floating_point" ], "out" => [ "none" ] },
+ "reg_req" => { "in" => [ "none", "fp" ], "out" => [ "none" ] },
"cmp_attr" =>
'
return (attr_a->pn_code != attr_b->pn_code);
"state" => "pinned",
"arity" => "2",
"comment" => "construct Alloca: allocate memory on Stack",
- "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }
+ "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }
},
-"Alloca_i" => {
- "op_flags" => "L|F",
- "state" => "pinned",
- "arity" => "1",
- "comment" => "construct Alloca: allocate memory on Stack",
- "reg_req" => { "out" => [ "general_purpose" ] }
-}
-
); # end of %nodes
extern ir_op *get_op_Mulh(void);
+typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
+ ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode);
+typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
+ ir_node *op, ir_node *mem, ir_mode *mode);
+
+/* TEMPORARY WORKAROUND */
+ir_node *be_new_NoReg(ir_graph *irg) {
+ return new_NoMem();
+}
/****************************************************************************************************
* _ _ __ _ _
*
****************************************************************************************************/
-
+#undef is_cnst
+#define is_cnst(op) (is_ia32_Const(op) || is_ia32_fConst(op))
/* determine if one operator is an Imm */
static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
if (op1)
- return is_ia32_Const(op1) ? op1 : (is_ia32_Const(op2) ? op2 : NULL);
- else return is_ia32_Const(op2) ? op2 : NULL;
+ return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL);
+ else return is_cnst(op2) ? op2 : NULL;
}
/* determine if one operator is not an Imm */
static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
- return !is_ia32_Const(op1) ? op1 : (!is_ia32_Const(op2) ? op2 : NULL);
+ return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL);
+}
+
+
+/**
+ * Construct a standard binary operation, set AM and immediate if required.
+ *
+ * @param env The transformation environment
+ * @param op1 The first operand
+ * @param op2 The second operand
+ * @param func The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
+ ir_node *new_op = NULL;
+ ir_mode *mode = env->mode;
+ dbg_info *dbg = env->dbg;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ firm_dbg_module_t *mod = env->mod;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+ ir_node *expr_op, *imm_op;
+
+
+ /* check if it's an operation with immediate */
+ if (is_op_commutative(get_irn_op(env->irn))) {
+ imm_op = get_immediate_op(op1, op2);
+ expr_op = get_expr_op(op1, op2);
+ }
+ else {
+ imm_op = get_immediate_op(NULL, op2);
+ expr_op = get_expr_op(op1, op2);
+ }
+
+ assert((expr_op || imm_op) && "invalid operands");
+
+ if (!expr_op) {
+ /* We have two consts here: not yet supported */
+ imm_op = NULL;
+ }
+
+ if (mode_is_float(mode)) {
+ /* floating point operations */
+ if (imm_op) {
+
+ new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+ set_ia32_Immop_attr(new_op, imm_op);
+ set_ia32_am_support(new_op, ia32_am_None);
+ }
+ else {
+ new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+ set_ia32_am_support(new_op, ia32_am_Source);
+ }
+ }
+ else {
+ /* integer operations */
+ if (imm_op) {
+ /* This is expr + const */
+ new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+ set_ia32_Immop_attr(new_op, imm_op);
+
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Dest);
+ }
+ else {
+ /* This is a normal operation */
+ new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Full);
+ }
+ }
+
+ return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
+}
+
+
+
+/**
+ * Construct a shift/rotate binary operation, sets AM and immediate if required.
+ *
+ * @param env The transformation environment
+ * @param op1 The first operand
+ * @param op2 The second operand
+ * @param func The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, construct_binop_func *func) {
+ ir_node *new_op = NULL;
+ ir_mode *mode = env->mode;
+ dbg_info *dbg = env->dbg;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ firm_dbg_module_t *mod = env->mod;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+ ir_node *expr_op, *imm_op;
+ tarval *tv;
+
+ assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
+
+ imm_op = get_immediate_op(NULL, op2);
+ expr_op = get_expr_op(op1, op2);
+
+ assert((expr_op || imm_op) && "invalid operands");
+
+ if (!expr_op) {
+ /* We have two consts here: not yet supported */
+ imm_op = NULL;
+ }
+
+ /* Limit imm_op within range imm8 */
+ if (imm_op) {
+ tv = get_ia32_Immop_tarval(imm_op);
+
+ if (tv) {
+ tv = tarval_mod(tv, new_tarval_from_long(32, mode_Iu));
+ }
+ else {
+ imm_op = NULL;
+ }
+ }
+
+ /* integer operations */
+ if (imm_op) {
+ /* This is shift/rot with const */
+
+ new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+ set_ia32_Immop_attr(new_op, imm_op);
+ }
+ else {
+ /* This is a normal shift/rot */
+ new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+ }
+
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Dest);
+
+ return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
+}
+
+
+/**
+ * Construct a standard unary operation, set AM and immediate if required.
+ *
+ * @param env The transformation environment
+ * @param op The operand
+ * @param func The node constructor function
+ * @return The constructed ia32 node.
+ */
+static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_func *func) {
+ ir_node *new_op = NULL;
+ ir_mode *mode = env->mode;
+ dbg_info *dbg = env->dbg;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+
+ new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode_T);
+
+ if (mode_is_float(mode)) {
+ /* floating point operations don't support implicit store */
+ set_ia32_am_support(new_op, ia32_am_None);
+ }
+ else {
+ set_ia32_am_support(new_op, ia32_am_Dest);
+ }
+
+ return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}
/**
* Creates an ia32 Add with immediate.
*
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Add_i node
+ * @param env The transformation environment
+ * @param expr_op The expression operator
+ * @param const_op The constant
+ * @return the created ia32 Add node
*/
static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- ir_node *new_op;
- tarval *tv = get_ia32_Immop_tarval(const_op);
- int normal_add = 0;
+ ir_node *new_op = NULL;
+ tarval *tv = get_ia32_Immop_tarval(const_op);
+ firm_dbg_module_t *mod = env->mod;
+ dbg_info *dbg = env->dbg;
+ ir_mode *mode = env->mode;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+ int normal_add = 1;
tarval_classification_t class_tv, class_negtv;
- firm_dbg_module_t *mod = env->mod;
- dbg_info *dbg = env->dbg;
- ir_mode *mode = env->mode;
- ir_graph *irg = env->irg;
- ir_node *block = env->block;
/* const_op: tarval or SymConst? */
if (tv) {
if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
DB((env->mod, LEVEL_2, "Add(1) to Inc ... "));
- new_op = new_rd_ia32_Inc(dbg, irg, block, expr_op, mode);
+ new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+ normal_add = 0;
}
else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
DB((mod, LEVEL_2, "Add(-1) to Dec ... "));
- new_op = new_rd_ia32_Dec(dbg, irg, block, expr_op, mode);
+ new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+ normal_add = 0;
}
- else
- normal_add = 1;
}
- else
- normal_add = 1;
- if (normal_add)
- new_op = new_rd_ia32_Lea_i(dbg, irg, block, expr_op, mode);
+ if (normal_add) {
+ new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+ set_ia32_Immop_attr(new_op, const_op);
+ }
return new_op;
}
* @return the created ia32 Add node
*/
static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- ir_node *shli_op;
- ir_node *expr_op;
- ir_node *new_op;
- int normal_add = 0;
- dbg_info *dbg = env->dbg;
- ir_mode *mode = env->mode;
- ir_graph *irg = env->irg;
- ir_node *block = env->block;
+ ir_node *new_op = NULL;
+ dbg_info *dbg = env->dbg;
+ ir_mode *mode = env->mode;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+ ir_node *expr_op, *imm_op;
+
+ imm_op = get_immediate_op(op1, op2);
+ expr_op = get_expr_op(op1, op2);
+
+ assert((expr_op || imm_op) && "invalid operands");
if (mode_is_float(mode)) {
- return new_rd_ia32_fAdd(dbg, irg, block, op1, op2, mode);
+ return gen_binop(env, op1, op2, new_rd_ia32_fAdd);
}
-
- /* try to optimize with LEA */
-
- shli_op = is_ia32_Shl_i(op1) ? op1 : (is_ia32_Shl_i(op2) ? op2 : NULL);
- expr_op = shli_op == op1 ? op2 : (shli_op == op2 ? op1 : NULL);
-
- if (shli_op) {
- tarval *tv = get_ia32_Immop_tarval(shli_op);
- tarval *offs = NULL;
- if (tv) {
- switch (get_tarval_long(tv)) {
- case 1:
- case 2:
- case 3:
- // If the other operand of the LEA is an LEA_i (that means LEA ofs(%regop1)),
- // we can skip it and transform the whole sequence into LEA ofs(%regop1, %regop2, shl_val),
- if (is_ia32_Lea_i(expr_op)) {
- offs = get_ia32_Immop_tarval(expr_op);
- expr_op = get_irn_n(expr_op, 0);
- }
-
- new_op = new_rd_ia32_Lea(dbg, irg, block, expr_op, get_irn_n(shli_op, 0), mode);
- set_ia32_Immop_tarval(new_op, tv);
- set_ia32_am_offs(new_op, offs);
-
- break;
- default:
- normal_add = 1;
- break;
- }
+ else {
+ /* integer ADD */
+ if (!expr_op) {
+ /* No expr_op means, that we have two const - one symconst and */
+ /* one tarval or another symconst - because this case is not */
+ /* covered by constant folding */
+
+ new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode_T);
+ add_ia32_am_offs(new_op, get_ia32_cnst(op1));
+ add_ia32_am_offs(new_op, get_ia32_cnst(op2));
+
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Source);
+ set_ia32_op_type(new_op, ia32_AddrModeS);
}
- else
- normal_add = 1;
- }
- else
- normal_add = 1;
-
- if (normal_add) {
- new_op = new_rd_ia32_Lea(dbg, irg, block, op1, op2, mode);
- set_ia32_Immop_tarval(new_op, get_tarval_null(mode_Iu));
- set_ia32_am_offs(new_op, NULL);
- }
+ else if (imm_op) {
+ /* This is expr + const */
+ new_op = gen_imm_Add(env, expr_op, imm_op);
- return new_op;
-}
-
-
-
-/**
- * Generates an ia32 Mul node.
- *
- * @param env The transformation environment
- * @param op1 The first faktor
- * @param op2 The second factor
- * @param mul_flav flavour_Mul/Mulh
- * @return The ready-to-go Mul node
- */
-ir_node *generate_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, op_flavour_t mul_flav, int is_imm_op) {
- ir_node *in_keep[1], *res;
- long pn_good, pn_bad;
- dbg_info *dbg = env->dbg;
- ir_graph *irg = env->irg;
- ir_node *block = env->block;
- ir_mode *mode = env->mode;
- ir_node *mul;
-
- /* create the mul */
- if (is_imm_op) {
- mul = new_rd_ia32_Mul_i(dbg, irg, block, op1, mode_T);
- set_ia32_Immop_attr(mul, op2);
- }
- else {
- mul = new_rd_ia32_Mul(dbg, irg, block, op1, op2, mode_T);
- }
- set_ia32_flavour(mul, mul_flav);
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Dest);
+ }
+ else {
+ /* This is a normal add */
+ new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
- /* create the mul infrastructure */
- if (mul_flav == flavour_Mul) {
- pn_good = pn_EAX;
- pn_bad = pn_EDX;
- }
- else { /* Mulh */
- pn_good = pn_EDX;
- pn_bad = pn_EAX;
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Full);
+ }
}
- res = new_rd_Proj(dbg, irg, block, mul, mode, pn_good);
- in_keep[0] = new_rd_Proj(dbg, irg, block, mul, mode, pn_bad);
-
- be_new_Keep(&ia32_reg_classes[CLASS_ia32_general_purpose], irg, block, 1, in_keep);
-
- return res;
+ return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}
-/**
- * Creates an ia32 Mul with immediate.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Mul_i node
- */
-static ir_node *gen_imm_Mul(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- /* Mul with immediate only possible with int, so we don't need to check for float */
- return generate_Mul(env, expr_op, const_op, flavour_Mul, 1);
-}
-
/**
* Creates an ia32 Mul.
*
* @return the created ia32 Mul node
*/
ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
+ ir_node *new_op;
+
if (mode_is_float(env->mode)) {
- return new_rd_ia32_fMul(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul);
}
else {
- return generate_Mul(env, op1, op2, flavour_Mul, 0);
+ new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul);
}
-}
+ return new_op;
+}
-/**
- * Creates an ia32 Mulh with immediate.
- * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
- * this result while Mul returns the lower 32 bit.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Mulh_i node
- */
-static ir_node *gen_imm_Mulh(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return generate_Mul(env, expr_op, const_op, flavour_Mulh, 1);
-}
/**
* Creates an ia32 Mulh.
* Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
* this result while Mul returns the lower 32 bit.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
* @return the created ia32 Mulh node
*/
static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return generate_Mul(env, op1, op2, flavour_Mulh, 0);
-}
+ ir_node *proj_EAX, *proj_EDX, *mulh;
+ ir_node *in[1];
+ assert(mode_is_float(env->mode) && "Mulh with float not supported");
+ proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh);
+ mulh = get_Proj_pred(proj_EAX);
+ proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX);
+ /* to be on the save side */
+ set_Proj_proj(proj_EAX, pn_EAX);
-/**
- * Creates an ia32 And with immediate.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 And_i node
- */
-static ir_node *gen_imm_And(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return new_rd_ia32_And_i(env->dbg, env->irg, env->block, expr_op, env->mode);
+ if (get_ia32_cnst(mulh)) {
+ /* Mulh with const cannot have AM */
+ set_ia32_am_support(mulh, ia32_am_None);
+ }
+ else {
+ /* Mulh cannot have AM for destination */
+ set_ia32_am_support(mulh, ia32_am_Source);
+ }
+
+ in[0] = proj_EAX;
+
+ /* keep EAX */
+ be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in);
+
+ return proj_EDX;
}
+
+
/**
* Creates an ia32 And.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 And node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 And node
*/
static ir_node *gen_And(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_And(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ if (mode_is_float(env->mode)) {
+ return gen_binop(env, op1, op2, new_rd_ia32_fAnd);
+ }
+ else {
+ return gen_binop(env, op1, op2, new_rd_ia32_And);
+ }
}
-/**
- * Creates an ia32 Or with immediate.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Or_i node
- */
-static ir_node *gen_imm_Or(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return new_rd_ia32_Or_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
/**
* Creates an ia32 Or.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 Or node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 Or node
*/
static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_Or(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ if (mode_is_float(env->mode)) {
+ return gen_binop(env, op1, op2, new_rd_ia32_fOr);
+ }
+ else {
+ return gen_binop(env, op1, op2, new_rd_ia32_Or);
+ }
}
-/**
- * Creates an ia32 Eor with immediate.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Eor_i node
- */
-static ir_node *gen_imm_Eor(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return new_rd_ia32_Eor_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
/**
* Creates an ia32 Eor.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 Eor node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 Eor node
*/
static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_Eor(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ if (mode_is_float(env->mode)) {
+ return gen_binop(env, op1, op2, new_rd_ia32_fEor);
+ }
+ else {
+ return gen_binop(env, op1, op2, new_rd_ia32_Eor);
+ }
}
/**
* Creates an ia32 Max.
*
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Max node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return the created ia32 Max node
*/
static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ ir_node *new_op;
+
+ if (mode_is_float(env->mode)) {
+ new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax);
+ }
+ else {
+ new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ set_ia32_am_support(new_op, ia32_am_None);
+ }
+
+ return new_op;
}
/**
* Creates an ia32 Min.
*
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Min node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return the created ia32 Min node
*/
static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ ir_node *new_op;
+
+ if (mode_is_float(env->mode)) {
+ new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin);
+ }
+ else {
+ new_op = new_rd_ia32_Min(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ set_ia32_am_support(new_op, ia32_am_None);
+ }
+
+ return new_op;
}
/**
* Creates an ia32 Sub with immediate.
*
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Sub_i node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 Sub node
*/
static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- ir_node *new_op;
- tarval *tv = get_ia32_Immop_tarval(const_op);
- int normal_sub = 0;
+ ir_node *new_op = NULL;
+ tarval *tv = get_ia32_Immop_tarval(const_op);
+ firm_dbg_module_t *mod = env->mod;
+ dbg_info *dbg = env->dbg;
+ ir_mode *mode = env->mode;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+ int normal_sub = 1;
tarval_classification_t class_tv, class_negtv;
- firm_dbg_module_t *mod = env->mod;
- dbg_info *dbg = env->dbg;
- ir_mode *mode = env->mode;
- ir_graph *irg = env->irg;
- ir_node *block = env->block;
/* const_op: tarval or SymConst? */
if (tv) {
if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
DB((mod, LEVEL_2, "Sub(1) to Dec ... "));
- new_op = new_rd_ia32_Dec(dbg, irg, block, expr_op, mode);
+ new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+ normal_sub = 0;
}
else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
DB((mod, LEVEL_2, "Sub(-1) to Inc ... "));
- new_op = new_rd_ia32_Inc(dbg, irg, block, expr_op, mode);
+ new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode_T);
+ normal_sub = 0;
}
- else
- normal_sub = 1;
}
- else
- normal_sub = 1;
- if (normal_sub)
- new_op = new_rd_ia32_Sub_i(dbg, irg, block, expr_op, mode);
+ if (normal_sub) {
+ new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode_T);
+ set_ia32_Immop_attr(new_op, const_op);
+ }
return new_op;
}
/**
* Creates an ia32 Sub.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 Sub node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 Sub node
*/
static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- if (mode_is_float(env->mode)) {
- return new_rd_ia32_fSub(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ ir_node *new_op = NULL;
+ dbg_info *dbg = env->dbg;
+ ir_mode *mode = env->mode;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+ ir_node *expr_op, *imm_op;
+
+ imm_op = get_immediate_op(NULL, op2);
+ expr_op = get_expr_op(op1, op2);
+
+ assert((expr_op || imm_op) && "invalid operands");
+
+ if (mode_is_float(mode)) {
+ return gen_binop(env, op1, op2, new_rd_ia32_fSub);
}
- return new_rd_ia32_Sub(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ else {
+ /* integer SUB */
+ if (!expr_op) {
+ /* No expr_op means, that we have two const - one symconst and */
+ /* one tarval or another symconst - because this case is not */
+ /* covered by constant folding */
+
+ new_op = new_rd_ia32_Lea(dbg, irg, block, noreg, noreg, mode);
+ add_ia32_am_offs(new_op, get_ia32_cnst(op1));
+ sub_ia32_am_offs(new_op, get_ia32_cnst(op2));
+
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Source);
+ set_ia32_op_type(new_op, ia32_AddrModeS);
+ }
+ else if (imm_op) {
+ /* This is expr - const */
+ new_op = gen_imm_Sub(env, expr_op, imm_op);
+
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Dest);
+ }
+ else {
+ /* This is a normal sub */
+ new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode_T);
+
+ /* set AM support */
+ set_ia32_am_support(new_op, ia32_am_Full);
+ }
+ }
+
+ return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}
* @param dm_flav flavour_Div/Mod/DivMod
* @return The created ia32 DivMod node
*/
-static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, op_flavour_t dm_flav) {
+static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir_node *divisor, ia32_op_flavour_t dm_flav) {
ir_node *res, *proj;
ir_node *edx_node, *cltd;
ir_node *in_keep[1];
if (mode_is_signed(mode)) {
/* in signed mode, we need to sign extend the dividend */
- cltd = new_rd_ia32_Cltd(dbg, irg, block, dividend, mode_T);
+ cltd = new_rd_ia32_Cdq(dbg, irg, block, dividend, mode_T);
dividend = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EAX);
edx_node = new_rd_Proj(dbg, irg, block, cltd, mode_Is, pn_EDX);
}
else {
edx_node = new_rd_ia32_Const(dbg, irg, block, mode_Iu);
- set_ia32_Const_type(edx_node, asmop_Const);
+ set_ia32_Const_type(edx_node, ia32_Const);
set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
}
in_keep[0] = new_rd_Proj(dbg, irg, block, res, mode_Is, pn_DivMod_res_div);
}
- be_new_Keep(&ia32_reg_classes[CLASS_ia32_general_purpose], irg, block, 1, in_keep);
+ be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], irg, block, 1, in_keep);
}
return res;
/**
* Creates an ia32 floating Div.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 fDiv node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 fDiv node
*/
static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_fDiv(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ return gen_binop(env, op1, op2, new_rd_ia32_fDiv);
}
-/**
- * Creates an ia32 Shl with immediate.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Shl_i node
- */
-static ir_node *gen_imm_Shl(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return new_rd_ia32_Shl_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
/**
* Creates an ia32 Shl.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 Shl node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 Shl node
*/
static ir_node *gen_Shl(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_Shl(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ return gen_shift_binop(env, op1, op2, new_rd_ia32_Shl);
}
-/**
- * Creates an ia32 Shr with immediate.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Shr_i node
- */
-static ir_node *gen_imm_Shr(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return new_rd_ia32_Shr_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
/**
* Creates an ia32 Shr.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 Shr node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 Shr node
*/
static ir_node *gen_Shr(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_Shr(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ return gen_shift_binop(env, op1, op2, new_rd_ia32_Shr);
}
-/**
- * Creates an ia32 Shrs with immediate.
- *
- * @param dbg firm dbg
- * @param block the block the new node should belong to
- * @param expr_op operator
- * @param mode node mode
- * @return the created ia23 Shrs_i node
- */
-static ir_node *gen_imm_Shrs(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return new_rd_ia32_Shrs_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
/**
* Creates an ia32 Shrs.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 Shrs node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 Shrs node
*/
static ir_node *gen_Shrs(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_Shrs(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ return gen_shift_binop(env, op1, op2, new_rd_ia32_Shrs);
}
/**
* Creates an ia32 RotL.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 RotL node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 RotL node
*/
static ir_node *gen_RotL(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_RotL(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ return gen_shift_binop(env, op1, op2, new_rd_ia32_RotL);
}
* NOTE: There is no RotR with immediate because this would always be a RotL
* "imm-mode_size_bits" which can be pre-calculated.
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 RotR node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 RotR node
*/
static ir_node *gen_RotR(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
- return new_rd_ia32_RotR(env->dbg, env->irg, env->block, op1, op2, env->mode);
+ return gen_shift_binop(env, op1, op2, new_rd_ia32_RotR);
}
-/**
- * Transforms a Rot with immediate into an ia32 RotL with immediate
- * as the Firm Rot is a RotL (see NOTE on RotR with immediate above).
- *
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 RotL node
- */
-static ir_node *gen_imm_Rot(ia32_transform_env_t *env, ir_node *expr_op, ir_node *const_op) {
- return new_rd_ia32_RotL_i(env->dbg, env->irg, env->block, expr_op, env->mode);
-}
-
/**
* Creates an ia32 RotR or RotL (depending on the found pattern).
*
- * @param dbg firm node dbg
- * @param block the block the new node should belong to
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @return the created ia32 RotL or RotR node
+ * @param env The transformation environment
+ * @param op1 The first operator
+ * @param op2 The second operator
+ * @return The created ia32 RotL or RotR node
*/
static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
ir_node *rotate = NULL;
operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
that means we can create a RotR instead of an Add and a RotL */
- if (is_ia32_Add_i(op2)) {
- ir_node *minus = get_irn_n(op2, 0); // is there an op_Minus?
+ if (is_Proj(op2)) {
+ ir_node *pred = get_Proj_pred(op2);
- if (is_ia32_Minus(minus)) {
- tarval *tv = get_ia32_Immop_tarval(op2);
- long bits = get_mode_size_bits(env->mode);
+ if (is_ia32_Add(pred)) {
+ ir_node *pred_pred = get_irn_n(pred, 2);
+ tarval *tv = get_ia32_Immop_tarval(pred);
+ long bits = get_mode_size_bits(env->mode);
- if (tarval_is_long(tv) && get_tarval_long(tv) == bits) {
- DB((env->mod, LEVEL_1, "RotL into RotR ... "));
- rotate = gen_RotR(env, op1, get_irn_n(minus, 0));
+ if (is_Proj(pred_pred)) {
+ pred_pred = get_Proj_pred(pred_pred);
}
- }
- }
-
- if (!rotate)
- rotate = gen_RotL(env, op1, op2);
-
- return rotate;
-}
-
-
-
-/**
- * Transforms commutative operations (op_Add, op_And, op_Or, op_Eor)
- * and non-commutative operations with com == 0 (op_Sub, op_Shl, op_Shr, op_Shrs, op_Rot)
- *
- * @param mod the debug module
- * @param block the block node belongs to
- * @param node the node to transform
- * @param op1 first operator
- * @param op2 second operator
- * @param mode node mode
- * @param com flag if op is commutative
- * @return the created assembler node
- */
-static ir_node *gen_arith_Op(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, int com) {
- firm_dbg_module_t *mod = env->mod;
- ir_node *node = env->irn;
- ir_node *imm_op = NULL;
- ir_node *expr_op = NULL;
- ir_node *asm_node = NULL;
- opcode opc = get_irn_opcode(node);
- ir_op *op = get_irn_op(node);
-
-#undef GENOP
-#undef GENOPI
-#undef GENOPI_SETATTR
-#define GENOP(a) case iro_##a: asm_node = gen_##a(env, op1, op2); break
-#define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(env, expr_op, imm_op); break
-#define GENOPI_SETATTR(a) case iro_##a: asm_node = gen_imm_##a(env, expr_op, imm_op); set_ia32_Immop_attr(asm_node, imm_op); break
-
- if (com)
- imm_op = get_immediate_op(op1, op2);
- else
- imm_op = get_immediate_op(NULL, op2);
-
- expr_op = get_expr_op(op1, op2);
- /* TODO: Op(Const, Const) support */
- if (is_ia32_Const(op1) && is_ia32_Const(op2)) {
- DB((mod, LEVEL_2, "%+F(Const, Const) -> binop ... ", get_irn_opname(node)));
- imm_op = NULL;
- }
-
- /* There are arithmetic operations which can't take an immediate */
- switch(opc) {
- case iro_Div:
- case iro_Mod:
- case iro_DivMod:
- DB((mod, LEVEL_2, "Div/Mod/DivMod imm -> binop ... "));
- imm_op = NULL;
- break;
- default:
- if (op == get_op_Min() || op == get_op_Max()) {
- DB((mod, LEVEL_2, "MIN/MAX imm -> binop ... "));
- imm_op = NULL;
+ if (is_ia32_Minus(pred_pred) &&
+ tarval_is_long(tv) &&
+ get_tarval_long(tv) == bits)
+ {
+ DB((env->mod, LEVEL_1, "RotL into RotR ... "));
+ rotate = gen_RotR(env, op1, get_irn_n(pred_pred, 2));
}
- break;
- }
- DB((mod, LEVEL_1, "(%+F -- %+F) ... ", op1, op2));
-
- if (!mode_is_float(env->mode) && imm_op) {
- DB((mod, LEVEL_1, "immop ... "));
-
- switch(opc) {
- GENOPI_SETATTR(Add);
- GENOPI(Mul);
- GENOPI_SETATTR(And);
- GENOPI_SETATTR(Or);
- GENOPI_SETATTR(Eor);
-
- GENOPI_SETATTR(Sub);
- GENOPI_SETATTR(Shl);
- GENOPI_SETATTR(Shr);
- GENOPI_SETATTR(Shrs);
- GENOPI_SETATTR(Rot);
- default:
- if (op == get_op_Mulh()) {
- asm_node = gen_imm_Mulh(env, expr_op, imm_op);
- }
- else {
- assert("binop_i: THIS SHOULD NOT HAPPEN");
- }
}
}
- else {
- DB((mod, LEVEL_1, "binop ... "));
-
- switch(opc) {
- GENOP(Add);
- GENOP(Mul);
- GENOP(And);
- GENOP(Or);
- GENOP(Eor);
-
- GENOP(Quot);
-
- GENOP(Div);
- GENOP(Mod);
- GENOP(DivMod);
-
- GENOP(Sub);
- GENOP(Shl);
- GENOP(Shr);
- GENOP(Shrs);
- GENOP(Rot);
- default:
- if (op == get_op_Max()) {
- asm_node = gen_Max(env, op1, op2);
- }
- else if (op == get_op_Min()) {
- asm_node = gen_Min(env, op1, op2);
- }
- else if (op == get_op_Mulh()) {
- asm_node = gen_Mulh(env, op1, op2);
- }
- else {
- assert("binop: THIS SHOULD NOT HAPPEN");
- }
- }
+
+ if (!rotate) {
+ rotate = gen_RotL(env, op1, op2);
}
- return asm_node;
+ return rotate;
}
-#undef GENOP
-#undef GENOPI
-#undef GENOPI_SETATTR
/**
* Transforms a Minus node.
*
- * @param mod the debug module
- * @param block the block the new node should belong to
- * @param node the ir Minus node
- * @param op operator
- * @param mode node mode
- * @return the created ia32 Minus node
+ * @param env The transformation environment
+ * @param op The operator
+ * @return The created ia32 Minus node
*/
static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
- if (is_ia32_Minus(op) || is_ia32_fMinus(op)) {
- DB((env->mod, LEVEL_1, "--(e) to e ..."));
- return get_irn_n(op, 0);
+ ir_node *new_op;
+
+ if (mode_is_float(env->mode)) {
+ assert(0);
}
else {
- if (mode_is_float(env->mode)) {
- return new_rd_ia32_fMinus(env->dbg, env->irg, env->block, op, env->mode);
- }
- return new_rd_ia32_Minus(env->dbg, env->irg, env->block, op, env->mode);
+ new_op = gen_unop(env, op, new_rd_ia32_Minus);
}
+
+ return new_op;
}
/**
* Transforms a Conv node.
*
- * @param mod the debug module
- * @param block the block the new node should belong to
- * @param node the ir Conv node
- * @param op operator
- * @param mode node mode
- * @return the created ia32 Conv node
+ * @param env The transformation environment
+ * @param op The operator
+ * @return The created ia32 Conv node
*/
static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
return new_rd_ia32_Conv(env->dbg, env->irg, env->block, op, env->mode);
/**
* Transforms a Not node.
*
- * @param mod the debug module
- * @param block the block the new node should belong to
- * @param node the ir Not node
- * @param op operator
- * @param mode node mode
- * @return the created ia32 Not node
+ * @param env The transformation environment
+ * @param op The operator
+ * @return The created ia32 Not node
*/
static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *op) {
- return new_rd_ia32_Not(env->dbg, env->irg, env->block, op, env->mode);
+ ir_node *new_op;
+
+ if (mode_is_float(env->mode)) {
+ assert(0);
+ }
+ else {
+ new_op = gen_unop(env, op, new_rd_ia32_Not);
+ }
+
+ return new_op;
}
/**
* Transforms an Abs node.
*
- * @param mod the debug module
- * @param block the block the new node should belong to
- * @param node the ir Abs node
- * @param op operator
- * @param mode node mode
- * @return the created ia32 Abs node
+ * @param env The transformation environment
+ * @param op The operator
+ * @return The created ia32 Abs node
*/
static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
ir_node *res, *p_eax, *p_edx;
ir_mode *mode = env->mode;
ir_graph *irg = env->irg;
ir_node *block = env->block;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
- res = new_rd_ia32_Cltd(dbg, irg, block, op, mode_T);
+ if (mode_is_float(mode)) {
+ assert(0);
+ }
+
+ res = new_rd_ia32_Cdq(dbg, irg, block, op, mode_T);
p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
- res = new_rd_ia32_Eor(dbg, irg, block, p_eax, p_edx, mode);
- res = new_rd_ia32_Sub(dbg, irg, block, res, p_edx, mode);
+ res = new_rd_ia32_Eor(dbg, irg, block, noreg, noreg, p_eax, p_edx, nomem, mode_T);
+ res = new_rd_Proj(dbg, irg, block, res, mode, 0);
+ res = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, res, p_edx, nomem, mode_T);
+ res = new_rd_Proj(dbg, irg, block, res, mode, 0);
return res;
}
* @return the created ia32 Load node
*/
static ir_node *gen_Load(ia32_transform_env_t *env) {
- ir_node *node = env->irn;
+ ir_node *node = env->irn;
+ ir_node *noreg = be_new_NoReg(env->irg);
if (mode_is_float(env->mode)) {
- return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
+ return new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
}
- return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), get_Load_mem(node), env->mode);
+ return new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode);
}
* @return the created ia32 Store node
*/
ir_node *gen_Store(ia32_transform_env_t *env) {
- ir_node *node = env->irn;
+ ir_node *node = env->irn;
+ ir_node *noreg = be_new_NoReg(env->irg);
if (mode_is_float(env->mode)) {
- return new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
+ return new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode);
}
- return new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), env->mode);
+ return new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode);
}
ir_node **in;
ir_node *new_call, *sync;
int i, j, n_new_call_in, ignore = 0;
- asmop_attr *attr;
+ ia32_attr_t *attr;
dbg_info *dbg = env->dbg;
ir_graph *irg = env->irg;
ir_node *block = env->block;
/* two results only appear when a 64bit int result is broken up into two 32bit results */
if (n_res == 1) {
if (mode_is_float(get_type_mode(get_method_res_type(get_Call_type(call), 0))))
- attr->out_req[0] = &ia32_default_req_ia32_floating_point_xmm0;
+ attr->out_req[0] = &ia32_default_req_ia32_fp_xmm0;
else
- attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
+ attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
}
else if (n_res == 2) {
- attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
- attr->out_req[1] = &ia32_default_req_ia32_general_purpose_edx;
+ attr->out_req[0] = &ia32_default_req_ia32_gp_eax;
+ attr->out_req[1] = &ia32_default_req_ia32_gp_edx;
}
/* stack parameter has no OUT register */
/**
* Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
*
- * @param mod the debug module
- * @param block the block the new node should belong to
- * @param node the ir Cond node
- * @param mode mode of the Cond
+ * @param env The transformation environment
* @return The transformed node.
*/
static ir_node *gen_Cond(ia32_transform_env_t *env) {
- dbg_info *dbg = env->dbg;
- ir_graph *irg = env->irg;
- ir_node *block = env->block;
- ir_node *node = env->irn;
- ir_node *sel = get_Cond_selector(node);
- ir_mode *sel_mode = get_irn_mode(sel);
- ir_node *res = NULL;
- ir_node *pred = NULL;
- ir_node *cmp_a, *cmp_b, *cnst, *expr;
+ dbg_info *dbg = env->dbg;
+ ir_graph *irg = env->irg;
+ ir_node *block = env->block;
+ ir_node *node = env->irn;
+ ir_node *sel = get_Cond_selector(node);
+ ir_mode *sel_mode = get_irn_mode(sel);
+ ir_node *res = NULL;
+ ir_node *pred = NULL;
+ ir_node *noreg = be_new_NoReg(irg);
+ ir_node *nomem = new_NoMem();
+ ir_node *cmp_a, *cmp_b, *cnst, *expr;
if (is_Proj(sel) && sel_mode == mode_b) {
pred = get_Proj_pred(sel);
expr = get_expr_op(cmp_a, cmp_b);
if (cnst && expr) {
- res = new_rd_ia32_CondJmp_i(dbg, irg, block, expr, mode_T);
+ res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T);
set_ia32_Immop_attr(res, cnst);
}
else {
- res = new_rd_ia32_CondJmp(dbg, irg, block, cmp_a, cmp_b, mode_T);
+ res = new_rd_ia32_CondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T);
}
set_ia32_pncode(res, get_Proj_proj(sel));
}
else {
- res = new_rd_ia32_SwitchJmp(dbg, irg, block, sel, mode_T);
+ res = new_rd_ia32_SwitchJmp(dbg, irg, block, noreg, noreg, sel, nomem, mode_T);
set_ia32_pncode(res, get_Cond_defaultProj(node));
}
-/**
- * Transforms an Alloc node into either ia32_Alloca or ia32_Malloc.
- */
-static ir_node *gen_Alloc(ia32_transform_env_t *env) {
- dbg_info *dbg = env->dbg;
- ir_graph *irg = env->irg;
- ir_node *block = env->block;
- ir_node *irn = env->irn;
- ir_mode *mode = env->mode;
- ir_node *size = get_Alloc_size(irn);
- ir_node *mem = get_Alloc_mem(irn);
- ir_node *res;
-
- if (get_Alloc_where(irn) == stack_alloc) {
- if (is_ia32_Const(size)) {
- res = new_rd_ia32_Alloca_i(dbg, irg, block, mem, mode);
- set_ia32_Immop_attr(res, size);
- }
- else {
- res = new_rd_ia32_Alloca(dbg, irg, block, size, mem, mode);
- }
- }
- else {
- assert(0 && "malloc should be already lowered");
- res = NULL;
- }
-
- return res;
-}
-
/*********************************************************
* _ _ _
* (_) | | (_)
tenv.mode = get_irn_mode(node);
tenv.cg = cgenv;
-#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
-#define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
-#define BINOP_COM(a) case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 1); break
-#define BINOP_NCOM(a) case iro_##a: asm_node = gen_arith_Op(&tenv, get_##a##_left(node), get_##a##_right(node), 0); break
-#define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break
-#define IGN(a) case iro_##a: break
-#define BAD(a) case iro_##a: goto bad
+#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
+#define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break
+#define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break
+#define IGN(a) case iro_##a: break
+#define BAD(a) case iro_##a: goto bad
DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
switch (code) {
- BINOP_COM(Add);
- BINOP_COM(Mul);
- BINOP_COM(And);
- BINOP_COM(Or);
- BINOP_COM(Eor);
-
- BINOP_NCOM(Sub);
- BINOP_NCOM(Shl);
- BINOP_NCOM(Shr);
- BINOP_NCOM(Shrs);
- BINOP_NCOM(Quot);
- BINOP_NCOM(Div);
- BINOP_NCOM(Mod);
- BINOP_NCOM(DivMod);
+ BINOP(Add);
+ BINOP(Sub);
+ BINOP(Mul);
+ BINOP(And);
+ BINOP(Or);
+ BINOP(Eor);
+
+ BINOP(Shl);
+ BINOP(Shr);
+ BINOP(Shrs);
+
+ BINOP(Quot);
+
+ BINOP(Div);
+ BINOP(Mod);
+ BINOP(DivMod);
UNOP(Minus);
UNOP(Conv);
GEN(Load);
GEN(Store);
- GEN(Call);
GEN(Cond);
+
GEN(Proj);
- GEN(Alloc);
+ GEN(Call);
+ IGN(Alloc);
IGN(Block);
IGN(Start);
BAD(CopyB);
default:
- if (get_irn_op(node) == get_op_Max() ||
- get_irn_op(node) == get_op_Min() ||
- get_irn_op(node) == get_op_Mulh())
- {
- asm_node = gen_arith_Op(&tenv, get_irn_n(node, 0), get_irn_n(node, 1), 1);
+ if (get_irn_op(node) == get_op_Max()) {
+ asm_node = gen_Max(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
+ }
+ else if (get_irn_op(node) == get_op_Min()) {
+ asm_node = gen_Min(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
+ }
+ else if (get_irn_op(node) == get_op_Mulh()) {
+ asm_node = gen_Mulh(&tenv, get_irn_n(node, 0), get_irn_n(node, 1));
}
break;
bad: