3 # This is the specification for the ia32 assembler Firm-operations
9 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
12 # The node description is done as a perl hash initializer with the
13 # following structure:
18 # op_flags => "N|L|C|X|I|F|Y|H|c|K",
20 # arity => "0|1|2|3 ... |variable|dynamic|any",
21 # state => "floats|pinned|mem_pinned|exc_pinned",
23 # { type => "type 1", name => "name 1" },
24 # { type => "type 2", name => "name 2" },
27 # comment => "any comment for constructor",
28 # reg_req => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
29 # cmp_attr => "c source code for comparing node attributes",
30 # outs => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
31 # ins => { "in1", "in2" } # optional, creates n_op_in1, ... consts
32 # mode => "mode_Iu" # optional, predefines the mode
33 # emit => "emit code with templates",
34 # attr => "additional attribute arguments for constructor",
35 # init_attr => "emit attribute initialization template",
36 # rd_constructor => "c source code which constructs an ir_node",
37 # hash_func => "name of the hash function for this operation",
38 # latency => "latency of this operation (can be float)"
39 # attr_type => "name of the attribute struct",
40 # modified_flags => [ "CF", ... ] # optional, list of modified flags
43 # ... # (all nodes you need to describe)
45 # ); # close the %nodes initializer
47 # op_flags: flags for the operation, OPTIONAL (default is "N")
48 # the op_flags correspond to the firm irop_flags:
51 # C irop_flag_commutative
52 # X irop_flag_cfopcode
53 # I irop_flag_ip_cfopcode
56 # H irop_flag_highlevel
57 # c irop_flag_constlike
59 # NB irop_flag_dump_noblock
60 # NI irop_flag_dump_noinput
62 # irn_flags: special node flags, OPTIONAL (default is 0)
63 # following irn_flags are supported:
67 # state: state of the operation, OPTIONAL (default is "floats")
69 # arity: arity of the operation, MUST NOT BE OMITTED
71 # args: the OPTIONAL arguments of the node constructor (debug, irg and block
72 # are always the first 3 arguments and are always autmatically
74 # If this key is missing the following arguments will be created:
75 # for i = 1 .. arity: ir_node *op_i
78 # outs: if a node defines more than one output, the names of the projections
79 # nodes having outs having automatically the mode mode_T
80 # example: [ "frame", "stack", "M" ]
82 # comment: OPTIONAL comment for the node constructor
84 # rd_constructor: for every operation there will be a
85 # new_rd_<arch>_<op-name> function with the arguments from above
86 # which creates the ir_node corresponding to the defined operation
87 # you can either put the complete source code of this function here
89 # This key is OPTIONAL. If omitted, the following constructor will
91 # if (!op_<arch>_<op-name>) assert(0);
95 # res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
98 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
102 # 0 - no special type
103 # 1 - caller save (register must be saved by the caller of a function)
104 # 2 - callee save (register must be saved by the called function)
105 # 4 - ignore (do not automatically assign this register)
106 # 8 - emitter can choose an arbitrary register of this class
107 # 16 - the register is a virtual one
108 # 32 - register represents a state
109 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
112 { name => "edx", type => 1 },
113 { name => "ecx", type => 1 },
114 { name => "eax", type => 1 },
115 { name => "ebx", type => 2 },
116 { name => "esi", type => 2 },
117 { name => "edi", type => 2 },
118 { name => "ebp", type => 2 },
119 { name => "esp", type => 4 },
120 { name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
121 { name => "gp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
122 { mode => "mode_Iu" }
125 { name => "mm0", type => 4 },
126 { name => "mm1", type => 4 },
127 { name => "mm2", type => 4 },
128 { name => "mm3", type => 4 },
129 { name => "mm4", type => 4 },
130 { name => "mm5", type => 4 },
131 { name => "mm6", type => 4 },
132 { name => "mm7", type => 4 },
133 { mode => "mode_E", flags => "manual_ra" }
136 { name => "xmm0", type => 1 },
137 { name => "xmm1", type => 1 },
138 { name => "xmm2", type => 1 },
139 { name => "xmm3", type => 1 },
140 { name => "xmm4", type => 1 },
141 { name => "xmm5", type => 1 },
142 { name => "xmm6", type => 1 },
143 { name => "xmm7", type => 1 },
144 { name => "xmm_NOREG", type => 4 | 16 }, # we need a dummy register for NoReg nodes
145 { name => "xmm_UKNWN", type => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
149 { name => "vf0", type => 1 },
150 { name => "vf1", type => 1 },
151 { name => "vf2", type => 1 },
152 { name => "vf3", type => 1 },
153 { name => "vf4", type => 1 },
154 { name => "vf5", type => 1 },
155 { name => "vf6", type => 1 },
156 { name => "vf7", type => 1 },
157 { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
158 { name => "vfp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
162 { name => "st0", realname => "st", type => 4 },
163 { name => "st1", realname => "st(1)", type => 4 },
164 { name => "st2", realname => "st(2)", type => 4 },
165 { name => "st3", realname => "st(3)", type => 4 },
166 { name => "st4", realname => "st(4)", type => 4 },
167 { name => "st5", realname => "st(5)", type => 4 },
168 { name => "st6", realname => "st(6)", type => 4 },
169 { name => "st7", realname => "st(7)", type => 4 },
170 { mode => "mode_E", flags => "manual_ra" }
172 fp_cw => [ # the floating point control word
173 { name => "fpcw", type => 4|32 },
174 { mode => "mode_fpcw", flags => "manual_ra|state" }
177 { name => "eflags", type => 0 },
178 { mode => "mode_Iu", flags => "manual_ra" }
183 GP => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
184 SSE => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
185 VFP => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
186 BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
191 bundels_per_cycle => 1
195 S0 => "${arch}_emit_source_register(node, 0);",
196 S1 => "${arch}_emit_source_register(node, 1);",
197 S2 => "${arch}_emit_source_register(node, 2);",
198 S3 => "${arch}_emit_source_register(node, 3);",
199 SB0 => "${arch}_emit_8bit_source_register_or_immediate(node, 0);",
200 SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
201 SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
202 SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
203 SH0 => "${arch}_emit_8bit_high_source_register(node, 0);",
204 SS0 => "${arch}_emit_16bit_source_register_or_immediate(node, 0);",
205 SI0 => "${arch}_emit_source_register_or_immediate(node, 0);",
206 SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
207 SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
208 D0 => "${arch}_emit_dest_register(node, 0);",
209 D1 => "${arch}_emit_dest_register(node, 1);",
210 DS0 => "${arch}_emit_dest_register_size(node, 0);",
211 DB0 => "${arch}_emit_8bit_dest_register(node, 0);",
212 X0 => "${arch}_emit_x87_register(node, 0);",
213 X1 => "${arch}_emit_x87_register(node, 1);",
214 EX => "${arch}_emit_extend_suffix(node);",
215 M => "${arch}_emit_mode_suffix(node);",
216 XM => "${arch}_emit_x87_mode_suffix(node);",
217 XXM => "${arch}_emit_xmm_mode_suffix(node);",
218 XSD => "${arch}_emit_xmm_mode_suffix_s(node);",
219 AM => "${arch}_emit_am(node);",
220 unop3 => "${arch}_emit_unop(node, n_ia32_unary_op);",
221 unop4 => "${arch}_emit_unop(node, n_ia32_binary_right);",
222 binop => "${arch}_emit_binop(node);",
223 x87_binop => "${arch}_emit_x87_binop(node);",
224 CMP0 => "${arch}_emit_cmp_suffix_node(node, 0);",
225 CMP3 => "${arch}_emit_cmp_suffix_node(node, 3);",
228 #--------------------------------------------------#
231 # _ __ _____ __ _ _ __ ___ _ __ ___ #
232 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
233 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
234 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
237 #--------------------------------------------------#
239 $default_op_attr_type = "ia32_op_attr_t";
240 $default_attr_type = "ia32_attr_t";
241 $default_copy_attr = "ia32_copy_attr";
243 sub ia32_custom_init_attr {
248 if(defined($node->{modified_flags})) {
249 $res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n";
251 if(defined($node->{am})) {
252 my $am = $node->{am};
253 if($am eq "source,unary") {
254 $res .= "\tset_ia32_am_support(res, ia32_am_unary);";
255 } elsif($am eq "source,binary") {
256 $res .= "\tset_ia32_am_support(res, ia32_am_binary);";
257 } elsif($am eq "none") {
260 die("Invalid address mode '$am' specified on op $name");
263 if($node->{state} ne "exc_pinned"
264 and $node->{state} ne "pinned") {
265 die("AM nodes must have pinned or AM pinned state ($name)");
271 $custom_init_attr_func = \&ia32_custom_init_attr;
275 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
276 "\tinit_ia32_x87_attributes(res);".
277 "\tinit_ia32_asm_attributes(res);",
279 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);",
281 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
282 "\tinit_ia32_call_attributes(res, pop, call_tp);",
283 ia32_condcode_attr_t =>
284 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
285 "\tinit_ia32_condcode_attributes(res, pnc);",
287 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
288 "\tinit_ia32_copyb_attributes(res, size);",
289 ia32_immediate_attr_t =>
290 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
291 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, no_pic_adjust, offset);",
293 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
294 "\tinit_ia32_x87_attributes(res);",
295 ia32_climbframe_attr_t =>
296 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
297 "\tinit_ia32_climbframe_attributes(res, count);",
301 ia32_asm_attr_t => "ia32_compare_asm_attr",
302 ia32_attr_t => "ia32_compare_nodes_attr",
303 ia32_call_attr_t => "ia32_compare_call_attr",
304 ia32_condcode_attr_t => "ia32_compare_condcode_attr",
305 ia32_copyb_attr_t => "ia32_compare_copyb_attr",
306 ia32_immediate_attr_t => "ia32_compare_immediate_attr",
307 ia32_x87_attr_t => "ia32_compare_x87_attr",
308 ia32_climbframe_attr_t => "ia32_compare_climbframe_attr",
314 $mode_xmm = "mode_E";
315 $mode_gp = "mode_Iu";
316 $mode_flags = "mode_Iu";
317 $mode_fpcw = "mode_fpcw";
318 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
319 $status_flags_wo_cf = [ "PF", "AF", "ZF", "SF", "OF" ];
320 $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
321 "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
328 reg_req => { out => [ "gp_NOREG:I" ] },
329 attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
330 attr_type => "ia32_immediate_attr_t",
331 hash_func => "ia32_hash_Immediate",
339 out_arity => "variable",
340 attr_type => "ia32_asm_attr_t",
341 attr => "ident *asm_text, const ia32_asm_reg_t *register_map",
342 init_attr => "attr->asm_text = asm_text;\n".
343 "\tattr->register_map = register_map;\n",
345 modified_flags => $status_flags,
348 # "allocates" a free register
352 reg_req => { out => [ "gp" ] },
357 cmp_attr => "return 1;",
360 #-----------------------------------------------------------------#
363 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
364 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
365 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
366 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
369 #-----------------------------------------------------------------#
371 # commutative operations
375 state => "exc_pinned",
376 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
377 out => [ "in_r4 in_r5", "flags", "none" ] },
378 ins => [ "base", "index", "mem", "left", "right" ],
379 outs => [ "res", "flags", "M" ],
380 emit => '. add%M %binop',
381 am => "source,binary",
385 modified_flags => $status_flags
390 state => "exc_pinned",
391 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
392 ins => [ "base", "index", "mem", "val" ],
393 emit => ". add%M %SI3, %AM",
397 modified_flags => $status_flags
402 state => "exc_pinned",
403 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
404 ins => [ "base", "index", "mem", "val" ],
405 emit => ". add%M %SB3, %AM",
409 modified_flags => $status_flags
413 state => "exc_pinned",
414 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
415 out => [ "in_r4 in_r5", "flags", "none" ] },
416 ins => [ "base", "index", "mem", "left", "right", "eflags" ],
417 outs => [ "res", "flags", "M" ],
418 emit => '. adc%M %binop',
419 am => "source,binary",
423 modified_flags => $status_flags
428 reg_req => { in => [ "none", "none" ], out => [ "none" ] },
429 ins => [ "left", "right" ],
433 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
434 ins => [ "left", "right", "eflags" ],
438 # we should not rematrialize this node. It produces 2 results and has
439 # very strict constraints
440 state => "exc_pinned",
441 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
442 out => [ "eax", "flags", "none", "edx" ] },
443 ins => [ "base", "index", "mem", "left", "right" ],
444 emit => '. mul%M %unop4',
445 outs => [ "res_low", "flags", "M", "res_high" ],
446 am => "source,binary",
449 modified_flags => $status_flags
453 # we should not rematrialize this node. It produces 2 results and has
454 # very strict constraints
456 cmp_attr => "return 1;",
457 reg_req => { in => [ "none", "none" ],
458 out => [ "none", "none", "none", "none" ] },
459 ins => [ "left", "right" ],
460 outs => [ "res_low", "flags", "M", "res_high" ],
465 state => "exc_pinned",
466 # TODO: adjust out requirements for the 3 operand form
467 # (no need for should_be_same then)
468 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
469 out => [ "in_r4 in_r5", "flags", "none" ] },
470 ins => [ "base", "index", "mem", "left", "right" ],
471 outs => [ "res", "flags", "M" ],
472 am => "source,binary",
476 modified_flags => $status_flags
481 state => "exc_pinned",
482 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
483 out => [ "eax", "flags", "none", "edx" ] },
484 ins => [ "base", "index", "mem", "left", "right" ],
485 emit => '. imul%M %unop4',
486 outs => [ "res_low", "flags", "M", "res_high" ],
487 am => "source,binary",
490 modified_flags => $status_flags
495 cmp_attr => "return 1;",
496 reg_req => { in => [ "none", "none" ],
497 out => [ "none", "none", "none", "none" ] },
498 ins => [ "left", "right" ],
499 outs => [ "res_low", "flags", "M", "res_high" ],
504 state => "exc_pinned",
505 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
506 out => [ "in_r4 in_r5", "flags", "none" ] },
507 ins => [ "base", "index", "mem", "left", "right" ],
508 outs => [ "res", "flags", "M" ],
509 op_modes => "commutative | am | immediate | mode_neutral",
510 am => "source,binary",
511 emit => '. and%M %binop',
515 modified_flags => $status_flags
520 state => "exc_pinned",
521 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
522 ins => [ "base", "index", "mem", "val" ],
523 emit => '. and%M %SI3, %AM',
527 modified_flags => $status_flags
532 state => "exc_pinned",
533 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
534 ins => [ "base", "index", "mem", "val" ],
535 emit => '. and%M %SB3, %AM',
539 modified_flags => $status_flags
544 state => "exc_pinned",
545 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
546 out => [ "in_r4 in_r5", "flags", "none" ] },
547 ins => [ "base", "index", "mem", "left", "right" ],
548 outs => [ "res", "flags", "M" ],
549 am => "source,binary",
550 emit => '. or%M %binop',
554 modified_flags => $status_flags
559 state => "exc_pinned",
560 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
561 ins => [ "base", "index", "mem", "val" ],
562 emit => '. or%M %SI3, %AM',
566 modified_flags => $status_flags
571 state => "exc_pinned",
572 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
573 ins => [ "base", "index", "mem", "val" ],
574 emit => '. or%M %SB3, %AM',
578 modified_flags => $status_flags
583 state => "exc_pinned",
584 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
585 out => [ "in_r4 in_r5", "flags", "none" ] },
586 ins => [ "base", "index", "mem", "left", "right" ],
587 outs => [ "res", "flags", "M" ],
588 am => "source,binary",
589 emit => '. xor%M %binop',
593 modified_flags => $status_flags
599 reg_req => { out => [ "gp", "flags" ] },
600 outs => [ "res", "flags" ],
601 emit => ". xor%M %D0, %D0",
605 modified_flags => $status_flags
610 state => "exc_pinned",
611 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
612 ins => [ "base", "index", "mem", "val" ],
613 emit => '. xor%M %SI3, %AM',
617 modified_flags => $status_flags
622 state => "exc_pinned",
623 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
624 ins => [ "base", "index", "mem", "val" ],
625 emit => '. xor%M %SB3, %AM',
629 modified_flags => $status_flags
632 # not commutative operations
636 state => "exc_pinned",
637 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
638 out => [ "in_r4", "flags", "none" ] },
639 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
640 outs => [ "res", "flags", "M" ],
641 am => "source,binary",
642 emit => '. sub%M %binop',
646 modified_flags => $status_flags
651 state => "exc_pinned",
652 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
653 ins => [ "base", "index", "mem", "subtrahend" ],
654 emit => '. sub%M %SI3, %AM',
658 modified_flags => $status_flags
663 state => "exc_pinned",
664 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
665 ins => [ "base", "index", "mem", "subtrahend" ],
666 emit => '. sub%M %SB3, %AM',
670 modified_flags => $status_flags
674 state => "exc_pinned",
675 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
676 out => [ "in_r4 !in_r5", "flags", "none" ] },
677 ins => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
678 outs => [ "res", "flags", "M" ],
679 am => "source,binary",
680 emit => '. sbb%M %binop',
684 modified_flags => $status_flags
689 reg_req => { in => [ "flags" ], out => [ "gp", "flags" ] },
690 outs => [ "res", "flags" ],
691 emit => ". sbb%M %D0, %D0",
695 modified_flags => $status_flags
699 reg_req => { in => [ "none", "none" ], out => [ "none" ] },
700 ins => [ "minuend", "subtrahend" ],
704 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
705 ins => [ "minuend", "subtrahend", "eflags" ],
710 state => "exc_pinned",
711 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
712 out => [ "eax", "flags", "none", "edx", "none" ] },
713 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
714 outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
715 am => "source,unary",
716 emit => ". idiv%M %unop3",
719 modified_flags => $status_flags
724 state => "exc_pinned",
725 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
726 out => [ "eax", "flags", "none", "edx", "none" ] },
727 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
728 outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
729 am => "source,unary",
730 emit => ". div%M %unop3",
733 modified_flags => $status_flags
738 reg_req => { in => [ "gp", "ecx" ],
739 out => [ "in_r1 !in_r2", "flags" ] },
740 ins => [ "val", "count" ],
741 outs => [ "res", "flags" ],
742 emit => '. shl%M %SB1, %S0',
746 modified_flags => $status_flags
751 state => "exc_pinned",
752 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
753 ins => [ "base", "index", "mem", "count" ],
754 emit => '. shl%M %SB3, %AM',
758 modified_flags => $status_flags
762 cmp_attr => "return 1;",
763 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
764 ins => [ "val", "count", "dep" ],
769 reg_req => { in => [ "gp", "gp", "ecx" ],
770 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
771 ins => [ "val_high", "val_low", "count" ],
772 outs => [ "res", "flags" ],
773 emit => ". shld%M %SB2, %S1, %D0",
777 modified_flags => $status_flags
781 cmp_attr => "return 1;",
782 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
783 ins => [ "val_high", "val_low", "count" ],
788 reg_req => { in => [ "gp", "ecx" ],
789 out => [ "in_r1 !in_r2", "flags" ] },
790 ins => [ "val", "count" ],
791 outs => [ "res", "flags" ],
792 emit => '. shr%M %SB1, %S0',
796 modified_flags => $status_flags
801 state => "exc_pinned",
802 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
803 ins => [ "base", "index", "mem", "count" ],
804 emit => '. shr%M %SB3, %AM',
808 modified_flags => $status_flags
812 cmp_attr => "return 1;",
813 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
814 ins => [ "val", "count", "dep" ],
819 reg_req => { in => [ "gp", "gp", "ecx" ],
820 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
821 ins => [ "val_high", "val_low", "count" ],
822 outs => [ "res", "flags" ],
823 emit => ". shrd%M %SB2, %S1, %D0",
827 modified_flags => $status_flags
831 cmp_attr => "return 1;",
832 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
833 ins => [ "val_high", "val_low", "count" ],
838 reg_req => { in => [ "gp", "ecx" ],
839 out => [ "in_r1 !in_r2", "flags" ] },
840 ins => [ "val", "count" ],
841 outs => [ "res", "flags" ],
842 emit => '. sar%M %SB1, %S0',
846 modified_flags => $status_flags
851 state => "exc_pinned",
852 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
853 ins => [ "base", "index", "mem", "count" ],
854 emit => '. sar%M %SB3, %AM',
858 modified_flags => $status_flags
862 cmp_attr => "return 1;",
863 ins => [ "val", "count", "dep" ],
864 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
869 reg_req => { in => [ "gp", "ecx" ],
870 out => [ "in_r1 !in_r2", "flags" ] },
871 ins => [ "val", "count" ],
872 outs => [ "res", "flags" ],
873 emit => '. ror%M %SB1, %S0',
877 modified_flags => $status_flags
882 state => "exc_pinned",
883 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
884 ins => [ "base", "index", "mem", "count" ],
885 emit => '. ror%M %SB3, %AM',
889 modified_flags => $status_flags
894 reg_req => { in => [ "gp", "ecx" ],
895 out => [ "in_r1 !in_r2", "flags" ] },
896 ins => [ "val", "count" ],
897 outs => [ "res", "flags" ],
898 emit => '. rol%M %SB1, %S0',
902 modified_flags => $status_flags
907 state => "exc_pinned",
908 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
909 ins => [ "base", "index", "mem", "count" ],
910 emit => '. rol%M %SB3, %AM',
914 modified_flags => $status_flags
921 reg_req => { in => [ "gp" ],
922 out => [ "in_r1", "flags" ] },
923 emit => '. neg%M %S0',
925 outs => [ "res", "flags" ],
929 modified_flags => $status_flags
934 state => "exc_pinned",
935 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
936 ins => [ "base", "index", "mem" ],
937 emit => '. neg%M %AM',
941 modified_flags => $status_flags
946 reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "in_r2" ] },
947 outs => [ "low_res", "high_res" ],
950 modified_flags => $status_flags
956 reg_req => { in => [ "gp" ],
957 out => [ "in_r1", "flags" ] },
959 outs => [ "res", "flags" ],
960 emit => '. inc%M %S0',
964 modified_flags => $status_flags_wo_cf
969 state => "exc_pinned",
970 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
971 ins => [ "base", "index", "mem" ],
972 emit => '. inc%M %AM',
976 modified_flags => $status_flags_wo_cf
981 reg_req => { in => [ "gp" ],
982 out => [ "in_r1", "flags" ] },
984 outs => [ "res", "flags" ],
985 emit => '. dec%M %S0',
989 modified_flags => $status_flags_wo_cf
994 state => "exc_pinned",
995 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
996 ins => [ "base", "index", "mem" ],
997 emit => '. dec%M %AM',
1001 modified_flags => $status_flags_wo_cf
1006 reg_req => { in => [ "gp" ],
1007 out => [ "in_r1", "flags" ] },
1009 outs => [ "res", "flags" ],
1010 emit => '. not%M %S0',
1019 state => "exc_pinned",
1020 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1021 ins => [ "base", "index", "mem" ],
1022 emit => '. not%M %AM',
1030 reg_req => { in => [ "flags" ], out => [ "flags" ] },
1034 mode => $mode_flags,
1035 modified_flags => $status_flags
1039 reg_req => { out => [ "flags" ] },
1043 mode => $mode_flags,
1044 modified_flags => $status_flags
1051 state => "exc_pinned",
1052 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
1053 out => [ "flags", "none", "none" ] },
1054 ins => [ "base", "index", "mem", "left", "right" ],
1055 outs => [ "eflags", "unused", "M" ],
1056 am => "source,binary",
1057 emit => '. cmp%M %binop',
1058 attr => "int ins_permuted, int cmp_unsigned",
1059 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1060 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1063 mode => $mode_flags,
1064 modified_flags => $status_flags
1069 state => "exc_pinned",
1070 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] ,
1071 out => [ "flags", "none", "none" ] },
1072 ins => [ "base", "index", "mem", "left", "right" ],
1073 outs => [ "eflags", "unused", "M" ],
1074 am => "source,binary",
1075 emit => '. cmpb %binop',
1076 attr => "int ins_permuted, int cmp_unsigned",
1077 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1078 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1081 mode => $mode_flags,
1082 modified_flags => $status_flags
1087 state => "exc_pinned",
1088 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] ,
1089 out => [ "flags", "none", "none" ] },
1090 ins => [ "base", "index", "mem", "left", "right" ],
1091 outs => [ "eflags", "unused", "M" ],
1092 am => "source,binary",
1093 emit => '. test%M %binop',
1094 attr => "int ins_permuted, int cmp_unsigned",
1095 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1096 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1099 mode => $mode_flags,
1100 modified_flags => $status_flags
1105 state => "exc_pinned",
1106 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] ,
1107 out => [ "flags", "none", "none" ] },
1108 ins => [ "base", "index", "mem", "left", "right" ],
1109 outs => [ "eflags", "unused", "M" ],
1110 am => "source,binary",
1111 emit => '. testb %binop',
1112 attr => "int ins_permuted, int cmp_unsigned",
1113 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1114 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1117 mode => $mode_flags,
1118 modified_flags => $status_flags
1123 reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
1124 ins => [ "eflags" ],
1126 attr_type => "ia32_condcode_attr_t",
1127 attr => "pn_Cmp pnc, int ins_permuted",
1128 init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1129 "\tset_ia32_ls_mode(res, mode_Bu);\n",
1130 emit => '. set%CMP0 %DB0',
1138 state => "exc_pinned",
1139 reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
1140 ins => [ "base", "index", "mem","eflags" ],
1141 attr_type => "ia32_condcode_attr_t",
1142 attr => "pn_Cmp pnc, int ins_permuted",
1143 init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1144 "\tset_ia32_ls_mode(res, mode_Bu);\n",
1145 emit => '. set%CMP3 %AM',
1153 # (note: leave the false,true order intact to make it compatible with other
1155 state => "exc_pinned",
1156 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ],
1157 out => [ "in_r4 in_r5", "flags", "none" ] },
1158 ins => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
1159 outs => [ "res", "flags", "M" ],
1160 am => "source,binary",
1161 attr_type => "ia32_condcode_attr_t",
1162 attr => "int ins_permuted, pn_Cmp pnc",
1163 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
1171 op_flags => "L|X|Y",
1172 reg_req => { in => [ "eflags" ], out => [ "none", "none" ] },
1173 ins => [ "eflags" ],
1174 outs => [ "false", "true" ],
1175 attr_type => "ia32_condcode_attr_t",
1176 attr => "pn_Cmp pnc",
1178 units => [ "BRANCH" ],
1183 op_flags => "L|X|Y",
1184 reg_req => { in => [ "gp" ] },
1186 attr_type => "ia32_condcode_attr_t",
1189 units => [ "BRANCH" ],
1190 modified_flags => $status_flags,
1191 init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
1198 reg_req => { out => [ "none" ] },
1200 units => [ "BRANCH" ],
1207 reg_req => { in => [ "gp", "gp", "none", "gp" ] },
1208 ins => [ "base", "index", "mem", "target" ],
1209 am => "source,unary",
1210 emit => '. jmp *%unop3',
1212 units => [ "BRANCH" ],
1214 init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
1220 reg_req => { out => [ "gp" ] },
1222 attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
1223 attr_type => "ia32_immediate_attr_t",
1230 reg_req => { out => [ "gp" ] },
1234 modified_flags => $status_flags,
1240 reg_req => { out => [ "gp_UKNWN:I" ] },
1250 reg_req => { out => [ "vfp_UKNWN:I" ] },
1255 attr_type => "ia32_x87_attr_t",
1261 reg_req => { out => [ "xmm_UKNWN:I" ] },
1270 op_flags => "c|NB|NI",
1271 reg_req => { out => [ "gp_NOREG:I" ] },
1280 op_flags => "c|NB|NI",
1281 reg_req => { out => [ "vfp_NOREG:I" ] },
1286 attr_type => "ia32_x87_attr_t",
1291 op_flags => "c|NB|NI",
1292 reg_req => { out => [ "xmm_NOREG:I" ] },
1302 reg_req => { out => [ "fpcw:I" ] },
1306 modified_flags => $fpcw_flags
1312 reg_req => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] },
1313 ins => [ "base", "index", "mem" ],
1315 emit => ". fldcw %AM",
1318 modified_flags => $fpcw_flags
1324 reg_req => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1325 ins => [ "base", "index", "mem", "fpcw" ],
1327 emit => ". fnstcw %AM",
1335 reg_req => { in => [ "fp_cw" ], out => [ "none" ] },
1343 # we should not rematrialize this node. It has very strict constraints.
1344 reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] },
1345 ins => [ "val", "clobbered" ],
1354 # Note that we add additional latency values depending on address mode, so a
1355 # lateny of 0 for load is correct
1359 state => "exc_pinned",
1360 reg_req => { in => [ "gp", "gp", "none" ],
1361 out => [ "gp", "none", "none", "none" ] },
1362 ins => [ "base", "index", "mem" ],
1363 outs => [ "res", "unused", "M", "X_exc" ],
1365 emit => ". mov%EX%.l %AM, %D0",
1371 state => "exc_pinned",
1372 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
1373 ins => [ "base", "index", "mem", "val" ],
1374 outs => [ "M", "X_exc" ],
1375 emit => '. mov%M %SI3, %AM',
1383 state => "exc_pinned",
1384 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] },
1385 ins => [ "base", "index", "mem", "val" ],
1386 outs => [ "M", "X_exc" ],
1387 emit => '. mov%M %SB3, %AM',
1395 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
1396 ins => [ "base", "index" ],
1397 emit => '. leal %AM, %D0',
1401 # lea doesn't modify the flags, but setting this seems advantageous since it
1402 # increases chances that the Lea is transformed back to an Add
1403 modified_flags => 1,
1407 state => "exc_pinned",
1408 reg_req => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp:I|S", "none" ] },
1409 ins => [ "base", "index", "mem", "val", "stack" ],
1410 emit => '. push%M %unop3',
1411 outs => [ "stack", "M" ],
1412 am => "source,unary",
1418 state => "exc_pinned",
1419 reg_req => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp:I|S" ] },
1420 ins => [ "mem", "stack" ],
1421 outs => [ "res", "M", "unused", "stack" ],
1422 emit => '. pop%M %D0',
1423 latency => 3, # Pop is more expensive than Push on Athlon
1428 state => "exc_pinned",
1429 reg_req => { in => [ "none", "esp" ], out => [ "ebp:I", "none", "none", "esp:I|S" ] },
1430 ins => [ "mem", "stack" ],
1431 outs => [ "res", "M", "unused", "stack" ],
1432 emit => '. pop%M %D0',
1433 latency => 3, # Pop is more expensive than Push on Athlon
1438 state => "exc_pinned",
1439 reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp:I|S" ] },
1440 ins => [ "base", "index", "mem", "stack" ],
1441 outs => [ "unused0", "M", "unused1", "stack" ],
1442 emit => '. pop%M %AM',
1443 latency => 3, # Pop is more expensive than Push on Athlon
1448 reg_req => { in => [ "esp" ], out => [ "ebp", "esp:I|S", "none" ] },
1450 outs => [ "frame", "stack", "M" ],
1456 reg_req => { in => [ "ebp" ], out => [ "ebp:I", "esp:I|S" ] },
1458 outs => [ "frame", "stack" ],
1465 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "none" ] },
1466 ins => [ "base", "index", "mem", "stack", "size" ],
1467 am => "source,binary",
1468 emit => '. addl %binop',
1470 outs => [ "stack", "M" ],
1472 modified_flags => $status_flags
1477 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "gp", "none" ] },
1478 ins => [ "base", "index", "mem", "stack", "size" ],
1479 am => "source,binary",
1480 emit => ". subl %binop\n".
1481 ". movl %%esp, %D1",
1483 outs => [ "stack", "addr", "M" ],
1485 modified_flags => $status_flags
1498 reg_req => { out => [ "gp" ] },
1504 # BT supports source address mode, but this is unused yet
1508 state => "exc_pinned",
1509 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
1510 ins => [ "left", "right" ],
1511 emit => '. bt%M %S1, %S0',
1514 mode => $mode_flags,
1515 modified_flags => $status_flags # only CF is set, but the other flags are undefined
1520 state => "exc_pinned",
1521 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1522 out => [ "gp", "flags", "none" ] },
1523 ins => [ "base", "index", "mem", "operand" ],
1524 outs => [ "res", "flags", "M" ],
1525 am => "source,binary",
1526 emit => '. bsf%M %unop3, %D0',
1530 modified_flags => $status_flags
1535 state => "exc_pinned",
1536 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1537 out => [ "gp", "flags", "none" ] },
1538 ins => [ "base", "index", "mem", "operand" ],
1539 outs => [ "res", "flags", "M" ],
1540 am => "source,binary",
1541 emit => '. bsr%M %unop3, %D0',
1545 modified_flags => $status_flags
1549 # SSE4.2 or SSE4a popcnt instruction
1553 state => "exc_pinned",
1554 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1555 out => [ "gp", "flags", "none" ] },
1556 ins => [ "base", "index", "mem", "operand" ],
1557 outs => [ "res", "flags", "M" ],
1558 am => "source,binary",
1559 emit => '. popcnt%M %unop3, %D0',
1563 modified_flags => $status_flags
1567 state => "exc_pinned",
1569 in => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ],
1570 out => [ "esp:I|S", "fpcw:I", "none", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ]
1572 ins => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ],
1573 outs => [ "stack", "fpcw", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ],
1574 attr_type => "ia32_call_attr_t",
1575 attr => "unsigned pop, ir_type *call_tp",
1576 am => "source,unary",
1577 units => [ "BRANCH" ],
1578 latency => 4, # random number
1579 modified_flags => $status_flags
1583 # a Helper node for frame-climbing, needed for __builtin_(frame|return)_address
1585 # PS: try gcc __builtin_frame_address(100000) :-)
1588 reg_req => { in => [ "gp", "gp", "gp"], out => [ "in_r3" ] },
1589 ins => [ "frame", "cnt", "tmp" ],
1591 latency => 4, # random number
1592 attr_type => "ia32_climbframe_attr_t",
1593 attr => "unsigned count",
1603 reg_req => { in => [ "gp" ],
1604 out => [ "in_r1" ] },
1605 emit => '. bswap%M %S0',
1613 # bswap16, use xchg here
1617 reg_req => { in => [ "eax ebx ecx edx" ],
1618 out => [ "in_r1" ] },
1619 emit => '. xchg %SB0, %SH0',
1631 reg_req => { in => [ "none" ], out => [ "none" ] },
1640 # Undefined Instruction on ALL x86 CPU's
1644 reg_req => { in => [ "none" ], out => [ "none" ] },
1647 emit => ". .value 0x0b0f",
1658 reg_req => { in => [ "edx", "eax", "none" ], out => [ "none" ] },
1659 ins => [ "port", "value", "mem" ],
1660 emit => '. out%M %SS0, %SI1',
1664 modified_flags => $status_flags
1673 reg_req => { in => [ "edx", "none" ], out => [ "eax", "none" ] },
1674 ins => [ "port", "mem" ],
1675 outs => [ "res", "M" ],
1676 emit => '. in%M %DS0, %SS0',
1680 modified_flags => $status_flags
1684 # Intel style prefetching
1688 state => "exc_pinned",
1689 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1690 ins => [ "base", "index", "mem" ],
1693 emit => ". prefetcht0 %AM",
1699 state => "exc_pinned",
1700 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1701 ins => [ "base", "index", "mem" ],
1704 emit => ". prefetcht1 %AM",
1710 state => "exc_pinned",
1711 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1712 ins => [ "base", "index", "mem" ],
1715 emit => ". prefetcht2 %AM",
1721 state => "exc_pinned",
1722 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1723 ins => [ "base", "index", "mem" ],
1726 emit => ". prefetchnta %AM",
1731 # 3DNow! prefetch instructions
1735 state => "exc_pinned",
1736 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1737 ins => [ "base", "index", "mem" ],
1740 emit => ". prefetch %AM",
1746 state => "exc_pinned",
1747 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1748 ins => [ "base", "index", "mem" ],
1751 emit => ". prefetchw %AM",
1755 #-----------------------------------------------------------------------------#
1756 # _____ _____ ______ __ _ _ _ #
1757 # / ____/ ____| ____| / _| | | | | | #
1758 # | (___| (___ | |__ | |_| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
1759 # \___ \\___ \| __| | _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1760 # ____) |___) | |____ | | | | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
1761 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1762 #-----------------------------------------------------------------------------#
1767 reg_req => { out => [ "xmm" ] },
1768 emit => '. xorp%XSD %D0, %D0',
1776 reg_req => { out => [ "xmm" ] },
1777 emit => '. pxor %D0, %D0',
1783 # produces all 1 bits
1786 reg_req => { out => [ "xmm" ] },
1787 emit => '. pcmpeqb %D0, %D0',
1793 # integer shift left, dword
1796 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1797 emit => '. pslld %SI1, %D0',
1803 # integer shift left, qword
1806 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1807 emit => '. psllq %SI1, %D0',
1813 # integer shift right, dword
1816 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1817 emit => '. psrld %SI1, %D0',
1823 # mov from integer to SSE register
1826 reg_req => { in => [ "gp" ], out => [ "xmm" ] },
1827 emit => '. movd %S0, %D0',
1833 # commutative operations
1837 state => "exc_pinned",
1838 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1839 out => [ "in_r4 in_r5", "flags", "none" ] },
1840 ins => [ "base", "index", "mem", "left", "right" ],
1841 outs => [ "res", "flags", "M" ],
1842 am => "source,binary",
1843 emit => '. add%XXM %binop',
1851 state => "exc_pinned",
1852 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1853 out => [ "in_r4 in_r5", "flags", "none" ] },
1854 ins => [ "base", "index", "mem", "left", "right" ],
1855 outs => [ "res", "flags", "M" ],
1856 am => "source,binary",
1857 emit => '. mul%XXM %binop',
1865 state => "exc_pinned",
1866 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1867 out => [ "in_r4 in_r5", "flags", "none" ] },
1868 ins => [ "base", "index", "mem", "left", "right" ],
1869 outs => [ "res", "flags", "M" ],
1870 am => "source,binary",
1871 emit => '. max%XXM %binop',
1879 state => "exc_pinned",
1880 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1881 out => [ "in_r4 in_r5", "flags", "none" ] },
1882 ins => [ "base", "index", "mem", "left", "right" ],
1883 outs => [ "res", "flags", "M" ],
1884 am => "source,binary",
1885 emit => '. min%XXM %binop',
1893 state => "exc_pinned",
1894 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1895 out => [ "in_r4 in_r5", "flags", "none" ] },
1896 ins => [ "base", "index", "mem", "left", "right" ],
1897 outs => [ "res", "flags", "M" ],
1898 am => "source,binary",
1899 emit => '. andp%XSD %binop',
1907 state => "exc_pinned",
1908 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1909 out => [ "in_r4 in_r5", "flags", "none" ] },
1910 ins => [ "base", "index", "mem", "left", "right" ],
1911 outs => [ "res", "flags", "M" ],
1912 am => "source,binary",
1913 emit => '. orp%XSD %binop',
1921 state => "exc_pinned",
1922 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1923 out => [ "in_r4 in_r5", "flags", "none" ] },
1924 ins => [ "base", "index", "mem", "left", "right" ],
1925 outs => [ "res", "flags", "M" ],
1926 am => "source,binary",
1927 emit => '. xorp%XSD %binop',
1933 # not commutative operations
1937 state => "exc_pinned",
1938 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1939 out => [ "in_r4 !in_r5", "flags", "none" ] },
1940 ins => [ "base", "index", "mem", "left", "right" ],
1941 outs => [ "res", "flags", "M" ],
1942 am => "source,binary",
1943 emit => '. andnp%XSD %binop',
1951 state => "exc_pinned",
1952 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1953 out => [ "in_r4", "flags", "none" ] },
1954 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
1955 outs => [ "res", "flags", "M" ],
1956 am => "source,binary",
1957 emit => '. sub%XXM %binop',
1965 state => "exc_pinned",
1966 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1967 out => [ "in_r4 !in_r5", "flags", "none" ] },
1968 ins => [ "base", "index", "mem", "dividend", "divisor" ],
1969 outs => [ "res", "flags", "M" ],
1970 am => "source,binary",
1971 emit => '. div%XXM %binop',
1980 state => "exc_pinned",
1981 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1982 out => [ "eflags" ] },
1983 ins => [ "base", "index", "mem", "left", "right" ],
1984 outs => [ "flags" ],
1985 am => "source,binary",
1986 attr => "int ins_permuted",
1987 init_attr => "attr->data.ins_permuted = ins_permuted;",
1988 emit => ' .ucomi%XXM %binop',
1991 mode => $mode_flags,
1992 modified_flags => 1,
1999 state => "exc_pinned",
2000 reg_req => { in => [ "gp", "gp", "none" ],
2001 out => [ "xmm", "none", "none", "none" ] },
2002 ins => [ "base", "index", "mem" ],
2003 outs => [ "res", "unused", "M", "X_exc" ],
2004 emit => '. mov%XXM %AM, %D0',
2005 attr => "ir_mode *load_mode",
2006 init_attr => "attr->ls_mode = load_mode;",
2013 state => "exc_pinned",
2014 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] },
2015 ins => [ "base", "index", "mem", "val" ],
2016 outs => [ "M", "X_exc" ],
2017 emit => '. mov%XXM %S3, %AM',
2025 state => "exc_pinned",
2026 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none" ] },
2027 ins => [ "base", "index", "mem", "val" ],
2029 emit => '. mov%XXM %S3, %AM',
2037 state => "exc_pinned",
2038 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
2039 ins => [ "base", "index", "mem", "val" ],
2040 am => "source,unary",
2041 emit => '. cvtsi2ss %unop3, %D0',
2049 state => "exc_pinned",
2050 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
2051 ins => [ "base", "index", "mem", "val" ],
2052 am => "source,unary",
2053 emit => '. cvtsi2sd %unop3, %D0',
2062 cmp_attr => "return 1;",
2063 ins => [ "val_high", "val_low" ],
2064 reg_req => { in => [ "none", "none" ], out => [ "none" ] }
2069 cmp_attr => "return 1;",
2071 outs => [ "res_high", "res_low" ],
2072 reg_req => { in => [ "none" ], out => [ "none", "none" ] }
2080 reg_req => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
2081 outs => [ "DST", "SRC", "CNT", "M" ],
2082 attr_type => "ia32_copyb_attr_t",
2083 attr => "unsigned size",
2086 # we don't care about this flag, so no need to mark this node
2087 # modified_flags => [ "DF" ]
2093 reg_req => { in => [ "edi", "esi", "none" ], out => [ "edi", "esi", "none" ] },
2094 outs => [ "DST", "SRC", "M" ],
2095 attr_type => "ia32_copyb_attr_t",
2096 attr => "unsigned size",
2099 # we don't care about this flag, so no need to mark this node
2100 # modified_flags => [ "DF" ]
2106 state => "exc_pinned",
2107 reg_req => { in => [ "eax" ], out => [ "eax" ] },
2117 state => "exc_pinned",
2118 reg_req => { in => [ "gp", "gp", "none", "gp" ],
2119 out => [ "gp", "none", "none" ] },
2120 ins => [ "base", "index", "mem", "val" ],
2121 outs => [ "res", "flags", "M" ],
2122 am => "source,unary",
2125 attr => "ir_mode *smaller_mode",
2126 init_attr => "attr->ls_mode = smaller_mode;",
2131 state => "exc_pinned",
2132 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
2133 out => [ "gp", "none", "none" ] },
2134 ins => [ "base", "index", "mem", "val" ],
2135 outs => [ "res", "flags", "M" ],
2136 am => "source,unary",
2139 attr => "ir_mode *smaller_mode",
2140 init_attr => "attr->ls_mode = smaller_mode;",
2145 state => "exc_pinned",
2146 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
2147 ins => [ "base", "index", "mem", "val" ],
2148 am => "source,unary",
2155 state => "exc_pinned",
2156 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
2157 ins => [ "base", "index", "mem", "val" ],
2158 am => "source,unary",
2165 state => "exc_pinned",
2166 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
2167 ins => [ "base", "index", "mem", "val" ],
2168 am => "source,unary",
2174 #----------------------------------------------------------#
2176 # (_) | | | | / _| | | | #
2177 # __ ___ _ __| |_ _ _ __ _| | | |_| | ___ __ _| |_ #
2178 # \ \ / / | '__| __| | | |/ _` | | | _| |/ _ \ / _` | __| #
2179 # \ V /| | | | |_| |_| | (_| | | | | | | (_) | (_| | |_ #
2180 # \_/ |_|_| \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
2182 # _ __ ___ __| | ___ ___ #
2183 # | '_ \ / _ \ / _` |/ _ \/ __| #
2184 # | | | | (_) | (_| | __/\__ \ #
2185 # |_| |_|\___/ \__,_|\___||___/ #
2186 #----------------------------------------------------------#
2188 # rematerialisation disabled for all float nodes for now, because the fpcw
2189 # handler runs before spilling and we might end up with wrong fpcw then
2193 state => "exc_pinned",
2194 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2195 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
2196 am => "source,binary",
2200 attr_type => "ia32_x87_attr_t",
2205 state => "exc_pinned",
2206 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2207 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
2208 am => "source,binary",
2212 attr_type => "ia32_x87_attr_t",
2217 state => "exc_pinned",
2218 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2219 ins => [ "base", "index", "mem", "minuend", "subtrahend", "fpcw" ],
2220 am => "source,binary",
2224 attr_type => "ia32_x87_attr_t",
2228 state => "exc_pinned",
2229 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
2230 ins => [ "base", "index", "mem", "dividend", "divisor", "fpcw" ],
2231 am => "source,binary",
2232 outs => [ "res", "M" ],
2235 attr_type => "ia32_x87_attr_t",
2239 reg_req => { in => [ "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2240 ins => [ "left", "right", "fpcw" ],
2244 attr_type => "ia32_x87_attr_t",
2249 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2254 attr_type => "ia32_x87_attr_t",
2259 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2264 attr_type => "ia32_x87_attr_t",
2267 # virtual Load and Store
2272 state => "exc_pinned",
2273 reg_req => { in => [ "gp", "gp", "none" ],
2274 out => [ "vfp", "none", "none", "none" ] },
2275 ins => [ "base", "index", "mem" ],
2276 outs => [ "res", "unused", "M", "X_exc" ],
2277 attr => "ir_mode *load_mode",
2278 init_attr => "attr->attr.ls_mode = load_mode;",
2281 attr_type => "ia32_x87_attr_t",
2287 state => "exc_pinned",
2288 reg_req => { in => [ "gp", "gp", "none", "vfp" ],
2289 out => [ "none", "none" ] },
2290 ins => [ "base", "index", "mem", "val" ],
2291 outs => [ "M", "X_exc" ],
2292 attr => "ir_mode *store_mode",
2293 init_attr => "attr->attr.ls_mode = store_mode;",
2297 attr_type => "ia32_x87_attr_t",
2303 state => "exc_pinned",
2304 reg_req => { in => [ "gp", "gp", "none" ],
2305 out => [ "vfp", "none", "none" ] },
2306 outs => [ "res", "unused", "M" ],
2307 ins => [ "base", "index", "mem" ],
2310 attr_type => "ia32_x87_attr_t",
2314 state => "exc_pinned",
2315 reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ], out => [ "none" ] },
2316 ins => [ "base", "index", "mem", "val", "fpcw" ],
2321 attr_type => "ia32_x87_attr_t",
2324 # SSE3 fisttp instruction
2326 state => "exc_pinned",
2327 reg_req => { in => [ "gp", "gp", "none", "vfp" ], out => [ "in_r4", "none" ]},
2328 ins => [ "base", "index", "mem", "val" ],
2329 outs => [ "res", "M" ],
2332 attr_type => "ia32_x87_attr_t",
2340 reg_req => { out => [ "vfp" ] },
2345 attr_type => "ia32_x87_attr_t",
2350 reg_req => { out => [ "vfp" ] },
2355 attr_type => "ia32_x87_attr_t",
2360 reg_req => { out => [ "vfp" ] },
2365 attr_type => "ia32_x87_attr_t",
2370 reg_req => { out => [ "vfp" ] },
2375 attr_type => "ia32_x87_attr_t",
2380 reg_req => { out => [ "vfp" ] },
2385 attr_type => "ia32_x87_attr_t",
2390 reg_req => { out => [ "vfp" ] },
2395 attr_type => "ia32_x87_attr_t",
2400 reg_req => { out => [ "vfp" ] },
2405 attr_type => "ia32_x87_attr_t",
2411 # we can't allow to rematerialize this node so we don't have
2412 # accidently produce Phi(Fucom, Fucom(ins_permuted))
2414 reg_req => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
2415 ins => [ "left", "right" ],
2416 outs => [ "flags" ],
2417 attr => "int ins_permuted",
2418 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2421 attr_type => "ia32_x87_attr_t",
2427 reg_req => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
2428 ins => [ "left", "right" ],
2429 outs => [ "flags" ],
2430 attr => "int ins_permuted",
2431 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2434 attr_type => "ia32_x87_attr_t",
2440 reg_req => { in => [ "vfp" ], out => [ "eax" ] },
2442 outs => [ "flags" ],
2443 attr => "int ins_permuted",
2444 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2447 attr_type => "ia32_x87_attr_t",
2453 reg_req => { in => [ "eax" ], out => [ "eflags" ] },
2455 outs => [ "flags" ],
2459 mode => $mode_flags,
2462 #------------------------------------------------------------------------#
2463 # ___ _____ __ _ _ _ #
2464 # __ _( _ )___ | / _| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
2465 # \ \/ / _ \ / / | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
2466 # > < (_) |/ / | _| | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
2467 # /_/\_\___//_/ |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
2468 #------------------------------------------------------------------------#
2470 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
2471 # are swapped, we work this around in the emitter...
2474 state => "exc_pinned",
2475 rd_constructor => "NONE",
2477 emit => '. fadd%XM %x87_binop',
2479 attr_type => "ia32_x87_attr_t",
2483 state => "exc_pinned",
2484 rd_constructor => "NONE",
2486 emit => '. faddp%XM %x87_binop',
2488 attr_type => "ia32_x87_attr_t",
2492 state => "exc_pinned",
2493 rd_constructor => "NONE",
2495 emit => '. fmul%XM %x87_binop',
2497 attr_type => "ia32_x87_attr_t",
2501 state => "exc_pinned",
2502 rd_constructor => "NONE",
2504 emit => '. fmulp%XM %x87_binop',,
2506 attr_type => "ia32_x87_attr_t",
2510 state => "exc_pinned",
2511 rd_constructor => "NONE",
2513 emit => '. fsub%XM %x87_binop',
2515 attr_type => "ia32_x87_attr_t",
2519 state => "exc_pinned",
2520 rd_constructor => "NONE",
2522 # see note about gas bugs
2523 emit => '. fsubrp%XM %x87_binop',
2525 attr_type => "ia32_x87_attr_t",
2529 state => "exc_pinned",
2530 rd_constructor => "NONE",
2533 emit => '. fsubr%XM %x87_binop',
2535 attr_type => "ia32_x87_attr_t",
2539 state => "exc_pinned",
2540 rd_constructor => "NONE",
2543 # see note about gas bugs
2544 emit => '. fsubp%XM %x87_binop',
2546 attr_type => "ia32_x87_attr_t",
2550 rd_constructor => "NONE",
2554 attr_type => "ia32_x87_attr_t",
2557 # this node is just here, to keep the simulator running
2558 # we can omit this when a fprem simulation function exists
2560 rd_constructor => "NONE",
2562 emit => '. fprem1\n'.
2565 attr_type => "ia32_x87_attr_t",
2569 state => "exc_pinned",
2570 rd_constructor => "NONE",
2572 emit => '. fdiv%XM %x87_binop',
2574 attr_type => "ia32_x87_attr_t",
2578 state => "exc_pinned",
2579 rd_constructor => "NONE",
2581 # see note about gas bugs
2582 emit => '. fdivrp%XM %x87_binop',
2584 attr_type => "ia32_x87_attr_t",
2588 state => "exc_pinned",
2589 rd_constructor => "NONE",
2591 emit => '. fdivr%XM %x87_binop',
2593 attr_type => "ia32_x87_attr_t",
2597 state => "exc_pinned",
2598 rd_constructor => "NONE",
2600 # see note about gas bugs
2601 emit => '. fdivp%XM %x87_binop',
2603 attr_type => "ia32_x87_attr_t",
2607 rd_constructor => "NONE",
2611 attr_type => "ia32_x87_attr_t",
2616 rd_constructor => "NONE",
2620 attr_type => "ia32_x87_attr_t",
2623 # x87 Load and Store
2626 rd_constructor => "NONE",
2627 op_flags => "R|L|F",
2628 state => "exc_pinned",
2630 emit => '. fld%XM %AM',
2631 attr_type => "ia32_x87_attr_t",
2636 rd_constructor => "NONE",
2637 op_flags => "R|L|F",
2638 state => "exc_pinned",
2640 emit => '. fst%XM %AM',
2642 attr_type => "ia32_x87_attr_t",
2647 rd_constructor => "NONE",
2648 op_flags => "R|L|F",
2649 state => "exc_pinned",
2651 emit => '. fstp%XM %AM',
2653 attr_type => "ia32_x87_attr_t",
2660 state => "exc_pinned",
2661 rd_constructor => "NONE",
2663 emit => '. fild%XM %AM',
2664 attr_type => "ia32_x87_attr_t",
2669 state => "exc_pinned",
2670 rd_constructor => "NONE",
2672 emit => '. fist%XM %AM',
2674 attr_type => "ia32_x87_attr_t",
2679 state => "exc_pinned",
2680 rd_constructor => "NONE",
2682 emit => '. fistp%XM %AM',
2684 attr_type => "ia32_x87_attr_t",
2688 # SSE3 fisttp instruction
2690 state => "exc_pinned",
2691 rd_constructor => "NONE",
2693 emit => '. fisttp%XM %AM',
2695 attr_type => "ia32_x87_attr_t",
2702 op_flags => "R|c|K",
2704 reg_req => { out => [ "vfp" ] },
2706 attr_type => "ia32_x87_attr_t",
2711 op_flags => "R|c|K",
2713 reg_req => { out => [ "vfp" ] },
2715 attr_type => "ia32_x87_attr_t",
2720 op_flags => "R|c|K",
2722 reg_req => { out => [ "vfp" ] },
2724 attr_type => "ia32_x87_attr_t",
2729 op_flags => "R|c|K",
2731 reg_req => { out => [ "vfp" ] },
2733 attr_type => "ia32_x87_attr_t",
2738 op_flags => "R|c|K",
2740 reg_req => { out => [ "vfp" ] },
2742 attr_type => "ia32_x87_attr_t",
2747 op_flags => "R|c|K",
2749 reg_req => { out => [ "vfp" ] },
2750 emit => '. fldll2t',
2751 attr_type => "ia32_x87_attr_t",
2756 op_flags => "R|c|K",
2758 reg_req => { out => [ "vfp" ] },
2760 attr_type => "ia32_x87_attr_t",
2765 # Note that it is NEVER allowed to do CSE on these nodes
2766 # Moreover, note the virtual register requierements!
2770 reg_req => { out => [ "none" ] },
2771 cmp_attr => "return 1;",
2772 emit => '. fxch %X0',
2773 attr_type => "ia32_x87_attr_t",
2780 reg_req => { out => [ "none" ] },
2781 cmp_attr => "return 1;",
2782 emit => '. fld %X0',
2783 attr_type => "ia32_x87_attr_t",
2789 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2790 cmp_attr => "return 1;",
2791 emit => '. fld %X0',
2792 attr_type => "ia32_x87_attr_t",
2798 reg_req => { out => [ "none" ] },
2799 cmp_attr => "return 1;",
2800 emit => '. fstp %X0',
2801 attr_type => "ia32_x87_attr_t",
2808 reg_req => { out => [ "none" ] },
2809 cmp_attr => "return 1;",
2810 emit => '. ffreep %X0',
2811 attr_type => "ia32_x87_attr_t",
2818 reg_req => { out => [ "none" ] },
2819 cmp_attr => "return 1;",
2821 attr_type => "ia32_x87_attr_t",
2828 reg_req => { out => [ "none" ] },
2829 cmp_attr => "return 1;",
2831 attr_type => "ia32_x87_attr_t",
2840 emit => ". fucom %X1\n".
2842 attr_type => "ia32_x87_attr_t",
2848 emit => ". fucomp %X1\n".
2850 attr_type => "ia32_x87_attr_t",
2856 emit => ". fucompp\n".
2858 attr_type => "ia32_x87_attr_t",
2864 emit => '. fucomi %X1',
2865 attr_type => "ia32_x87_attr_t",
2871 emit => '. fucompi %X1',
2872 attr_type => "ia32_x87_attr_t",
2880 attr_type => "ia32_x87_attr_t",
2885 # -------------------------------------------------------------------------------- #
2886 # ____ ____ _____ _ _ #
2887 # / ___/ ___|| ____| __ _____ ___| |_ ___ _ __ _ __ ___ __| | ___ ___ #
2888 # \___ \___ \| _| \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __| #
2889 # ___) |__) | |___ \ V / __/ (__| || (_) | | | | | | (_) | (_| | __/\__ \ #
2890 # |____/____/|_____| \_/ \___|\___|\__\___/|_| |_| |_|\___/ \__,_|\___||___/ #
2892 # -------------------------------------------------------------------------------- #
2895 # Spilling and reloading of SSE registers, hardcoded, not generated #
2899 state => "exc_pinned",
2900 reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2901 emit => '. movdqu %D0, %AM',
2902 outs => [ "res", "M" ],
2909 state => "exc_pinned",
2910 reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
2911 ins => [ "base", "index", "mem", "val" ],
2912 emit => '. movdqu %binop',
2920 # Include the generated SIMD node specification written by the SIMD optimization
2921 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2922 unless ($return = do $my_script_name) {
2923 warn "couldn't parse $my_script_name: $@" if $@;
2924 warn "couldn't do $my_script_name: $!" unless defined $return;
2925 warn "couldn't run $my_script_name" unless $return;
2928 # Transform some attributes
2929 foreach my $op (keys(%nodes)) {
2930 my $node = $nodes{$op};
2931 my $op_attr_init = $node->{op_attr_init};
2933 if(defined($op_attr_init)) {
2934 $op_attr_init .= "\n\t";
2939 if(!defined($node->{latency})) {
2941 $node->{latency} = 0;
2943 die("Latency missing for op $op");
2946 $op_attr_init .= "attr->latency = ".$node->{latency} . ";";
2948 $node->{op_attr_init} = $op_attr_init;