+ir_node *be_new_SubSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, ir_node *sz)
+{
+ be_node_attr_t *a;
+ ir_node *irn;
+ ir_node *in[be_pos_SubSP_last];
+
+ in[be_pos_SubSP_old_sp] = old_sp;
+ in[be_pos_SubSP_size] = sz;
+
+ irn = new_ir_node(NULL, irg, bl, op_be_SubSP, mode_T, be_pos_SubSP_last, in);
+ a = init_node_attr(irn, be_pos_SubSP_last);
+
+ be_node_set_flags(irn, OUT_POS(pn_be_SubSP_sp),
+ arch_irn_flags_ignore | arch_irn_flags_modify_sp);
+
+ /* Set output constraint to stack register. */
+ be_set_constr_single_reg(irn, be_pos_SubSP_old_sp, sp);
+ be_node_set_reg_class(irn, be_pos_SubSP_size, arch_register_get_class(sp));
+ be_set_constr_single_reg(irn, OUT_POS(pn_be_SubSP_sp), sp);
+ a->reg_data[pn_be_SubSP_sp].reg = sp;
+
+ return irn;
+}
+
+ir_node *be_new_RegParams(ir_graph *irg, ir_node *bl, int n_outs)
+{
+ ir_node *res;
+ int i;
+
+ res = new_ir_node(NULL, irg, bl, op_be_RegParams, mode_T, 0, NULL);
+ init_node_attr(res, -1);
+ for(i = 0; i < n_outs; ++i)
+ add_register_req(res);
+
+ return res;
+}
+
+ir_node *be_RegParams_append_out_reg(ir_node *regparams,
+ const arch_env_t *arch_env,
+ const arch_register_t *reg)
+{
+ ir_graph *irg = get_irn_irg(regparams);
+ ir_node *block = get_nodes_block(regparams);
+ be_node_attr_t *attr = get_irn_attr(regparams);
+ const arch_register_class_t *cls = arch_register_get_class(reg);
+ ir_mode *mode = arch_register_class_mode(cls);
+ int n = ARR_LEN(attr->reg_data);
+ ir_node *proj;
+
+ assert(be_is_RegParams(regparams));
+ proj = new_r_Proj(irg, block, regparams, mode, n);
+ add_register_req(regparams);
+ be_set_constr_single_reg(regparams, BE_OUT_POS(n), reg);
+ arch_set_irn_register(arch_env, proj, reg);
+
+ /* TODO decide, whether we need to set ignore/modify sp flags here? */
+
+ return proj;
+}
+
+ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame, ir_graph *irg, ir_node *bl, ir_node *frame, ir_entity *ent)
+{
+ be_frame_attr_t *a;
+ ir_node *irn;
+ ir_node *in[1];
+
+ in[0] = frame;
+ irn = new_ir_node(NULL, irg, bl, op_be_FrameAddr, get_irn_mode(frame), 1, in);
+ a = init_node_attr(irn, 1);
+ a->ent = ent;
+ a->offset = 0;
+ be_node_set_reg_class(irn, 0, cls_frame);
+ be_node_set_reg_class(irn, OUT_POS(0), cls_frame);
+
+ return optimize_node(irn);
+}
+
+ir_node *be_get_FrameAddr_frame(const ir_node *node) {
+ assert(be_is_FrameAddr(node));
+ return get_irn_n(node, be_pos_FrameAddr_ptr);
+}
+
+ir_entity *be_get_FrameAddr_entity(const ir_node *node)
+{
+ const be_frame_attr_t *attr = get_irn_generic_attr_const(node);
+ return attr->ent;
+}
+
+ir_node *be_new_CopyKeep(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, int n, ir_node *in_keep[], ir_mode *mode)
+{
+ ir_node *irn;
+ ir_node **in = (ir_node **) alloca((n + 1) * sizeof(in[0]));
+
+ in[0] = src;
+ memcpy(&in[1], in_keep, n * sizeof(in[0]));
+ irn = new_ir_node(NULL, irg, bl, op_be_CopyKeep, mode, n + 1, in);
+ init_node_attr(irn, n + 1);
+ be_node_set_reg_class(irn, OUT_POS(0), cls);
+ be_node_set_reg_class(irn, 0, cls);
+
+ return irn;
+}
+
+ir_node *be_new_CopyKeep_single(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *src, ir_node *keep, ir_mode *mode)
+{
+ return be_new_CopyKeep(cls, irg, bl, src, 1, &keep, mode);
+}
+
+ir_node *be_get_CopyKeep_op(const ir_node *cpy) {
+ return get_irn_n(cpy, be_pos_CopyKeep_op);
+}
+
+void be_set_CopyKeep_op(ir_node *cpy, ir_node *op) {
+ set_irn_n(cpy, be_pos_CopyKeep_op, op);
+}
+
+ir_node *be_new_Barrier(ir_graph *irg, ir_node *bl, int n, ir_node *in[])
+{
+ ir_node *res;
+ int i;
+
+ res = new_ir_node(NULL, irg, bl, op_be_Barrier, mode_T, -1, NULL);
+ init_node_attr(res, -1);
+ for(i = 0; i < n; ++i) {
+ add_irn_n(res, in[i]);
+ add_register_req(res);
+ }
+
+ return res;
+}
+
+ir_node *be_Barrier_append_node(ir_node *barrier, ir_node *node)
+{
+ ir_graph *irg = get_irn_irg(barrier);
+ ir_node *block = get_nodes_block(barrier);
+ ir_mode *mode = get_irn_mode(node);
+ int n = add_irn_n(barrier, node);
+
+ ir_node *proj = new_r_Proj(irg, block, barrier, mode, n);
+ add_register_req(barrier);
+
+ return proj;
+}
+
+/* Construct a new be_Unwind. */
+ir_node *be_new_Unwind(dbg_info *dbg, ir_graph *irg, ir_node *block,
+ ir_node *mem, ir_node *sp)
+{
+ ir_node *res;
+ ir_node *in[2];
+
+ in[be_pos_Unwind_mem] = mem;
+ in[be_pos_Unwind_sp] = sp;
+ res = new_ir_node(dbg, irg, block, op_be_Unwind, mode_X, 2, in);
+ init_node_attr(res, -1);
+
+ return res;
+}
+
+int be_has_frame_entity(const ir_node *irn)
+{
+ switch (get_irn_opcode(irn)) {
+ case beo_Spill:
+ case beo_Reload:
+ case beo_FrameAddr:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+ir_entity *be_get_frame_entity(const ir_node *irn)
+{
+ if (be_has_frame_entity(irn)) {
+ const be_frame_attr_t *a = get_irn_attr_const(irn);
+ return a->ent;
+ }
+ return NULL;
+}
+
+int be_get_frame_offset(const ir_node *irn)
+{
+ assert(is_be_node(irn));
+ if (be_has_frame_entity(irn)) {
+ const be_frame_attr_t *a = get_irn_attr_const(irn);
+ return a->offset;
+ }
+ return 0;
+}
+
+void be_set_MemPerm_in_entity(const ir_node *irn, int n, ir_entity *ent)
+{
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
+
+ assert(be_is_MemPerm(irn));
+ assert(n < be_get_MemPerm_entity_arity(irn));
+
+ attr->in_entities[n] = ent;
+}
+
+ir_entity* be_get_MemPerm_in_entity(const ir_node* irn, int n)
+{
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
+
+ assert(be_is_MemPerm(irn));
+ assert(n < be_get_MemPerm_entity_arity(irn));
+
+ return attr->in_entities[n];
+}
+
+void be_set_MemPerm_out_entity(const ir_node *irn, int n, ir_entity *ent)
+{
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
+
+ assert(be_is_MemPerm(irn));
+ assert(n < be_get_MemPerm_entity_arity(irn));
+
+ attr->out_entities[n] = ent;
+}
+
+ir_entity* be_get_MemPerm_out_entity(const ir_node* irn, int n)
+{
+ const be_memperm_attr_t *attr = get_irn_attr_const(irn);
+
+ assert(be_is_MemPerm(irn));
+ assert(n < be_get_MemPerm_entity_arity(irn));
+
+ return attr->out_entities[n];
+}
+
+int be_get_MemPerm_entity_arity(const ir_node *irn)
+{
+ return get_irn_arity(irn) - 1;
+}
+
+void be_set_constr_single_reg(ir_node *node, int pos, const arch_register_t *reg)
+{
+ arch_register_req_t *req = get_req(node, pos);
+ const arch_register_class_t *cls = arch_register_get_class(reg);
+ ir_graph *irg = get_irn_irg(node);
+ struct obstack *obst = get_irg_obstack(irg);
+ unsigned *limited_bitset;
+
+ assert(req->cls == NULL || req->cls == cls);
+ assert(! (req->type & arch_register_req_type_limited));
+ assert(req->limited == NULL);
+
+ limited_bitset = rbitset_obstack_alloc(obst, arch_register_class_n_regs(cls));
+ rbitset_set(limited_bitset, arch_register_get_index(reg));
+
+ req->cls = cls;
+ req->type |= arch_register_req_type_limited;
+ req->limited = limited_bitset;
+}
+
+void be_set_constr_limited(ir_node *node, int pos, const arch_register_req_t *req)
+{
+ ir_graph *irg = get_irn_irg(node);
+ struct obstack *obst = get_irg_obstack(irg);
+ arch_register_req_t *r = get_req(node, pos);
+
+ assert(arch_register_req_is(req, limited));
+ assert(!(req->type & (arch_register_req_type_should_be_same | arch_register_req_type_must_be_different)));
+ memcpy(r, req, sizeof(r[0]));
+ r->limited = rbitset_duplicate_obstack_alloc(obst, req->limited, req->cls->n_regs);
+}
+
+void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
+{
+ be_req_t *bereq = get_be_req(irn, pos);
+ bereq->flags = flags;
+}
+
+void be_node_add_flags(ir_node *irn, int pos, arch_irn_flags_t flags)
+{
+ be_req_t *bereq = get_be_req(irn, pos);
+ bereq->flags |= flags;
+}
+
+void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls)
+{
+ arch_register_req_t *req = get_req(irn, pos);
+
+ req->cls = cls;
+
+ if (cls == NULL) {
+ req->type = arch_register_req_type_none;
+ } else if (req->type == arch_register_req_type_none) {
+ req->type = arch_register_req_type_normal;
+ }
+}
+
+void be_node_set_req_type(ir_node *irn, int pos, arch_register_req_type_t type)
+{
+ arch_register_req_t *req = get_req(irn, pos);
+ req->type = type;
+}
+
+ir_node *be_get_IncSP_pred(ir_node *irn) {
+ assert(be_is_IncSP(irn));
+ return get_irn_n(irn, 0);
+}
+
+void be_set_IncSP_pred(ir_node *incsp, ir_node *pred) {
+ assert(be_is_IncSP(incsp));
+ set_irn_n(incsp, 0, pred);
+}
+
+void be_set_IncSP_offset(ir_node *irn, int offset)
+{
+ be_incsp_attr_t *a = get_irn_attr(irn);
+ assert(be_is_IncSP(irn));
+ a->offset = offset;
+}
+
+int be_get_IncSP_offset(const ir_node *irn)
+{
+ const be_incsp_attr_t *a = get_irn_attr_const(irn);
+ assert(be_is_IncSP(irn));
+ return a->offset;
+}
+
+int be_get_IncSP_align(const ir_node *irn)