3 # This is the specification for the ia32 assembler Firm-operations
10 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
13 # The node description is done as a perl hash initializer with the
14 # following structure:
19 # op_flags => "N|L|C|X|I|F|Y|H|c|K",
20 # irn_flags => "R|N|I|S"
21 # arity => "0|1|2|3 ... |variable|dynamic|any",
22 # state => "floats|pinned|mem_pinned|exc_pinned",
24 # { type => "type 1", name => "name 1" },
25 # { type => "type 2", name => "name 2" },
28 # comment => "any comment for constructor",
29 # reg_req => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
30 # cmp_attr => "c source code for comparing node attributes",
31 # emit => "emit code with templates",
32 # attr => "attitional attribute arguments for constructor"
33 # init_attr => "emit attribute initialization template"
34 # rd_constructor => "c source code which constructs an ir_node"
35 # attr_type => "name of the attribute struct",
38 # ... # (all nodes you need to describe)
40 # ); # close the %nodes initializer
42 # op_flags: flags for the operation, OPTIONAL (default is "N")
43 # the op_flags correspond to the firm irop_flags:
46 # C irop_flag_commutative
47 # X irop_flag_cfopcode
48 # I irop_flag_ip_cfopcode
51 # H irop_flag_highlevel
52 # c irop_flag_constlike
55 # irn_flags: special node flags, OPTIONAL (default is 0)
56 # following irn_flags are supported:
59 # I ignore for register allocation
60 # S modifies stack pointer
62 # state: state of the operation, OPTIONAL (default is "floats")
64 # arity: arity of the operation, MUST NOT BE OMITTED
66 # args: the OPTIONAL arguments of the node constructor (debug, irg and block
67 # are always the first 3 arguments and are always autmatically
69 # If this key is missing the following arguments will be created:
70 # for i = 1 .. arity: ir_node *op_i
73 # outs: if a node defines more than one output, the names of the projections
74 # nodes having outs having automatically the mode mode_T
75 # One can also annotate some flags for each out, additional to irn_flags.
76 # They are separated from name with a colon ':', and concatenated by pipe '|'
77 # Only I and S are available at the moment (same meaning as in irn_flags).
78 # example: [ "frame:I", "stack:I|S", "M" ]
80 # comment: OPTIONAL comment for the node constructor
82 # rd_constructor: for every operation there will be a
83 # new_rd_<arch>_<op-name> function with the arguments from above
84 # which creates the ir_node corresponding to the defined operation
85 # you can either put the complete source code of this function here
87 # This key is OPTIONAL. If omitted, the following constructor will
89 # if (!op_<arch>_<op-name>) assert(0);
93 # res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
96 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
100 # 0 - no special type
101 # 1 - caller save (register must be saved by the caller of a function)
102 # 2 - callee save (register must be saved by the called function)
103 # 4 - ignore (do not assign this register)
104 # 8 - emitter can choose an arbitrary register of this class
105 # 16 - the register is a virtual one
106 # 32 - register represents a state
107 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
110 { name => "edx", type => 1 },
111 { name => "ecx", type => 1 },
112 { name => "eax", type => 1 },
113 { name => "ebx", type => 2 },
114 { name => "esi", type => 2 },
115 { name => "edi", type => 2 },
116 { name => "ebp", type => 2 },
117 { name => "esp", type => 4 },
118 { name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
119 { name => "gp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
120 { mode => "mode_Iu" }
123 { name => "mm0", type => 4 },
124 { name => "mm1", type => 4 },
125 { name => "mm2", type => 4 },
126 { name => "mm3", type => 4 },
127 { name => "mm4", type => 4 },
128 { name => "mm5", type => 4 },
129 { name => "mm6", type => 4 },
130 { name => "mm7", type => 4 },
131 { mode => "mode_E", flags => "manual_ra" }
134 { name => "xmm0", type => 1 },
135 { name => "xmm1", type => 1 },
136 { name => "xmm2", type => 1 },
137 { name => "xmm3", type => 1 },
138 { name => "xmm4", type => 1 },
139 { name => "xmm5", type => 1 },
140 { name => "xmm6", type => 1 },
141 { name => "xmm7", type => 1 },
142 { name => "xmm_NOREG", type => 4 | 16 }, # we need a dummy register for NoReg nodes
143 { name => "xmm_UKNWN", type => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
147 { name => "vf0", type => 1 | 16 },
148 { name => "vf1", type => 1 | 16 },
149 { name => "vf2", type => 1 | 16 },
150 { name => "vf3", type => 1 | 16 },
151 { name => "vf4", type => 1 | 16 },
152 { name => "vf5", type => 1 | 16 },
153 { name => "vf6", type => 1 | 16 },
154 { name => "vf7", type => 1 | 16 },
155 { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
156 { name => "vfp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
160 { name => "st0", realname => "st", type => 4 },
161 { name => "st1", realname => "st(1)", type => 4 },
162 { name => "st2", realname => "st(2)", type => 4 },
163 { name => "st3", realname => "st(3)", type => 4 },
164 { name => "st4", realname => "st(4)", type => 4 },
165 { name => "st5", realname => "st(5)", type => 4 },
166 { name => "st6", realname => "st(6)", type => 4 },
167 { name => "st7", realname => "st(7)", type => 4 },
168 { mode => "mode_E", flags => "manual_ra" }
170 fp_cw => [ # the floating point control word
171 { name => "fpcw", type => 4|32 },
172 { mode => "mode_fpcw", flags => "manual_ra|state" }
175 { name => "eflags", type => 0 },
176 { mode => "mode_Iu", flags => "manual_ra" }
181 GP => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
182 SSE => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
183 VFP => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
184 BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
189 bundels_per_cycle => 1
193 S0 => "${arch}_emit_source_register(node, 0);",
194 S1 => "${arch}_emit_source_register(node, 1);",
195 S2 => "${arch}_emit_source_register(node, 2);",
196 S3 => "${arch}_emit_source_register(node, 3);",
197 SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
198 SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
199 SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
200 SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
201 D0 => "${arch}_emit_dest_register(node, 0);",
202 D1 => "${arch}_emit_dest_register(node, 1);",
203 DB0 => "${arch}_emit_8bit_dest_register(node, 0);",
204 X0 => "${arch}_emit_x87_register(node, 0);",
205 X1 => "${arch}_emit_x87_register(node, 1);",
206 SE => "${arch}_emit_extend_suffix(get_ia32_ls_mode(node));",
207 ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
208 ia32_emit_mode_suffix(node);",
209 M => "${arch}_emit_mode_suffix(node);",
210 XM => "${arch}_emit_x87_mode_suffix(node);",
211 XXM => "${arch}_emit_xmm_mode_suffix(node);",
212 XSD => "${arch}_emit_xmm_mode_suffix_s(node);",
213 AM => "${arch}_emit_am(node);",
214 unop3 => "${arch}_emit_unop(node, 3);",
215 unop4 => "${arch}_emit_unop(node, 4);",
216 unop5 => "${arch}_emit_unop(node, 5);",
217 binop => "${arch}_emit_binop(node);",
218 x87_binop => "${arch}_emit_x87_binop(node);",
219 CMP0 => "${arch}_emit_cmp_suffix_node(node, 0);",
220 CMP3 => "${arch}_emit_cmp_suffix_node(node, 3);",
223 #--------------------------------------------------#
226 # _ __ _____ __ _ _ __ ___ _ __ ___ #
227 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
228 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
229 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
232 #--------------------------------------------------#
234 $default_op_attr_type = "ia32_op_attr_t";
235 $default_attr_type = "ia32_attr_t";
236 $default_copy_attr = "ia32_copy_attr";
238 sub ia32_custom_init_attr {
243 if(defined($node->{modified_flags})) {
244 $res .= "\tset_ia32_flags(res, get_ia32_flags(res) | arch_irn_flags_modify_flags);\n";
246 if(defined($node->{am})) {
247 my $am = $node->{am};
248 if($am eq "source,unary") {
249 $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_unary);";
250 } elsif($am eq "source,binary") {
251 $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_binary);";
252 } elsif($am eq "dest,unary") {
253 $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_unary);";
254 } elsif($am eq "dest,binary") {
255 $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_binary);";
256 } elsif($am eq "dest,ternary") {
257 $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_ternary);";
258 } elsif($am eq "source,ternary") {
259 $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_ternary);";
260 } elsif($am eq "none") {
263 die("Invalid address mode '$am' specified on op $name");
266 if($node->{state} ne "exc_pinned"
267 and $node->{state} ne "pinned") {
268 die("AM nodes must have pinned or AM pinned state ($name)");
274 $custom_init_attr_func = \&ia32_custom_init_attr;
277 ia32_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
279 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
280 "\tinit_ia32_x87_attributes(res);",
282 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
283 "\tinit_ia32_x87_attributes(res);".
284 "\tinit_ia32_asm_attributes(res);",
285 ia32_immediate_attr_t =>
286 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
287 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);",
289 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
290 "\tinit_ia32_copyb_attributes(res, size);",
291 ia32_condcode_attr_t =>
292 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
293 "\tinit_ia32_condcode_attributes(res, pnc);",
297 ia32_attr_t => "ia32_compare_nodes_attr",
298 ia32_x87_attr_t => "ia32_compare_x87_attr",
299 ia32_asm_attr_t => "ia32_compare_asm_attr",
300 ia32_immediate_attr_t => "ia32_compare_immediate_attr",
301 ia32_copyb_attr_t => "ia32_compare_copyb_attr",
302 ia32_condcode_attr_t => "ia32_compare_condcode_attr",
308 $mode_xmm = "mode_E";
309 $mode_gp = "mode_Iu";
310 $mode_flags = "mode_Iu";
311 $mode_fpcw = "mode_fpcw";
312 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
313 $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
314 "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
322 reg_req => { out => [ "gp_NOREG" ] },
323 attr => "ir_entity *symconst, int symconst_sign, long offset",
324 attr_type => "ia32_immediate_attr_t",
332 out_arity => "variable",
333 attr_type => "ia32_asm_attr_t",
334 attr => "ident *asm_text, const ia32_asm_reg_t *register_map",
335 init_attr => "attr->asm_text = asm_text;\n".
336 "\tattr->register_map = register_map;\n",
344 reg_req => { out => [ "gp" ] },
349 cmp_attr => "return 1;",
352 #-----------------------------------------------------------------#
355 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
356 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
357 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
358 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
361 #-----------------------------------------------------------------#
363 # commutative operations
367 state => "exc_pinned",
368 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
369 out => [ "in_r4 in_r5", "flags", "none" ] },
370 ins => [ "base", "index", "mem", "left", "right" ],
371 outs => [ "res", "flags", "M" ],
372 emit => '. add%M %binop',
373 am => "source,binary",
377 modified_flags => $status_flags
382 state => "exc_pinned",
383 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
384 ins => [ "base", "index", "mem", "val" ],
385 emit => ". add%M %SI3, %AM",
389 modified_flags => $status_flags
394 state => "exc_pinned",
395 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
396 ins => [ "base", "index", "mem", "val" ],
397 emit => ". add%M %SB3, %AM",
401 modified_flags => $status_flags
405 state => "exc_pinned",
406 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
407 out => [ "in_r4 in_r5", "flags", "none" ] },
408 ins => [ "base", "index", "mem", "left", "right", "eflags" ],
409 outs => [ "res", "flags", "M" ],
410 emit => '. adc%M %binop',
411 am => "source,binary",
415 modified_flags => $status_flags
420 reg_req => { in => [ "none", "none" ], out => [ "none" ] },
421 ins => [ "left", "right" ],
425 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
426 ins => [ "left", "right", "eflags" ],
430 # we should not rematrialize this node. It produces 2 results and has
431 # very strict constrains
432 state => "exc_pinned",
433 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
434 out => [ "eax", "edx", "none" ] },
435 ins => [ "base", "index", "mem", "val_high", "val_low" ],
436 emit => '. mul%M %unop4',
437 outs => [ "res_low", "res_high", "M" ],
438 am => "source,binary",
441 modified_flags => $status_flags
445 # we should not rematrialize this node. It produces 2 results and has
446 # very strict constrains
448 cmp_attr => "return 1;",
449 outs => [ "EAX", "EDX", "M" ],
455 state => "exc_pinned",
456 # TODO: adjust out requirements for the 3 operand form
457 # (no need for should_be_same then)
458 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
459 out => [ "in_r4 in_r5", "flags", "none" ] },
460 ins => [ "base", "index", "mem", "left", "right" ],
461 outs => [ "res", "flags", "M" ],
462 am => "source,binary",
466 modified_flags => $status_flags
471 state => "exc_pinned",
472 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
473 out => [ "eax", "edx", "none" ] },
474 ins => [ "base", "index", "mem", "val_high", "val_low" ],
475 emit => '. imul%M %unop4',
476 outs => [ "res_low", "res_high", "M" ],
477 am => "source,binary",
480 modified_flags => $status_flags
485 cmp_attr => "return 1;",
486 outs => [ "res_low", "res_high", "M" ],
492 state => "exc_pinned",
493 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
494 out => [ "in_r4 in_r5", "flags", "none" ] },
495 ins => [ "base", "index", "mem", "left", "right" ],
496 outs => [ "res", "flags", "M" ],
497 op_modes => "commutative | am | immediate | mode_neutral",
498 am => "source,binary",
499 emit => '. and%M %binop',
503 modified_flags => $status_flags
508 state => "exc_pinned",
509 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
510 ins => [ "base", "index", "mem", "val" ],
511 emit => '. and%M %SI3, %AM',
515 modified_flags => $status_flags
520 state => "exc_pinned",
521 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
522 ins => [ "base", "index", "mem", "val" ],
523 emit => '. and%M %SB3, %AM',
527 modified_flags => $status_flags
532 state => "exc_pinned",
533 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
534 out => [ "in_r4 in_r5", "flags", "none" ] },
535 ins => [ "base", "index", "mem", "left", "right" ],
536 outs => [ "res", "flags", "M" ],
537 am => "source,binary",
538 emit => '. or%M %binop',
542 modified_flags => $status_flags
547 state => "exc_pinned",
548 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
549 ins => [ "base", "index", "mem", "val" ],
550 emit => '. or%M %SI3, %AM',
554 modified_flags => $status_flags
559 state => "exc_pinned",
560 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
561 ins => [ "base", "index", "mem", "val" ],
562 emit => '. or%M %SB3, %AM',
566 modified_flags => $status_flags
571 state => "exc_pinned",
572 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
573 out => [ "in_r4 in_r5", "flags", "none" ] },
574 ins => [ "base", "index", "mem", "left", "right" ],
575 outs => [ "res", "flags", "M" ],
576 am => "source,binary",
577 emit => '. xor%M %binop',
581 modified_flags => $status_flags
586 state => "exc_pinned",
587 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
588 ins => [ "base", "index", "mem", "val" ],
589 emit => '. xor%M %SI3, %AM',
593 modified_flags => $status_flags
598 state => "exc_pinned",
599 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
600 ins => [ "base", "index", "mem", "val" ],
601 emit => '. xor%M %SB3, %AM',
605 modified_flags => $status_flags
608 # not commutative operations
612 state => "exc_pinned",
613 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
614 out => [ "in_r4", "flags", "none" ] },
615 ins => [ "base", "index", "mem", "left", "right" ],
616 outs => [ "res", "flags", "M" ],
617 am => "source,binary",
618 emit => '. sub%M %binop',
622 modified_flags => $status_flags
627 state => "exc_pinned",
628 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
629 ins => [ "base", "index", "mem", "val" ],
630 emit => '. sub%M %SI3, %AM',
634 modified_flags => $status_flags
639 state => "exc_pinned",
640 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
641 ins => [ "base", "index", "mem", "val" ],
642 emit => '. sub%M %SB3, %AM',
646 modified_flags => $status_flags
650 state => "exc_pinned",
651 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
652 out => [ "in_r4 !in_r5", "flags", "none" ] },
653 ins => [ "base", "index", "mem", "left", "right", "eflags" ],
654 outs => [ "res", "flags", "M" ],
655 am => "source,binary",
656 emit => '. sbb%M %binop',
660 modified_flags => $status_flags
664 reg_req => { in => [ "none", "none" ], out => [ "none" ] },
665 ins => [ "left", "right" ],
669 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
670 ins => [ "left", "right", "eflags" ],
675 state => "exc_pinned",
676 reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ],
677 out => [ "eax", "flags", "none", "edx", "none" ] },
678 ins => [ "base", "index", "mem", "left_low", "left_high", "right" ],
679 outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
680 am => "source,ternary",
681 emit => ". idiv%M %unop5",
684 modified_flags => $status_flags
689 state => "exc_pinned",
690 reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ],
691 out => [ "eax", "flags", "none", "edx", "none" ] },
692 ins => [ "base", "index", "mem", "left_low", "left_high", "right" ],
693 outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
694 am => "source,ternary",
695 emit => ". div%M %unop5",
698 modified_flags => $status_flags
703 reg_req => { in => [ "gp", "ecx" ],
704 out => [ "in_r1 !in_r2", "flags" ] },
705 ins => [ "val", "count" ],
706 outs => [ "res", "flags" ],
707 emit => '. shl %SB1, %S0',
711 modified_flags => $status_flags
716 state => "exc_pinned",
717 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
718 ins => [ "base", "index", "mem", "count" ],
719 emit => '. shl%M %SB3, %AM',
723 modified_flags => $status_flags
727 cmp_attr => "return 1;",
728 ins => [ "val", "count", "dep" ],
734 reg_req => { in => [ "gp", "gp", "ecx" ],
735 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
736 ins => [ "val_high", "val_low", "count" ],
737 outs => [ "res", "flags" ],
738 emit => ". shld%M %SB2, %S1, %D0",
742 modified_flags => $status_flags
746 cmp_attr => "return 1;",
747 ins => [ "val_high", "val_low", "count" ],
753 reg_req => { in => [ "gp", "ecx" ],
754 out => [ "in_r1 !in_r2", "flags" ] },
755 ins => [ "val", "count" ],
756 outs => [ "res", "flags" ],
757 emit => '. shr %SB1, %S0',
761 modified_flags => $status_flags
766 state => "exc_pinned",
767 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
768 ins => [ "base", "index", "mem", "count" ],
769 emit => '. shr%M %SB3, %AM',
773 modified_flags => $status_flags
777 cmp_attr => "return 1;",
778 ins => [ "val", "count", "dep" ],
784 reg_req => { in => [ "gp", "gp", "ecx" ],
785 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
786 ins => [ "val_high", "val_low", "count" ],
787 outs => [ "res", "flags" ],
788 emit => ". shrd%M %SB2, %S1, %D0",
792 modified_flags => $status_flags
796 cmp_attr => "return 1;",
798 ins => [ "val_high", "val_low", "count" ],
803 reg_req => { in => [ "gp", "ecx" ],
804 out => [ "in_r1 !in_r2", "flags" ] },
805 ins => [ "val", "count" ],
806 outs => [ "res", "flags" ],
807 emit => '. sar %SB1, %S0',
811 modified_flags => $status_flags
816 state => "exc_pinned",
817 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
818 ins => [ "base", "index", "mem", "count" ],
819 emit => '. sar%M %SB3, %AM',
823 modified_flags => $status_flags
827 cmp_attr => "return 1;",
828 ins => [ "val", "count", "dep" ],
834 reg_req => { in => [ "gp", "ecx" ],
835 out => [ "in_r1 !in_r2", "flags" ] },
836 ins => [ "val", "count" ],
837 outs => [ "res", "flags" ],
838 emit => '. ror %SB1, %S0',
842 modified_flags => $status_flags
847 state => "exc_pinned",
848 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
849 ins => [ "base", "index", "mem", "count" ],
850 emit => '. ror%M %SB3, %AM',
854 modified_flags => $status_flags
859 reg_req => { in => [ "gp", "ecx" ],
860 out => [ "in_r1 !in_r2", "flags" ] },
861 ins => [ "val", "count" ],
862 outs => [ "res", "flags" ],
863 emit => '. rol %SB1, %S0',
867 modified_flags => $status_flags
872 state => "exc_pinned",
873 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
874 ins => [ "base", "index", "mem", "count" ],
875 emit => '. rol%M %SB3, %AM',
879 modified_flags => $status_flags
886 reg_req => { in => [ "gp" ],
887 out => [ "in_r1", "flags" ] },
890 outs => [ "res", "flags" ],
894 modified_flags => $status_flags
899 state => "exc_pinned",
900 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
901 ins => [ "base", "index", "mem" ],
902 emit => '. neg%M %AM',
906 modified_flags => $status_flags
911 reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] },
912 outs => [ "low_res", "high_res" ],
915 modified_flags => $status_flags
921 reg_req => { in => [ "gp" ],
922 out => [ "in_r1", "flags" ] },
923 outs => [ "res", "flags" ],
928 modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
933 state => "exc_pinned",
934 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
935 ins => [ "base", "index", "mem" ],
936 emit => '. inc%M %AM',
940 modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
945 reg_req => { in => [ "gp" ],
946 out => [ "in_r1", "flags" ] },
947 outs => [ "res", "flags" ],
952 modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
957 state => "exc_pinned",
958 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
959 ins => [ "base", "index", "mem" ],
960 emit => '. dec%M %AM',
964 modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
969 reg_req => { in => [ "gp" ],
970 out => [ "in_r1", "flags" ] },
972 outs => [ "res", "flags" ],
982 state => "exc_pinned",
983 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
984 ins => [ "base", "index", "mem" ],
985 emit => '. not%M %AM',
993 reg_req => { in => [ "flags" ], out => [ "flags" ] },
998 modified_flags => $status_flags
1002 reg_req => { out => [ "flags" ] },
1006 mode => $mode_flags,
1007 modified_flags => $status_flags
1014 state => "exc_pinned",
1015 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
1016 ins => [ "base", "index", "mem", "left", "right" ],
1017 outs => [ "eflags" ],
1018 am => "source,binary",
1019 emit => '. cmp%M %binop',
1020 attr => "int ins_permuted, int cmp_unsigned",
1021 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1022 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1025 mode => $mode_flags,
1026 modified_flags => $status_flags
1031 state => "exc_pinned",
1032 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
1033 ins => [ "base", "index", "mem", "left", "right" ],
1034 outs => [ "eflags" ],
1035 am => "source,binary",
1036 emit => '. cmpb %binop',
1037 attr => "int ins_permuted, int cmp_unsigned",
1038 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1039 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1042 mode => $mode_flags,
1043 modified_flags => $status_flags
1048 state => "exc_pinned",
1049 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
1050 ins => [ "base", "index", "mem", "left", "right" ],
1051 outs => [ "eflags" ],
1052 am => "source,binary",
1053 emit => '. test%M %binop',
1054 attr => "int ins_permuted, int cmp_unsigned",
1055 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1056 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1059 mode => $mode_flags,
1060 modified_flags => $status_flags
1065 state => "exc_pinned",
1066 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
1067 ins => [ "base", "index", "mem", "left", "right" ],
1068 outs => [ "eflags" ],
1069 am => "source,binary",
1070 emit => '. testb %binop',
1071 attr => "int ins_permuted, int cmp_unsigned",
1072 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1073 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1076 mode => $mode_flags,
1077 modified_flags => $status_flags
1082 reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
1083 ins => [ "eflags" ],
1084 attr_type => "ia32_condcode_attr_t",
1085 attr => "pn_Cmp pnc, int ins_permuted",
1086 init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1087 "\tset_ia32_ls_mode(res, mode_Bu);\n",
1088 emit => '. set%CMP0 %DB0',
1096 state => "exc_pinned",
1097 reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
1098 ins => [ "base", "index", "mem","eflags" ],
1099 attr_type => "ia32_condcode_attr_t",
1100 attr => "pn_Cmp pnc, int ins_permuted",
1101 init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1102 "\tset_ia32_ls_mode(res, mode_Bu);\n",
1103 emit => '. set%CMP3 %AM',
1111 # (note: leave the false,true order intact to make it compatible with other
1113 state => "exc_pinned",
1114 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ], out => [ "in_r4 in_r5" ] },
1115 ins => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
1116 am => "source,binary",
1117 attr_type => "ia32_condcode_attr_t",
1118 attr => "int ins_permuted, pn_Cmp pnc",
1119 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
1127 op_flags => "L|X|Y",
1128 reg_req => { in => [ "eflags" ], out => [ "none", "none" ] },
1129 ins => [ "eflags" ],
1130 outs => [ "false", "true" ],
1131 attr_type => "ia32_condcode_attr_t",
1132 attr => "pn_Cmp pnc",
1134 units => [ "BRANCH" ],
1139 op_flags => "L|X|Y",
1140 reg_req => { in => [ "gp" ], out => [ "none" ] },
1142 attr_type => "ia32_condcode_attr_t",
1143 attr => "pn_Cmp pnc",
1145 units => [ "BRANCH" ],
1146 modified_flags => $status_flags,
1152 reg_req => { in => [ "gp", "gp", "none", "gp" ] },
1153 ins => [ "base", "index", "mem", "target" ],
1154 am => "source,unary",
1155 emit => '. jmp *%unop3',
1157 units => [ "BRANCH" ],
1164 reg_req => { out => [ "gp" ] },
1166 attr => "ir_entity *symconst, int symconst_sign, long offset",
1167 attr_type => "ia32_immediate_attr_t",
1174 reg_req => { out => [ "gp" ] },
1178 modified_flags => $status_flags,
1185 reg_req => { out => [ "gp_UKNWN" ] },
1196 reg_req => { out => [ "vfp_UKNWN" ] },
1201 attr_type => "ia32_x87_attr_t",
1208 reg_req => { out => [ "xmm_UKNWN" ] },
1219 reg_req => { out => [ "gp_NOREG" ] },
1230 reg_req => { out => [ "vfp_NOREG" ] },
1235 attr_type => "ia32_x87_attr_t",
1242 reg_req => { out => [ "xmm_NOREG" ] },
1253 reg_req => { out => [ "fp_cw" ] },
1257 modified_flags => $fpcw_flags
1263 reg_req => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
1264 ins => [ "base", "index", "mem" ],
1266 emit => ". fldcw %AM",
1269 modified_flags => $fpcw_flags
1275 reg_req => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1276 ins => [ "base", "index", "mem", "fpcw" ],
1278 emit => ". fnstcw %AM",
1286 reg_req => { in => [ "fp_cw" ], out => [ "none" ] },
1294 # we should not rematrialize this node. It has very strict constraints.
1295 reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] },
1296 ins => [ "val", "globbered" ],
1305 # Note that we add additional latency values depending on address mode, so a
1306 # lateny of 0 for load is correct
1310 state => "exc_pinned",
1311 reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none", "none" ] },
1312 ins => [ "base", "index", "mem" ],
1313 outs => [ "res", "M", "X_exc" ],
1315 emit => ". mov%SE%ME%.l %AM, %D0",
1321 cmp_attr => "return 1;",
1322 outs => [ "res", "M" ],
1328 cmp_attr => "return 1;",
1329 state => "exc_pinned",
1336 state => "exc_pinned",
1337 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
1338 ins => [ "base", "index", "mem", "val" ],
1339 outs => [ "M", "X_exc" ],
1340 emit => '. mov%M %SI3, %AM',
1348 state => "exc_pinned",
1349 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] },
1350 ins => [ "base", "index", "mem", "val" ],
1351 outs => [ "M", "X_exc" ],
1352 emit => '. mov%M %SB3, %AM',
1360 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
1361 ins => [ "base", "index" ],
1362 emit => '. leal %AM, %D0',
1366 # lea doesn't modify the flags, but setting this seems advantageous since it
1367 # increases chances that the Lea is transformed back to an Add
1368 modified_flags => 1,
1372 state => "exc_pinned",
1373 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp", "none" ] },
1374 ins => [ "base", "index", "mem", "val", "stack" ],
1375 emit => '. push%M %unop4',
1376 outs => [ "stack:I|S", "M" ],
1377 am => "source,binary",
1383 state => "exc_pinned",
1384 reg_req => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp" ] },
1385 ins => [ "mem", "stack" ],
1386 outs => [ "res", "M", "unused", "stack:I|S" ],
1387 emit => '. pop%M %D0',
1388 latency => 3, # Pop is more expensive than Push on Athlon
1393 state => "exc_pinned",
1394 reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp" ] },
1395 ins => [ "base", "index", "mem", "stack" ],
1396 outs => [ "unused0", "M", "unused1", "stack:I|S" ],
1397 emit => '. pop%M %AM',
1398 latency => 3, # Pop is more expensive than Push on Athlon
1403 reg_req => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
1405 outs => [ "frame:I", "stack:I|S", "M" ],
1411 reg_req => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
1413 outs => [ "frame:I", "stack:I|S" ],
1421 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
1422 ins => [ "base", "index", "mem", "stack", "size" ],
1423 am => "source,binary",
1424 emit => '. addl %binop',
1426 outs => [ "stack:I|S", "M" ],
1428 modified_flags => $status_flags
1434 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
1435 ins => [ "base", "index", "mem", "stack", "size" ],
1436 am => "source,binary",
1437 emit => ". subl %binop\n".
1438 ". movl %%esp, %D1",
1440 outs => [ "stack:I|S", "addr", "M" ],
1442 modified_flags => $status_flags
1455 reg_req => { out => [ "gp" ] },
1461 #-----------------------------------------------------------------------------#
1462 # _____ _____ ______ __ _ _ _ #
1463 # / ____/ ____| ____| / _| | | | | | #
1464 # | (___| (___ | |__ | |_| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
1465 # \___ \\___ \| __| | _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1466 # ____) |___) | |____ | | | | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
1467 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1468 #-----------------------------------------------------------------------------#
1472 reg_req => { out => [ "xmm" ] },
1473 emit => '. xorp%XSD %D0, %D0',
1479 # commutative operations
1483 state => "exc_pinned",
1484 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1485 ins => [ "base", "index", "mem", "left", "right" ],
1486 am => "source,binary",
1487 emit => '. add%XXM %binop',
1495 state => "exc_pinned",
1496 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1497 ins => [ "base", "index", "mem", "left", "right" ],
1498 am => "source,binary",
1499 emit => '. mul%XXM %binop',
1507 state => "exc_pinned",
1508 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1509 ins => [ "base", "index", "mem", "left", "right" ],
1510 am => "source,binary",
1511 emit => '. max%XXM %binop',
1519 state => "exc_pinned",
1520 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1521 ins => [ "base", "index", "mem", "left", "right" ],
1522 am => "source,binary",
1523 emit => '. min%XXM %binop',
1531 state => "exc_pinned",
1532 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1533 ins => [ "base", "index", "mem", "left", "right" ],
1534 am => "source,binary",
1535 emit => '. andp%XSD %binop',
1543 state => "exc_pinned",
1544 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1545 ins => [ "base", "index", "mem", "left", "right" ],
1546 am => "source,binary",
1547 emit => '. orp%XSD %binop',
1555 state => "exc_pinned",
1556 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1557 ins => [ "base", "index", "mem", "left", "right" ],
1558 am => "source,binary",
1559 emit => '. xorp%XSD %binop',
1565 # not commutative operations
1569 state => "exc_pinned",
1570 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1571 ins => [ "base", "index", "mem", "left", "right" ],
1572 am => "source,binary",
1573 emit => '. andnp%XSD %binop',
1581 state => "exc_pinned",
1582 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1583 ins => [ "base", "index", "mem", "left", "right" ],
1584 am => "source,binary",
1585 emit => '. sub%XXM %binop',
1593 state => "exc_pinned",
1594 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
1595 ins => [ "base", "index", "mem", "left", "right" ],
1596 am => "source,binary",
1597 outs => [ "res", "M" ],
1598 emit => '. div%XXM %binop',
1607 state => "exc_pinned",
1608 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eflags" ] },
1609 ins => [ "base", "index", "mem", "left", "right" ],
1610 outs => [ "flags" ],
1611 am => "source,binary",
1612 attr => "int ins_permuted",
1613 init_attr => "attr->data.ins_permuted = ins_permuted;",
1614 emit => ' .ucomi%XXM %binop',
1617 mode => $mode_flags,
1618 modified_flags => 1,
1625 state => "exc_pinned",
1626 reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none", "none" ] },
1627 ins => [ "base", "index", "mem" ],
1628 outs => [ "res", "M", "X_exc" ],
1629 emit => '. mov%XXM %AM, %D0',
1630 attr => "ir_mode *load_mode",
1631 init_attr => "attr->ls_mode = load_mode;",
1638 state => "exc_pinned",
1639 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] },
1640 ins => [ "base", "index", "mem", "val" ],
1641 outs => [ "M", "X_exc" ],
1642 emit => '. mov%XXM %S3, %AM',
1650 state => "exc_pinned",
1651 reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
1652 ins => [ "base", "index", "mem", "val" ],
1653 emit => '. mov%XXM %S3, %AM',
1661 state => "exc_pinned",
1662 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1663 ins => [ "base", "index", "mem", "val" ],
1664 am => "source,unary",
1665 emit => '. cvtsi2ss %unop3, %D0',
1673 state => "exc_pinned",
1674 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1675 ins => [ "base", "index", "mem", "val" ],
1676 am => "source,unary",
1677 emit => '. cvtsi2sd %unop3, %D0',
1686 cmp_attr => "return 1;",
1687 ins => [ "val_high", "val_low" ],
1692 cmp_attr => "return 1;",
1694 outs => [ "res_high", "res_low" ],
1702 reg_req => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1703 outs => [ "DST", "SRC", "CNT", "M" ],
1704 attr_type => "ia32_copyb_attr_t",
1705 attr => "unsigned size",
1708 # we don't care about this flag, so no need to mark this node
1709 # modified_flags => [ "DF" ]
1715 reg_req => { in => [ "edi", "esi", "none" ], out => [ "edi", "esi", "none" ] },
1716 outs => [ "DST", "SRC", "M" ],
1717 attr_type => "ia32_copyb_attr_t",
1718 attr => "unsigned size",
1721 # we don't care about this flag, so no need to mark this node
1722 # modified_flags => [ "DF" ]
1728 state => "exc_pinned",
1729 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] },
1730 ins => [ "base", "index", "mem", "val" ],
1731 am => "source,unary",
1734 attr => "ir_mode *smaller_mode",
1735 init_attr => "attr->ls_mode = smaller_mode;",
1740 state => "exc_pinned",
1741 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "gp", "none" ] },
1742 ins => [ "base", "index", "mem", "val" ],
1743 am => "source,unary",
1746 attr => "ir_mode *smaller_mode",
1747 init_attr => "attr->ls_mode = smaller_mode;",
1752 state => "exc_pinned",
1753 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
1754 ins => [ "base", "index", "mem", "val" ],
1755 am => "source,unary",
1762 state => "exc_pinned",
1763 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1764 ins => [ "base", "index", "mem", "val" ],
1765 am => "source,unary",
1772 state => "exc_pinned",
1773 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1774 ins => [ "base", "index", "mem", "val" ],
1775 am => "source,unary",
1781 #----------------------------------------------------------#
1783 # (_) | | | | / _| | | | #
1784 # __ ___ _ __| |_ _ _ __ _| | | |_| | ___ __ _| |_ #
1785 # \ \ / / | '__| __| | | |/ _` | | | _| |/ _ \ / _` | __| #
1786 # \ V /| | | | |_| |_| | (_| | | | | | | (_) | (_| | |_ #
1787 # \_/ |_|_| \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1789 # _ __ ___ __| | ___ ___ #
1790 # | '_ \ / _ \ / _` |/ _ \/ __| #
1791 # | | | | (_) | (_| | __/\__ \ #
1792 # |_| |_|\___/ \__,_|\___||___/ #
1793 #----------------------------------------------------------#
1795 # rematerialisation disabled for all float nodes for now, because the fpcw
1796 # handler runs before spilling and we might end up with wrong fpcw then
1800 state => "exc_pinned",
1801 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1802 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1803 am => "source,binary",
1807 attr_type => "ia32_x87_attr_t",
1812 state => "exc_pinned",
1813 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1814 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1815 am => "source,binary",
1819 attr_type => "ia32_x87_attr_t",
1824 state => "exc_pinned",
1825 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1826 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1827 am => "source,binary",
1831 attr_type => "ia32_x87_attr_t",
1835 state => "exc_pinned",
1836 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
1837 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1838 am => "source,binary",
1839 outs => [ "res", "M" ],
1842 attr_type => "ia32_x87_attr_t",
1846 reg_req => { in => [ "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1847 ins => [ "left", "right", "fpcw" ],
1851 attr_type => "ia32_x87_attr_t",
1856 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
1861 attr_type => "ia32_x87_attr_t",
1866 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
1871 attr_type => "ia32_x87_attr_t",
1874 # virtual Load and Store
1879 state => "exc_pinned",
1880 reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none", "none" ] },
1881 ins => [ "base", "index", "mem" ],
1882 outs => [ "res", "M", "X_exc" ],
1883 attr => "ir_mode *load_mode",
1884 init_attr => "attr->attr.ls_mode = load_mode;",
1887 attr_type => "ia32_x87_attr_t",
1893 state => "exc_pinned",
1894 reg_req => { in => [ "gp", "gp", "none", "vfp" ], out => [ "none", "none" ] },
1895 ins => [ "base", "index", "mem", "val" ],
1896 outs => [ "M", "X_exc" ],
1897 attr => "ir_mode *store_mode",
1898 init_attr => "attr->attr.ls_mode = store_mode;",
1902 attr_type => "ia32_x87_attr_t",
1908 state => "exc_pinned",
1909 reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1910 outs => [ "res", "M" ],
1911 ins => [ "base", "index", "mem" ],
1914 attr_type => "ia32_x87_attr_t",
1918 cmp_attr => "return 1;",
1919 outs => [ "res", "M" ],
1924 state => "exc_pinned",
1925 reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
1926 ins => [ "base", "index", "mem", "val", "fpcw" ],
1930 attr_type => "ia32_x87_attr_t",
1934 cmp_attr => "return 1;",
1935 state => "exc_pinned",
1945 reg_req => { out => [ "vfp" ] },
1949 attr_type => "ia32_x87_attr_t",
1954 reg_req => { out => [ "vfp" ] },
1958 attr_type => "ia32_x87_attr_t",
1963 reg_req => { out => [ "vfp" ] },
1967 attr_type => "ia32_x87_attr_t",
1972 reg_req => { out => [ "vfp" ] },
1976 attr_type => "ia32_x87_attr_t",
1981 reg_req => { out => [ "vfp" ] },
1985 attr_type => "ia32_x87_attr_t",
1990 reg_req => { out => [ "vfp" ] },
1994 attr_type => "ia32_x87_attr_t",
1999 reg_req => { out => [ "vfp" ] },
2003 attr_type => "ia32_x87_attr_t",
2009 # we can't allow to rematerialize this node so we don't have
2010 # accidently produce Phi(Fucom, Fucom(ins_permuted))
2012 reg_req => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
2013 ins => [ "left", "right" ],
2014 outs => [ "flags" ],
2015 attr => "int ins_permuted",
2016 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2019 attr_type => "ia32_x87_attr_t",
2025 reg_req => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
2026 ins => [ "left", "right" ],
2027 outs => [ "flags" ],
2028 attr => "int ins_permuted",
2029 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2032 attr_type => "ia32_x87_attr_t",
2038 reg_req => { in => [ "vfp" ], out => [ "eax" ] },
2040 outs => [ "flags" ],
2041 attr => "int ins_permuted",
2042 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2045 attr_type => "ia32_x87_attr_t",
2051 reg_req => { in => [ "eax" ], out => [ "eflags" ] },
2053 outs => [ "flags" ],
2057 mode => $mode_flags,
2060 #------------------------------------------------------------------------#
2061 # ___ _____ __ _ _ _ #
2062 # __ _( _ )___ | / _| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
2063 # \ \/ / _ \ / / | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
2064 # > < (_) |/ / | _| | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
2065 # /_/\_\___//_/ |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
2066 #------------------------------------------------------------------------#
2068 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
2069 # are swapped, we work this around in the emitter...
2072 state => "exc_pinned",
2073 rd_constructor => "NONE",
2075 emit => '. fadd%XM %x87_binop',
2077 attr_type => "ia32_x87_attr_t",
2081 state => "exc_pinned",
2082 rd_constructor => "NONE",
2084 emit => '. faddp%XM %x87_binop',
2086 attr_type => "ia32_x87_attr_t",
2090 state => "exc_pinned",
2091 rd_constructor => "NONE",
2093 emit => '. fmul%XM %x87_binop',
2095 attr_type => "ia32_x87_attr_t",
2099 state => "exc_pinned",
2100 rd_constructor => "NONE",
2102 emit => '. fmulp%XM %x87_binop',,
2104 attr_type => "ia32_x87_attr_t",
2108 state => "exc_pinned",
2109 rd_constructor => "NONE",
2111 emit => '. fsub%XM %x87_binop',
2113 attr_type => "ia32_x87_attr_t",
2117 state => "exc_pinned",
2118 rd_constructor => "NONE",
2120 # see note about gas bugs
2121 emit => '. fsubrp%XM %x87_binop',
2123 attr_type => "ia32_x87_attr_t",
2127 state => "exc_pinned",
2128 rd_constructor => "NONE",
2131 emit => '. fsubr%XM %x87_binop',
2133 attr_type => "ia32_x87_attr_t",
2137 state => "exc_pinned",
2138 rd_constructor => "NONE",
2141 # see note about gas bugs
2142 emit => '. fsubp%XM %x87_binop',
2144 attr_type => "ia32_x87_attr_t",
2148 rd_constructor => "NONE",
2152 attr_type => "ia32_x87_attr_t",
2155 # this node is just here, to keep the simulator running
2156 # we can omit this when a fprem simulation function exists
2158 rd_constructor => "NONE",
2160 emit => '. fprem1\n'.
2163 attr_type => "ia32_x87_attr_t",
2167 state => "exc_pinned",
2168 rd_constructor => "NONE",
2170 emit => '. fdiv%XM %x87_binop',
2172 attr_type => "ia32_x87_attr_t",
2176 state => "exc_pinned",
2177 rd_constructor => "NONE",
2179 # see note about gas bugs
2180 emit => '. fdivrp%XM %x87_binop',
2182 attr_type => "ia32_x87_attr_t",
2186 state => "exc_pinned",
2187 rd_constructor => "NONE",
2189 emit => '. fdivr%XM %x87_binop',
2191 attr_type => "ia32_x87_attr_t",
2195 state => "exc_pinned",
2196 rd_constructor => "NONE",
2198 # see note about gas bugs
2199 emit => '. fdivp%XM %x87_binop',
2201 attr_type => "ia32_x87_attr_t",
2205 rd_constructor => "NONE",
2209 attr_type => "ia32_x87_attr_t",
2214 rd_constructor => "NONE",
2218 attr_type => "ia32_x87_attr_t",
2221 # x87 Load and Store
2224 rd_constructor => "NONE",
2225 op_flags => "R|L|F",
2226 state => "exc_pinned",
2228 emit => '. fld%XM %AM',
2229 attr_type => "ia32_x87_attr_t",
2234 rd_constructor => "NONE",
2235 op_flags => "R|L|F",
2236 state => "exc_pinned",
2238 emit => '. fst%XM %AM',
2240 attr_type => "ia32_x87_attr_t",
2245 rd_constructor => "NONE",
2246 op_flags => "R|L|F",
2247 state => "exc_pinned",
2249 emit => '. fstp%XM %AM',
2251 attr_type => "ia32_x87_attr_t",
2258 state => "exc_pinned",
2259 rd_constructor => "NONE",
2261 emit => '. fild%M %AM',
2262 attr_type => "ia32_x87_attr_t",
2267 state => "exc_pinned",
2268 rd_constructor => "NONE",
2270 emit => '. fist%M %AM',
2272 attr_type => "ia32_x87_attr_t",
2277 state => "exc_pinned",
2278 rd_constructor => "NONE",
2280 emit => '. fistp%M %AM',
2282 attr_type => "ia32_x87_attr_t",
2289 op_flags => "R|c|K",
2291 reg_req => { out => [ "vfp" ] },
2293 attr_type => "ia32_x87_attr_t",
2298 op_flags => "R|c|K",
2300 reg_req => { out => [ "vfp" ] },
2302 attr_type => "ia32_x87_attr_t",
2307 op_flags => "R|c|K",
2309 reg_req => { out => [ "vfp" ] },
2311 attr_type => "ia32_x87_attr_t",
2316 op_flags => "R|c|K",
2318 reg_req => { out => [ "vfp" ] },
2320 attr_type => "ia32_x87_attr_t",
2325 op_flags => "R|c|K",
2327 reg_req => { out => [ "vfp" ] },
2329 attr_type => "ia32_x87_attr_t",
2334 op_flags => "R|c|K",
2336 reg_req => { out => [ "vfp" ] },
2337 emit => '. fldll2t',
2338 attr_type => "ia32_x87_attr_t",
2343 op_flags => "R|c|K",
2345 reg_req => { out => [ "vfp" ] },
2347 attr_type => "ia32_x87_attr_t",
2352 # Note that it is NEVER allowed to do CSE on these nodes
2353 # Moreover, note the virtual register requierements!
2358 cmp_attr => "return 1;",
2359 emit => '. fxch %X0',
2360 attr_type => "ia32_x87_attr_t",
2368 cmp_attr => "return 1;",
2369 emit => '. fld %X0',
2370 attr_type => "ia32_x87_attr_t",
2376 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2377 cmp_attr => "return 1;",
2378 emit => '. fld %X0',
2379 attr_type => "ia32_x87_attr_t",
2386 cmp_attr => "return 1;",
2387 emit => '. fstp %X0',
2388 attr_type => "ia32_x87_attr_t",
2396 cmp_attr => "return 1;",
2397 emit => '. ffreep %X0',
2398 attr_type => "ia32_x87_attr_t",
2406 cmp_attr => "return 1;",
2408 attr_type => "ia32_x87_attr_t",
2416 cmp_attr => "return 1;",
2418 attr_type => "ia32_x87_attr_t",
2427 emit => ". fucom %X1\n".
2429 attr_type => "ia32_x87_attr_t",
2435 emit => ". fucomp %X1\n".
2437 attr_type => "ia32_x87_attr_t",
2443 emit => ". fucompp\n".
2445 attr_type => "ia32_x87_attr_t",
2451 emit => '. fucomi %X1',
2452 attr_type => "ia32_x87_attr_t",
2458 emit => '. fucompi %X1',
2459 attr_type => "ia32_x87_attr_t",
2467 attr_type => "ia32_x87_attr_t",
2472 # -------------------------------------------------------------------------------- #
2473 # ____ ____ _____ _ _ #
2474 # / ___/ ___|| ____| __ _____ ___| |_ ___ _ __ _ __ ___ __| | ___ ___ #
2475 # \___ \___ \| _| \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __| #
2476 # ___) |__) | |___ \ V / __/ (__| || (_) | | | | | | (_) | (_| | __/\__ \ #
2477 # |____/____/|_____| \_/ \___|\___|\__\___/|_| |_| |_|\___/ \__,_|\___||___/ #
2479 # -------------------------------------------------------------------------------- #
2482 # Spilling and reloading of SSE registers, hardcoded, not generated #
2486 state => "exc_pinned",
2487 reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2488 emit => '. movdqu %D0, %AM',
2489 outs => [ "res", "M" ],
2496 state => "exc_pinned",
2497 reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
2498 ins => [ "base", "index", "mem", "val" ],
2499 emit => '. movdqu %binop',
2507 # Include the generated SIMD node specification written by the SIMD optimization
2508 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2509 unless ($return = do $my_script_name) {
2510 warn "couldn't parse $my_script_name: $@" if $@;
2511 warn "couldn't do $my_script_name: $!" unless defined $return;
2512 warn "couldn't run $my_script_name" unless $return;
2515 # Transform some attributes
2516 foreach my $op (keys(%nodes)) {
2517 my $node = $nodes{$op};
2518 my $op_attr_init = $node->{op_attr_init};
2520 if(defined($op_attr_init)) {
2521 $op_attr_init .= "\n\t";
2526 if(!defined($node->{latency})) {
2528 $node->{latency} = 0;
2530 die("Latency missing for op $op");
2533 $op_attr_init .= "attr->latency = ".$node->{latency} . ";";
2535 $node->{op_attr_init} = $op_attr_init;