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",
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 # outs => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
32 # ins => { "in1", "in2" } # optional, creates n_op_in1, ... consts
33 # mode => "mode_Iu" # optional, predefines the mode
34 # emit => "emit code with templates",
35 # attr => "additional attribute arguments for constructor",
36 # init_attr => "emit attribute initialization template",
37 # rd_constructor => "c source code which constructs an ir_node",
38 # hash_func => "name of the hash function for this operation",
39 # latency => "latency of this operation (can be float)"
40 # attr_type => "name of the attribute struct",
41 # modified_flags => [ "CF", ... ] # optional, list of modified flags
44 # ... # (all nodes you need to describe)
46 # ); # close the %nodes initializer
48 # op_flags: flags for the operation, OPTIONAL (default is "N")
49 # the op_flags correspond to the firm irop_flags:
52 # C irop_flag_commutative
53 # X irop_flag_cfopcode
54 # I irop_flag_ip_cfopcode
57 # H irop_flag_highlevel
58 # c irop_flag_constlike
60 # NB irop_flag_dump_noblock
61 # NI irop_flag_dump_noinput
63 # irn_flags: special node flags, OPTIONAL (default is 0)
64 # following irn_flags are supported:
68 # state: state of the operation, OPTIONAL (default is "floats")
70 # arity: arity of the operation, MUST NOT BE OMITTED
72 # args: the OPTIONAL arguments of the node constructor (debug, irg and block
73 # are always the first 3 arguments and are always autmatically
75 # If this key is missing the following arguments will be created:
76 # for i = 1 .. arity: ir_node *op_i
79 # outs: if a node defines more than one output, the names of the projections
80 # nodes having outs having automatically the mode mode_T
81 # example: [ "frame", "stack", "M" ]
83 # comment: OPTIONAL comment for the node constructor
85 # rd_constructor: for every operation there will be a
86 # new_rd_<arch>_<op-name> function with the arguments from above
87 # which creates the ir_node corresponding to the defined operation
88 # you can either put the complete source code of this function here
90 # This key is OPTIONAL. If omitted, the following constructor will
92 # if (!op_<arch>_<op-name>) assert(0);
96 # res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
99 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
103 # 0 - no special type
104 # 1 - caller save (register must be saved by the caller of a function)
105 # 2 - callee save (register must be saved by the called function)
106 # 4 - ignore (do not assign this register)
107 # 8 - emitter can choose an arbitrary register of this class
108 # 16 - the register is a virtual one
109 # 32 - register represents a state
110 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
113 { name => "edx", type => 1 },
114 { name => "ecx", type => 1 },
115 { name => "eax", type => 1 },
116 { name => "ebx", type => 2 },
117 { name => "esi", type => 2 },
118 { name => "edi", type => 2 },
119 { name => "ebp", type => 2 },
120 { name => "esp", type => 4 },
121 { name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
122 { name => "gp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
123 { mode => "mode_Iu" }
126 { name => "mm0", type => 4 },
127 { name => "mm1", type => 4 },
128 { name => "mm2", type => 4 },
129 { name => "mm3", type => 4 },
130 { name => "mm4", type => 4 },
131 { name => "mm5", type => 4 },
132 { name => "mm6", type => 4 },
133 { name => "mm7", type => 4 },
134 { mode => "mode_E", flags => "manual_ra" }
137 { name => "xmm0", type => 1 },
138 { name => "xmm1", type => 1 },
139 { name => "xmm2", type => 1 },
140 { name => "xmm3", type => 1 },
141 { name => "xmm4", type => 1 },
142 { name => "xmm5", type => 1 },
143 { name => "xmm6", type => 1 },
144 { name => "xmm7", type => 1 },
145 { name => "xmm_NOREG", type => 4 | 16 }, # we need a dummy register for NoReg nodes
146 { name => "xmm_UKNWN", type => 4 | 8 | 16}, # we need a dummy register for Unknown nodes
150 { name => "vf0", type => 1 },
151 { name => "vf1", type => 1 },
152 { name => "vf2", type => 1 },
153 { name => "vf3", type => 1 },
154 { name => "vf4", type => 1 },
155 { name => "vf5", type => 1 },
156 { name => "vf6", type => 1 },
157 { name => "vf7", type => 1 },
158 { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
159 { name => "vfp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes
163 { name => "st0", realname => "st", type => 4 },
164 { name => "st1", realname => "st(1)", type => 4 },
165 { name => "st2", realname => "st(2)", type => 4 },
166 { name => "st3", realname => "st(3)", type => 4 },
167 { name => "st4", realname => "st(4)", type => 4 },
168 { name => "st5", realname => "st(5)", type => 4 },
169 { name => "st6", realname => "st(6)", type => 4 },
170 { name => "st7", realname => "st(7)", type => 4 },
171 { mode => "mode_E", flags => "manual_ra" }
173 fp_cw => [ # the floating point control word
174 { name => "fpcw", type => 4|32 },
175 { mode => "mode_fpcw", flags => "manual_ra|state" }
178 { name => "eflags", type => 0 },
179 { mode => "mode_Iu", flags => "manual_ra" }
184 GP => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
185 SSE => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
186 VFP => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
187 BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
192 bundels_per_cycle => 1
196 S0 => "${arch}_emit_source_register(node, 0);",
197 S1 => "${arch}_emit_source_register(node, 1);",
198 S2 => "${arch}_emit_source_register(node, 2);",
199 S3 => "${arch}_emit_source_register(node, 3);",
200 SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
201 SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
202 SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
203 SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
204 SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
205 D0 => "${arch}_emit_dest_register(node, 0);",
206 D1 => "${arch}_emit_dest_register(node, 1);",
207 DB0 => "${arch}_emit_8bit_dest_register(node, 0);",
208 X0 => "${arch}_emit_x87_register(node, 0);",
209 X1 => "${arch}_emit_x87_register(node, 1);",
210 SE => "${arch}_emit_extend_suffix(get_ia32_ls_mode(node));",
211 ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
212 ia32_emit_mode_suffix(node);",
213 M => "${arch}_emit_mode_suffix(node);",
214 XM => "${arch}_emit_x87_mode_suffix(node);",
215 XXM => "${arch}_emit_xmm_mode_suffix(node);",
216 XSD => "${arch}_emit_xmm_mode_suffix_s(node);",
217 AM => "${arch}_emit_am(node);",
218 unop3 => "${arch}_emit_unop(node, n_ia32_unary_op);",
219 unop4 => "${arch}_emit_unop(node, n_ia32_binary_right);",
220 binop => "${arch}_emit_binop(node);",
221 x87_binop => "${arch}_emit_x87_binop(node);",
222 CMP0 => "${arch}_emit_cmp_suffix_node(node, 0);",
223 CMP3 => "${arch}_emit_cmp_suffix_node(node, 3);",
226 #--------------------------------------------------#
229 # _ __ _____ __ _ _ __ ___ _ __ ___ #
230 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
231 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
232 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
235 #--------------------------------------------------#
237 $default_op_attr_type = "ia32_op_attr_t";
238 $default_attr_type = "ia32_attr_t";
239 $default_copy_attr = "ia32_copy_attr";
241 sub ia32_custom_init_attr {
246 if(defined($node->{modified_flags})) {
247 $res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n";
249 if(defined($node->{am})) {
250 my $am = $node->{am};
251 if($am eq "source,unary") {
252 $res .= "\tset_ia32_am_support(res, ia32_am_unary);";
253 } elsif($am eq "source,binary") {
254 $res .= "\tset_ia32_am_support(res, ia32_am_binary);";
255 } elsif($am eq "none") {
258 die("Invalid address mode '$am' specified on op $name");
261 if($node->{state} ne "exc_pinned"
262 and $node->{state} ne "pinned") {
263 die("AM nodes must have pinned or AM pinned state ($name)");
269 $custom_init_attr_func = \&ia32_custom_init_attr;
273 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
274 "\tinit_ia32_x87_attributes(res);".
275 "\tinit_ia32_asm_attributes(res);",
277 "\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_call_attributes(res, pop, call_tp);",
281 ia32_condcode_attr_t =>
282 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
283 "\tinit_ia32_condcode_attributes(res, pnc);",
285 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
286 "\tinit_ia32_copyb_attributes(res, size);",
287 ia32_immediate_attr_t =>
288 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
289 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);",
291 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
292 "\tinit_ia32_x87_attributes(res);",
296 ia32_asm_attr_t => "ia32_compare_asm_attr",
297 ia32_attr_t => "ia32_compare_nodes_attr",
298 ia32_call_attr_t => "ia32_compare_call_attr",
299 ia32_condcode_attr_t => "ia32_compare_condcode_attr",
300 ia32_copyb_attr_t => "ia32_compare_copyb_attr",
301 ia32_immediate_attr_t => "ia32_compare_immediate_attr",
302 ia32_x87_attr_t => "ia32_compare_x87_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 $status_flags_wo_cf = [ "PF", "AF", "ZF", "SF", "OF" ];
314 $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
315 "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
322 reg_req => { out => [ "gp_NOREG:I" ] },
323 attr => "ir_entity *symconst, int symconst_sign, long offset",
324 attr_type => "ia32_immediate_attr_t",
325 hash_func => "ia32_hash_Immediate",
333 out_arity => "variable",
334 attr_type => "ia32_asm_attr_t",
335 attr => "ident *asm_text, const ia32_asm_reg_t *register_map",
336 init_attr => "attr->asm_text = asm_text;\n".
337 "\tattr->register_map = register_map;\n",
339 modified_flags => $status_flags,
342 # "allocates" a free register
346 reg_req => { out => [ "gp" ] },
351 cmp_attr => "return 1;",
354 #-----------------------------------------------------------------#
357 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
358 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
359 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
360 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
363 #-----------------------------------------------------------------#
365 # commutative operations
369 state => "exc_pinned",
370 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
371 out => [ "in_r4 in_r5", "flags", "none" ] },
372 ins => [ "base", "index", "mem", "left", "right" ],
373 outs => [ "res", "flags", "M" ],
374 emit => '. add%M %binop',
375 am => "source,binary",
379 modified_flags => $status_flags
384 state => "exc_pinned",
385 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
386 ins => [ "base", "index", "mem", "val" ],
387 emit => ". add%M %SI3, %AM",
391 modified_flags => $status_flags
396 state => "exc_pinned",
397 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
398 ins => [ "base", "index", "mem", "val" ],
399 emit => ". add%M %SB3, %AM",
403 modified_flags => $status_flags
407 state => "exc_pinned",
408 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
409 out => [ "in_r4 in_r5", "flags", "none" ] },
410 ins => [ "base", "index", "mem", "left", "right", "eflags" ],
411 outs => [ "res", "flags", "M" ],
412 emit => '. adc%M %binop',
413 am => "source,binary",
417 modified_flags => $status_flags
422 reg_req => { in => [ "none", "none" ], out => [ "none" ] },
423 ins => [ "left", "right" ],
427 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
428 ins => [ "left", "right", "eflags" ],
432 # we should not rematrialize this node. It produces 2 results and has
433 # very strict constraints
434 state => "exc_pinned",
435 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
436 out => [ "eax", "flags", "edx", "none" ] },
437 ins => [ "base", "index", "mem", "left", "right" ],
438 emit => '. mul%M %unop4',
439 outs => [ "res_low", "flags", "res_high", "M" ],
440 am => "source,binary",
443 modified_flags => $status_flags
447 # we should not rematrialize this node. It produces 2 results and has
448 # very strict constraints
450 cmp_attr => "return 1;",
451 outs => [ "EAX", "flags", "EDX", "M" ],
457 state => "exc_pinned",
458 # TODO: adjust out requirements for the 3 operand form
459 # (no need for should_be_same then)
460 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
461 out => [ "in_r4 in_r5", "flags", "none" ] },
462 ins => [ "base", "index", "mem", "left", "right" ],
463 outs => [ "res", "flags", "M" ],
464 am => "source,binary",
468 modified_flags => $status_flags
473 state => "exc_pinned",
474 reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ],
475 out => [ "eax", "flags", "edx", "none" ] },
476 ins => [ "base", "index", "mem", "left", "right" ],
477 emit => '. imul%M %unop4',
478 outs => [ "res_low", "flags", "res_high", "M" ],
479 am => "source,binary",
482 modified_flags => $status_flags
487 cmp_attr => "return 1;",
488 outs => [ "res_low", "res_high", "M" ],
494 state => "exc_pinned",
495 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
496 out => [ "in_r4 in_r5", "flags", "none" ] },
497 ins => [ "base", "index", "mem", "left", "right" ],
498 outs => [ "res", "flags", "M" ],
499 op_modes => "commutative | am | immediate | mode_neutral",
500 am => "source,binary",
501 emit => '. and%M %binop',
505 modified_flags => $status_flags
510 state => "exc_pinned",
511 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
512 ins => [ "base", "index", "mem", "val" ],
513 emit => '. and%M %SI3, %AM',
517 modified_flags => $status_flags
522 state => "exc_pinned",
523 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
524 ins => [ "base", "index", "mem", "val" ],
525 emit => '. and%M %SB3, %AM',
529 modified_flags => $status_flags
534 state => "exc_pinned",
535 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
536 out => [ "in_r4 in_r5", "flags", "none" ] },
537 ins => [ "base", "index", "mem", "left", "right" ],
538 outs => [ "res", "flags", "M" ],
539 am => "source,binary",
540 emit => '. or%M %binop',
544 modified_flags => $status_flags
549 state => "exc_pinned",
550 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
551 ins => [ "base", "index", "mem", "val" ],
552 emit => '. or%M %SI3, %AM',
556 modified_flags => $status_flags
561 state => "exc_pinned",
562 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
563 ins => [ "base", "index", "mem", "val" ],
564 emit => '. or%M %SB3, %AM',
568 modified_flags => $status_flags
573 state => "exc_pinned",
574 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
575 out => [ "in_r4 in_r5", "flags", "none" ] },
576 ins => [ "base", "index", "mem", "left", "right" ],
577 outs => [ "res", "flags", "M" ],
578 am => "source,binary",
579 emit => '. xor%M %binop',
583 modified_flags => $status_flags
589 reg_req => { out => [ "gp", "flags" ] },
590 outs => [ "res", "flags" ],
591 emit => ". xor%M %D0, %D0",
595 modified_flags => $status_flags
600 state => "exc_pinned",
601 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
602 ins => [ "base", "index", "mem", "val" ],
603 emit => '. xor%M %SI3, %AM',
607 modified_flags => $status_flags
612 state => "exc_pinned",
613 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
614 ins => [ "base", "index", "mem", "val" ],
615 emit => '. xor%M %SB3, %AM',
619 modified_flags => $status_flags
622 # not commutative operations
626 state => "exc_pinned",
627 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
628 out => [ "in_r4", "flags", "none" ] },
629 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
630 outs => [ "res", "flags", "M" ],
631 am => "source,binary",
632 emit => '. sub%M %binop',
636 modified_flags => $status_flags
641 state => "exc_pinned",
642 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
643 ins => [ "base", "index", "mem", "subtrahend" ],
644 emit => '. sub%M %SI3, %AM',
648 modified_flags => $status_flags
653 state => "exc_pinned",
654 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
655 ins => [ "base", "index", "mem", "subtrahend" ],
656 emit => '. sub%M %SB3, %AM',
660 modified_flags => $status_flags
664 state => "exc_pinned",
665 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
666 out => [ "in_r4 !in_r5", "flags", "none" ] },
667 ins => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
668 outs => [ "res", "flags", "M" ],
669 am => "source,binary",
670 emit => '. sbb%M %binop',
674 modified_flags => $status_flags
679 reg_req => { in => [ "flags" ], out => [ "gp", "flags" ] },
680 outs => [ "res", "flags" ],
681 emit => ". sbb%M %D0, %D0",
685 modified_flags => $status_flags
689 reg_req => { in => [ "none", "none" ], out => [ "none" ] },
690 ins => [ "minuend", "subtrahend" ],
694 reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
695 ins => [ "minuend", "subtrahend", "eflags" ],
700 state => "exc_pinned",
701 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
702 out => [ "eax", "flags", "none", "edx", "none" ] },
703 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
704 outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
705 am => "source,unary",
706 emit => ". idiv%M %unop3",
709 modified_flags => $status_flags
714 state => "exc_pinned",
715 reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
716 out => [ "eax", "flags", "none", "edx", "none" ] },
717 ins => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
718 outs => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
719 am => "source,unary",
720 emit => ". div%M %unop3",
723 modified_flags => $status_flags
728 reg_req => { in => [ "gp", "ecx" ],
729 out => [ "in_r1 !in_r2", "flags" ] },
730 ins => [ "val", "count" ],
731 outs => [ "res", "flags" ],
732 emit => '. shl%M %SB1, %S0',
736 modified_flags => $status_flags
741 state => "exc_pinned",
742 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
743 ins => [ "base", "index", "mem", "count" ],
744 emit => '. shl%M %SB3, %AM',
748 modified_flags => $status_flags
752 cmp_attr => "return 1;",
753 ins => [ "val", "count", "dep" ],
759 reg_req => { in => [ "gp", "gp", "ecx" ],
760 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
761 ins => [ "val_high", "val_low", "count" ],
762 outs => [ "res", "flags" ],
763 emit => ". shld%M %SB2, %S1, %D0",
767 modified_flags => $status_flags
771 cmp_attr => "return 1;",
772 ins => [ "val_high", "val_low", "count" ],
778 reg_req => { in => [ "gp", "ecx" ],
779 out => [ "in_r1 !in_r2", "flags" ] },
780 ins => [ "val", "count" ],
781 outs => [ "res", "flags" ],
782 emit => '. shr%M %SB1, %S0',
786 modified_flags => $status_flags
791 state => "exc_pinned",
792 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
793 ins => [ "base", "index", "mem", "count" ],
794 emit => '. shr%M %SB3, %AM',
798 modified_flags => $status_flags
802 cmp_attr => "return 1;",
803 ins => [ "val", "count", "dep" ],
809 reg_req => { in => [ "gp", "gp", "ecx" ],
810 out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
811 ins => [ "val_high", "val_low", "count" ],
812 outs => [ "res", "flags" ],
813 emit => ". shrd%M %SB2, %S1, %D0",
817 modified_flags => $status_flags
821 cmp_attr => "return 1;",
823 ins => [ "val_high", "val_low", "count" ],
828 reg_req => { in => [ "gp", "ecx" ],
829 out => [ "in_r1 !in_r2", "flags" ] },
830 ins => [ "val", "count" ],
831 outs => [ "res", "flags" ],
832 emit => '. sar%M %SB1, %S0',
836 modified_flags => $status_flags
841 state => "exc_pinned",
842 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
843 ins => [ "base", "index", "mem", "count" ],
844 emit => '. sar%M %SB3, %AM',
848 modified_flags => $status_flags
852 cmp_attr => "return 1;",
853 ins => [ "val", "count", "dep" ],
859 reg_req => { in => [ "gp", "ecx" ],
860 out => [ "in_r1 !in_r2", "flags" ] },
861 ins => [ "val", "count" ],
862 outs => [ "res", "flags" ],
863 emit => '. ror%M %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 => '. ror%M %SB3, %AM',
879 modified_flags => $status_flags
884 reg_req => { in => [ "gp", "ecx" ],
885 out => [ "in_r1 !in_r2", "flags" ] },
886 ins => [ "val", "count" ],
887 outs => [ "res", "flags" ],
888 emit => '. rol%M %SB1, %S0',
892 modified_flags => $status_flags
897 state => "exc_pinned",
898 reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
899 ins => [ "base", "index", "mem", "count" ],
900 emit => '. rol%M %SB3, %AM',
904 modified_flags => $status_flags
911 reg_req => { in => [ "gp" ],
912 out => [ "in_r1", "flags" ] },
913 emit => '. neg%M %S0',
915 outs => [ "res", "flags" ],
919 modified_flags => $status_flags
924 state => "exc_pinned",
925 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
926 ins => [ "base", "index", "mem" ],
927 emit => '. neg%M %AM',
931 modified_flags => $status_flags
936 reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "in_r2" ] },
937 outs => [ "low_res", "high_res" ],
940 modified_flags => $status_flags
946 reg_req => { in => [ "gp" ],
947 out => [ "in_r1", "flags" ] },
949 outs => [ "res", "flags" ],
950 emit => '. inc%M %S0',
954 modified_flags => $status_flags_wo_cf
959 state => "exc_pinned",
960 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
961 ins => [ "base", "index", "mem" ],
962 emit => '. inc%M %AM',
966 modified_flags => $status_flags_wo_cf
971 reg_req => { in => [ "gp" ],
972 out => [ "in_r1", "flags" ] },
974 outs => [ "res", "flags" ],
975 emit => '. dec%M %S0',
979 modified_flags => $status_flags_wo_cf
984 state => "exc_pinned",
985 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
986 ins => [ "base", "index", "mem" ],
987 emit => '. dec%M %AM',
991 modified_flags => $status_flags_wo_cf
996 reg_req => { in => [ "gp" ],
997 out => [ "in_r1", "flags" ] },
999 outs => [ "res", "flags" ],
1000 emit => '. not%M %S0',
1009 state => "exc_pinned",
1010 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1011 ins => [ "base", "index", "mem" ],
1012 emit => '. not%M %AM',
1020 reg_req => { in => [ "flags" ], out => [ "flags" ] },
1024 mode => $mode_flags,
1025 modified_flags => $status_flags
1029 reg_req => { out => [ "flags" ] },
1033 mode => $mode_flags,
1034 modified_flags => $status_flags
1041 state => "exc_pinned",
1042 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
1043 out => [ "flags", "none", "none" ] },
1044 ins => [ "base", "index", "mem", "left", "right" ],
1045 outs => [ "eflags", "unused", "M" ],
1046 am => "source,binary",
1047 emit => '. cmp%M %binop',
1048 attr => "int ins_permuted, int cmp_unsigned",
1049 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1050 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1053 mode => $mode_flags,
1054 modified_flags => $status_flags
1059 state => "exc_pinned",
1060 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
1061 ins => [ "base", "index", "mem", "left", "right" ],
1062 outs => [ "eflags" ],
1063 am => "source,binary",
1064 emit => '. cmpb %binop',
1065 attr => "int ins_permuted, int cmp_unsigned",
1066 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1067 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1070 mode => $mode_flags,
1071 modified_flags => $status_flags
1076 state => "exc_pinned",
1077 reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
1078 ins => [ "base", "index", "mem", "left", "right" ],
1079 outs => [ "eflags" ],
1080 am => "source,binary",
1081 emit => '. test%M %binop',
1082 attr => "int ins_permuted, int cmp_unsigned",
1083 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1084 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1087 mode => $mode_flags,
1088 modified_flags => $status_flags
1093 state => "exc_pinned",
1094 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
1095 ins => [ "base", "index", "mem", "left", "right" ],
1096 outs => [ "eflags" ],
1097 am => "source,binary",
1098 emit => '. testb %binop',
1099 attr => "int ins_permuted, int cmp_unsigned",
1100 init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1101 "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1104 mode => $mode_flags,
1105 modified_flags => $status_flags
1110 reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
1111 ins => [ "eflags" ],
1112 attr_type => "ia32_condcode_attr_t",
1113 attr => "pn_Cmp pnc, int ins_permuted",
1114 init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1115 "\tset_ia32_ls_mode(res, mode_Bu);\n",
1116 emit => '. set%CMP0 %DB0',
1124 state => "exc_pinned",
1125 reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
1126 ins => [ "base", "index", "mem","eflags" ],
1127 attr_type => "ia32_condcode_attr_t",
1128 attr => "pn_Cmp pnc, int ins_permuted",
1129 init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1130 "\tset_ia32_ls_mode(res, mode_Bu);\n",
1131 emit => '. set%CMP3 %AM',
1139 # (note: leave the false,true order intact to make it compatible with other
1141 state => "exc_pinned",
1142 reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ], out => [ "in_r4 in_r5" ] },
1143 ins => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
1144 am => "source,binary",
1145 attr_type => "ia32_condcode_attr_t",
1146 attr => "int ins_permuted, pn_Cmp pnc",
1147 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
1155 op_flags => "L|X|Y",
1156 reg_req => { in => [ "eflags" ], out => [ "none", "none" ] },
1157 ins => [ "eflags" ],
1158 outs => [ "false", "true" ],
1159 attr_type => "ia32_condcode_attr_t",
1160 attr => "pn_Cmp pnc",
1162 units => [ "BRANCH" ],
1167 op_flags => "L|X|Y",
1168 reg_req => { in => [ "gp" ], out => [ "none" ] },
1170 attr_type => "ia32_condcode_attr_t",
1173 units => [ "BRANCH" ],
1174 modified_flags => $status_flags,
1180 reg_req => { in => [ "gp", "gp", "none", "gp" ] },
1181 ins => [ "base", "index", "mem", "target" ],
1182 am => "source,unary",
1183 emit => '. jmp *%unop3',
1185 units => [ "BRANCH" ],
1192 reg_req => { out => [ "gp" ] },
1194 attr => "ir_entity *symconst, int symconst_sign, long offset",
1195 attr_type => "ia32_immediate_attr_t",
1202 reg_req => { out => [ "gp" ] },
1206 modified_flags => $status_flags,
1212 reg_req => { out => [ "gp_UKNWN:I" ] },
1222 reg_req => { out => [ "vfp_UKNWN:I" ] },
1227 attr_type => "ia32_x87_attr_t",
1233 reg_req => { out => [ "xmm_UKNWN:I" ] },
1242 op_flags => "c|NB|NI",
1243 reg_req => { out => [ "gp_NOREG:I" ] },
1252 op_flags => "c|NB|NI",
1253 reg_req => { out => [ "vfp_NOREG:I" ] },
1258 attr_type => "ia32_x87_attr_t",
1263 op_flags => "c|NB|NI",
1264 reg_req => { out => [ "xmm_NOREG:I" ] },
1274 reg_req => { out => [ "fpcw:I" ] },
1278 modified_flags => $fpcw_flags
1284 reg_req => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] },
1285 ins => [ "base", "index", "mem" ],
1287 emit => ". fldcw %AM",
1290 modified_flags => $fpcw_flags
1296 reg_req => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1297 ins => [ "base", "index", "mem", "fpcw" ],
1299 emit => ". fnstcw %AM",
1307 reg_req => { in => [ "fp_cw" ], out => [ "none" ] },
1315 # we should not rematrialize this node. It has very strict constraints.
1316 reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] },
1317 ins => [ "val", "clobbered" ],
1326 # Note that we add additional latency values depending on address mode, so a
1327 # lateny of 0 for load is correct
1331 state => "exc_pinned",
1332 reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none", "none" ] },
1333 ins => [ "base", "index", "mem" ],
1334 outs => [ "res", "M", "X_exc" ],
1336 emit => ". mov%SE%ME%.l %AM, %D0",
1342 state => "exc_pinned",
1343 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
1344 ins => [ "base", "index", "mem", "val" ],
1345 outs => [ "M", "X_exc" ],
1346 emit => '. mov%M %SI3, %AM',
1354 state => "exc_pinned",
1355 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] },
1356 ins => [ "base", "index", "mem", "val" ],
1357 outs => [ "M", "X_exc" ],
1358 emit => '. mov%M %SB3, %AM',
1366 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
1367 ins => [ "base", "index" ],
1368 emit => '. leal %AM, %D0',
1372 # lea doesn't modify the flags, but setting this seems advantageous since it
1373 # increases chances that the Lea is transformed back to an Add
1374 modified_flags => 1,
1378 state => "exc_pinned",
1379 reg_req => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp:I|S", "none" ] },
1380 ins => [ "base", "index", "mem", "val", "stack" ],
1381 emit => '. push%M %unop3',
1382 outs => [ "stack", "M" ],
1383 am => "source,unary",
1389 state => "exc_pinned",
1390 reg_req => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp:I|S" ] },
1391 ins => [ "mem", "stack" ],
1392 outs => [ "res", "M", "unused", "stack" ],
1393 emit => '. pop%M %D0',
1394 latency => 3, # Pop is more expensive than Push on Athlon
1399 state => "exc_pinned",
1400 reg_req => { in => [ "none", "esp" ], out => [ "ebp:I", "none", "none", "esp:I|S" ] },
1401 ins => [ "mem", "stack" ],
1402 outs => [ "res", "M", "unused", "stack" ],
1403 emit => '. pop%M %D0',
1404 latency => 3, # Pop is more expensive than Push on Athlon
1409 state => "exc_pinned",
1410 reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp:I|S" ] },
1411 ins => [ "base", "index", "mem", "stack" ],
1412 outs => [ "unused0", "M", "unused1", "stack" ],
1413 emit => '. pop%M %AM',
1414 latency => 3, # Pop is more expensive than Push on Athlon
1419 reg_req => { in => [ "esp" ], out => [ "ebp", "esp:I|S", "none" ] },
1421 outs => [ "frame", "stack", "M" ],
1427 reg_req => { in => [ "ebp" ], out => [ "ebp:I", "esp:I|S" ] },
1429 outs => [ "frame", "stack" ],
1436 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "none" ] },
1437 ins => [ "base", "index", "mem", "stack", "size" ],
1438 am => "source,binary",
1439 emit => '. addl %binop',
1441 outs => [ "stack", "M" ],
1443 modified_flags => $status_flags
1448 reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "gp", "none" ] },
1449 ins => [ "base", "index", "mem", "stack", "size" ],
1450 am => "source,binary",
1451 emit => ". subl %binop\n".
1452 ". movl %%esp, %D1",
1454 outs => [ "stack", "addr", "M" ],
1456 modified_flags => $status_flags
1469 reg_req => { out => [ "gp" ] },
1476 state => "exc_pinned",
1477 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
1478 ins => [ "left", "right" ],
1479 emit => '. bt%M %S1, %S0',
1482 mode => $mode_flags,
1483 modified_flags => $status_flags # only CF is set, but the other flags are undefined
1487 state => "exc_pinned",
1489 in => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ],
1490 out => [ "esp:I|S", "fpcw:I", "none", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ]
1492 ins => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ],
1493 outs => [ "stack", "fpcw", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ],
1494 attr_type => "ia32_call_attr_t",
1495 attr => "unsigned pop, ir_type *call_tp",
1496 am => "source,unary",
1497 units => [ "BRANCH" ],
1498 latency => 4, # random number
1499 modified_flags => $status_flags
1502 #-----------------------------------------------------------------------------#
1503 # _____ _____ ______ __ _ _ _ #
1504 # / ____/ ____| ____| / _| | | | | | #
1505 # | (___| (___ | |__ | |_| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
1506 # \___ \\___ \| __| | _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1507 # ____) |___) | |____ | | | | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
1508 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1509 #-----------------------------------------------------------------------------#
1514 reg_req => { out => [ "xmm" ] },
1515 emit => '. xorp%XSD %D0, %D0',
1523 reg_req => { out => [ "xmm" ] },
1524 emit => '. pxor %D0, %D0',
1530 # produces all 1 bits
1533 reg_req => { out => [ "xmm" ] },
1534 emit => '. pcmpeqb %D0, %D0',
1540 # integer shift left, dword
1543 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1544 emit => '. pslld %SI1, %D0',
1550 # integer shift left, qword
1553 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1554 emit => '. psllq %SI1, %D0',
1560 # integer shift right, dword
1563 reg_req => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1564 emit => '. psrld %SI1, %D0',
1570 # mov from integer to SSE register
1573 reg_req => { in => [ "gp" ], out => [ "xmm" ] },
1574 emit => '. movd %S0, %D0',
1580 # commutative operations
1584 state => "exc_pinned",
1585 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1586 ins => [ "base", "index", "mem", "left", "right" ],
1587 am => "source,binary",
1588 emit => '. add%XXM %binop',
1596 state => "exc_pinned",
1597 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1598 ins => [ "base", "index", "mem", "left", "right" ],
1599 am => "source,binary",
1600 emit => '. mul%XXM %binop',
1608 state => "exc_pinned",
1609 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1610 ins => [ "base", "index", "mem", "left", "right" ],
1611 am => "source,binary",
1612 emit => '. max%XXM %binop',
1620 state => "exc_pinned",
1621 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1622 ins => [ "base", "index", "mem", "left", "right" ],
1623 am => "source,binary",
1624 emit => '. min%XXM %binop',
1632 state => "exc_pinned",
1633 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1634 ins => [ "base", "index", "mem", "left", "right" ],
1635 am => "source,binary",
1636 emit => '. andp%XSD %binop',
1644 state => "exc_pinned",
1645 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1646 ins => [ "base", "index", "mem", "left", "right" ],
1647 am => "source,binary",
1648 emit => '. orp%XSD %binop',
1656 state => "exc_pinned",
1657 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1658 ins => [ "base", "index", "mem", "left", "right" ],
1659 am => "source,binary",
1660 emit => '. xorp%XSD %binop',
1666 # not commutative operations
1670 state => "exc_pinned",
1671 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1672 ins => [ "base", "index", "mem", "left", "right" ],
1673 am => "source,binary",
1674 emit => '. andnp%XSD %binop',
1682 state => "exc_pinned",
1683 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1684 ins => [ "base", "index", "mem", "minuend", "subtrahend" ],
1685 am => "source,binary",
1686 emit => '. sub%XXM %binop',
1694 state => "exc_pinned",
1695 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
1696 ins => [ "base", "index", "mem", "dividend", "divisor" ],
1697 am => "source,binary",
1698 outs => [ "res", "M" ],
1699 emit => '. div%XXM %binop',
1708 state => "exc_pinned",
1709 reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eflags" ] },
1710 ins => [ "base", "index", "mem", "left", "right" ],
1711 outs => [ "flags" ],
1712 am => "source,binary",
1713 attr => "int ins_permuted",
1714 init_attr => "attr->data.ins_permuted = ins_permuted;",
1715 emit => ' .ucomi%XXM %binop',
1718 mode => $mode_flags,
1719 modified_flags => 1,
1726 state => "exc_pinned",
1727 reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none", "none" ] },
1728 ins => [ "base", "index", "mem" ],
1729 outs => [ "res", "M", "X_exc" ],
1730 emit => '. mov%XXM %AM, %D0',
1731 attr => "ir_mode *load_mode",
1732 init_attr => "attr->ls_mode = load_mode;",
1739 state => "exc_pinned",
1740 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] },
1741 ins => [ "base", "index", "mem", "val" ],
1742 outs => [ "M", "X_exc" ],
1743 emit => '. mov%XXM %S3, %AM',
1751 state => "exc_pinned",
1752 reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
1753 ins => [ "base", "index", "mem", "val" ],
1754 emit => '. mov%XXM %S3, %AM',
1762 state => "exc_pinned",
1763 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1764 ins => [ "base", "index", "mem", "val" ],
1765 am => "source,unary",
1766 emit => '. cvtsi2ss %unop3, %D0',
1774 state => "exc_pinned",
1775 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1776 ins => [ "base", "index", "mem", "val" ],
1777 am => "source,unary",
1778 emit => '. cvtsi2sd %unop3, %D0',
1787 cmp_attr => "return 1;",
1788 ins => [ "val_high", "val_low" ],
1793 cmp_attr => "return 1;",
1795 outs => [ "res_high", "res_low" ],
1803 reg_req => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1804 outs => [ "DST", "SRC", "CNT", "M" ],
1805 attr_type => "ia32_copyb_attr_t",
1806 attr => "unsigned size",
1809 # we don't care about this flag, so no need to mark this node
1810 # modified_flags => [ "DF" ]
1816 reg_req => { in => [ "edi", "esi", "none" ], out => [ "edi", "esi", "none" ] },
1817 outs => [ "DST", "SRC", "M" ],
1818 attr_type => "ia32_copyb_attr_t",
1819 attr => "unsigned size",
1822 # we don't care about this flag, so no need to mark this node
1823 # modified_flags => [ "DF" ]
1829 state => "exc_pinned",
1830 reg_req => { in => [ "eax" ], out => [ "eax" ] },
1840 state => "exc_pinned",
1841 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] },
1842 ins => [ "base", "index", "mem", "val" ],
1843 outs => [ "res", "M" ],
1844 am => "source,unary",
1847 attr => "ir_mode *smaller_mode",
1848 init_attr => "attr->ls_mode = smaller_mode;",
1853 state => "exc_pinned",
1854 reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "gp", "none" ] },
1855 ins => [ "base", "index", "mem", "val" ],
1856 am => "source,unary",
1859 attr => "ir_mode *smaller_mode",
1860 init_attr => "attr->ls_mode = smaller_mode;",
1865 state => "exc_pinned",
1866 reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
1867 ins => [ "base", "index", "mem", "val" ],
1868 am => "source,unary",
1875 state => "exc_pinned",
1876 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1877 ins => [ "base", "index", "mem", "val" ],
1878 am => "source,unary",
1885 state => "exc_pinned",
1886 reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1887 ins => [ "base", "index", "mem", "val" ],
1888 am => "source,unary",
1894 #----------------------------------------------------------#
1896 # (_) | | | | / _| | | | #
1897 # __ ___ _ __| |_ _ _ __ _| | | |_| | ___ __ _| |_ #
1898 # \ \ / / | '__| __| | | |/ _` | | | _| |/ _ \ / _` | __| #
1899 # \ V /| | | | |_| |_| | (_| | | | | | | (_) | (_| | |_ #
1900 # \_/ |_|_| \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1902 # _ __ ___ __| | ___ ___ #
1903 # | '_ \ / _ \ / _` |/ _ \/ __| #
1904 # | | | | (_) | (_| | __/\__ \ #
1905 # |_| |_|\___/ \__,_|\___||___/ #
1906 #----------------------------------------------------------#
1908 # rematerialisation disabled for all float nodes for now, because the fpcw
1909 # handler runs before spilling and we might end up with wrong fpcw then
1913 state => "exc_pinned",
1914 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1915 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1916 am => "source,binary",
1920 attr_type => "ia32_x87_attr_t",
1925 state => "exc_pinned",
1926 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1927 ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
1928 am => "source,binary",
1932 attr_type => "ia32_x87_attr_t",
1937 state => "exc_pinned",
1938 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1939 ins => [ "base", "index", "mem", "minuend", "subtrahend", "fpcw" ],
1940 am => "source,binary",
1944 attr_type => "ia32_x87_attr_t",
1948 state => "exc_pinned",
1949 reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
1950 ins => [ "base", "index", "mem", "dividend", "divisor", "fpcw" ],
1951 am => "source,binary",
1952 outs => [ "res", "M" ],
1955 attr_type => "ia32_x87_attr_t",
1959 reg_req => { in => [ "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1960 ins => [ "left", "right", "fpcw" ],
1964 attr_type => "ia32_x87_attr_t",
1969 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
1974 attr_type => "ia32_x87_attr_t",
1979 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
1984 attr_type => "ia32_x87_attr_t",
1987 # virtual Load and Store
1992 state => "exc_pinned",
1993 reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none", "none" ] },
1994 ins => [ "base", "index", "mem" ],
1995 outs => [ "res", "M", "X_exc" ],
1996 attr => "ir_mode *load_mode",
1997 init_attr => "attr->attr.ls_mode = load_mode;",
2000 attr_type => "ia32_x87_attr_t",
2006 state => "exc_pinned",
2007 reg_req => { in => [ "gp", "gp", "none", "vfp" ], out => [ "none", "none" ] },
2008 ins => [ "base", "index", "mem", "val" ],
2009 outs => [ "M", "X_exc" ],
2010 attr => "ir_mode *store_mode",
2011 init_attr => "attr->attr.ls_mode = store_mode;",
2015 attr_type => "ia32_x87_attr_t",
2021 state => "exc_pinned",
2022 reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
2023 outs => [ "res", "M" ],
2024 ins => [ "base", "index", "mem" ],
2027 attr_type => "ia32_x87_attr_t",
2031 state => "exc_pinned",
2032 reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
2033 ins => [ "base", "index", "mem", "val", "fpcw" ],
2037 attr_type => "ia32_x87_attr_t",
2040 # SSE3 fisttp instruction
2042 state => "exc_pinned",
2043 reg_req => { in => [ "gp", "gp", "none", "vfp" ], out => [ "in_r4", "none" ]},
2044 ins => [ "base", "index", "mem", "val" ],
2045 outs => [ "res", "M" ],
2048 attr_type => "ia32_x87_attr_t",
2056 reg_req => { out => [ "vfp" ] },
2061 attr_type => "ia32_x87_attr_t",
2066 reg_req => { out => [ "vfp" ] },
2071 attr_type => "ia32_x87_attr_t",
2076 reg_req => { out => [ "vfp" ] },
2081 attr_type => "ia32_x87_attr_t",
2086 reg_req => { out => [ "vfp" ] },
2091 attr_type => "ia32_x87_attr_t",
2096 reg_req => { out => [ "vfp" ] },
2101 attr_type => "ia32_x87_attr_t",
2106 reg_req => { out => [ "vfp" ] },
2111 attr_type => "ia32_x87_attr_t",
2116 reg_req => { out => [ "vfp" ] },
2121 attr_type => "ia32_x87_attr_t",
2127 # we can't allow to rematerialize this node so we don't have
2128 # accidently produce Phi(Fucom, Fucom(ins_permuted))
2130 reg_req => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
2131 ins => [ "left", "right" ],
2132 outs => [ "flags" ],
2133 attr => "int ins_permuted",
2134 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2137 attr_type => "ia32_x87_attr_t",
2143 reg_req => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
2144 ins => [ "left", "right" ],
2145 outs => [ "flags" ],
2146 attr => "int ins_permuted",
2147 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2150 attr_type => "ia32_x87_attr_t",
2156 reg_req => { in => [ "vfp" ], out => [ "eax" ] },
2158 outs => [ "flags" ],
2159 attr => "int ins_permuted",
2160 init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2163 attr_type => "ia32_x87_attr_t",
2169 reg_req => { in => [ "eax" ], out => [ "eflags" ] },
2171 outs => [ "flags" ],
2175 mode => $mode_flags,
2178 #------------------------------------------------------------------------#
2179 # ___ _____ __ _ _ _ #
2180 # __ _( _ )___ | / _| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
2181 # \ \/ / _ \ / / | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
2182 # > < (_) |/ / | _| | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
2183 # /_/\_\___//_/ |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
2184 #------------------------------------------------------------------------#
2186 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
2187 # are swapped, we work this around in the emitter...
2190 state => "exc_pinned",
2191 rd_constructor => "NONE",
2193 emit => '. fadd%XM %x87_binop',
2195 attr_type => "ia32_x87_attr_t",
2199 state => "exc_pinned",
2200 rd_constructor => "NONE",
2202 emit => '. faddp%XM %x87_binop',
2204 attr_type => "ia32_x87_attr_t",
2208 state => "exc_pinned",
2209 rd_constructor => "NONE",
2211 emit => '. fmul%XM %x87_binop',
2213 attr_type => "ia32_x87_attr_t",
2217 state => "exc_pinned",
2218 rd_constructor => "NONE",
2220 emit => '. fmulp%XM %x87_binop',,
2222 attr_type => "ia32_x87_attr_t",
2226 state => "exc_pinned",
2227 rd_constructor => "NONE",
2229 emit => '. fsub%XM %x87_binop',
2231 attr_type => "ia32_x87_attr_t",
2235 state => "exc_pinned",
2236 rd_constructor => "NONE",
2238 # see note about gas bugs
2239 emit => '. fsubrp%XM %x87_binop',
2241 attr_type => "ia32_x87_attr_t",
2245 state => "exc_pinned",
2246 rd_constructor => "NONE",
2249 emit => '. fsubr%XM %x87_binop',
2251 attr_type => "ia32_x87_attr_t",
2255 state => "exc_pinned",
2256 rd_constructor => "NONE",
2259 # see note about gas bugs
2260 emit => '. fsubp%XM %x87_binop',
2262 attr_type => "ia32_x87_attr_t",
2266 rd_constructor => "NONE",
2270 attr_type => "ia32_x87_attr_t",
2273 # this node is just here, to keep the simulator running
2274 # we can omit this when a fprem simulation function exists
2276 rd_constructor => "NONE",
2278 emit => '. fprem1\n'.
2281 attr_type => "ia32_x87_attr_t",
2285 state => "exc_pinned",
2286 rd_constructor => "NONE",
2288 emit => '. fdiv%XM %x87_binop',
2290 attr_type => "ia32_x87_attr_t",
2294 state => "exc_pinned",
2295 rd_constructor => "NONE",
2297 # see note about gas bugs
2298 emit => '. fdivrp%XM %x87_binop',
2300 attr_type => "ia32_x87_attr_t",
2304 state => "exc_pinned",
2305 rd_constructor => "NONE",
2307 emit => '. fdivr%XM %x87_binop',
2309 attr_type => "ia32_x87_attr_t",
2313 state => "exc_pinned",
2314 rd_constructor => "NONE",
2316 # see note about gas bugs
2317 emit => '. fdivp%XM %x87_binop',
2319 attr_type => "ia32_x87_attr_t",
2323 rd_constructor => "NONE",
2327 attr_type => "ia32_x87_attr_t",
2332 rd_constructor => "NONE",
2336 attr_type => "ia32_x87_attr_t",
2339 # x87 Load and Store
2342 rd_constructor => "NONE",
2343 op_flags => "R|L|F",
2344 state => "exc_pinned",
2346 emit => '. fld%XM %AM',
2347 attr_type => "ia32_x87_attr_t",
2352 rd_constructor => "NONE",
2353 op_flags => "R|L|F",
2354 state => "exc_pinned",
2356 emit => '. fst%XM %AM',
2358 attr_type => "ia32_x87_attr_t",
2363 rd_constructor => "NONE",
2364 op_flags => "R|L|F",
2365 state => "exc_pinned",
2367 emit => '. fstp%XM %AM',
2369 attr_type => "ia32_x87_attr_t",
2376 state => "exc_pinned",
2377 rd_constructor => "NONE",
2379 emit => '. fild%XM %AM',
2380 attr_type => "ia32_x87_attr_t",
2385 state => "exc_pinned",
2386 rd_constructor => "NONE",
2388 emit => '. fist%XM %AM',
2390 attr_type => "ia32_x87_attr_t",
2395 state => "exc_pinned",
2396 rd_constructor => "NONE",
2398 emit => '. fistp%XM %AM',
2400 attr_type => "ia32_x87_attr_t",
2404 # SSE3 firsttp instruction
2406 state => "exc_pinned",
2407 rd_constructor => "NONE",
2409 emit => '. fisttp%XM %AM',
2411 attr_type => "ia32_x87_attr_t",
2418 op_flags => "R|c|K",
2420 reg_req => { out => [ "vfp" ] },
2422 attr_type => "ia32_x87_attr_t",
2427 op_flags => "R|c|K",
2429 reg_req => { out => [ "vfp" ] },
2431 attr_type => "ia32_x87_attr_t",
2436 op_flags => "R|c|K",
2438 reg_req => { out => [ "vfp" ] },
2440 attr_type => "ia32_x87_attr_t",
2445 op_flags => "R|c|K",
2447 reg_req => { out => [ "vfp" ] },
2449 attr_type => "ia32_x87_attr_t",
2454 op_flags => "R|c|K",
2456 reg_req => { out => [ "vfp" ] },
2458 attr_type => "ia32_x87_attr_t",
2463 op_flags => "R|c|K",
2465 reg_req => { out => [ "vfp" ] },
2466 emit => '. fldll2t',
2467 attr_type => "ia32_x87_attr_t",
2472 op_flags => "R|c|K",
2474 reg_req => { out => [ "vfp" ] },
2476 attr_type => "ia32_x87_attr_t",
2481 # Note that it is NEVER allowed to do CSE on these nodes
2482 # Moreover, note the virtual register requierements!
2487 cmp_attr => "return 1;",
2488 emit => '. fxch %X0',
2489 attr_type => "ia32_x87_attr_t",
2497 cmp_attr => "return 1;",
2498 emit => '. fld %X0',
2499 attr_type => "ia32_x87_attr_t",
2505 reg_req => { in => [ "vfp"], out => [ "vfp" ] },
2506 cmp_attr => "return 1;",
2507 emit => '. fld %X0',
2508 attr_type => "ia32_x87_attr_t",
2515 cmp_attr => "return 1;",
2516 emit => '. fstp %X0',
2517 attr_type => "ia32_x87_attr_t",
2525 cmp_attr => "return 1;",
2526 emit => '. ffreep %X0',
2527 attr_type => "ia32_x87_attr_t",
2535 cmp_attr => "return 1;",
2537 attr_type => "ia32_x87_attr_t",
2545 cmp_attr => "return 1;",
2547 attr_type => "ia32_x87_attr_t",
2556 emit => ". fucom %X1\n".
2558 attr_type => "ia32_x87_attr_t",
2564 emit => ". fucomp %X1\n".
2566 attr_type => "ia32_x87_attr_t",
2572 emit => ". fucompp\n".
2574 attr_type => "ia32_x87_attr_t",
2580 emit => '. fucomi %X1',
2581 attr_type => "ia32_x87_attr_t",
2587 emit => '. fucompi %X1',
2588 attr_type => "ia32_x87_attr_t",
2596 attr_type => "ia32_x87_attr_t",
2601 # -------------------------------------------------------------------------------- #
2602 # ____ ____ _____ _ _ #
2603 # / ___/ ___|| ____| __ _____ ___| |_ ___ _ __ _ __ ___ __| | ___ ___ #
2604 # \___ \___ \| _| \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __| #
2605 # ___) |__) | |___ \ V / __/ (__| || (_) | | | | | | (_) | (_| | __/\__ \ #
2606 # |____/____/|_____| \_/ \___|\___|\__\___/|_| |_| |_|\___/ \__,_|\___||___/ #
2608 # -------------------------------------------------------------------------------- #
2611 # Spilling and reloading of SSE registers, hardcoded, not generated #
2615 state => "exc_pinned",
2616 reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2617 emit => '. movdqu %D0, %AM',
2618 outs => [ "res", "M" ],
2625 state => "exc_pinned",
2626 reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
2627 ins => [ "base", "index", "mem", "val" ],
2628 emit => '. movdqu %binop',
2636 # Include the generated SIMD node specification written by the SIMD optimization
2637 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2638 unless ($return = do $my_script_name) {
2639 warn "couldn't parse $my_script_name: $@" if $@;
2640 warn "couldn't do $my_script_name: $!" unless defined $return;
2641 warn "couldn't run $my_script_name" unless $return;
2644 # Transform some attributes
2645 foreach my $op (keys(%nodes)) {
2646 my $node = $nodes{$op};
2647 my $op_attr_init = $node->{op_attr_init};
2649 if(defined($op_attr_init)) {
2650 $op_attr_init .= "\n\t";
2655 if(!defined($node->{latency})) {
2657 $node->{latency} = 0;
2659 die("Latency missing for op $op");
2662 $op_attr_init .= "attr->latency = ".$node->{latency} . ";";
2664 $node->{op_attr_init} = $op_attr_init;