3 # This is the specification for the ia32 assembler Firm-operations
9 $mode_fp87 = "ia32_mode_E";
11 $mode_flags = "mode_Iu";
12 $mode_fpcw = "ia32_mode_fpcw";
15 $normal = 0; # no special type
16 $ignore = 1; # ignore (do not assign this register)
17 $arbitrary = 2; # emitter can choose an arbitrary register of this class
18 $virtual = 4; # the register is a virtual one
19 $state = 8; # register represents a state
20 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
30 { name => "esp", type => $ignore },
31 { name => "gp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes
35 { name => "mm0", type => $ignore },
36 { name => "mm1", type => $ignore },
37 { name => "mm2", type => $ignore },
38 { name => "mm3", type => $ignore },
39 { name => "mm4", type => $ignore },
40 { name => "mm5", type => $ignore },
41 { name => "mm6", type => $ignore },
42 { name => "mm7", type => $ignore },
43 { mode => $mode_mmx, flags => "manual_ra" }
54 { name => "xmm_NOREG", type => $ignore | $virtual }, # we need a dummy register for NoReg nodes
66 { name => "vfp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes
67 { mode => $mode_fp87 }
70 { name => "st0", realname => "st", type => $ignore },
71 { name => "st1", realname => "st(1)", type => $ignore },
72 { name => "st2", realname => "st(2)", type => $ignore },
73 { name => "st3", realname => "st(3)", type => $ignore },
74 { name => "st4", realname => "st(4)", type => $ignore },
75 { name => "st5", realname => "st(5)", type => $ignore },
76 { name => "st6", realname => "st(6)", type => $ignore },
77 { name => "st7", realname => "st(7)", type => $ignore },
78 { mode => $mode_fp87, flags => "manual_ra" }
80 fp_cw => [ # the floating point control word
81 { name => "fpcw", type => $ignore | $state },
82 { mode => $mode_fpcw, flags => "manual_ra|state" }
85 { name => "eflags", type => 0 },
86 { mode => "mode_Iu", flags => "manual_ra" }
91 GP => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
92 SSE => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
93 VFP => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
94 BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
99 bundels_per_cycle => 1
103 S0 => "${arch}_emit_source_register(node, 0);",
104 S1 => "${arch}_emit_source_register(node, 1);",
105 S2 => "${arch}_emit_source_register(node, 2);",
106 S3 => "${arch}_emit_source_register(node, 3);",
107 SB0 => "${arch}_emit_8bit_source_register_or_immediate(node, 0);",
108 SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
109 SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
110 SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
111 SH0 => "${arch}_emit_8bit_high_source_register(node, 0);",
112 SS0 => "${arch}_emit_16bit_source_register_or_immediate(node, 0);",
113 SI0 => "${arch}_emit_source_register_or_immediate(node, 0);",
114 SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
115 SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
116 D0 => "${arch}_emit_dest_register(node, 0);",
117 D1 => "${arch}_emit_dest_register(node, 1);",
118 DS0 => "${arch}_emit_dest_register_size(node, 0);",
119 DB0 => "${arch}_emit_8bit_dest_register(node, 0);",
120 X0 => "${arch}_emit_x87_register(node, 0);",
121 X1 => "${arch}_emit_x87_register(node, 1);",
122 EX => "${arch}_emit_extend_suffix(node);",
123 M => "${arch}_emit_mode_suffix(node);",
124 XM => "${arch}_emit_x87_mode_suffix(node);",
125 XXM => "${arch}_emit_xmm_mode_suffix(node);",
126 XSD => "${arch}_emit_xmm_mode_suffix_s(node);",
127 AM => "${arch}_emit_am(node);",
128 unop3 => "${arch}_emit_unop(node, n_ia32_unary_op);",
129 unop4 => "${arch}_emit_unop(node, n_ia32_binary_right);",
130 binop => "${arch}_emit_binop(node);",
131 x87_binop => "${arch}_emit_x87_binop(node);",
132 CMP3 => "${arch}_emit_cmp_suffix_node(node, 3);",
138 $default_op_attr_type = "ia32_op_attr_t";
139 $default_attr_type = "ia32_attr_t";
140 $default_copy_attr = "ia32_copy_attr";
142 sub ia32_custom_init_attr {
148 if(defined($node->{modified_flags})) {
149 $res .= "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);\n";
151 if(defined($node->{am})) {
152 my $am = $node->{am};
153 if($am eq "source,unary") {
154 $res .= "\tset_ia32_am_support(res, ia32_am_unary);";
155 } elsif($am eq "source,binary") {
156 $res .= "\tset_ia32_am_support(res, ia32_am_binary);";
157 } elsif($am eq "none") {
160 die("Invalid address mode '$am' specified on op $name");
163 if($node->{state} ne "exc_pinned"
164 and $node->{state} ne "pinned") {
165 die("AM nodes must have pinned or AM pinned state ($name)");
171 $custom_init_attr_func = \&ia32_custom_init_attr;
175 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
176 "\tinit_ia32_x87_attributes(res);".
177 "\tinit_ia32_asm_attributes(res);",
179 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
181 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
182 "\tinit_ia32_call_attributes(res, pop, call_tp);",
183 ia32_condcode_attr_t =>
184 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
185 "\tinit_ia32_condcode_attributes(res, condition_code);",
186 ia32_switch_attr_t =>
187 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
188 "\tinit_ia32_switch_attributes(res, default_pn);",
190 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
191 "\tinit_ia32_copyb_attributes(res, size);",
192 ia32_immediate_attr_t =>
193 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
194 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, no_pic_adjust, offset);",
196 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
197 "\tinit_ia32_x87_attributes(res);",
198 ia32_climbframe_attr_t =>
199 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
200 "\tinit_ia32_climbframe_attributes(res, count);",
204 ia32_asm_attr_t => "ia32_compare_asm_attr",
205 ia32_attr_t => "ia32_compare_nodes_attr",
206 ia32_call_attr_t => "ia32_compare_call_attr",
207 ia32_condcode_attr_t => "ia32_compare_condcode_attr",
208 ia32_switch_attr_t => "ia32_compare_switch_attr",
209 ia32_copyb_attr_t => "ia32_compare_copyb_attr",
210 ia32_immediate_attr_t => "ia32_compare_immediate_attr",
211 ia32_x87_attr_t => "ia32_compare_x87_attr",
212 ia32_climbframe_attr_t => "ia32_compare_climbframe_attr",
218 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
219 $status_flags_wo_cf = [ "PF", "AF", "ZF", "SF", "OF" ];
220 $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
221 "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
227 op_flags => [ "constlike" ],
228 irn_flags => [ "not_scheduled" ],
229 reg_req => { out => [ "gp_NOREG:I" ] },
230 attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
231 attr_type => "ia32_immediate_attr_t",
232 hash_func => "ia32_hash_Immediate",
240 out_arity => "variable",
241 attr_type => "ia32_asm_attr_t",
242 attr => "ident *asm_text, const ia32_asm_reg_t *register_map",
243 init_attr => "attr->asm_text = asm_text;\n".
244 "\tattr->register_map = register_map;\n",
246 modified_flags => $status_flags,
249 # "allocates" a free register
251 op_flags => [ "constlike", "cse_neutral" ],
252 irn_flags => [ "rematerializable" ],
253 reg_req => { out => [ "gp" ] },
258 cmp_attr => "return 1;",
262 irn_flags => [ "rematerializable" ],
263 state => "exc_pinned",
264 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
265 out => [ "in_r4 in_r5", "flags", "none" ] },
266 ins => [ "base", "index", "mem", "left", "right" ],
267 outs => [ "res", "flags", "M" ],
268 emit => '. add%M %binop',
269 am => "source,binary",
273 modified_flags => $status_flags
277 irn_flags => [ "rematerializable" ],
278 state => "exc_pinned",
279 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
280 ins => [ "base", "index", "mem", "val" ],
281 emit => ". add%M %SI3, %AM",
285 modified_flags => $status_flags
289 irn_flags => [ "rematerializable" ],
290 state => "exc_pinned",
291 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
292 ins => [ "base", "index", "mem", "val" ],
293 emit => ". add%M %SB3, %AM",
297 modified_flags => $status_flags
301 state => "exc_pinned",
302 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
303 out => [ "in_r4 in_r5", "flags", "none" ] },
304 ins => [ "base", "index", "mem", "left", "right", "eflags" ],
305 outs => [ "res", "flags", "M" ],
306 emit => '. adc%M %binop',
307 am => "source,binary",
311 modified_flags => $status_flags
315 ins => [ "left", "right" ],
321 ins => [ "left", "right", "eflags" ],
327 # we should not rematrialize this node. It produces 2 results and has
328 # very strict constraints
329 state => "exc_pinned",
330 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
331 out => [ "eax", "flags", "none", "edx" ] },
332 ins => [ "base", "index", "mem", "left", "right" ],
333 emit => '. mul%M %unop4',
334 outs => [ "res_low", "flags", "M", "res_high" ],
335 am => "source,binary",
338 modified_flags => $status_flags
342 ins => [ "left", "right" ],
343 outs => [ "res_low", "flags", "M", "res_high" ],
349 irn_flags => [ "rematerializable" ],
350 state => "exc_pinned",
351 # TODO: adjust out requirements for the 3 operand form
352 # (no need for should_be_same then)
353 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
354 out => [ "in_r4 in_r5", "flags", "none" ] },
355 ins => [ "base", "index", "mem", "left", "right" ],
356 outs => [ "res", "flags", "M" ],
357 am => "source,binary",
361 modified_flags => $status_flags
365 irn_flags => [ "rematerializable" ],
366 state => "exc_pinned",
367 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
368 out => [ "eax", "flags", "none", "edx" ] },
369 ins => [ "base", "index", "mem", "left", "right" ],
370 emit => '. imul%M %unop4',
371 outs => [ "res_low", "flags", "M", "res_high" ],
372 am => "source,binary",
375 modified_flags => $status_flags
379 ins => [ "left", "right" ],
380 outs => [ "res_low", "flags", "M", "res_high" ],
386 irn_flags => [ "rematerializable" ],
387 state => "exc_pinned",
388 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
389 out => [ "in_r4 in_r5", "flags", "none" ] },
390 ins => [ "base", "index", "mem", "left", "right" ],
391 outs => [ "res", "flags", "M" ],
392 am => "source,binary",
393 emit => '. and%M %binop',
397 modified_flags => $status_flags
401 irn_flags => [ "rematerializable" ],
402 state => "exc_pinned",
403 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
404 ins => [ "base", "index", "mem", "val" ],
405 emit => '. and%M %SI3, %AM',
409 modified_flags => $status_flags
413 irn_flags => [ "rematerializable" ],
414 state => "exc_pinned",
415 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
416 ins => [ "base", "index", "mem", "val" ],
417 emit => '. and%M %SB3, %AM',
421 modified_flags => $status_flags
425 irn_flags => [ "rematerializable" ],
426 state => "exc_pinned",
427 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
428 out => [ "in_r4 in_r5", "flags", "none" ] },
429 ins => [ "base", "index", "mem", "left", "right" ],
430 outs => [ "res", "flags", "M" ],
431 am => "source,binary",
432 emit => '. or%M %binop',
436 modified_flags => $status_flags
440 irn_flags => [ "rematerializable" ],
441 state => "exc_pinned",
442 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
443 ins => [ "base", "index", "mem", "val" ],
444 emit => '. or%M %SI3, %AM',
448 modified_flags => $status_flags
452 irn_flags => [ "rematerializable" ],
453 state => "exc_pinned",
454 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
455 ins => [ "base", "index", "mem", "val" ],
456 emit => '. or%M %SB3, %AM',
460 modified_flags => $status_flags
464 irn_flags => [ "rematerializable" ],
465 state => "exc_pinned",
466 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
467 out => [ "in_r4 in_r5", "flags", "none" ] },
468 ins => [ "base", "index", "mem", "left", "right" ],
469 outs => [ "res", "flags", "M" ],
470 am => "source,binary",
471 emit => '. xor%M %binop',
475 modified_flags => $status_flags
479 op_flags => [ "constlike" ],
480 irn_flags => [ "rematerializable" ],
481 reg_req => { out => [ "gp", "flags" ] },
482 outs => [ "res", "flags" ],
483 emit => ". xor%M %D0, %D0",
487 modified_flags => $status_flags
491 irn_flags => [ "rematerializable" ],
492 state => "exc_pinned",
493 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
494 ins => [ "base", "index", "mem", "val" ],
495 emit => '. xor%M %SI3, %AM',
499 modified_flags => $status_flags
503 irn_flags => [ "rematerializable" ],
504 state => "exc_pinned",
505 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
506 ins => [ "base", "index", "mem", "val" ],
507 emit => '. xor%M %SB3, %AM',
511 modified_flags => $status_flags
515 irn_flags => [ "rematerializable" ],
516 state => "exc_pinned",
517 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
518 out => [ "in_r4", "flags", "none" ] },
519 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
520 outs => [ "res", "flags", "M" ],
521 am => "source,binary",
522 emit => '. sub%M %binop',
526 modified_flags => $status_flags
530 irn_flags => [ "rematerializable" ],
531 state => "exc_pinned",
532 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
533 ins => [ "base", "index", "mem", "subtrahend" ],
534 emit => '. sub%M %SI3, %AM',
538 modified_flags => $status_flags
542 irn_flags => [ "rematerializable" ],
543 state => "exc_pinned",
544 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
545 ins => [ "base", "index", "mem", "subtrahend" ],
546 emit => '. sub%M %SB3, %AM',
550 modified_flags => $status_flags
554 state => "exc_pinned",
555 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
556 out => [ "in_r4", "flags", "none" ] },
557 ins => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
558 outs => [ "res", "flags", "M" ],
559 am => "source,binary",
560 emit => '. sbb%M %binop',
564 modified_flags => $status_flags
568 # Spiller currently fails when rematerializing flag consumers
569 # irn_flags => [ "rematerializable" ],
570 reg_req => { in => [ "flags" ], out => [ "gp", "flags" ] },
571 outs => [ "res", "flags" ],
572 emit => ". sbb%M %D0, %D0",
576 modified_flags => $status_flags
580 ins => [ "minuend", "subtrahend" ],
586 ins => [ "minuend", "subtrahend", "eflags" ],
592 op_flags => [ "fragile", "labeled" ],
593 state => "exc_pinned",
594 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
595 out => [ "eax", "flags", "none", "edx", "none", "none" ] },
596 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
597 outs => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
598 am => "source,unary",
599 emit => ". idiv%M %unop3",
602 modified_flags => $status_flags
606 op_flags => [ "fragile", "labeled" ],
607 state => "exc_pinned",
608 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
609 out => [ "eax", "flags", "none", "edx", "none", "none" ] },
610 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
611 outs => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
612 am => "source,unary",
613 emit => ". div%M %unop3",
616 modified_flags => $status_flags
620 irn_flags => [ "rematerializable" ],
621 reg_req => { in => [ "gp", "ecx" ],
622 out => [ "in_r1 !in_r2", "flags" ] },
623 ins => [ "val", "count" ],
624 outs => [ "res", "flags" ],
625 emit => '. shl%M %SB1, %S0',
629 modified_flags => $status_flags
633 irn_flags => [ "rematerializable" ],
634 state => "exc_pinned",
635 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
636 ins => [ "base", "index", "mem", "count" ],
637 emit => '. shl%M %SB3, %AM',
641 modified_flags => $status_flags
645 irn_flags => [ "rematerializable" ],
646 reg_req => { in => [ "gp", "gp", "ecx" ],
647 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
648 ins => [ "val_high", "val_low", "count" ],
649 outs => [ "res", "flags" ],
650 emit => ". shld%M %SB2, %S1, %D0",
654 modified_flags => $status_flags
658 irn_flags => [ "rematerializable" ],
659 reg_req => { in => [ "gp", "ecx" ],
660 out => [ "in_r1 !in_r2", "flags" ] },
661 ins => [ "val", "count" ],
662 outs => [ "res", "flags" ],
663 emit => '. shr%M %SB1, %S0',
667 modified_flags => $status_flags
671 irn_flags => [ "rematerializable" ],
672 state => "exc_pinned",
673 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
674 ins => [ "base", "index", "mem", "count" ],
675 emit => '. shr%M %SB3, %AM',
679 modified_flags => $status_flags
683 irn_flags => [ "rematerializable" ],
684 reg_req => { in => [ "gp", "gp", "ecx" ],
685 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
686 ins => [ "val_high", "val_low", "count" ],
687 outs => [ "res", "flags" ],
688 emit => ". shrd%M %SB2, %S1, %D0",
692 modified_flags => $status_flags
696 irn_flags => [ "rematerializable" ],
697 reg_req => { in => [ "gp", "ecx" ],
698 out => [ "in_r1 !in_r2", "flags" ] },
699 ins => [ "val", "count" ],
700 outs => [ "res", "flags" ],
701 emit => '. sar%M %SB1, %S0',
705 modified_flags => $status_flags
709 irn_flags => [ "rematerializable" ],
710 state => "exc_pinned",
711 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
712 ins => [ "base", "index", "mem", "count" ],
713 emit => '. sar%M %SB3, %AM',
717 modified_flags => $status_flags
721 irn_flags => [ "rematerializable" ],
722 reg_req => { in => [ "gp", "ecx" ],
723 out => [ "in_r1 !in_r2", "flags" ] },
724 ins => [ "val", "count" ],
725 outs => [ "res", "flags" ],
726 emit => '. ror%M %SB1, %S0',
730 modified_flags => $status_flags
734 irn_flags => [ "rematerializable" ],
735 state => "exc_pinned",
736 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
737 ins => [ "base", "index", "mem", "count" ],
738 emit => '. ror%M %SB3, %AM',
742 modified_flags => $status_flags
746 irn_flags => [ "rematerializable" ],
747 reg_req => { in => [ "gp", "ecx" ],
748 out => [ "in_r1 !in_r2", "flags" ] },
749 ins => [ "val", "count" ],
750 outs => [ "res", "flags" ],
751 emit => '. rol%M %SB1, %S0',
755 modified_flags => $status_flags
759 irn_flags => [ "rematerializable" ],
760 state => "exc_pinned",
761 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
762 ins => [ "base", "index", "mem", "count" ],
763 emit => '. rol%M %SB3, %AM',
767 modified_flags => $status_flags
771 irn_flags => [ "rematerializable" ],
772 reg_req => { in => [ "gp" ],
773 out => [ "in_r1", "flags" ] },
774 emit => '. neg%M %S0',
776 outs => [ "res", "flags" ],
780 modified_flags => $status_flags
784 irn_flags => [ "rematerializable" ],
785 state => "exc_pinned",
786 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
787 ins => [ "base", "index", "mem" ],
788 emit => '. neg%M %AM',
792 modified_flags => $status_flags
796 irn_flags => [ "rematerializable" ],
797 reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "in_r2" ] },
798 outs => [ "low_res", "high_res" ],
801 modified_flags => $status_flags
806 irn_flags => [ "rematerializable" ],
807 reg_req => { in => [ "gp" ],
808 out => [ "in_r1", "flags" ] },
810 outs => [ "res", "flags" ],
811 emit => '. inc%M %S0',
815 modified_flags => $status_flags_wo_cf
819 irn_flags => [ "rematerializable" ],
820 state => "exc_pinned",
821 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
822 ins => [ "base", "index", "mem" ],
823 emit => '. inc%M %AM',
827 modified_flags => $status_flags_wo_cf
831 irn_flags => [ "rematerializable" ],
832 reg_req => { in => [ "gp" ],
833 out => [ "in_r1", "flags" ] },
835 outs => [ "res", "flags" ],
836 emit => '. dec%M %S0',
840 modified_flags => $status_flags_wo_cf
844 irn_flags => [ "rematerializable" ],
845 state => "exc_pinned",
846 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
847 ins => [ "base", "index", "mem" ],
848 emit => '. dec%M %AM',
852 modified_flags => $status_flags_wo_cf
856 irn_flags => [ "rematerializable" ],
857 reg_req => { in => [ "gp" ],
858 out => [ "in_r1" ] },
861 emit => '. not%M %S0',
869 irn_flags => [ "rematerializable" ],
870 state => "exc_pinned",
871 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
872 ins => [ "base", "index", "mem" ],
873 emit => '. not%M %AM',
881 reg_req => { in => [ "flags" ], out => [ "flags" ] },
886 modified_flags => $status_flags
890 reg_req => { out => [ "flags" ] },
895 modified_flags => $status_flags
899 irn_flags => [ "rematerializable" ],
900 state => "exc_pinned",
901 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
902 out => [ "flags", "none", "none" ] },
903 ins => [ "base", "index", "mem", "left", "right" ],
904 outs => [ "eflags", "unused", "M" ],
905 am => "source,binary",
906 emit => '. cmp%M %binop',
907 attr => "bool ins_permuted",
908 init_attr => "attr->data.ins_permuted = ins_permuted;",
912 modified_flags => $status_flags
916 irn_flags => [ "rematerializable" ],
917 state => "exc_pinned",
918 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] ,
919 out => [ "flags", "none", "none" ] },
920 ins => [ "base", "index", "mem", "left", "right" ],
921 outs => [ "eflags", "unused", "M" ],
922 am => "source,binary",
923 emit => '. cmpb %binop',
924 attr => "bool ins_permuted",
925 init_attr => "attr->data.ins_permuted = ins_permuted;",
929 modified_flags => $status_flags
933 irn_flags => [ "rematerializable" ],
934 state => "exc_pinned",
935 reg_req => { in => [ "eax ebx ecx edx" ],
936 out => [ "in_r1", "flags" ] },
937 emit => '. xorb %SH0, %SB0',
939 outs => [ "res", "flags" ],
943 modified_flags => $status_flags,
947 irn_flags => [ "rematerializable" ],
948 state => "exc_pinned",
949 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] ,
950 out => [ "flags", "none", "none" ] },
951 ins => [ "base", "index", "mem", "left", "right" ],
952 outs => [ "eflags", "unused", "M" ],
953 am => "source,binary",
954 emit => '. test%M %binop',
955 attr => "bool ins_permuted",
956 init_attr => "attr->data.ins_permuted = ins_permuted;",
960 modified_flags => $status_flags
964 irn_flags => [ "rematerializable" ],
965 state => "exc_pinned",
966 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] ,
967 out => [ "flags", "none", "none" ] },
968 ins => [ "base", "index", "mem", "left", "right" ],
969 outs => [ "eflags", "unused", "M" ],
970 am => "source,binary",
971 emit => '. testb %binop',
972 attr => "bool ins_permuted",
973 init_attr => "attr->data.ins_permuted = ins_permuted;",
977 modified_flags => $status_flags
981 #irn_flags => [ "rematerializable" ],
982 reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
985 attr_type => "ia32_condcode_attr_t",
986 attr => "ia32_condition_code_t condition_code",
987 # The way we handle Setcc with float nodes (potentially) destroys the flags
988 # (when we emit the setX; setp; orb and the setX;setnp;andb sequences)
989 init_attr => "set_ia32_ls_mode(res, mode_Bu);\n"
990 . "\tif (condition_code & ia32_cc_additional_float_cases) {\n"
991 . "\t\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);\n"
992 . "\t\t/* attr->latency = 3; */\n"
1000 #irn_flags => [ "rematerializable" ],
1001 state => "exc_pinned",
1002 reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
1003 ins => [ "base", "index", "mem","eflags" ],
1004 attr_type => "ia32_condcode_attr_t",
1005 attr => "ia32_condition_code_t condition_code",
1006 init_attr => "set_ia32_ls_mode(res, mode_Bu);\n",
1007 emit => '. set%CMP3 %AM',
1014 #irn_flags => [ "rematerializable" ],
1015 state => "exc_pinned",
1016 # (note: leave the false,true order intact to make it compatible with other
1018 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ],
1019 out => [ "in_r4 in_r5", "flags", "none" ] },
1020 ins => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
1021 outs => [ "res", "flags", "M" ],
1022 am => "source,binary",
1023 attr_type => "ia32_condcode_attr_t",
1024 attr => "ia32_condition_code_t condition_code",
1032 op_flags => [ "labeled", "cfopcode", "forking" ],
1033 reg_req => { in => [ "eflags" ], out => [ "none", "none" ] },
1034 ins => [ "eflags" ],
1035 outs => [ "false", "true" ],
1036 attr_type => "ia32_condcode_attr_t",
1037 attr => "ia32_condition_code_t condition_code",
1039 units => [ "BRANCH" ],
1044 op_flags => [ "labeled", "cfopcode", "forking" ],
1045 reg_req => { in => [ "gp", "gp" ] },
1046 ins => [ "base", "index" ],
1048 attr_type => "ia32_switch_attr_t",
1049 attr => "long default_pn",
1051 units => [ "BRANCH" ],
1052 init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
1057 irn_flags => [ "simple_jump" ],
1058 op_flags => [ "cfopcode" ],
1059 reg_req => { out => [ "none" ] },
1061 units => [ "BRANCH" ],
1067 op_flags => [ "cfopcode", "unknown_jump" ],
1068 reg_req => { in => [ "gp", "gp", "none", "gp" ] },
1069 ins => [ "base", "index", "mem", "target" ],
1070 am => "source,unary",
1071 emit => '. jmp *%unop3',
1073 units => [ "BRANCH" ],
1075 init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
1079 op_flags => [ "constlike" ],
1080 irn_flags => [ "rematerializable" ],
1081 reg_req => { out => [ "gp" ] },
1083 attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
1084 attr_type => "ia32_immediate_attr_t",
1090 op_flags => [ "constlike" ],
1091 irn_flags => [ "rematerializable" ],
1092 reg_req => { out => [ "gp" ] },
1099 op_flags => [ "constlike" ],
1100 reg_req => { out => [ "gp" ] },
1104 modified_flags => $status_flags,
1109 op_flags => [ "constlike", "dump_noblock", "dump_noinput" ],
1110 irn_flags => [ "not_scheduled" ],
1111 reg_req => { out => [ "gp_NOREG:I" ] },
1120 op_flags => [ "constlike", "dump_noblock", "dump_noinput" ],
1121 irn_flags => [ "not_scheduled" ],
1122 reg_req => { out => [ "vfp_NOREG:I" ] },
1127 attr_type => "ia32_x87_attr_t",
1132 op_flags => [ "constlike", "dump_noblock", "dump_noinput" ],
1133 irn_flags => [ "not_scheduled" ],
1134 reg_req => { out => [ "xmm_NOREG:I" ] },
1143 op_flags => [ "constlike" ],
1144 irn_flags => [ "not_scheduled" ],
1145 reg_req => { out => [ "fpcw:I" ] },
1149 modified_flags => $fpcw_flags
1153 op_flags => [ "labeled" ],
1155 reg_req => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] },
1156 ins => [ "base", "index", "mem" ],
1158 emit => ". fldcw %AM",
1161 modified_flags => $fpcw_flags
1165 op_flags => [ "labeled" ],
1167 reg_req => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1168 ins => [ "base", "index", "mem", "fpcw" ],
1170 emit => ". fnstcw %AM",
1176 op_flags => [ "labeled" ],
1178 reg_req => { in => [ "fp_cw" ], out => [ "none" ] },
1186 # we should not rematrialize this node. It has very strict constraints.
1187 reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] },
1188 ins => [ "val", "clobbered" ],
1197 # Note that we add additional latency values depending on address mode, so a
1198 # lateny of 0 for load is correct
1201 op_flags => [ "fragile", "labeled" ],
1202 state => "exc_pinned",
1203 reg_req => { in => [ "gp", "gp", "none" ],
1204 out => [ "gp", "none", "none", "none", "none" ] },
1205 ins => [ "base", "index", "mem" ],
1206 outs => [ "res", "unused", "M", "X_regular", "X_except" ],
1208 emit => ". mov%EX%.l %AM, %D0",
1213 op_flags => [ "fragile", "labeled" ],
1214 state => "exc_pinned",
1215 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1216 out => [ "none", "none", "none" ] },
1217 ins => [ "base", "index", "mem", "val" ],
1218 outs => [ "M", "X_regular", "X_except" ],
1219 emit => '. mov%M %SI3, %AM',
1225 op_flags => [ "fragile", "labeled" ],
1226 state => "exc_pinned",
1227 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
1228 out => ["none", "none", "none" ] },
1229 ins => [ "base", "index", "mem", "val" ],
1230 outs => [ "M", "X_regular", "X_except" ],
1231 emit => '. mov%M %SB3, %AM',
1237 irn_flags => [ "rematerializable" ],
1238 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
1239 ins => [ "base", "index" ],
1240 emit => '. leal %AM, %D0',
1244 # lea doesn't modify the flags, but setting this seems advantageous since it
1245 # increases chances that the Lea is transformed back to an Add
1246 modified_flags => 1,
1250 state => "exc_pinned",
1251 reg_req => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp:I|S", "none" ] },
1252 ins => [ "base", "index", "mem", "val", "stack" ],
1253 emit => '. push%M %unop3',
1254 outs => [ "stack", "M" ],
1255 am => "source,unary",
1261 state => "exc_pinned",
1262 reg_req => { in => [ "esp" ], out => [ "esp:I|S" ] },
1264 outs => [ "stack" ],
1265 emit => '. pushl %%eax',
1272 state => "exc_pinned",
1273 reg_req => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp:I|S" ] },
1274 ins => [ "mem", "stack" ],
1275 outs => [ "res", "M", "unused", "stack" ],
1276 emit => '. pop%M %D0',
1277 latency => 3, # Pop is more expensive than Push on Athlon
1282 state => "exc_pinned",
1283 reg_req => { in => [ "none", "esp" ], out => [ "ebp:I", "none", "none", "esp:I|S" ] },
1284 ins => [ "mem", "stack" ],
1285 outs => [ "res", "M", "unused", "stack" ],
1286 emit => '. pop%M %D0',
1287 latency => 3, # Pop is more expensive than Push on Athlon
1292 state => "exc_pinned",
1293 reg_req => { in => [ "ebp" ], out => [ "esp:I|S" ] },
1296 emit => '. movl %S0, %D0',
1303 state => "exc_pinned",
1304 reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp:I|S" ] },
1305 ins => [ "base", "index", "mem", "stack" ],
1306 outs => [ "unused0", "M", "unused1", "stack" ],
1307 emit => '. pop%M %AM',
1308 latency => 3, # Pop is more expensive than Push on Athlon
1313 reg_req => { in => [ "esp" ], out => [ "ebp", "esp:I|S", "none" ] },
1315 outs => [ "frame", "stack", "M" ],
1321 reg_req => { in => [ "ebp" ], out => [ "ebp:I", "esp:I|S" ] },
1323 outs => [ "frame", "stack" ],
1326 state => "exc_pinned",
1331 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "none" ] },
1332 ins => [ "base", "index", "mem", "stack", "size" ],
1333 am => "source,binary",
1334 emit => '. addl %binop',
1336 outs => [ "stack", "M" ],
1338 modified_flags => $status_flags
1343 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "gp", "none" ] },
1344 ins => [ "base", "index", "mem", "stack", "size" ],
1345 am => "source,binary",
1346 emit => ". subl %binop\n".
1347 ". movl %%esp, %D1",
1349 outs => [ "stack", "addr", "M" ],
1351 modified_flags => $status_flags
1355 op_flags => [ "keep" ],
1363 irn_flags => [ "rematerializable" ],
1364 reg_req => { out => [ "gp" ] },
1366 emit => ". movl %%gs:0, %D0",
1372 # BT supports source address mode, but this is unused yet
1375 irn_flags => [ "rematerializable" ],
1376 state => "exc_pinned",
1377 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
1378 ins => [ "left", "right" ],
1379 emit => '. bt%M %S1, %S0',
1382 mode => $mode_flags,
1383 modified_flags => $status_flags # only CF is set, but the other flags are undefined
1387 irn_flags => [ "rematerializable" ],
1388 state => "exc_pinned",
1389 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1390 out => [ "gp", "flags", "none" ] },
1391 ins => [ "base", "index", "mem", "operand" ],
1392 outs => [ "res", "flags", "M" ],
1393 am => "source,binary",
1394 emit => '. bsf%M %unop3, %D0',
1398 modified_flags => $status_flags
1402 irn_flags => [ "rematerializable" ],
1403 state => "exc_pinned",
1404 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1405 out => [ "gp", "flags", "none" ] },
1406 ins => [ "base", "index", "mem", "operand" ],
1407 outs => [ "res", "flags", "M" ],
1408 am => "source,binary",
1409 emit => '. bsr%M %unop3, %D0',
1413 modified_flags => $status_flags
1417 # SSE4.2 or SSE4a popcnt instruction
1420 irn_flags => [ "rematerializable" ],
1421 state => "exc_pinned",
1422 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1423 out => [ "gp", "flags", "none" ] },
1424 ins => [ "base", "index", "mem", "operand" ],
1425 outs => [ "res", "flags", "M" ],
1426 am => "source,binary",
1427 emit => '. popcnt%M %unop3, %D0',
1431 modified_flags => $status_flags
1435 op_flags => [ "fragile" ],
1436 state => "exc_pinned",
1438 in => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ],
1439 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", "none", "none" ]
1441 ins => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ],
1442 outs => [ "stack", "fpcw", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "X_regular", "X_except" ],
1443 attr_type => "ia32_call_attr_t",
1444 attr => "unsigned pop, ir_type *call_tp",
1445 am => "source,unary",
1446 units => [ "BRANCH" ],
1447 latency => 4, # random number
1448 modified_flags => $status_flags
1452 # a Helper node for frame-climbing, needed for __builtin_(frame|return)_address
1454 # PS: try gcc __builtin_frame_address(100000) :-)
1457 reg_req => { in => [ "gp", "gp", "gp"], out => [ "in_r3" ] },
1458 ins => [ "frame", "cnt", "tmp" ],
1460 latency => 4, # random number
1461 attr_type => "ia32_climbframe_attr_t",
1462 attr => "unsigned count",
1471 irn_flags => [ "rematerializable" ],
1472 reg_req => { in => [ "gp" ],
1473 out => [ "in_r1" ] },
1474 emit => '. bswap%M %S0',
1482 # bswap16, use xchg here
1485 irn_flags => [ "rematerializable" ],
1486 reg_req => { in => [ "eax ebx ecx edx" ],
1487 out => [ "in_r1" ] },
1488 emit => '. xchg %SB0, %SH0',
1500 reg_req => { in => [ "none" ], out => [ "none" ] },
1509 # Undefined Instruction on ALL x86 CPU's
1513 reg_req => { in => [ "none" ], out => [ "none" ] },
1516 emit => ". .value 0x0b0f",
1525 irn_flags => [ "rematerializable" ],
1527 reg_req => { in => [ "edx", "eax", "none" ], out => [ "none" ] },
1528 ins => [ "port", "value", "mem" ],
1529 emit => '. out%M %SS0, %SI1',
1533 modified_flags => $status_flags
1540 irn_flags => [ "rematerializable" ],
1542 reg_req => { in => [ "edx", "none" ], out => [ "eax", "none" ] },
1543 ins => [ "port", "mem" ],
1544 outs => [ "res", "M" ],
1545 emit => '. in%M %DS0, %SS0',
1549 modified_flags => $status_flags
1553 # Intel style prefetching
1556 op_flags => [ "labeled" ],
1557 state => "exc_pinned",
1558 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1559 ins => [ "base", "index", "mem" ],
1562 emit => ". prefetcht0 %AM",
1567 op_flags => [ "labeled" ],
1568 state => "exc_pinned",
1569 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1570 ins => [ "base", "index", "mem" ],
1573 emit => ". prefetcht1 %AM",
1578 op_flags => [ "labeled" ],
1579 state => "exc_pinned",
1580 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1581 ins => [ "base", "index", "mem" ],
1584 emit => ". prefetcht2 %AM",
1589 op_flags => [ "labeled" ],
1590 state => "exc_pinned",
1591 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1592 ins => [ "base", "index", "mem" ],
1595 emit => ". prefetchnta %AM",
1600 # 3DNow! prefetch instructions
1603 op_flags => [ "labeled" ],
1604 state => "exc_pinned",
1605 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1606 ins => [ "base", "index", "mem" ],
1609 emit => ". prefetch %AM",
1614 op_flags => [ "labeled" ],
1615 state => "exc_pinned",
1616 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1617 ins => [ "base", "index", "mem" ],
1620 emit => ". prefetchw %AM",
1626 irn_flags => [ "rematerializable" ],
1627 reg_req => { out => [ "xmm" ] },
1628 emit => '. xorp%XSD %D0, %D0',
1635 op_flags => [ "constlike" ],
1636 irn_flags => [ "rematerializable" ],
1637 reg_req => { out => [ "xmm" ] },
1644 irn_flags => [ "rematerializable" ],
1645 reg_req => { out => [ "xmm" ] },
1646 emit => '. pxor %D0, %D0',
1652 # produces all 1 bits
1654 irn_flags => [ "rematerializable" ],
1655 reg_req => { out => [ "xmm" ] },
1656 emit => '. pcmpeqb %D0, %D0',
1662 # integer shift left, dword
1664 irn_flags => [ "rematerializable" ],
1665 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1666 emit => '. pslld %SI1, %D0',
1672 # integer shift left, qword
1674 irn_flags => [ "rematerializable" ],
1675 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1676 emit => '. psllq %SI1, %D0',
1682 # integer shift right, dword
1684 irn_flags => [ "rematerializable" ],
1685 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1686 emit => '. psrld %SI1, %D0',
1692 # mov from integer to SSE register
1694 irn_flags => [ "rematerializable" ],
1695 reg_req => { in => [ "gp" ], out => [ "xmm" ] },
1696 emit => '. movd %S0, %D0',
1703 irn_flags => [ "rematerializable" ],
1704 state => "exc_pinned",
1705 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1706 out => [ "in_r4 in_r5", "flags", "none" ] },
1707 ins => [ "base", "index", "mem", "left", "right" ],
1708 outs => [ "res", "flags", "M" ],
1709 am => "source,binary",
1710 emit => '. add%XXM %binop',
1717 irn_flags => [ "rematerializable" ],
1718 state => "exc_pinned",
1719 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1720 out => [ "in_r4 in_r5", "flags", "none" ] },
1721 ins => [ "base", "index", "mem", "left", "right" ],
1722 outs => [ "res", "flags", "M" ],
1723 am => "source,binary",
1724 emit => '. mul%XXM %binop',
1731 irn_flags => [ "rematerializable" ],
1732 state => "exc_pinned",
1733 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1734 out => [ "in_r4 in_r5", "flags", "none" ] },
1735 ins => [ "base", "index", "mem", "left", "right" ],
1736 outs => [ "res", "flags", "M" ],
1737 am => "source,binary",
1738 emit => '. max%XXM %binop',
1745 irn_flags => [ "rematerializable" ],
1746 state => "exc_pinned",
1747 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1748 out => [ "in_r4 in_r5", "flags", "none" ] },
1749 ins => [ "base", "index", "mem", "left", "right" ],
1750 outs => [ "res", "flags", "M" ],
1751 am => "source,binary",
1752 emit => '. min%XXM %binop',
1759 irn_flags => [ "rematerializable" ],
1760 state => "exc_pinned",
1761 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1762 out => [ "in_r4 in_r5", "flags", "none" ] },
1763 ins => [ "base", "index", "mem", "left", "right" ],
1764 outs => [ "res", "flags", "M" ],
1765 am => "source,binary",
1766 emit => '. andp%XSD %binop',
1773 irn_flags => [ "rematerializable" ],
1774 state => "exc_pinned",
1775 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1776 out => [ "in_r4 in_r5", "flags", "none" ] },
1777 ins => [ "base", "index", "mem", "left", "right" ],
1778 outs => [ "res", "flags", "M" ],
1779 am => "source,binary",
1780 emit => '. orp%XSD %binop',
1787 irn_flags => [ "rematerializable" ],
1788 state => "exc_pinned",
1789 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1790 out => [ "in_r4 in_r5", "flags", "none" ] },
1791 ins => [ "base", "index", "mem", "left", "right" ],
1792 outs => [ "res", "flags", "M" ],
1793 am => "source,binary",
1794 emit => '. xorp%XSD %binop',
1801 irn_flags => [ "rematerializable" ],
1802 state => "exc_pinned",
1803 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1804 out => [ "in_r4 !in_r5", "flags", "none" ] },
1805 ins => [ "base", "index", "mem", "left", "right" ],
1806 outs => [ "res", "flags", "M" ],
1807 am => "source,binary",
1808 emit => '. andnp%XSD %binop',
1815 irn_flags => [ "rematerializable" ],
1816 state => "exc_pinned",
1817 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1818 out => [ "in_r4", "flags", "none" ] },
1819 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
1820 outs => [ "res", "flags", "M" ],
1821 am => "source,binary",
1822 emit => '. sub%XXM %binop',
1829 irn_flags => [ "rematerializable" ],
1830 state => "exc_pinned",
1831 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1832 out => [ "in_r4 !in_r5", "flags", "none" ] },
1833 ins => [ "base", "index", "mem", "dividend", "divisor" ],
1834 outs => [ "res", "flags", "M" ],
1835 am => "source,binary",
1836 emit => '. div%XXM %binop',
1842 irn_flags => [ "rematerializable" ],
1843 state => "exc_pinned",
1844 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1845 out => [ "eflags" ] },
1846 ins => [ "base", "index", "mem", "left", "right" ],
1847 outs => [ "flags" ],
1848 am => "source,binary",
1849 attr => "bool ins_permuted",
1850 init_attr => "attr->data.ins_permuted = ins_permuted;",
1851 emit => ' .ucomi%XXM %binop',
1854 mode => $mode_flags,
1855 modified_flags => 1,
1859 op_flags => [ "fragile", "labeled" ],
1860 state => "exc_pinned",
1861 reg_req => { in => [ "gp", "gp", "none" ],
1862 out => [ "xmm", "none", "none", "none", "none" ] },
1863 ins => [ "base", "index", "mem" ],
1864 outs => [ "res", "unused", "M", "X_regular", "X_except" ],
1865 emit => '. mov%XXM %AM, %D0',
1866 attr => "ir_mode *load_mode",
1867 init_attr => "attr->ls_mode = load_mode;",
1873 op_flags => [ "fragile", "labeled" ],
1874 state => "exc_pinned",
1875 reg_req => { in => [ "gp", "gp", "none", "xmm" ],
1876 out => [ "none", "none", "none" ] },
1877 ins => [ "base", "index", "mem", "val" ],
1878 outs => [ "M", "X_regular", "X_except" ],
1879 emit => '. mov%XXM %S3, %AM',
1885 op_flags => [ "fragile", "labeled" ],
1886 state => "exc_pinned",
1887 reg_req => { in => [ "gp", "gp", "none", "xmm" ],
1888 out => [ "none", "none", "none" ] },
1889 ins => [ "base", "index", "mem", "val" ],
1890 outs => [ "M", "X_regular", "X_except" ],
1891 emit => '. mov%XXM %S3, %AM',
1897 op_flags => [ "labeled" ],
1898 state => "exc_pinned",
1899 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1900 ins => [ "base", "index", "mem", "val" ],
1901 am => "source,unary",
1902 emit => '. cvtsi2ss %unop3, %D0',
1909 op_flags => [ "labeled" ],
1910 state => "exc_pinned",
1911 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1912 ins => [ "base", "index", "mem", "val" ],
1913 am => "source,unary",
1914 emit => '. cvtsi2sd %unop3, %D0',
1922 ins => [ "val_high", "val_low" ],
1924 dump_func => "NULL",
1929 outs => [ "res_high", "res_low" ],
1931 dump_func => "NULL",
1935 op_flags => [ "fragile" ],
1937 reg_req => { in => [ "edi", "esi", "ecx", "none" ],
1938 out => [ "edi", "esi", "ecx", "none", "none", "none" ] },
1939 ins => [ "dest", "source", "count", "mem" ],
1940 outs => [ "dest", "source", "count", "M", "X_regular", "X_except" ],
1941 attr_type => "ia32_copyb_attr_t",
1942 attr => "unsigned size",
1945 # we don't care about this flag, so no need to mark this node
1946 # modified_flags => [ "DF" ]
1950 op_flags => [ "fragile" ],
1952 reg_req => { in => [ "edi", "esi", "none" ],
1953 out => [ "edi", "esi", "none", "none", "none" ] },
1954 ins => [ "dest", "source", "mem" ],
1955 outs => [ "dest", "source", "M", "X_regular", "X_except" ],
1956 attr_type => "ia32_copyb_attr_t",
1957 attr => "unsigned size",
1960 # we don't care about this flag, so no need to mark this node
1961 # modified_flags => [ "DF" ]
1965 state => "exc_pinned",
1966 reg_req => { in => [ "eax" ], out => [ "eax" ] },
1976 op_flags => [ "fragile" ],
1977 state => "exc_pinned",
1978 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1979 out => [ "gp", "none", "none", "none", "none" ] },
1980 ins => [ "base", "index", "mem", "val" ],
1981 outs => [ "res", "flags", "M", "X_regular", "X_except" ],
1982 am => "source,unary",
1985 attr => "ir_mode *smaller_mode",
1986 init_attr => "attr->ls_mode = smaller_mode;",
1991 op_flags => [ "fragile" ],
1992 state => "exc_pinned",
1993 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
1994 out => [ "gp", "none", "none", "none", "none" ] },
1995 ins => [ "base", "index", "mem", "val" ],
1996 outs => [ "res", "flags", "M", "X_regular", "X_except" ],
1997 am => "source,unary",
2000 attr => "ir_mode *smaller_mode",
2001 init_attr => "attr->ls_mode = smaller_mode;",
2006 state => "exc_pinned",
2007 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
2008 ins => [ "base", "index", "mem", "val" ],
2009 am => "source,unary",
2016 state => "exc_pinned",
2017 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
2018 ins => [ "base", "index", "mem", "val" ],
2019 am => "source,unary",
2026 state => "exc_pinned",
2027 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
2028 ins => [ "base", "index", "mem", "val" ],
2029 am => "source,unary",
2035 # rematerialisation disabled for all float nodes for now, because the fpcw
2036 # handler runs before spilling and we might end up with wrong fpcw then
2039 # irn_flags => [ "rematerializable" ],
2040 state => "exc_pinned",
2041 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ],
2042 out => [ "vfp", "none", "none" ] },
2043 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
2044 outs => [ "res", "dummy", "M" ],
2045 am => "source,binary",
2049 attr_type => "ia32_x87_attr_t",
2053 # irn_flags => [ "rematerializable" ],
2054 state => "exc_pinned",
2055 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ],
2056 out => [ "vfp", "none", "none" ] },
2057 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
2058 outs => [ "res", "dummy", "M" ],
2059 am => "source,binary",
2063 attr_type => "ia32_x87_attr_t",
2067 # irn_flags => [ "rematerializable" ],
2068 state => "exc_pinned",
2069 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ],
2070 out => [ "vfp", "none", "none" ] },
2071 ins => [ "base", "index", "mem", "minuend", "subtrahend", "fpcw" ],
2072 outs => [ "res", "dummy", "M" ],
2073 am => "source,binary",
2077 attr_type => "ia32_x87_attr_t",
2081 state => "exc_pinned",
2082 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ],
2083 out => [ "vfp", "none", "none" ] },
2084 ins => [ "base", "index", "mem", "dividend", "divisor", "fpcw" ],
2085 outs => [ "res", "dummy", "M" ],
2086 am => "source,binary",
2089 attr_type => "ia32_x87_attr_t",
2093 reg_req => { in => [ "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2094 ins => [ "left", "right", "fpcw" ],
2098 attr_type => "ia32_x87_attr_t",
2102 irn_flags => [ "rematerializable" ],
2103 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2108 attr_type => "ia32_x87_attr_t",
2112 irn_flags => [ "rematerializable" ],
2113 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2118 attr_type => "ia32_x87_attr_t",
2122 irn_flags => [ "rematerializable" ],
2123 op_flags => [ "fragile", "labeled" ],
2124 state => "exc_pinned",
2125 reg_req => { in => [ "gp", "gp", "none" ],
2126 out => [ "vfp", "none", "none", "none", "none" ] },
2127 ins => [ "base", "index", "mem" ],
2128 outs => [ "res", "unused", "M", "X_regular", "X_except" ],
2129 attr => "ir_mode *load_mode",
2130 init_attr => "attr->attr.ls_mode = load_mode;",
2133 attr_type => "ia32_x87_attr_t",
2137 irn_flags => [ "rematerializable" ],
2138 op_flags => [ "fragile", "labeled" ],
2139 state => "exc_pinned",
2140 reg_req => { in => [ "gp", "gp", "none", "vfp" ],
2141 out => [ "none", "none", "none" ] },
2142 ins => [ "base", "index", "mem", "val" ],
2143 outs => [ "M", "X_regular", "X_except" ],
2144 attr => "ir_mode *store_mode",
2145 init_attr => "attr->attr.ls_mode = store_mode;",
2148 attr_type => "ia32_x87_attr_t",
2152 state => "exc_pinned",
2153 reg_req => { in => [ "gp", "gp", "none" ],
2154 out => [ "vfp", "none", "none" ] },
2155 outs => [ "res", "unused", "M" ],
2156 ins => [ "base", "index", "mem" ],
2159 attr_type => "ia32_x87_attr_t",
2163 op_flags => [ "fragile" ],
2164 state => "exc_pinned",
2165 reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ],
2166 out => [ "none", "none", "none", "none" ] },
2167 ins => [ "base", "index", "mem", "val", "fpcw" ],
2168 outs => [ "dummy", "M", "X_regular", "X_except" ],
2171 attr_type => "ia32_x87_attr_t",
2174 # SSE3 fisttp instruction
2176 op_flags => [ "fragile" ],
2177 state => "exc_pinned",
2178 reg_req => { in => [ "gp", "gp", "none", "vfp" ],
2179 out => [ "in_r4", "none", "none", "none" ]},
2180 ins => [ "base", "index", "mem", "val" ],
2181 outs => [ "res", "M", "X_regular", "X_except" ],
2184 attr_type => "ia32_x87_attr_t",
2188 irn_flags => [ "rematerializable" ],
2189 reg_req => { out => [ "vfp" ] },
2194 attr_type => "ia32_x87_attr_t",
2198 irn_flags => [ "rematerializable" ],
2199 reg_req => { out => [ "vfp" ] },
2204 attr_type => "ia32_x87_attr_t",
2208 irn_flags => [ "rematerializable" ],
2209 reg_req => { out => [ "vfp" ] },
2214 attr_type => "ia32_x87_attr_t",
2218 irn_flags => [ "rematerializable" ],
2219 reg_req => { out => [ "vfp" ] },
2224 attr_type => "ia32_x87_attr_t",
2228 irn_flags => [ "rematerializable" ],
2229 reg_req => { out => [ "vfp" ] },
2234 attr_type => "ia32_x87_attr_t",
2238 irn_flags => [ "rematerializable" ],
2239 reg_req => { out => [ "vfp" ] },
2244 attr_type => "ia32_x87_attr_t",
2248 irn_flags => [ "rematerializable" ],
2249 reg_req => { out => [ "vfp" ] },
2254 attr_type => "ia32_x87_attr_t",
2258 # we can't allow to rematerialize this node so we don't
2259 # accidently produce Phi(Fucom, Fucom(ins_permuted))
2260 # irn_flags => [ "rematerializable" ],
2261 reg_req => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
2262 ins => [ "left", "right" ],
2263 outs => [ "flags" ],
2264 attr => "bool ins_permuted",
2265 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2268 attr_type => "ia32_x87_attr_t",
2273 irn_flags => [ "rematerializable" ],
2274 reg_req => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
2275 ins => [ "left", "right" ],
2276 outs => [ "flags" ],
2277 attr => "bool ins_permuted",
2278 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2281 attr_type => "ia32_x87_attr_t",
2286 # irn_flags => [ "rematerializable" ],
2287 reg_req => { in => [ "vfp" ], out => [ "eax" ] },
2289 outs => [ "flags" ],
2290 attr => "bool ins_permuted",
2291 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2294 attr_type => "ia32_x87_attr_t",
2299 irn_flags => [ "rematerializable" ],
2300 reg_req => { in => [ "eax" ], out => [ "eflags" ] },
2302 outs => [ "flags" ],
2306 mode => $mode_flags,
2310 state => "exc_pinned",
2311 emit => '. fadd%XM %x87_binop',
2313 attr_type => "ia32_x87_attr_t",
2318 state => "exc_pinned",
2319 emit => '. faddp%XM %x87_binop',
2321 attr_type => "ia32_x87_attr_t",
2326 state => "exc_pinned",
2327 emit => '. fmul%XM %x87_binop',
2329 attr_type => "ia32_x87_attr_t",
2334 state => "exc_pinned",
2335 emit => '. fmulp%XM %x87_binop',,
2337 attr_type => "ia32_x87_attr_t",
2342 state => "exc_pinned",
2343 emit => '. fsub%XM %x87_binop',
2345 attr_type => "ia32_x87_attr_t",
2349 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
2350 # are swapped, we work this around in the emitter...
2353 state => "exc_pinned",
2354 # see note about gas bugs
2355 emit => '. fsubrp%XM %x87_binop',
2357 attr_type => "ia32_x87_attr_t",
2362 state => "exc_pinned",
2363 irn_flags => [ "rematerializable" ],
2364 emit => '. fsubr%XM %x87_binop',
2366 attr_type => "ia32_x87_attr_t",
2371 state => "exc_pinned",
2372 irn_flags => [ "rematerializable" ],
2373 # see note about gas bugs before fsubp
2374 emit => '. fsubp%XM %x87_binop',
2376 attr_type => "ia32_x87_attr_t",
2383 attr_type => "ia32_x87_attr_t",
2387 # this node is just here, to keep the simulator running
2388 # we can omit this when a fprem simulation function exists
2390 emit => '. fprem1\n'.
2393 attr_type => "ia32_x87_attr_t",
2398 state => "exc_pinned",
2399 emit => '. fdiv%XM %x87_binop',
2401 attr_type => "ia32_x87_attr_t",
2406 state => "exc_pinned",
2407 # see note about gas bugs before fsubp
2408 emit => '. fdivrp%XM %x87_binop',
2410 attr_type => "ia32_x87_attr_t",
2415 state => "exc_pinned",
2416 emit => '. fdivr%XM %x87_binop',
2418 attr_type => "ia32_x87_attr_t",
2423 state => "exc_pinned",
2424 # see note about gas bugs before fsubp
2425 emit => '. fdivp%XM %x87_binop',
2427 attr_type => "ia32_x87_attr_t",
2434 attr_type => "ia32_x87_attr_t",
2439 op_flags => [ "keep" ],
2440 irn_flags => [ "rematerializable" ],
2443 attr_type => "ia32_x87_attr_t",
2448 irn_flags => [ "rematerializable" ],
2449 op_flags => [ "labeled" ],
2450 state => "exc_pinned",
2451 emit => '. fld%XM %AM',
2452 attr_type => "ia32_x87_attr_t",
2458 irn_flags => [ "rematerializable" ],
2459 op_flags => [ "labeled" ],
2460 state => "exc_pinned",
2461 emit => '. fst%XM %AM',
2463 attr_type => "ia32_x87_attr_t",
2469 irn_flags => [ "rematerializable" ],
2470 op_flags => [ "labeled" ],
2471 state => "exc_pinned",
2472 emit => '. fstp%XM %AM',
2474 attr_type => "ia32_x87_attr_t",
2480 state => "exc_pinned",
2481 emit => '. fild%XM %AM',
2482 attr_type => "ia32_x87_attr_t",
2488 state => "exc_pinned",
2489 emit => '. fist%XM %AM',
2491 attr_type => "ia32_x87_attr_t",
2497 state => "exc_pinned",
2498 emit => '. fistp%XM %AM',
2500 attr_type => "ia32_x87_attr_t",
2505 # SSE3 fisttp instruction
2507 state => "exc_pinned",
2508 emit => '. fisttp%XM %AM',
2510 attr_type => "ia32_x87_attr_t",
2516 op_flags => [ "constlike", "keep" ],
2517 irn_flags => [ "rematerializable" ],
2518 reg_req => { out => [ "vfp" ] },
2520 attr_type => "ia32_x87_attr_t",
2525 op_flags => [ "constlike", "keep" ],
2526 irn_flags => [ "rematerializable" ],
2527 reg_req => { out => [ "vfp" ] },
2529 attr_type => "ia32_x87_attr_t",
2534 op_flags => [ "constlike", "keep" ],
2535 irn_flags => [ "rematerializable" ],
2536 reg_req => { out => [ "vfp" ] },
2538 attr_type => "ia32_x87_attr_t",
2543 op_flags => [ "constlike", "keep" ],
2544 irn_flags => [ "rematerializable" ],
2545 reg_req => { out => [ "vfp" ] },
2547 attr_type => "ia32_x87_attr_t",
2552 op_flags => [ "constlike", "keep" ],
2553 irn_flags => [ "rematerializable" ],
2554 reg_req => { out => [ "vfp" ] },
2556 attr_type => "ia32_x87_attr_t",
2561 op_flags => [ "constlike", "keep" ],
2562 irn_flags => [ "rematerializable" ],
2563 reg_req => { out => [ "vfp" ] },
2564 emit => '. fldll2t',
2565 attr_type => "ia32_x87_attr_t",
2570 op_flags => [ "constlike", "keep" ],
2571 irn_flags => [ "rematerializable" ],
2572 reg_req => { out => [ "vfp" ] },
2574 attr_type => "ia32_x87_attr_t",
2579 # Note that it is NEVER allowed to do CSE on these nodes
2580 # Moreover, note the virtual register requierements!
2583 op_flags => [ "keep" ],
2584 reg_req => { out => [ "none" ] },
2585 cmp_attr => "return 1;",
2586 emit => '. fxch %X0',
2587 attr_type => "ia32_x87_attr_t",
2593 op_flags => [ "keep" ],
2594 reg_req => { out => [ "none" ] },
2595 cmp_attr => "return 1;",
2596 emit => '. fld %X0',
2597 attr_type => "ia32_x87_attr_t",
2603 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2604 cmp_attr => "return 1;",
2605 emit => '. fld %X0',
2606 attr_type => "ia32_x87_attr_t",
2611 op_flags => [ "keep" ],
2612 reg_req => { out => [ "none" ] },
2613 cmp_attr => "return 1;",
2614 emit => '. fstp %X0',
2615 attr_type => "ia32_x87_attr_t",
2621 op_flags => [ "keep" ],
2622 reg_req => { out => [ "none" ] },
2623 cmp_attr => "return 1;",
2624 emit => '. ffreep %X0',
2625 attr_type => "ia32_x87_attr_t",
2631 op_flags => [ "keep" ],
2632 reg_req => { out => [ "none" ] },
2633 cmp_attr => "return 1;",
2635 attr_type => "ia32_x87_attr_t",
2641 op_flags => [ "keep" ],
2642 reg_req => { out => [ "none" ] },
2643 cmp_attr => "return 1;",
2645 attr_type => "ia32_x87_attr_t",
2652 emit => ". fucom %X1\n".
2654 attr_type => "ia32_x87_attr_t",
2660 emit => ". fucomp %X1\n".
2662 attr_type => "ia32_x87_attr_t",
2668 emit => ". fucompp\n".
2670 attr_type => "ia32_x87_attr_t",
2676 emit => '. fucomi %X1',
2677 attr_type => "ia32_x87_attr_t",
2683 emit => '. fucompi %X1',
2684 attr_type => "ia32_x87_attr_t",
2692 attr_type => "ia32_x87_attr_t",
2696 # Spilling and reloading of SSE registers, hardcoded, not generated #
2699 op_flags => [ "fragile", "labeled" ],
2700 state => "exc_pinned",
2701 reg_req => { in => [ "gp", "gp", "none" ],
2702 out => [ "xmm", "none", "none", "none" ] },
2703 emit => '. movdqu %D0, %AM',
2704 ins => [ "base", "index", "mem" ],
2705 outs => [ "res", "M", "X_regular", "X_except" ],
2711 op_flags => [ "fragile", "labeled" ],
2712 state => "exc_pinned",
2713 reg_req => { in => [ "gp", "gp", "none", "xmm" ],
2714 out => [ "none", "none", "none" ] },
2715 ins => [ "base", "index", "mem", "val" ],
2716 outs => [ "M", "X_regular", "X_except" ],
2717 emit => '. movdqu %binop',
2724 # Transform some attributes
2725 foreach my $op (keys(%nodes)) {
2726 my $node = $nodes{$op};
2727 my $op_attr_init = $node->{op_attr_init};
2729 if(defined($op_attr_init)) {
2730 $op_attr_init .= "\n\t";
2735 if(!defined($node->{latency})) {
2737 $node->{latency} = 0;
2739 die("Latency missing for op $op");
2742 $op_attr_init .= "attr->latency = ".$node->{latency} . ";";
2744 $node->{op_attr_init} = $op_attr_init;