static void parse_asm_constraints(constraint_t *constraint, const char *c,
int is_output)
{
- asm_constraint_flags_t flags = 0;
char immediate_type = '\0';
unsigned limited = 0;
const arch_register_class_t *cls = NULL;
case '\n':
break;
- case '=':
- flags |= ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
- | ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
- break;
-
- case '+':
- flags |= ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
- | ASM_CONSTRAINT_FLAG_MODIFIER_READ;
- break;
+ /* Skip out/in-out marker */
+ case '=': break;
+ case '+': break;
case '*':
++c;
ir_node *gen_ASM(ir_node *node)
{
ir_graph *irg = current_ir_graph;
-#ifdef FIRM_GRGEN_BE
- ir_node *new_block = get_nodes_block(node);
-#else
- ir_node *block = get_nodes_block(node);
- ir_node *new_block = be_transform_node(block);
-#endif
+ ir_node *block = NULL;
+ ir_node *new_block = NULL;
dbg_info *dbgi = get_irn_dbg_info(node);
int i, arity;
int out_idx;
memset(&clobber_bits, 0, sizeof(clobber_bits));
+ switch (be_transformer) {
+ case TRANSFORMER_DEFAULT:
+ block = get_nodes_block(node);
+ new_block = be_transform_node(block);
+ break;
+
+#ifdef FIRM_GRGEN_BE
+ case TRANSFORMER_PBQP:
+ new_block = get_nodes_block(node);
+ break;
+#endif
+
+ default:
+ panic("invalid transformer");
+ }
+
/* workaround for lots of buggy code out there as most people think volatile
* asm is enough for everything and forget the flags (linux kernel, etc.)
*/
clobbers = get_ASM_clobbers(node);
n_clobbers = 0;
- for(i = 0; i < get_ASM_n_clobbers(node); ++i) {
+ for (i = 0; i < get_ASM_n_clobbers(node); ++i) {
const arch_register_req_t *req;
const char *c = get_id_str(clobbers[i]);
out_constraints = get_ASM_output_constraints(node);
/* determine size of register_map */
- for(out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
+ for (out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
const ir_asm_constraint *constraint = &out_constraints[out_idx];
if (constraint->pos > reg_map_size)
reg_map_size = constraint->pos;
}
- for(i = 0; i < arity; ++i) {
+ for (i = 0; i < arity; ++i) {
const ir_asm_constraint *constraint = &in_constraints[i];
if(constraint->pos > reg_map_size)
reg_map_size = constraint->pos;
/* construct output constraints */
out_reg_reqs = obstack_alloc(obst, out_arity * sizeof(out_reg_reqs[0]));
- for(out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
+ for (out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
const ir_asm_constraint *constraint = &out_constraints[out_idx];
const char *c = get_id_str(constraint->constraint);
unsigned pos = constraint->pos;
/* inputs + input constraints */
in_reg_reqs = obstack_alloc(obst, arity * sizeof(in_reg_reqs[0]));
- for(i = 0; i < arity; ++i) {
+ for (i = 0; i < arity; ++i) {
ir_node *pred = get_irn_n(node, i);
const ir_asm_constraint *constraint = &in_constraints[i];
ident *constr_id = constraint->constraint;
}
if (input == NULL) {
+ ir_node *pred = NULL;
+ switch (be_transformer) {
+ case TRANSFORMER_DEFAULT:
+ pred = get_irn_n(node, i);
+ input = be_transform_node(pred);
+ break;
+
#ifdef FIRM_GRGEN_BE
- input = get_irn_n(node, i);
-#else
- ir_node *pred = get_irn_n(node, i);
- input = be_transform_node(pred);
+ case TRANSFORMER_PBQP:
+ input = get_irn_n(node, i);
+ break;
#endif
+ default: panic("invalid transformer");
+ }
+
if (parsed_constraint.cls == NULL
&& parsed_constraint.same_as < 0) {
is_memory_op = 1;
}
/* parse clobbers */
- for(i = 0; i < get_ASM_n_clobbers(node); ++i) {
+ for (i = 0; i < get_ASM_n_clobbers(node); ++i) {
const char *c = get_id_str(clobbers[i]);
const arch_register_req_t *req;
new_node = new_rd_ia32_Asm(dbgi, irg, new_block, arity, in, out_arity,
get_ASM_text(node), register_map);
+ /* Prevent the ASM node from being scheduled before the Barrier, if it has
+ * no inputs */
+ if (arity == 0 && get_irg_start_block(irg) == new_block) {
+ add_irn_dep(new_node, get_irg_frame(irg));
+ }
+
set_ia32_out_req_all(new_node, out_reg_reqs);
set_ia32_in_req_all(new_node, in_reg_reqs);
return new_node;
}
+ir_node *gen_CopyB(ir_node *node) {
+ ir_node *block = NULL;
+ ir_node *src = NULL;
+ ir_node *new_src = NULL;
+ ir_node *dst = NULL;
+ ir_node *new_dst = NULL;
+ ir_node *mem = NULL;
+ ir_node *new_mem = NULL;
+ ir_node *res = NULL;
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ int size = get_type_size_bytes(get_CopyB_type(node));
+ int rem;
+
+ switch (be_transformer) {
+ case TRANSFORMER_DEFAULT:
+ block = be_transform_node(get_nodes_block(node));
+ src = get_CopyB_src(node);
+ new_src = be_transform_node(src);
+ dst = get_CopyB_dst(node);
+ new_dst = be_transform_node(dst);
+ mem = get_CopyB_mem(node);
+ new_mem = be_transform_node(mem);
+ break;
+
+#ifdef FIRM_GRGEN_BE
+ case TRANSFORMER_PBQP:
+ block = get_nodes_block(node);
+ new_src = get_CopyB_src(node);
+ new_dst = get_CopyB_dst(node);
+ new_mem = get_CopyB_mem(node);
+ break;
+#endif
+
+ default: panic("invalid transformer");
+ }
+
+ /* If we have to copy more than 32 bytes, we use REP MOVSx and */
+ /* then we need the size explicitly in ECX. */
+ if (size >= 32 * 4) {
+ rem = size & 0x3; /* size % 4 */
+ size >>= 2;
+
+ res = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, size);
+ add_irn_dep(res, get_irg_frame(irg));
+
+ res = new_rd_ia32_CopyB(dbgi, irg, block, new_dst, new_src, res, new_mem, rem);
+ } else {
+ if(size == 0) {
+ ir_fprintf(stderr, "Optimization warning copyb %+F with size <4\n",
+ node);
+ }
+ res = new_rd_ia32_CopyB_i(dbgi, irg, block, new_dst, new_src, new_mem, size);
+ }
+
+ SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
+
+ return res;
+}
+
+ir_node *gen_Proj_tls(ir_node *node) {
+ ir_node *block = NULL;
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = NULL;
+ ir_node *res = NULL;
+
+ switch (be_transformer) {
+ case TRANSFORMER_DEFAULT:
+ block = be_transform_node(get_nodes_block(node));
+ break;
+
+#ifdef FIRM_GRGEN_BE
+ case TRANSFORMER_PBQP:
+ block = get_nodes_block(node);
+ break;
+#endif
+
+ default: panic("invalid transformer");
+ }
+
+ res = new_rd_ia32_LdTls(dbgi, irg, block, mode_Iu);
+
+ return res;
+}
+
ir_node *gen_Unknown(ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
if (same_as >= n_outs)
panic("invalid output number in same_as constraint");
- other_constr = out_reqs[same_as];
+ other_constr = out_reqs[same_as];
- req = obstack_alloc(obst, sizeof(req[0]));
- req->cls = other_constr->cls;
- req->type = arch_register_req_type_should_be_same;
- req->limited = NULL;
- req->other_same = 1U << pos;
- req->other_different = 0;
+ req = obstack_alloc(obst, sizeof(req[0]));
+ *req = *other_constr;
+ req->type |= arch_register_req_type_should_be_same;
+ req->other_same = 1U << pos;
/* switch constraints. This is because in firm we have same_as
* constraints on the output constraints while in the gcc asm syntax
unsigned *limited;
if(reg == NULL) {
- panic("Register '%s' mentioned in asm clobber is unknown\n", clobber);
+ panic("Register '%s' mentioned in asm clobber is unknown", clobber);
}
assert(reg->index < 32);