1 # This is the specification for the ia32 assembler Firm-operations
7 $mode_fp87 = "ia32_mode_E";
9 $mode_flags = "mode_Iu";
10 $mode_fpcw = "ia32_mode_fpcw";
14 { name => "edx", dwarf => 2 },
15 { name => "ecx", dwarf => 1 },
16 { name => "eax", dwarf => 0 },
17 { name => "ebx", dwarf => 3 },
18 { name => "esi", dwarf => 6 },
19 { name => "edi", dwarf => 7 },
20 { name => "ebp", dwarf => 5 },
21 { name => "esp", dwarf => 4, type => "ignore" },
22 { name => "gp_NOREG", type => "ignore | virtual" }, # we need a dummy register for NoReg nodes
26 { name => "mm0", dwarf => 29, type => "ignore" },
27 { name => "mm1", dwarf => 30, type => "ignore" },
28 { name => "mm2", dwarf => 31, type => "ignore" },
29 { name => "mm3", dwarf => 32, type => "ignore" },
30 { name => "mm4", dwarf => 33, type => "ignore" },
31 { name => "mm5", dwarf => 34, type => "ignore" },
32 { name => "mm6", dwarf => 35, type => "ignore" },
33 { name => "mm7", dwarf => 36, type => "ignore" },
34 { mode => $mode_mmx, flags => "manual_ra" }
37 { name => "xmm0", dwarf => 21 },
38 { name => "xmm1", dwarf => 22 },
39 { name => "xmm2", dwarf => 23 },
40 { name => "xmm3", dwarf => 24 },
41 { name => "xmm4", dwarf => 25 },
42 { name => "xmm5", dwarf => 26 },
43 { name => "xmm6", dwarf => 27 },
44 { name => "xmm7", dwarf => 28 },
45 { name => "xmm_NOREG", type => "ignore | virtual" }, # we need a dummy register for NoReg nodes
49 { name => "st0", realname => "st", dwarf => 11 },
50 { name => "st1", realname => "st(1)", dwarf => 12 },
51 { name => "st2", realname => "st(2)", dwarf => 13 },
52 { name => "st3", realname => "st(3)", dwarf => 14 },
53 { name => "st4", realname => "st(4)", dwarf => 15 },
54 { name => "st5", realname => "st(5)", dwarf => 16 },
55 { name => "st6", realname => "st(6)", dwarf => 17 },
56 { name => "st7", realname => "st(7)", dwarf => 18 },
57 { name => "fp_NOREG", type => "ignore | virtual" }, # we need a dummy register for NoReg nodes
58 { mode => $mode_fp87 }
60 fp_cw => [ # the floating point control word
61 { name => "fpcw", dwarf => 37, type => "state" },
62 { mode => $mode_fpcw, flags => "manual_ra | state" }
65 { name => "eflags", dwarf => 9 },
66 { mode => "mode_Iu", flags => "manual_ra" }
70 $default_attr_type = "ia32_attr_t";
71 $default_copy_attr = "ia32_copy_attr";
73 sub ia32_custom_init_attr {
79 if(defined($node->{modified_flags})) {
80 $res .= "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);\n";
82 if(defined($node->{am})) {
84 if($am eq "source,unary") {
85 $res .= "\tset_ia32_am_support(res, ia32_am_unary);";
86 } elsif($am eq "source,binary") {
87 $res .= "\tset_ia32_am_support(res, ia32_am_binary);";
88 } elsif($am eq "none") {
91 die("Invalid address mode '$am' specified on op $name");
94 if($node->{state} ne "exc_pinned"
95 and $node->{state} ne "pinned") {
96 die("AM nodes must have pinned or AM pinned state ($name)");
102 $custom_init_attr_func = \&ia32_custom_init_attr;
106 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
107 "\tinit_ia32_asm_attributes(res);",
109 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);",
111 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
112 "\tinit_ia32_call_attributes(res, pop, call_tp);",
113 ia32_condcode_attr_t =>
114 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
115 "\tinit_ia32_condcode_attributes(res, condition_code);",
116 ia32_switch_attr_t =>
117 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
118 "\tinit_ia32_switch_attributes(res, switch_table);",
120 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
121 "\tinit_ia32_copyb_attributes(res, size);",
122 ia32_immediate_attr_t =>
123 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
124 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, no_pic_adjust, offset);",
126 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
127 "\tinit_ia32_x87_attributes(res);",
128 ia32_climbframe_attr_t =>
129 "\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
130 "\tinit_ia32_climbframe_attributes(res, count);",
134 ia32_asm_attr_t => "ia32_compare_asm_attr",
135 ia32_attr_t => "ia32_compare_nodes_attr",
136 ia32_call_attr_t => "ia32_compare_call_attr",
137 ia32_condcode_attr_t => "ia32_compare_condcode_attr",
138 ia32_copyb_attr_t => "ia32_compare_copyb_attr",
139 ia32_switch_attr_t => "ia32_compare_nodes_attr",
140 ia32_immediate_attr_t => "ia32_compare_immediate_attr",
141 ia32_x87_attr_t => "ia32_compare_x87_attr",
142 ia32_climbframe_attr_t => "ia32_compare_climbframe_attr",
145 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
146 $status_flags_wo_cf = [ "PF", "AF", "ZF", "SF", "OF" ];
147 $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
148 "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
150 my %binop_flags_constructors = (
152 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
153 out => [ "flags", "none", "none" ] },
156 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ],
157 out => [ "flags", "none", "none" ] },
165 op_flags => [ "constlike" ],
166 irn_flags => [ "not_scheduled" ],
167 reg_req => { out => [ "gp_NOREG:I" ] },
168 attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
169 attr_type => "ia32_immediate_attr_t",
170 hash_func => "ia32_hash_Immediate",
178 out_arity => "variable",
179 attr_type => "ia32_asm_attr_t",
180 attr => "ident *asm_text, const ia32_asm_reg_t *register_map",
181 init_attr => "attr->asm_text = asm_text;\n".
182 "\tattr->register_map = register_map;\n",
184 modified_flags => $status_flags,
187 # "allocates" a free register
189 op_flags => [ "constlike", "cse_neutral" ],
190 irn_flags => [ "rematerializable" ],
191 reg_req => { out => [ "gp" ] },
195 cmp_attr => "return 1;",
199 irn_flags => [ "rematerializable" ],
200 state => "exc_pinned",
201 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
202 out => [ "in_r4 in_r5", "flags", "none" ] },
203 ins => [ "base", "index", "mem", "left", "right" ],
204 outs => [ "res", "flags", "M" ],
206 am => "source,binary",
209 modified_flags => $status_flags
213 irn_flags => [ "rematerializable" ],
214 state => "exc_pinned",
215 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
216 ins => [ "base", "index", "mem", "val" ],
217 emit => "add%M %#S3, %AM",
220 modified_flags => $status_flags
224 irn_flags => [ "rematerializable" ],
225 state => "exc_pinned",
226 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
227 ins => [ "base", "index", "mem", "val" ],
228 emit => "add%M %#S3, %AM",
231 modified_flags => $status_flags
235 state => "exc_pinned",
236 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
237 out => [ "in_r4 in_r5", "flags", "none" ] },
238 ins => [ "base", "index", "mem", "left", "right", "eflags" ],
239 outs => [ "res", "flags", "M" ],
241 am => "source,binary",
244 modified_flags => $status_flags
248 ins => [ "left", "right" ],
254 ins => [ "left", "right", "eflags" ],
260 # we should not rematrialize this node. It produces 2 results and has
261 # very strict constraints
262 state => "exc_pinned",
263 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
264 out => [ "eax", "flags", "none", "edx" ] },
265 ins => [ "base", "index", "mem", "left", "right" ],
266 emit => 'mul%M %AS4',
267 outs => [ "res_low", "flags", "M", "res_high" ],
268 am => "source,binary",
270 modified_flags => $status_flags
274 ins => [ "left", "right" ],
275 outs => [ "res_low", "flags", "M", "res_high" ],
281 irn_flags => [ "rematerializable" ],
282 state => "exc_pinned",
283 # TODO: adjust out requirements for the 3 operand form
284 # (no need for should_be_same then)
285 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
286 out => [ "in_r4 in_r5", "flags", "none" ] },
287 ins => [ "base", "index", "mem", "left", "right" ],
288 outs => [ "res", "flags", "M" ],
289 am => "source,binary",
292 modified_flags => $status_flags
296 irn_flags => [ "rematerializable" ],
297 state => "exc_pinned",
298 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
299 out => [ "eax", "flags", "none", "edx" ] },
300 ins => [ "base", "index", "mem", "left", "right" ],
301 emit => 'imul%M %AS4',
302 outs => [ "res_low", "flags", "M", "res_high" ],
303 am => "source,binary",
305 modified_flags => $status_flags
309 ins => [ "left", "right" ],
310 outs => [ "res_low", "flags", "M", "res_high" ],
316 irn_flags => [ "rematerializable" ],
317 state => "exc_pinned",
318 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
319 out => [ "in_r4 in_r5", "flags", "none" ] },
320 ins => [ "base", "index", "mem", "left", "right" ],
321 outs => [ "res", "flags", "M" ],
322 am => "source,binary",
326 modified_flags => $status_flags
330 irn_flags => [ "rematerializable" ],
331 state => "exc_pinned",
332 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
333 ins => [ "base", "index", "mem", "val" ],
334 emit => 'and%M %#S3, %AM',
337 modified_flags => $status_flags
341 irn_flags => [ "rematerializable" ],
342 state => "exc_pinned",
343 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
344 ins => [ "base", "index", "mem", "val" ],
345 emit => 'and%M %#S3, %AM',
348 modified_flags => $status_flags
352 irn_flags => [ "rematerializable" ],
353 state => "exc_pinned",
354 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
355 out => [ "in_r4 in_r5", "flags", "none" ] },
356 ins => [ "base", "index", "mem", "left", "right" ],
357 outs => [ "res", "flags", "M" ],
358 am => "source,binary",
362 modified_flags => $status_flags
366 irn_flags => [ "rematerializable" ],
367 state => "exc_pinned",
368 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
369 ins => [ "base", "index", "mem", "val" ],
370 emit => 'or%M %#S3, %AM',
373 modified_flags => $status_flags
377 irn_flags => [ "rematerializable" ],
378 state => "exc_pinned",
379 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
380 ins => [ "base", "index", "mem", "val" ],
381 emit => 'or%M %#S3, %AM',
384 modified_flags => $status_flags
388 irn_flags => [ "rematerializable" ],
389 state => "exc_pinned",
390 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
391 out => [ "in_r4 in_r5", "flags", "none" ] },
392 ins => [ "base", "index", "mem", "left", "right" ],
393 outs => [ "res", "flags", "M" ],
394 am => "source,binary",
398 modified_flags => $status_flags
402 op_flags => [ "constlike" ],
403 irn_flags => [ "rematerializable" ],
404 reg_req => { out => [ "gp", "flags" ] },
405 outs => [ "res", "flags" ],
406 emit => "xor%M %D0, %D0",
409 modified_flags => $status_flags
413 irn_flags => [ "rematerializable" ],
414 state => "exc_pinned",
415 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
416 ins => [ "base", "index", "mem", "val" ],
417 emit => 'xor%M %#S3, %AM',
420 modified_flags => $status_flags
424 irn_flags => [ "rematerializable" ],
425 state => "exc_pinned",
426 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
427 ins => [ "base", "index", "mem", "val" ],
428 emit => 'xor%M %#S3, %AM',
431 modified_flags => $status_flags
435 irn_flags => [ "rematerializable" ],
436 state => "exc_pinned",
437 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
438 out => [ "in_r4", "flags", "none" ] },
439 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
440 outs => [ "res", "flags", "M" ],
441 am => "source,binary",
445 modified_flags => $status_flags
449 irn_flags => [ "rematerializable" ],
450 state => "exc_pinned",
451 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
452 ins => [ "base", "index", "mem", "subtrahend" ],
453 emit => 'sub%M %#S3, %AM',
456 modified_flags => $status_flags
460 irn_flags => [ "rematerializable" ],
461 state => "exc_pinned",
462 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
463 ins => [ "base", "index", "mem", "subtrahend" ],
464 emit => 'sub%M %#S3, %AM',
467 modified_flags => $status_flags
471 state => "exc_pinned",
472 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
473 out => [ "in_r4", "flags", "none" ] },
474 ins => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
475 outs => [ "res", "flags", "M" ],
476 am => "source,binary",
480 modified_flags => $status_flags
484 # Spiller currently fails when rematerializing flag consumers
485 # irn_flags => [ "rematerializable" ],
486 reg_req => { in => [ "flags" ], out => [ "gp", "flags" ] },
487 outs => [ "res", "flags" ],
488 emit => "sbb%M %D0, %D0",
491 modified_flags => $status_flags
495 ins => [ "minuend", "subtrahend" ],
501 ins => [ "minuend", "subtrahend", "eflags" ],
507 op_flags => [ "fragile", "uses_memory" ],
508 state => "exc_pinned",
509 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
510 out => [ "eax", "flags", "none", "edx", "none", "none" ] },
511 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
512 outs => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
513 am => "source,unary",
514 emit => "idiv%M %AS3",
516 modified_flags => $status_flags
520 op_flags => [ "fragile", "uses_memory" ],
521 state => "exc_pinned",
522 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
523 out => [ "eax", "flags", "none", "edx", "none", "none" ] },
524 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
525 outs => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
526 am => "source,unary",
527 emit => "div%M %AS3",
529 modified_flags => $status_flags
533 irn_flags => [ "rematerializable" ],
534 reg_req => { in => [ "gp", "ecx" ],
535 out => [ "in_r1 !in_r2", "flags" ] },
536 ins => [ "val", "count" ],
537 outs => [ "res", "flags" ],
538 emit => 'shl%M %<S1, %S0',
541 modified_flags => $status_flags
545 irn_flags => [ "rematerializable" ],
546 state => "exc_pinned",
547 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
548 ins => [ "base", "index", "mem", "count" ],
549 emit => 'shl%M %<S3, %AM',
552 modified_flags => $status_flags
556 irn_flags => [ "rematerializable" ],
557 reg_req => { in => [ "gp", "gp", "ecx" ],
558 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
559 ins => [ "val_high", "val_low", "count" ],
560 outs => [ "res", "flags" ],
561 emit => "shld%M %<S2, %S1, %D0",
564 modified_flags => $status_flags
568 irn_flags => [ "rematerializable" ],
569 reg_req => { in => [ "gp", "ecx" ],
570 out => [ "in_r1 !in_r2", "flags" ] },
571 ins => [ "val", "count" ],
572 outs => [ "res", "flags" ],
573 emit => 'shr%M %<S1, %S0',
576 modified_flags => $status_flags
580 irn_flags => [ "rematerializable" ],
581 state => "exc_pinned",
582 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
583 ins => [ "base", "index", "mem", "count" ],
584 emit => 'shr%M %<S3, %AM',
587 modified_flags => $status_flags
591 irn_flags => [ "rematerializable" ],
592 reg_req => { in => [ "gp", "gp", "ecx" ],
593 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
594 ins => [ "val_high", "val_low", "count" ],
595 outs => [ "res", "flags" ],
596 emit => "shrd%M %<S2, %S1, %D0",
599 modified_flags => $status_flags
603 irn_flags => [ "rematerializable" ],
604 reg_req => { in => [ "gp", "ecx" ],
605 out => [ "in_r1 !in_r2", "flags" ] },
606 ins => [ "val", "count" ],
607 outs => [ "res", "flags" ],
608 emit => 'sar%M %<S1, %S0',
611 modified_flags => $status_flags
615 irn_flags => [ "rematerializable" ],
616 state => "exc_pinned",
617 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
618 ins => [ "base", "index", "mem", "count" ],
619 emit => 'sar%M %<S3, %AM',
622 modified_flags => $status_flags
626 irn_flags => [ "rematerializable" ],
627 reg_req => { in => [ "gp", "ecx" ],
628 out => [ "in_r1 !in_r2", "flags" ] },
629 ins => [ "val", "count" ],
630 outs => [ "res", "flags" ],
631 emit => 'ror%M %<S1, %S0',
634 modified_flags => $status_flags
638 irn_flags => [ "rematerializable" ],
639 state => "exc_pinned",
640 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
641 ins => [ "base", "index", "mem", "count" ],
642 emit => 'ror%M %<S3, %AM',
645 modified_flags => $status_flags
649 irn_flags => [ "rematerializable" ],
650 reg_req => { in => [ "gp", "ecx" ],
651 out => [ "in_r1 !in_r2", "flags" ] },
652 ins => [ "val", "count" ],
653 outs => [ "res", "flags" ],
654 emit => 'rol%M %<S1, %D0',
657 modified_flags => $status_flags
661 irn_flags => [ "rematerializable" ],
662 state => "exc_pinned",
663 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
664 ins => [ "base", "index", "mem", "count" ],
665 emit => 'rol%M %<S3, %AM',
668 modified_flags => $status_flags
672 irn_flags => [ "rematerializable" ],
673 reg_req => { in => [ "gp" ],
674 out => [ "in_r1", "flags" ] },
677 outs => [ "res", "flags" ],
680 modified_flags => $status_flags
684 irn_flags => [ "rematerializable" ],
685 state => "exc_pinned",
686 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
687 ins => [ "base", "index", "mem" ],
691 modified_flags => $status_flags
695 irn_flags => [ "rematerializable" ],
696 reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "in_r2" ] },
697 outs => [ "low_res", "high_res" ],
699 modified_flags => $status_flags
704 irn_flags => [ "rematerializable" ],
705 reg_req => { in => [ "gp" ],
706 out => [ "in_r1", "flags" ] },
708 outs => [ "res", "flags" ],
712 modified_flags => $status_flags_wo_cf
716 irn_flags => [ "rematerializable" ],
717 state => "exc_pinned",
718 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
719 ins => [ "base", "index", "mem" ],
723 modified_flags => $status_flags_wo_cf
727 irn_flags => [ "rematerializable" ],
728 reg_req => { in => [ "gp" ],
729 out => [ "in_r1", "flags" ] },
731 outs => [ "res", "flags" ],
735 modified_flags => $status_flags_wo_cf
739 irn_flags => [ "rematerializable" ],
740 state => "exc_pinned",
741 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
742 ins => [ "base", "index", "mem" ],
746 modified_flags => $status_flags_wo_cf
750 irn_flags => [ "rematerializable" ],
751 reg_req => { in => [ "gp" ],
752 out => [ "in_r1" ] },
762 irn_flags => [ "rematerializable" ],
763 state => "exc_pinned",
764 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
765 ins => [ "base", "index", "mem" ],
773 reg_req => { in => [ "flags" ], out => [ "flags" ] },
777 modified_flags => $status_flags
781 reg_req => { out => [ "flags" ] },
785 modified_flags => $status_flags
789 irn_flags => [ "rematerializable" ],
790 state => "exc_pinned",
791 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
792 out => [ "flags", "none", "none" ] },
793 ins => [ "base", "index", "mem", "left", "right" ],
794 outs => [ "eflags", "unused", "M" ],
795 am => "source,binary",
797 attr => "bool ins_permuted",
798 init_attr => "attr->data.ins_permuted = ins_permuted;",
801 modified_flags => $status_flags
805 irn_flags => [ "rematerializable" ],
806 state => "exc_pinned",
807 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] ,
808 out => [ "flags", "none", "none" ] },
809 ins => [ "base", "index", "mem", "left", "right" ],
810 outs => [ "eflags", "unused", "M" ],
811 am => "source,binary",
813 attr => "bool ins_permuted",
814 init_attr => "attr->data.ins_permuted = ins_permuted;",
817 modified_flags => $status_flags
821 irn_flags => [ "rematerializable" ],
822 state => "exc_pinned",
823 reg_req => { in => [ "eax ebx ecx edx" ],
824 out => [ "in_r1", "flags" ] },
825 emit => 'xorb %>S0, %<S0',
827 outs => [ "res", "flags" ],
830 modified_flags => $status_flags,
834 irn_flags => [ "rematerializable" ],
835 state => "exc_pinned",
836 constructors => \%binop_flags_constructors,
837 ins => [ "base", "index", "mem", "left", "right" ],
838 outs => [ "eflags", "unused", "M" ],
839 am => "source,binary",
841 attr => "bool ins_permuted",
842 init_attr => "attr->data.ins_permuted = ins_permuted;",
845 modified_flags => $status_flags
849 #irn_flags => [ "rematerializable" ],
850 reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
853 attr_type => "ia32_condcode_attr_t",
854 attr => "ia32_condition_code_t condition_code",
855 # The way we handle Setcc with float nodes (potentially) destroys the flags
856 # (when we emit the setX; setp; orb and the setX;setnp;andb sequences)
857 init_attr => "set_ia32_ls_mode(res, mode_Bu);\n"
858 . "\tif (condition_code & ia32_cc_additional_float_cases) {\n"
859 . "\t\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);\n"
860 . "\t\t/* attr->latency = 3; */\n"
867 #irn_flags => [ "rematerializable" ],
868 state => "exc_pinned",
869 reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
870 ins => [ "base", "index", "mem","eflags" ],
871 attr_type => "ia32_condcode_attr_t",
872 attr => "ia32_condition_code_t condition_code",
873 init_attr => "set_ia32_ls_mode(res, mode_Bu);\n",
874 emit => 'set%P3 %AM',
880 #irn_flags => [ "rematerializable" ],
881 state => "exc_pinned",
882 # (note: leave the false,true order intact to make it compatible with other
884 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ],
885 out => [ "in_r4 in_r5", "flags", "none" ] },
886 ins => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
887 outs => [ "res", "flags", "M" ],
888 am => "source,binary",
889 attr_type => "ia32_condcode_attr_t",
890 attr => "ia32_condition_code_t condition_code",
897 op_flags => [ "cfopcode", "forking" ],
898 reg_req => { in => [ "eflags" ], out => [ "none", "none" ] },
900 outs => [ "false", "true" ],
901 attr_type => "ia32_condcode_attr_t",
902 attr => "ia32_condition_code_t condition_code",
908 op_flags => [ "cfopcode", "forking" ],
909 reg_req => { in => [ "gp", "gp" ] },
910 ins => [ "base", "index" ],
911 out_arity => "variable",
912 attr_type => "ia32_switch_attr_t",
913 attr => "const ir_switch_table *switch_table",
919 irn_flags => [ "simple_jump" ],
920 op_flags => [ "cfopcode" ],
921 reg_req => { out => [ "none" ] },
928 op_flags => [ "cfopcode", "unknown_jump" ],
929 reg_req => { in => [ "gp", "gp", "none", "gp" ],
930 out => [ "none", "flags", "none" ] },
931 ins => [ "base", "index", "mem", "target" ],
932 outs => [ "jmp", "flags", "M" ],
933 am => "source,unary",
940 op_flags => [ "constlike" ],
941 irn_flags => [ "rematerializable" ],
942 reg_req => { out => [ "gp" ] },
943 emit => "movl %I, %D0",
944 attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
945 attr_type => "ia32_immediate_attr_t",
951 op_flags => [ "constlike" ],
952 irn_flags => [ "rematerializable" ],
953 reg_req => { out => [ "gp" ] },
960 op_flags => [ "constlike" ],
961 reg_req => { out => [ "gp" ] },
964 modified_flags => $status_flags,
969 op_flags => [ "constlike", "dump_noblock" ],
970 irn_flags => [ "not_scheduled" ],
971 reg_req => { out => [ "gp_NOREG:I" ] },
978 op_flags => [ "constlike", "dump_noblock" ],
979 irn_flags => [ "not_scheduled" ],
980 reg_req => { out => [ "fp_NOREG:I" ] },
983 attr_type => "ia32_x87_attr_t",
988 op_flags => [ "constlike", "dump_noblock" ],
989 irn_flags => [ "not_scheduled" ],
990 reg_req => { out => [ "xmm_NOREG:I" ] },
997 op_flags => [ "constlike" ],
998 irn_flags => [ "not_scheduled" ],
999 reg_req => { out => [ "fpcw" ] },
1002 modified_flags => $fpcw_flags
1006 op_flags => [ "uses_memory" ],
1008 reg_req => { in => [ "gp", "gp", "none" ], out => [ "fpcw" ] },
1009 ins => [ "base", "index", "mem" ],
1011 emit => "fldcw %AM",
1013 modified_flags => $fpcw_flags
1017 op_flags => [ "uses_memory" ],
1019 reg_req => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1020 ins => [ "base", "index", "mem", "fpcw" ],
1022 emit => "fnstcw %AM",
1027 op_flags => [ "uses_memory" ],
1029 reg_req => { in => [ "fp_cw" ], out => [ "none" ] },
1037 # we should not rematrialize this node. It has very strict constraints.
1038 reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] },
1039 ins => [ "val", "clobbered" ],
1047 # Note that we add additional latency values depending on address mode, so a
1048 # lateny of 0 for load is correct
1051 op_flags => [ "uses_memory", "fragile" ],
1052 state => "exc_pinned",
1053 reg_req => { in => [ "gp", "gp", "none" ],
1054 out => [ "gp", "none", "none", "none", "none" ] },
1055 ins => [ "base", "index", "mem" ],
1056 outs => [ "res", "unused", "M", "X_regular", "X_except" ],
1058 emit => "mov%#Ml %AM, %D0",
1062 op_flags => [ "uses_memory", "fragile" ],
1063 state => "exc_pinned",
1064 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1065 out => [ "none", "none", "none" ] },
1066 ins => [ "base", "index", "mem", "val" ],
1067 outs => [ "M", "X_regular", "X_except" ],
1068 emit => 'mov%M %#S3, %AM',
1073 op_flags => [ "uses_memory", "fragile" ],
1074 state => "exc_pinned",
1075 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
1076 out => ["none", "none", "none" ] },
1077 ins => [ "base", "index", "mem", "val" ],
1078 outs => [ "M", "X_regular", "X_except" ],
1079 emit => 'mov%M %#S3, %AM',
1084 irn_flags => [ "rematerializable" ],
1085 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
1086 ins => [ "base", "index" ],
1087 emit => 'leal %AM, %D0',
1090 # lea doesn't modify the flags, but setting this seems advantageous since it
1091 # increases chances that the Lea is transformed back to an Add
1092 modified_flags => 1,
1096 state => "exc_pinned",
1097 reg_req => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp:I|S", "none" ] },
1098 ins => [ "base", "index", "mem", "val", "stack" ],
1099 emit => 'push%M %AS3',
1100 outs => [ "stack", "M" ],
1101 am => "source,unary",
1106 state => "exc_pinned",
1107 reg_req => { in => [ "esp" ], out => [ "esp:I|S" ] },
1109 outs => [ "stack" ],
1110 emit => 'pushl %%eax',
1116 state => "exc_pinned",
1117 reg_req => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp:I|S" ] },
1118 ins => [ "mem", "stack" ],
1119 outs => [ "res", "M", "unused", "stack" ],
1120 emit => 'pop%M %D0',
1121 latency => 3, # Pop is more expensive than Push on Athlon
1125 state => "exc_pinned",
1126 reg_req => { in => [ "none", "esp" ], out => [ "ebp:I", "none", "none", "esp:I|S" ] },
1127 ins => [ "mem", "stack" ],
1128 outs => [ "res", "M", "unused", "stack" ],
1129 emit => 'pop%M %D0',
1130 latency => 3, # Pop is more expensive than Push on Athlon
1134 state => "exc_pinned",
1135 reg_req => { in => [ "ebp" ], out => [ "esp:I|S" ] },
1138 emit => 'movl %S0, %D0',
1144 state => "exc_pinned",
1145 reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp:I|S" ] },
1146 ins => [ "base", "index", "mem", "stack" ],
1147 outs => [ "unused0", "M", "unused1", "stack" ],
1148 emit => 'pop%M %AM',
1149 latency => 3, # Pop is more expensive than Push on Athlon
1153 reg_req => { in => [ "esp" ], out => [ "ebp", "esp:I|S", "none" ] },
1155 outs => [ "frame", "stack", "M" ],
1160 reg_req => { in => [ "ebp" ], out => [ "ebp:I", "esp:I|S" ] },
1162 outs => [ "frame", "stack" ],
1164 state => "exc_pinned",
1169 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "none" ] },
1170 ins => [ "base", "index", "mem", "stack", "size" ],
1171 am => "source,binary",
1174 outs => [ "stack", "M" ],
1175 modified_flags => $status_flags
1180 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "gp", "none" ] },
1181 ins => [ "base", "index", "mem", "stack", "size" ],
1182 am => "source,binary",
1183 emit => "subl %B\n".
1186 outs => [ "stack", "addr", "M" ],
1187 modified_flags => $status_flags
1191 op_flags => [ "keep" ],
1199 irn_flags => [ "rematerializable" ],
1200 reg_req => { out => [ "gp" ] },
1201 emit => "movl %%gs:0, %D0",
1207 # BT supports source address mode, but this is unused yet
1210 irn_flags => [ "rematerializable" ],
1211 state => "exc_pinned",
1212 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
1213 ins => [ "left", "right" ],
1214 emit => 'bt%M %S1, %S0',
1216 mode => $mode_flags,
1217 modified_flags => $status_flags # only CF is set, but the other flags are undefined
1221 irn_flags => [ "rematerializable" ],
1222 state => "exc_pinned",
1223 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1224 out => [ "gp", "flags", "none" ] },
1225 ins => [ "base", "index", "mem", "operand" ],
1226 outs => [ "res", "flags", "M" ],
1227 am => "source,binary",
1228 emit => 'bsf%M %AS3, %D0',
1231 modified_flags => $status_flags
1235 irn_flags => [ "rematerializable" ],
1236 state => "exc_pinned",
1237 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1238 out => [ "gp", "flags", "none" ] },
1239 ins => [ "base", "index", "mem", "operand" ],
1240 outs => [ "res", "flags", "M" ],
1241 am => "source,binary",
1242 emit => 'bsr%M %AS3, %D0',
1245 modified_flags => $status_flags
1249 # SSE4.2 or SSE4a popcnt instruction
1252 irn_flags => [ "rematerializable" ],
1253 state => "exc_pinned",
1254 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1255 out => [ "gp", "flags", "none" ] },
1256 ins => [ "base", "index", "mem", "operand" ],
1257 outs => [ "res", "flags", "M" ],
1258 am => "source,binary",
1259 emit => 'popcnt%M %AS3, %D0',
1262 modified_flags => $status_flags
1266 op_flags => [ "uses_memory", "fragile" ],
1267 state => "exc_pinned",
1269 in => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ],
1270 out => [ "esp:I|S", "fpcw", "none", "eax", "ecx", "edx", "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "none", "none" ]
1272 ins => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ],
1273 outs => [ "stack", "fpcw", "M", "eax", "ecx", "edx", "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "X_regular", "X_except" ],
1274 emit => "call %*AS3",
1275 attr_type => "ia32_call_attr_t",
1276 attr => "unsigned pop, ir_type *call_tp",
1277 am => "source,unary",
1278 latency => 4, # random number
1279 modified_flags => $status_flags
1283 # a Helper node for frame-climbing, needed for __builtin_(frame|return)_address
1285 # PS: try gcc __builtin_frame_address(100000) :-)
1288 reg_req => { in => [ "gp", "gp", "gp"], out => [ "in_r3" ] },
1289 ins => [ "frame", "cnt", "tmp" ],
1291 latency => 4, # random number
1292 attr_type => "ia32_climbframe_attr_t",
1293 attr => "unsigned count",
1301 irn_flags => [ "rematerializable" ],
1302 reg_req => { in => [ "gp" ],
1303 out => [ "in_r1" ] },
1305 emit => 'bswap%M %S0',
1312 # bswap16, use xchg here
1315 irn_flags => [ "rematerializable" ],
1316 reg_req => { in => [ "eax ebx ecx edx" ],
1317 out => [ "in_r1" ] },
1318 emit => 'xchg %<S0, %>S0',
1329 reg_req => { in => [ "none" ], out => [ "none" ] },
1337 # Undefined Instruction on ALL x86 CPU's
1341 reg_req => { in => [ "none" ], out => [ "none" ] },
1352 irn_flags => [ "rematerializable" ],
1354 reg_req => { in => [ "edx", "eax", "none" ], out => [ "none" ] },
1355 ins => [ "port", "value", "mem" ],
1356 emit => 'out%M %^S0, %#S1',
1359 modified_flags => $status_flags
1366 irn_flags => [ "rematerializable" ],
1368 reg_req => { in => [ "edx", "none" ], out => [ "eax", "none" ] },
1369 ins => [ "port", "mem" ],
1370 outs => [ "res", "M" ],
1371 emit => 'in%M %#D0, %^S0',
1374 modified_flags => $status_flags
1378 # Intel style prefetching
1381 op_flags => [ "uses_memory" ],
1382 state => "exc_pinned",
1383 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1384 ins => [ "base", "index", "mem" ],
1387 emit => "prefetcht0 %AM",
1391 op_flags => [ "uses_memory" ],
1392 state => "exc_pinned",
1393 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1394 ins => [ "base", "index", "mem" ],
1397 emit => "prefetcht1 %AM",
1401 op_flags => [ "uses_memory" ],
1402 state => "exc_pinned",
1403 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1404 ins => [ "base", "index", "mem" ],
1407 emit => "prefetcht2 %AM",
1411 op_flags => [ "uses_memory" ],
1412 state => "exc_pinned",
1413 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1414 ins => [ "base", "index", "mem" ],
1417 emit => "prefetchnta %AM",
1421 # 3DNow! prefetch instructions
1424 op_flags => [ "uses_memory" ],
1425 state => "exc_pinned",
1426 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1427 ins => [ "base", "index", "mem" ],
1430 emit => "prefetch %AM",
1434 op_flags => [ "uses_memory" ],
1435 state => "exc_pinned",
1436 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1437 ins => [ "base", "index", "mem" ],
1440 emit => "prefetchw %AM",
1445 irn_flags => [ "rematerializable" ],
1446 reg_req => { out => [ "xmm" ] },
1447 emit => 'xorp%FX %D0, %D0',
1453 op_flags => [ "constlike" ],
1454 irn_flags => [ "rematerializable" ],
1455 reg_req => { out => [ "xmm" ] },
1462 irn_flags => [ "rematerializable" ],
1463 reg_req => { out => [ "xmm" ] },
1464 emit => 'pxor %D0, %D0',
1469 # produces all 1 bits
1471 irn_flags => [ "rematerializable" ],
1472 reg_req => { out => [ "xmm" ] },
1473 emit => 'pcmpeqb %D0, %D0',
1478 # integer shift left, dword
1480 irn_flags => [ "rematerializable" ],
1481 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1482 emit => 'pslld %#S1, %D0',
1487 # integer shift left, qword
1489 irn_flags => [ "rematerializable" ],
1490 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1491 emit => 'psllq %#S1, %D0',
1496 # integer shift right, dword
1498 irn_flags => [ "rematerializable" ],
1499 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1500 emit => 'psrld %#S1, %D0',
1505 # mov from integer to SSE register
1507 irn_flags => [ "rematerializable" ],
1508 reg_req => { in => [ "gp" ], out => [ "xmm" ] },
1509 emit => 'movd %S0, %D0',
1515 irn_flags => [ "rematerializable" ],
1516 state => "exc_pinned",
1517 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1518 out => [ "in_r4 in_r5", "flags", "none" ] },
1519 ins => [ "base", "index", "mem", "left", "right" ],
1520 outs => [ "res", "flags", "M" ],
1521 am => "source,binary",
1522 emit => 'adds%FX %B',
1528 irn_flags => [ "rematerializable" ],
1529 state => "exc_pinned",
1530 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1531 out => [ "in_r4 in_r5", "flags", "none" ] },
1532 ins => [ "base", "index", "mem", "left", "right" ],
1533 outs => [ "res", "flags", "M" ],
1534 am => "source,binary",
1535 emit => 'muls%FX %B',
1541 irn_flags => [ "rematerializable" ],
1542 state => "exc_pinned",
1543 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1544 out => [ "in_r4 in_r5", "flags", "none" ] },
1545 ins => [ "base", "index", "mem", "left", "right" ],
1546 outs => [ "res", "flags", "M" ],
1547 am => "source,binary",
1548 emit => 'maxs%FX %B',
1554 irn_flags => [ "rematerializable" ],
1555 state => "exc_pinned",
1556 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1557 out => [ "in_r4 in_r5", "flags", "none" ] },
1558 ins => [ "base", "index", "mem", "left", "right" ],
1559 outs => [ "res", "flags", "M" ],
1560 am => "source,binary",
1561 emit => 'mins%FX %B',
1567 irn_flags => [ "rematerializable" ],
1568 state => "exc_pinned",
1569 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1570 out => [ "in_r4 in_r5", "flags", "none" ] },
1571 ins => [ "base", "index", "mem", "left", "right" ],
1572 outs => [ "res", "flags", "M" ],
1573 am => "source,binary",
1574 emit => 'andp%FX %B',
1580 irn_flags => [ "rematerializable" ],
1581 state => "exc_pinned",
1582 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1583 out => [ "in_r4 in_r5", "flags", "none" ] },
1584 ins => [ "base", "index", "mem", "left", "right" ],
1585 outs => [ "res", "flags", "M" ],
1586 am => "source,binary",
1587 emit => 'orp%FX %B',
1593 irn_flags => [ "rematerializable" ],
1594 state => "exc_pinned",
1595 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1596 out => [ "in_r4 in_r5", "flags", "none" ] },
1597 ins => [ "base", "index", "mem", "left", "right" ],
1598 outs => [ "res", "flags", "M" ],
1599 am => "source,binary",
1600 emit => 'xorp%FX %B',
1606 irn_flags => [ "rematerializable" ],
1607 state => "exc_pinned",
1608 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1609 out => [ "in_r4 !in_r5", "flags", "none" ] },
1610 ins => [ "base", "index", "mem", "left", "right" ],
1611 outs => [ "res", "flags", "M" ],
1612 am => "source,binary",
1613 emit => 'andnp%FX %B',
1619 irn_flags => [ "rematerializable" ],
1620 state => "exc_pinned",
1621 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1622 out => [ "in_r4", "flags", "none" ] },
1623 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
1624 outs => [ "res", "flags", "M" ],
1625 am => "source,binary",
1626 emit => 'subs%FX %B',
1632 irn_flags => [ "rematerializable" ],
1633 state => "exc_pinned",
1634 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1635 out => [ "in_r4 !in_r5", "flags", "none" ] },
1636 ins => [ "base", "index", "mem", "dividend", "divisor" ],
1637 outs => [ "res", "flags", "M" ],
1638 am => "source,binary",
1639 emit => 'divs%FX %B',
1644 irn_flags => [ "rematerializable" ],
1645 state => "exc_pinned",
1646 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1647 out => [ "eflags" ] },
1648 ins => [ "base", "index", "mem", "left", "right" ],
1649 outs => [ "flags" ],
1650 am => "source,binary",
1651 attr => "bool ins_permuted",
1652 init_attr => "attr->data.ins_permuted = ins_permuted;",
1653 emit => 'ucomis%FX %B',
1655 mode => $mode_flags,
1656 modified_flags => 1,
1660 op_flags => [ "uses_memory", "fragile" ],
1661 state => "exc_pinned",
1662 reg_req => { in => [ "gp", "gp", "none" ],
1663 out => [ "xmm", "none", "none", "none", "none" ] },
1664 ins => [ "base", "index", "mem" ],
1665 outs => [ "res", "unused", "M", "X_regular", "X_except" ],
1666 emit => 'movs%FX %AM, %D0',
1667 attr => "ir_mode *load_mode",
1668 init_attr => "attr->ls_mode = load_mode;",
1673 op_flags => [ "uses_memory", "fragile" ],
1674 state => "exc_pinned",
1675 reg_req => { in => [ "gp", "gp", "none", "xmm" ],
1676 out => [ "none", "none", "none" ] },
1677 ins => [ "base", "index", "mem", "val" ],
1678 outs => [ "M", "X_regular", "X_except" ],
1679 emit => 'movs%FX %S3, %AM',
1684 op_flags => [ "uses_memory", "fragile" ],
1685 state => "exc_pinned",
1686 reg_req => { in => [ "gp", "gp", "none", "xmm" ],
1687 out => [ "none", "none", "none" ] },
1688 ins => [ "base", "index", "mem", "val" ],
1689 outs => [ "M", "X_regular", "X_except" ],
1690 emit => 'movs%FX %S3, %AM',
1695 state => "exc_pinned",
1696 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1697 ins => [ "base", "index", "mem", "val" ],
1698 am => "source,unary",
1699 emit => 'cvtsi2ss %AS3, %D0',
1705 state => "exc_pinned",
1706 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1707 ins => [ "base", "index", "mem", "val" ],
1708 am => "source,unary",
1709 emit => 'cvtsi2sd %AS3, %D0',
1716 ins => [ "val_high", "val_low" ],
1718 dump_func => "NULL",
1723 outs => [ "res_high", "res_low" ],
1725 dump_func => "NULL",
1729 op_flags => [ "uses_memory", "fragile" ],
1731 reg_req => { in => [ "edi", "esi", "ecx", "none" ],
1732 out => [ "edi", "esi", "ecx", "none", "none", "none" ] },
1733 ins => [ "dest", "source", "count", "mem" ],
1734 outs => [ "dest", "source", "count", "M", "X_regular", "X_except" ],
1735 attr_type => "ia32_copyb_attr_t",
1736 attr => "unsigned size",
1738 # we don't care about this flag, so no need to mark this node
1739 # modified_flags => [ "DF" ]
1743 op_flags => [ "uses_memory", "fragile" ],
1745 reg_req => { in => [ "edi", "esi", "none" ],
1746 out => [ "edi", "esi", "none", "none", "none" ] },
1747 ins => [ "dest", "source", "mem" ],
1748 outs => [ "dest", "source", "M", "X_regular", "X_except" ],
1749 attr_type => "ia32_copyb_attr_t",
1750 attr => "unsigned size",
1752 # we don't care about this flag, so no need to mark this node
1753 # modified_flags => [ "DF" ]
1757 state => "exc_pinned",
1758 reg_req => { in => [ "eax" ], out => [ "eax" ] },
1767 op_flags => [ "uses_memory", "fragile" ],
1768 state => "exc_pinned",
1769 reg_req => { in => [ "gp", "gp", "none", "gp" ],
1770 out => [ "gp", "none", "none", "none", "none" ] },
1771 ins => [ "base", "index", "mem", "val" ],
1772 outs => [ "res", "flags", "M", "X_regular", "X_except" ],
1773 emit => "mov%#Ml %#AS3, %D0",
1774 am => "source,unary",
1776 attr => "ir_mode *smaller_mode",
1777 init_attr => "attr->ls_mode = smaller_mode;",
1782 op_flags => [ "uses_memory", "fragile" ],
1783 state => "exc_pinned",
1784 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
1785 out => [ "gp", "none", "none", "none", "none" ] },
1786 ins => [ "base", "index", "mem", "val" ],
1787 outs => [ "res", "flags", "M", "X_regular", "X_except" ],
1788 emit => "mov%#Ml %#AS3, %D0",
1789 am => "source,unary",
1791 attr => "ir_mode *smaller_mode",
1792 init_attr => "attr->ls_mode = smaller_mode;",
1797 state => "exc_pinned",
1798 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
1799 ins => [ "base", "index", "mem", "val" ],
1800 am => "source,unary",
1806 state => "exc_pinned",
1807 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1808 ins => [ "base", "index", "mem", "val" ],
1809 am => "source,unary",
1815 state => "exc_pinned",
1816 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1817 ins => [ "base", "index", "mem", "val" ],
1818 am => "source,unary",
1823 # rematerialisation disabled for all float nodes for now, because the fpcw
1824 # handler runs before spilling and we might end up with wrong fpcw then
1827 # irn_flags => [ "rematerializable" ],
1828 state => "exc_pinned",
1829 reg_req => { in => [ "gp", "gp", "none", "fp", "fp", "fpcw" ],
1830 out => [ "fp", "none", "none" ] },
1831 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1832 outs => [ "res", "dummy", "M" ],
1833 emit => 'fadd%FP%FM %AF',
1834 am => "source,binary",
1837 attr_type => "ia32_x87_attr_t",
1841 # irn_flags => [ "rematerializable" ],
1842 state => "exc_pinned",
1843 reg_req => { in => [ "gp", "gp", "none", "fp", "fp", "fpcw" ],
1844 out => [ "fp", "none", "none" ] },
1845 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1846 outs => [ "res", "dummy", "M" ],
1847 emit => 'fmul%FP%FM %AF',
1848 am => "source,binary",
1851 attr_type => "ia32_x87_attr_t",
1855 # irn_flags => [ "rematerializable" ],
1856 state => "exc_pinned",
1857 reg_req => { in => [ "gp", "gp", "none", "fp", "fp", "fpcw" ],
1858 out => [ "fp", "none", "none" ] },
1859 ins => [ "base", "index", "mem", "minuend", "subtrahend", "fpcw" ],
1860 outs => [ "res", "dummy", "M" ],
1861 emit => 'fsub%FR%FP%FM %AF',
1862 am => "source,binary",
1865 attr_type => "ia32_x87_attr_t",
1869 state => "exc_pinned",
1870 reg_req => { in => [ "gp", "gp", "none", "fp", "fp", "fpcw" ],
1871 out => [ "fp", "none", "none" ] },
1872 ins => [ "base", "index", "mem", "dividend", "divisor", "fpcw" ],
1873 outs => [ "res", "dummy", "M" ],
1874 emit => 'fdiv%FR%FP%FM %AF',
1875 am => "source,binary",
1877 attr_type => "ia32_x87_attr_t",
1881 reg_req => { in => [ "fp", "fp", "fpcw" ], out => [ "fp" ] },
1882 ins => [ "left", "right", "fpcw" ],
1886 attr_type => "ia32_x87_attr_t",
1890 irn_flags => [ "rematerializable" ],
1891 reg_req => { in => [ "fp"], out => [ "fp" ] },
1896 attr_type => "ia32_x87_attr_t",
1900 irn_flags => [ "rematerializable" ],
1901 reg_req => { in => [ "fp"], out => [ "fp" ] },
1906 attr_type => "ia32_x87_attr_t",
1910 irn_flags => [ "rematerializable" ],
1911 op_flags => [ "uses_memory", "fragile" ],
1912 state => "exc_pinned",
1913 reg_req => { in => [ "gp", "gp", "none" ],
1914 out => [ "fp", "none", "none", "none", "none" ] },
1915 ins => [ "base", "index", "mem" ],
1916 outs => [ "res", "unused", "M", "X_regular", "X_except" ],
1917 emit => 'fld%FM %AM',
1918 attr => "ir_mode *load_mode",
1919 init_attr => "attr->attr.ls_mode = load_mode;",
1921 attr_type => "ia32_x87_attr_t",
1925 irn_flags => [ "rematerializable" ],
1926 op_flags => [ "uses_memory", "fragile" ],
1927 state => "exc_pinned",
1928 reg_req => { in => [ "gp", "gp", "none", "fp" ],
1929 out => [ "none", "none", "none" ] },
1930 ins => [ "base", "index", "mem", "val" ],
1931 outs => [ "M", "X_regular", "X_except" ],
1932 emit => 'fst%FP%FM %AM',
1933 attr => "ir_mode *store_mode",
1934 init_attr => "attr->attr.ls_mode = store_mode;",
1936 attr_type => "ia32_x87_attr_t",
1940 state => "exc_pinned",
1941 reg_req => { in => [ "gp", "gp", "none" ],
1942 out => [ "fp", "none", "none" ] },
1943 outs => [ "res", "unused", "M" ],
1944 ins => [ "base", "index", "mem" ],
1945 emit => 'fild%FM %AM',
1947 attr_type => "ia32_x87_attr_t",
1951 op_flags => [ "uses_memory", "fragile" ],
1952 state => "exc_pinned",
1953 reg_req => { in => [ "gp", "gp", "none", "fp", "fpcw" ],
1954 out => [ "none", "none", "none", "none" ] },
1955 ins => [ "base", "index", "mem", "val", "fpcw" ],
1956 outs => [ "dummy", "M", "X_regular", "X_except" ],
1957 emit => 'fist%FP%FM %AM',
1959 attr_type => "ia32_x87_attr_t",
1962 # SSE3 fisttp instruction
1964 op_flags => [ "uses_memory", "fragile" ],
1965 state => "exc_pinned",
1966 reg_req => { in => [ "gp", "gp", "none", "fp" ],
1967 out => [ "in_r4", "none", "none", "none" ]},
1968 ins => [ "base", "index", "mem", "val" ],
1969 outs => [ "res", "M", "X_regular", "X_except" ],
1970 emit => 'fisttp%FM %AM',
1972 attr_type => "ia32_x87_attr_t",
1976 irn_flags => [ "rematerializable" ],
1977 reg_req => { out => [ "fp" ] },
1982 attr_type => "ia32_x87_attr_t",
1986 irn_flags => [ "rematerializable" ],
1987 reg_req => { out => [ "fp" ] },
1992 attr_type => "ia32_x87_attr_t",
1996 irn_flags => [ "rematerializable" ],
1997 reg_req => { out => [ "fp" ] },
2002 attr_type => "ia32_x87_attr_t",
2006 irn_flags => [ "rematerializable" ],
2007 reg_req => { out => [ "fp" ] },
2012 attr_type => "ia32_x87_attr_t",
2016 irn_flags => [ "rematerializable" ],
2017 reg_req => { out => [ "fp" ] },
2022 attr_type => "ia32_x87_attr_t",
2026 irn_flags => [ "rematerializable" ],
2027 reg_req => { out => [ "fp" ] },
2032 attr_type => "ia32_x87_attr_t",
2036 irn_flags => [ "rematerializable" ],
2037 reg_req => { out => [ "fp" ] },
2042 attr_type => "ia32_x87_attr_t",
2046 # we can't allow to rematerialize this node so we don't
2047 # accidently produce Phi(Fucom, Fucom(ins_permuted))
2048 # irn_flags => [ "rematerializable" ],
2049 reg_req => { in => [ "fp", "fp" ], out => [ "eax" ] },
2050 ins => [ "left", "right" ],
2051 outs => [ "flags" ],
2052 emit => "fucom%FP %F0\n".
2054 attr => "bool ins_permuted",
2055 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2057 attr_type => "ia32_x87_attr_t",
2062 # we can't allow to rematerialize this node so we don't
2063 # accidently produce Phi(Fucom, Fucom(ins_permuted))
2064 # irn_flags => [ "rematerializable" ],
2065 reg_req => { in => [ "fp", "fp" ], out => [ "eax" ] },
2066 ins => [ "left", "right" ],
2067 outs => [ "flags" ],
2068 emit => "fucompp\n".
2070 attr => "bool ins_permuted",
2071 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2073 attr_type => "ia32_x87_attr_t",
2078 irn_flags => [ "rematerializable" ],
2079 reg_req => { in => [ "fp", "fp" ], out => [ "eflags" ] },
2080 ins => [ "left", "right" ],
2081 outs => [ "flags" ],
2082 emit => 'fucom%FPi %F0',
2083 attr => "bool ins_permuted",
2084 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2086 attr_type => "ia32_x87_attr_t",
2091 # irn_flags => [ "rematerializable" ],
2092 reg_req => { in => [ "fp" ], out => [ "eax" ] },
2094 outs => [ "flags" ],
2097 attr => "bool ins_permuted",
2098 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2100 attr_type => "ia32_x87_attr_t",
2105 irn_flags => [ "rematerializable" ],
2106 reg_req => { in => [ "eax" ], out => [ "eflags" ] },
2108 outs => [ "flags" ],
2111 mode => $mode_flags,
2115 # Note that it is NEVER allowed to do CSE on these nodes
2116 # Moreover, note the virtual register requierements!
2119 op_flags => [ "keep" ],
2120 reg_req => { out => [ "none" ] },
2121 cmp_attr => "return 1;",
2123 attr_type => "ia32_x87_attr_t",
2129 op_flags => [ "keep" ],
2130 reg_req => { out => [ "none" ] },
2131 cmp_attr => "return 1;",
2133 attr_type => "ia32_x87_attr_t",
2139 reg_req => { in => [ "fp"], out => [ "fp" ] },
2140 cmp_attr => "return 1;",
2142 attr_type => "ia32_x87_attr_t",
2147 op_flags => [ "keep" ],
2148 reg_req => { out => [ "none" ] },
2149 cmp_attr => "return 1;",
2151 attr_type => "ia32_x87_attr_t",
2157 op_flags => [ "keep" ],
2158 reg_req => { out => [ "none" ] },
2159 cmp_attr => "return 1;",
2160 emit => 'ffreep %F0',
2161 attr_type => "ia32_x87_attr_t",
2167 op_flags => [ "keep" ],
2168 reg_req => { out => [ "none" ] },
2169 cmp_attr => "return 1;",
2171 attr_type => "ia32_x87_attr_t",
2177 op_flags => [ "keep" ],
2178 reg_req => { out => [ "none" ] },
2179 cmp_attr => "return 1;",
2181 attr_type => "ia32_x87_attr_t",
2186 # Spilling and reloading of SSE registers, hardcoded, not generated #
2189 op_flags => [ "uses_memory", "fragile" ],
2190 state => "exc_pinned",
2191 reg_req => { in => [ "gp", "gp", "none" ],
2192 out => [ "xmm", "none", "none", "none" ] },
2193 emit => 'movdqu %D0, %AM',
2194 ins => [ "base", "index", "mem" ],
2195 outs => [ "res", "M", "X_regular", "X_except" ],
2200 op_flags => [ "uses_memory", "fragile" ],
2201 state => "exc_pinned",
2202 reg_req => { in => [ "gp", "gp", "none", "xmm" ],
2203 out => [ "none", "none", "none" ] },
2204 ins => [ "base", "index", "mem", "val" ],
2205 outs => [ "M", "X_regular", "X_except" ],
2206 emit => 'movdqu %B',
2212 # Transform some attributes
2213 foreach my $op (keys(%nodes)) {
2214 my $node = $nodes{$op};
2215 my $op_attr_init = $node->{op_attr_init};
2217 if(defined($op_attr_init)) {
2218 $op_attr_init .= "\n\t";
2223 if(!defined($node->{latency})) {
2225 $node->{latency} = 0;
2227 die("Latency missing for op $op");
2230 $op_attr_init .= "ia32_init_op(op, ".$node->{latency} . ");";
2232 $node->{op_attr_init} = $op_attr_init;