X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fscripts%2Fgenerate_new_opcodes.pl;h=11e271d2354cf10e42e44ec731e469299cd1634e;hb=9f8583960d32b77955bc27cb18dbbe6f42a0a8f3;hp=224c592cac1824eda9b75ecd693f24978327418b;hpb=abf293cbed2074633dfb9aeff21675201cd20096;p=libfirm diff --git a/ir/be/scripts/generate_new_opcodes.pl b/ir/be/scripts/generate_new_opcodes.pl index 224c592ca..11e271d23 100755 --- a/ir/be/scripts/generate_new_opcodes.pl +++ b/ir/be/scripts/generate_new_opcodes.pl @@ -18,6 +18,8 @@ my $line_nr = 0; our $arch; our $additional_opcodes; our %nodes; +our %cpu; +our $default_cmp_attr; # include spec file @@ -61,9 +63,11 @@ push(@obst_header, "void ".$arch."_create_opcodes(void);\n"); push(@obst_enum_op, "typedef enum _$arch\_opcodes {\n"); foreach my $op (keys(%nodes)) { - my %n = %{ $nodes{"$op"} }; - my $tuple = 0; - my $n_res = 0; + my %n = %{ $nodes{"$op"} }; + my $known_mode; + my $n_res = 0; + my $num_outs = 0; + my @out_flags; # determine arity from in requirements $arity = exists($n{"arity"}) ? $n{"arity"} : 0; @@ -75,15 +79,29 @@ foreach my $op (keys(%nodes)) { $op = $arch."_".$op; $temp = ""; + # define some proj numbers if (exists($n{"outs"})) { undef my @outs; - @outs = @{ $n{"outs"} }; + + @outs = @{ $n{"outs"} }; + $num_outs = $#outs + 1; + push(@obst_proj, "\nenum pn_$op {\n"); + for (my $idx = 0; $idx <= $#outs; $idx++) { + # check, if we have additional flags annotated to out + if ($outs[$idx] =~ /:(S|I(\|(S|I))*)/) { + push(@out_flags, $1); + $outs[$idx] =~ s/:(S|I(\|(S|I))*)//; + } push(@obst_proj, " pn_$op\_".$outs[$idx]." = $idx,\n"); } + push(@obst_proj, "};\n"); - $tuple = 1; + $known_mode = "mode_T"; + } + if (exists($n{"mode"})) { + $known_mode = $n{"mode"}; } push(@obst_opvar, "ir_op *op_$op = NULL;\n"); @@ -98,13 +116,17 @@ foreach my $op (keys(%nodes)) { $cmp_attr_func = 0; # create compare attribute function if needed - if (exists($n{"cmp_attr"})) { + if (exists($n{"cmp_attr"}) || defined($default_cmp_attr)) { push(@obst_cmp_attr, "static int cmp_attr_$op(ir_node *a, ir_node *b) {\n"); - push(@obst_cmp_attr, " $arch\_attr_t *attr_a = get_$arch\_attr(a);\n"); - push(@obst_cmp_attr, " $arch\_attr_t *attr_b = get_$arch\_attr(b);\n"); - push(@obst_cmp_attr, " (void) attr_a;\n"); - push(@obst_cmp_attr, " (void) attr_b;\n"); - push(@obst_cmp_attr, $n{"cmp_attr"}); + push(@obst_cmp_attr, "\t$arch\_attr_t *attr_a = get_$arch\_attr(a);\n"); + push(@obst_cmp_attr, "\t$arch\_attr_t *attr_b = get_$arch\_attr(b);\n"); + push(@obst_cmp_attr, "\t(void) attr_a;\n"); + push(@obst_cmp_attr, "\t(void) attr_b;\n"); + if(exists($n{"cmp_attr"})) { + push(@obst_cmp_attr, "\t".$n{"cmp_attr"}."\n"); + } else { + push(@obst_cmp_attr, "\t$default_cmp_attr\n"); + } push(@obst_cmp_attr, "}\n\n"); $cmp_attr_func = 1; @@ -134,7 +156,7 @@ foreach my $op (keys(%nodes)) { $complete_args .= ", ir_node *op".$i; $arg_names .= ", op".$i; } - if ($tuple == 0) { + if (!defined($known_mode)) { $complete_args .= ", ir_mode *mode"; $arg_names .= ", mode"; } @@ -165,10 +187,17 @@ foreach my $op (keys(%nodes)) { next; } - $temp = " ir_node *res;\n"; - $temp .= " ir_node *in[$arity];\n" if ($arity > 0); - $temp .= " int flags = 0;\n"; - $temp .= " $arch\_attr_t *attr;\n" if (exists($n{"init_attr"})); + $temp = "\tir_node *res;\n"; + $temp .= "\tir_node *in[$arity];\n" if ($arity > 0); + $temp .= "\tint flags = 0;\n"; + $temp .= "\t$arch\_attr_t *attr;\n" if (exists($n{"init_attr"})); + + my $exec_units = "NULL"; + # set up static variables for cpu execution unit assigments + if (exists($n{"units"})) { + $temp .= gen_execunit_list_initializer($n{"units"}); + $exec_units = "_exec_units"; + } undef my $in_req_var; undef my $out_req_var; @@ -185,47 +214,49 @@ foreach my $op (keys(%nodes)) { if (@in) { $in_req_var = "_in_req_$op"; - $temp .= " static const $arch\_register_req_t *".$in_req_var."[] =\n {\n"; + $temp .= "\tstatic const $arch\_register_req_t *".$in_req_var."[] =\n"; + $temp .= "\t{\n"; for ($idx = 0; $idx <= $#in; $idx++) { - $temp .= " ".$op."_reg_req_in_".$idx.",\n"; + $temp .= "\t\t".$op."_reg_req_in_".$idx.",\n"; } - $temp .= " };\n"; + $temp .= "\t};\n"; } if (@out) { $out_req_var = "_out_req_$op"; - $temp .= " static const $arch\_register_req_t *".$out_req_var."[] =\n {\n"; + $temp .= "\tstatic const $arch\_register_req_t *".$out_req_var."[] =\n"; + $temp .= "\t{\n"; for ($idx = 0; $idx <= $#out; $idx++) { - $temp .= " ".$op."_reg_req_out_".$idx.",\n"; + $temp .= "\t\t".$op."_reg_req_out_".$idx.",\n"; } - $temp .= " };\n"; + $temp .= "\t};\n"; } } $temp .= "\n"; - $temp .= " if (!op_$op) {\n"; - $temp .= " assert(0);\n"; - $temp .= " return NULL;\n"; - $temp .= " }\n\n"; + $temp .= "\tif (!op_$op) {\n"; + $temp .= "\t\tassert(0);\n"; + $temp .= "\t\treturn NULL;\n"; + $temp .= "\t}\n\n"; for (my $i = 1; $i <= $arity; $i++) { - $temp .= " in[".($i - 1)."] = op".$i.";\n"; + $temp .= "\tin[".($i - 1)."] = op".$i.";\n"; } # set flags if (exists($n{"irn_flags"})) { foreach my $flag (split(/\|/, $n{"irn_flags"})) { if ($flag eq "R") { - $temp .= " flags |= arch_irn_flags_rematerializable; /* op can be easily recalculated */\n"; + $temp .= "\tflags |= arch_irn_flags_rematerializable; /* op can be easily recalculated */\n"; } elsif ($flag eq "N") { - $temp .= " flags |= arch_irn_flags_dont_spill; /* op is NOT spillable */\n"; + $temp .= "\tflags |= arch_irn_flags_dont_spill; /* op is NOT spillable */\n"; } elsif ($flag eq "I") { - $temp .= " flags |= arch_irn_flags_ignore; /* ignore op for register allocation */\n"; + $temp .= "\tflags |= arch_irn_flags_ignore; /* ignore op for register allocation */\n"; } elsif ($flag eq "S") { - $temp .= " flags |= arch_irn_flags_modify_sp; /* op modifies stack pointer */\n"; + $temp .= "\tflags |= arch_irn_flags_modify_sp; /* op modifies stack pointer */\n"; } } } @@ -249,18 +280,18 @@ foreach my $op (keys(%nodes)) { } if (@out) { - $out_param = $out_req_var.", ".($#out + 1); - $n_res = $#out; + $n_res = $#out + 1; + $out_param = "$out_req_var, $exec_units, $n_res"; } else { - $out_param = "NULL, 0"; + $out_param = "NULL, $exec_units, 0"; } } else { - $in_param = "NULL"; - $out_param = "NULL, 0"; + $in_param = "NULL"; + $out_param = "NULL, $exec_units, 0"; } - $temp .= "\n /* create node */\n"; + $temp .= "\n\t/* create node */\n"; my $latency = 1; if (exists($n{"latency"})) { @@ -268,24 +299,47 @@ foreach my $op (keys(%nodes)) { } my $mode = "mode"; - if ($tuple == 1) { - $mode = "mode_T"; + if (defined($known_mode)) { + $mode = $known_mode; + } + $temp .= "\tres = new_ir_node(db, irg, block, op_$op, $mode, $arity, ".($arity > 0 ? "in" : "NULL").");\n"; + + $temp .= "\n\t/* init node attributes */\n"; + $temp .= "\tinit_$arch\_attributes(res, flags, $in_param, $out_param, $latency);\n"; + + # set flags for outs + if ($#out_flags >= 0) { + $temp .= "\n\t/* set flags for outs */\n"; + for (my $idx = 0; $idx <= $#out_flags; $idx++) { + my $flags = ""; + my $prefix = ""; + + foreach my $flag (split(/\|/, $out_flags[$idx])) { + if ($flag eq "I") { + $flags .= $prefix."arch_irn_flags_ignore"; + $prefix = " | "; + } + elsif ($flag eq "S") { + $flags .= $prefix."arch_irn_flags_modify_sp"; + $prefix = " | "; + } + } + + $temp .= "\tset_$arch\_out_flags(res, $flags, $idx);\n"; + } } - $temp .= " res = new_ir_node(db, irg, block, op_$op, $mode, $arity, ".($arity > 0 ? "in" : "NULL").");\n"; - $temp .= "\n /* init node attributes */\n"; - $temp .= " init_$arch\_attributes(res, flags, $in_param, $out_param, $latency);\n"; if (exists($n{"init_attr"})) { - $temp .= " attr = get_$arch\_attr(res);\n"; + $temp .= "\tattr = get_$arch\_attr(res);\n"; $temp .= $n{"init_attr"}."\n"; } - $temp .= "\n /* optimize node */\n"; - $temp .= " res = optimize_node(res);\n"; - $temp .= " irn_vrfy_irg(res, irg);\n\n"; + $temp .= "\n\t/* optimize node */\n"; + $temp .= "\tres = optimize_node(res);\n"; + $temp .= "\tirn_vrfy_irg(res, irg);\n\n"; - $temp .= "\n return res;\n"; + $temp .= "\n\treturn res;\n"; push(@obst_constructor, $temp); } @@ -302,24 +356,24 @@ foreach my $op (keys(%nodes)) { $n{"op_flags"} = "N" if (! exists($n{"op_flags"})); - push(@obst_new_irop, "\n memset(&ops, 0, sizeof(ops));\n"); - push(@obst_new_irop, " ops.dump_node = $arch\_dump_node;\n"); + push(@obst_new_irop, "\n\tmemset(&ops, 0, sizeof(ops));\n"); + push(@obst_new_irop, "\tops.dump_node = $arch\_dump_node;\n"); if ($cmp_attr_func) { - push(@obst_new_irop, " ops.node_cmp_attr = cmp_attr_$op;\n"); + push(@obst_new_irop, "\tops.node_cmp_attr = cmp_attr_$op;\n"); } $n_opcodes++; - $temp = " op_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", ".$n{"op_flags"}; + $temp = "\top_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", ".$n{"op_flags"}; $temp .= "|M, ".translate_arity($arity).", 0, sizeof($arch\_attr_t) + $n_res * sizeof(arch_register_t *), &ops);\n"; push(@obst_new_irop, $temp); - push(@obst_new_irop, " set_op_tag(op_$op, &$arch\_op_tag);\n"); - push(@obst_enum_op, " iro_$op,\n"); + push(@obst_new_irop, "\tset_op_tag(op_$op, &$arch\_op_tag);\n"); + push(@obst_enum_op, "\tiro_$op,\n"); push(@obst_header, "\n"); } -push(@obst_enum_op, " iro_$arch\_last_generated,\n"); -push(@obst_enum_op, " iro_$arch\_last = iro_$arch\_last_generated"); +push(@obst_enum_op, "\tiro_$arch\_last_generated,\n"); +push(@obst_enum_op, "\tiro_$arch\_last = iro_$arch\_last_generated"); push(@obst_enum_op, " + $additional_opcodes") if (defined($additional_opcodes)); push(@obst_enum_op, "\n} $arch\_opcodes;\n\n"); @@ -368,23 +422,23 @@ print OUT< add them all + my $tp_name = "$arch\_execution_units_$unit"; + my $idx = 0; + foreach (@{ $cpu{"$unit"} }) { + next if ($idx++ == 0); # skip first element (it's not a unit) + my $unit_name = "$uc_arch\_EXECUNIT_TP_$unit\_$_"; + push(@{ $init{"$unit"} }, "\t\t&".$tp_name."[".$unit_name."]"); + } + } + else { + # operation can be executed only a certain unit + # -> find corresponding unit type + my $found = 0; +TP_SEARCH: foreach my $cur_type (keys(%cpu)) { + foreach my $cur_unit (@{ $cpu{"$cur_type"} }) { + if ($unit eq $cur_unit) { + my $tp_name = "$arch\_execution_units_$cur_type"; + my $unit_name = "$uc_arch\_EXECUNIT_TP_$cur_type\_$unit"; + push(@{ $init{"$unit"} }, "\t\t&".$tp_name."[".$unit_name."]"); + $found = 1; + last TP_SEARCH; + } + } + } + + if (! $found) { + print STDERR "Invalid execution unit $unit specified!\n"; + } + } + } + + # prepare the 2-dim array init + foreach my $key (keys(%init)) { + $ret .= "\tstatic const be_execution_unit_t *_allowed_units_".$key."[] =\n"; + $ret .= "\t{\n"; + foreach (@{ $init{"$key"} }) { + $ret .= "$_,\n"; + } + $ret .= "\t\tNULL\n"; + $ret .= "\t};\n"; + $ret2 .= "\t\t_allowed_units_$key,\n"; + } + $ret2 .= "\t\tNULL\n"; + + $ret .= "\tstatic const be_execution_unit_t **_exec_units[] =\n"; + $ret .= "\t{\n"; + $ret .= $ret2; + $ret .= "\t};\n"; + + return $ret; +}