c16d787b215b1af0939796dd5444bf841d8b46d5
[libfirm] / ir / be / ia32 / ia32_spec.pl
1 # Creation: 2005/10/19
2 # $Id$
3 # This is the specification for the ia32 assembler Firm-operations
4
5 use File::Basename;
6
7 $new_emit_syntax = 1;
8 my $myname = $0;
9
10 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
11 $arch = "ia32";
12
13 # The node description is done as a perl hash initializer with the
14 # following structure:
15 #
16 # %nodes = (
17 #
18 # <op-name> => {
19 #   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
20 #   irn_flags => "R|N"
21 #   arity     => "0|1|2|3 ... |variable|dynamic|any",
22 #   state     => "floats|pinned|mem_pinned|exc_pinned",
23 #   args      => [
24 #                    { type => "type 1", name => "name 1" },
25 #                    { type => "type 2", name => "name 2" },
26 #                    ...
27 #                  ],
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
42 # },
43 #
44 # ... # (all nodes you need to describe)
45 #
46 # ); # close the %nodes initializer
47
48 # op_flags: flags for the operation, OPTIONAL (default is "N")
49 # the op_flags correspond to the firm irop_flags:
50 #   N   irop_flag_none
51 #   L   irop_flag_labeled
52 #   C   irop_flag_commutative
53 #   X   irop_flag_cfopcode
54 #   I   irop_flag_ip_cfopcode
55 #   F   irop_flag_fragile
56 #   Y   irop_flag_forking
57 #   H   irop_flag_highlevel
58 #   c   irop_flag_constlike
59 #   K   irop_flag_keep
60 #   NB  irop_flag_dump_noblock
61 #   NI  irop_flag_dump_noinput
62 #
63 # irn_flags: special node flags, OPTIONAL (default is 0)
64 # following irn_flags are supported:
65 #   R   rematerializeable
66 #   N   not spillable
67 #
68 # state: state of the operation, OPTIONAL (default is "floats")
69 #
70 # arity: arity of the operation, MUST NOT BE OMITTED
71 #
72 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
73 #        are always the first 3 arguments and are always autmatically
74 #        created)
75 #        If this key is missing the following arguments will be created:
76 #        for i = 1 .. arity: ir_node *op_i
77 #        ir_mode *mode
78 #
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" ]
82 #
83 # comment: OPTIONAL comment for the node constructor
84 #
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
89 #
90 #      This key is OPTIONAL. If omitted, the following constructor will
91 #      be created:
92 #      if (!op_<arch>_<op-name>) assert(0);
93 #      for i = 1 to arity
94 #         set in[i] = op_i
95 #      done
96 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
97 #      return res
98 #
99 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
100 #
101
102 # register types:
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 automatically 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
111 %reg_classes = (
112         gp => [
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" }
124         ],
125         mmx => [
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" }
135         ],
136         xmm => [
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
147                 { mode => "mode_E" }
148         ],
149         vfp => [
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
160                 { mode => "mode_E" }
161         ],
162         st => [
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" }
172         ],
173         fp_cw => [      # the floating point control word
174                 { name => "fpcw", type => 4|32 },
175                 { mode => "mode_fpcw", flags => "manual_ra|state" }
176         ],
177         flags => [
178                 { name => "eflags", type => 0 },
179                 { mode => "mode_Iu", flags => "manual_ra" }
180         ],
181 ); # %reg_classes
182
183 %cpu = (
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" ],
188 ); # %cpu
189
190 %vliw = (
191         bundle_size       => 1,
192         bundels_per_cycle => 1
193 ); # vliw
194
195 %emit_templates = (
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         SB0 => "${arch}_emit_8bit_source_register_or_immediate(node, 0);",
201         SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
202         SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
203         SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
204         SH0 => "${arch}_emit_8bit_high_source_register(node, 0);",
205         SS0 => "${arch}_emit_16bit_source_register_or_immediate(node, 0);",
206         SI0 => "${arch}_emit_source_register_or_immediate(node, 0);",
207         SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
208         SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
209         D0 => "${arch}_emit_dest_register(node, 0);",
210         D1 => "${arch}_emit_dest_register(node, 1);",
211         DS0 => "${arch}_emit_dest_register_size(node, 0);",
212         DB0 => "${arch}_emit_8bit_dest_register(node, 0);",
213         X0 => "${arch}_emit_x87_register(node, 0);",
214         X1 => "${arch}_emit_x87_register(node, 1);",
215         EX => "${arch}_emit_extend_suffix(node);",
216         M  => "${arch}_emit_mode_suffix(node);",
217         XM => "${arch}_emit_x87_mode_suffix(node);",
218         XXM => "${arch}_emit_xmm_mode_suffix(node);",
219         XSD => "${arch}_emit_xmm_mode_suffix_s(node);",
220         AM => "${arch}_emit_am(node);",
221         unop3 => "${arch}_emit_unop(node, n_ia32_unary_op);",
222         unop4 => "${arch}_emit_unop(node, n_ia32_binary_right);",
223         binop => "${arch}_emit_binop(node);",
224         x87_binop => "${arch}_emit_x87_binop(node);",
225         CMP0  => "${arch}_emit_cmp_suffix_node(node, 0);",
226         CMP3  => "${arch}_emit_cmp_suffix_node(node, 3);",
227 );
228
229 #--------------------------------------------------#
230 #                        _                         #
231 #                       (_)                        #
232 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
233 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
234 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
235 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
236 #                                      | |         #
237 #                                      |_|         #
238 #--------------------------------------------------#
239
240 $default_op_attr_type = "ia32_op_attr_t";
241 $default_attr_type    = "ia32_attr_t";
242 $default_copy_attr    = "ia32_copy_attr";
243
244 sub ia32_custom_init_attr {
245         my $node = shift;
246         my $name = shift;
247         my $res = "";
248
249         if(defined($node->{modified_flags})) {
250                 $res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n";
251         }
252         if(defined($node->{am})) {
253                 my $am = $node->{am};
254                 if($am eq "source,unary") {
255                         $res .= "\tset_ia32_am_support(res, ia32_am_unary);";
256                 } elsif($am eq "source,binary") {
257                         $res .= "\tset_ia32_am_support(res, ia32_am_binary);";
258                 } elsif($am eq "none") {
259                         # nothing to do
260                 } else {
261                         die("Invalid address mode '$am' specified on op $name");
262                 }
263                 if($am ne "none") {
264                         if($node->{state} ne "exc_pinned"
265                                         and $node->{state} ne "pinned") {
266                                 die("AM nodes must have pinned or AM pinned state ($name)");
267                         }
268                 }
269         }
270         return $res;
271 }
272 $custom_init_attr_func = \&ia32_custom_init_attr;
273
274 %init_attr = (
275         ia32_asm_attr_t =>
276                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
277                 "\tinit_ia32_x87_attributes(res);".
278                 "\tinit_ia32_asm_attributes(res);",
279         ia32_attr_t     =>
280                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);",
281         ia32_call_attr_t =>
282                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
283                 "\tinit_ia32_call_attributes(res, pop, call_tp);",
284         ia32_condcode_attr_t =>
285                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
286                 "\tinit_ia32_condcode_attributes(res, pnc);",
287         ia32_copyb_attr_t =>
288                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
289                 "\tinit_ia32_copyb_attributes(res, size);",
290         ia32_immediate_attr_t =>
291                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
292                 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, no_pic_adjust, offset);",
293         ia32_x87_attr_t =>
294                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
295                 "\tinit_ia32_x87_attributes(res);",
296         ia32_climbframe_attr_t =>
297                 "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
298                 "\tinit_ia32_climbframe_attributes(res, count);",
299 );
300
301 %compare_attr = (
302         ia32_asm_attr_t       => "ia32_compare_asm_attr",
303         ia32_attr_t            => "ia32_compare_nodes_attr",
304         ia32_call_attr_t       => "ia32_compare_call_attr",
305         ia32_condcode_attr_t   => "ia32_compare_condcode_attr",
306         ia32_copyb_attr_t      => "ia32_compare_copyb_attr",
307         ia32_immediate_attr_t  => "ia32_compare_immediate_attr",
308         ia32_x87_attr_t        => "ia32_compare_x87_attr",
309         ia32_climbframe_attr_t => "ia32_compare_climbframe_attr",
310 );
311
312 %operands = (
313 );
314
315 $mode_xmm           = "mode_E";
316 $mode_gp            = "mode_Iu";
317 $mode_flags         = "mode_Iu";
318 $mode_fpcw          = "mode_fpcw";
319 $status_flags       = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
320 $status_flags_wo_cf = [       "PF", "AF", "ZF", "SF", "OF" ];
321 $fpcw_flags         = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
322                         "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
323
324 %nodes = (
325
326 Immediate => {
327         state     => "pinned",
328         op_flags  => "c",
329         reg_req   => { out => [ "gp_NOREG:I" ] },
330         attr      => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
331         attr_type => "ia32_immediate_attr_t",
332         hash_func => "ia32_hash_Immediate",
333         latency   => 0,
334         mode      => $mode_gp,
335 },
336
337 Asm => {
338         mode      => "mode_T",
339         arity     => "variable",
340         out_arity => "variable",
341         attr_type => "ia32_asm_attr_t",
342         attr      => "ident *asm_text, const ia32_asm_reg_t *register_map",
343         init_attr => "attr->asm_text = asm_text;\n".
344                      "\tattr->register_map = register_map;\n",
345         latency   => 10,
346         modified_flags => $status_flags,
347 },
348
349 # "allocates" a free register
350 ProduceVal => {
351         op_flags  => "c",
352         irn_flags => "R",
353         reg_req   => { out => [ "gp" ] },
354         emit      => "",
355         units     => [ ],
356         latency   => 0,
357         mode      => $mode_gp,
358         cmp_attr  => "return 1;",
359 },
360
361 #-----------------------------------------------------------------#
362 #  _       _                                         _            #
363 # (_)     | |                                       | |           #
364 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
365 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
366 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
367 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
368 #                   __/ |                                         #
369 #                  |___/                                          #
370 #-----------------------------------------------------------------#
371
372 # commutative operations
373
374 Add => {
375         irn_flags => "R",
376         state     => "exc_pinned",
377         reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ],
378                        out => [ "in_r4 in_r5", "flags", "none" ] },
379         ins       => [ "base", "index", "mem", "left", "right" ],
380         outs      => [ "res", "flags", "M" ],
381         emit      => '. add%M %binop',
382         am        => "source,binary",
383         units     => [ "GP" ],
384         latency   => 1,
385         mode      => $mode_gp,
386         modified_flags => $status_flags
387 },
388
389 AddMem => {
390         irn_flags => "R",
391         state     => "exc_pinned",
392         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
393         ins       => [ "base", "index", "mem", "val" ],
394         emit      => ". add%M %SI3, %AM",
395         units     => [ "GP" ],
396         latency   => 1,
397         mode      => "mode_M",
398         modified_flags => $status_flags
399 },
400
401 AddMem8Bit => {
402         irn_flags => "R",
403         state     => "exc_pinned",
404         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
405         ins       => [ "base", "index", "mem", "val" ],
406         emit      => ". add%M %SB3, %AM",
407         units     => [ "GP" ],
408         latency   => 1,
409         mode      => "mode_M",
410         modified_flags => $status_flags
411 },
412
413 Adc => {
414         state     => "exc_pinned",
415         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
416                        out => [ "in_r4 in_r5", "flags", "none" ] },
417         ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
418         outs      => [ "res", "flags", "M" ],
419         emit      => '. adc%M %binop',
420         am        => "source,binary",
421         units     => [ "GP" ],
422         latency   => 1,
423         mode      => $mode_gp,
424         modified_flags => $status_flags
425 },
426
427 l_Add => {
428         op_flags  => "C",
429         reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
430         ins       => [ "left", "right" ],
431 },
432
433 l_Adc => {
434         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
435         ins       => [ "left", "right", "eflags" ],
436 },
437
438 Mul => {
439         # we should not rematrialize this node. It produces 2 results and has
440         # very strict constraints
441         state     => "exc_pinned",
442         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ],
443                        out => [ "eax", "flags", "none", "edx" ] },
444         ins       => [ "base", "index", "mem", "left", "right" ],
445         emit      => '. mul%M %unop4',
446         outs      => [ "res_low", "flags", "M", "res_high" ],
447         am        => "source,binary",
448         latency   => 10,
449         units     => [ "GP" ],
450         modified_flags => $status_flags
451 },
452
453 l_Mul => {
454         # we should not rematrialize this node. It produces 2 results and has
455         # very strict constraints
456         op_flags  => "C",
457         cmp_attr  => "return 1;",
458         reg_req   => { in => [ "none", "none" ],
459                        out => [ "none", "none", "none", "none" ] },
460         ins       => [ "left", "right" ],
461         outs      => [ "res_low", "flags", "M", "res_high" ],
462 },
463
464 IMul => {
465         irn_flags => "R",
466         state     => "exc_pinned",
467         # TODO: adjust out requirements for the 3 operand form
468         # (no need for should_be_same then)
469         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
470                            out => [ "in_r4 in_r5", "flags", "none" ] },
471         ins       => [ "base", "index", "mem", "left", "right" ],
472         outs      => [ "res", "flags", "M" ],
473         am        => "source,binary",
474         latency   => 5,
475         units     => [ "GP" ],
476         mode      => $mode_gp,
477         modified_flags => $status_flags
478 },
479
480 IMul1OP => {
481         irn_flags => "R",
482         state     => "exc_pinned",
483         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ],
484                        out => [ "eax", "flags", "none", "edx" ] },
485         ins       => [ "base", "index", "mem", "left", "right" ],
486         emit      => '. imul%M %unop4',
487         outs      => [ "res_low", "flags", "M", "res_high" ],
488         am        => "source,binary",
489         latency   => 5,
490         units     => [ "GP" ],
491         modified_flags => $status_flags
492 },
493
494 l_IMul => {
495         op_flags  => "C",
496         cmp_attr  => "return 1;",
497         reg_req   => { in => [ "none", "none" ],
498                        out => [ "none", "none", "none", "none" ] },
499         ins       => [ "left", "right" ],
500         outs      => [ "res_low", "flags", "M", "res_high" ],
501 },
502
503 And => {
504         irn_flags => "R",
505         state     => "exc_pinned",
506         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
507                            out => [ "in_r4 in_r5", "flags", "none" ] },
508         ins       => [ "base", "index", "mem", "left", "right" ],
509         outs      => [ "res", "flags", "M" ],
510         op_modes  => "commutative | am | immediate | mode_neutral",
511         am        => "source,binary",
512         emit      => '. and%M %binop',
513         units     => [ "GP" ],
514         latency   => 1,
515         mode      => $mode_gp,
516         modified_flags => $status_flags
517 },
518
519 AndMem => {
520         irn_flags => "R",
521         state     => "exc_pinned",
522         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
523         ins       => [ "base", "index", "mem", "val" ],
524         emit      => '. and%M %SI3, %AM',
525         units     => [ "GP" ],
526         latency   => 1,
527         mode      => "mode_M",
528         modified_flags => $status_flags
529 },
530
531 AndMem8Bit => {
532         irn_flags => "R",
533         state     => "exc_pinned",
534         reg_req   => { in => [ "gp", "gp", "none",  "eax ebx ecx edx" ], out => [ "none" ] },
535         ins       => [ "base", "index", "mem", "val" ],
536         emit      => '. and%M %SB3, %AM',
537         units     => [ "GP" ],
538         latency   => 1,
539         mode      => "mode_M",
540         modified_flags => $status_flags
541 },
542
543 Or => {
544         irn_flags => "R",
545         state     => "exc_pinned",
546         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
547                        out => [ "in_r4 in_r5", "flags", "none" ] },
548         ins       => [ "base", "index", "mem", "left", "right" ],
549         outs      => [ "res", "flags", "M" ],
550         am        => "source,binary",
551         emit      => '. or%M %binop',
552         units     => [ "GP" ],
553         latency   => 1,
554         mode      => $mode_gp,
555         modified_flags => $status_flags
556 },
557
558 OrMem => {
559         irn_flags => "R",
560         state     => "exc_pinned",
561         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
562         ins       => [ "base", "index", "mem", "val" ],
563         emit      => '. or%M %SI3, %AM',
564         units     => [ "GP" ],
565         latency   => 1,
566         mode      => "mode_M",
567         modified_flags => $status_flags
568 },
569
570 OrMem8Bit => {
571         irn_flags => "R",
572         state     => "exc_pinned",
573         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
574         ins       => [ "base", "index", "mem", "val" ],
575         emit      => '. or%M %SB3, %AM',
576         units     => [ "GP" ],
577         latency   => 1,
578         mode      => "mode_M",
579         modified_flags => $status_flags
580 },
581
582 Xor => {
583         irn_flags => "R",
584         state     => "exc_pinned",
585         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
586                        out => [ "in_r4 in_r5", "flags", "none" ] },
587         ins       => [ "base", "index", "mem", "left", "right" ],
588         outs      => [ "res", "flags", "M" ],
589         am        => "source,binary",
590         emit      => '. xor%M %binop',
591         units     => [ "GP" ],
592         latency   => 1,
593         mode      => $mode_gp,
594         modified_flags => $status_flags
595 },
596
597 Xor0 => {
598         op_flags  => "c",
599         irn_flags => "R",
600         reg_req   => { out => [ "gp", "flags" ] },
601         outs      => [ "res", "flags" ],
602         emit      => ". xor%M %D0, %D0",
603         units     => [ "GP" ],
604         latency   => 1,
605         mode      => $mode_gp,
606         modified_flags => $status_flags
607 },
608
609 XorMem => {
610         irn_flags => "R",
611         state     => "exc_pinned",
612         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
613         ins       => [ "base", "index", "mem", "val" ],
614         emit      => '. xor%M %SI3, %AM',
615         units     => [ "GP" ],
616         latency   => 1,
617         mode      => "mode_M",
618         modified_flags => $status_flags
619 },
620
621 XorMem8Bit => {
622         irn_flags => "R",
623         state     => "exc_pinned",
624         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
625         ins       => [ "base", "index", "mem", "val" ],
626         emit      => '. xor%M %SB3, %AM',
627         units     => [ "GP" ],
628         latency   => 1,
629         mode      => "mode_M",
630         modified_flags => $status_flags
631 },
632
633 # not commutative operations
634
635 Sub => {
636         irn_flags => "R",
637         state     => "exc_pinned",
638         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
639                        out => [ "in_r4", "flags", "none" ] },
640         ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
641         outs      => [ "res", "flags", "M" ],
642         am        => "source,binary",
643         emit      => '. sub%M %binop',
644         units     => [ "GP" ],
645         latency   => 1,
646         mode      => $mode_gp,
647         modified_flags => $status_flags
648 },
649
650 SubMem => {
651         irn_flags => "R",
652         state     => "exc_pinned",
653         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
654         ins       => [ "base", "index", "mem", "subtrahend" ],
655         emit      => '. sub%M %SI3, %AM',
656         units     => [ "GP" ],
657         latency   => 1,
658         mode      => 'mode_M',
659         modified_flags => $status_flags
660 },
661
662 SubMem8Bit => {
663         irn_flags => "R",
664         state     => "exc_pinned",
665         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
666         ins       => [ "base", "index", "mem", "subtrahend" ],
667         emit      => '. sub%M %SB3, %AM',
668         units     => [ "GP" ],
669         latency   => 1,
670         mode      => 'mode_M',
671         modified_flags => $status_flags
672 },
673
674 Sbb => {
675         state     => "exc_pinned",
676         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
677                        out => [ "in_r4 !in_r5", "flags", "none" ] },
678         ins       => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
679         outs      => [ "res", "flags", "M" ],
680         am        => "source,binary",
681         emit      => '. sbb%M %binop',
682         units     => [ "GP" ],
683         latency   => 1,
684         mode      => $mode_gp,
685         modified_flags => $status_flags
686 },
687
688 Sbb0 => {
689         irn_flags => "R",
690         reg_req   => { in => [ "flags" ], out => [ "gp", "flags" ] },
691         outs      => [ "res", "flags" ],
692         emit      => ". sbb%M %D0, %D0",
693         units     => [ "GP" ],
694         latency   => 1,
695         mode      => $mode_gp,
696         modified_flags => $status_flags
697 },
698
699 l_Sub => {
700         reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
701         ins       => [ "minuend", "subtrahend" ],
702 },
703
704 l_Sbb => {
705         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
706         ins       => [ "minuend", "subtrahend", "eflags" ],
707 },
708
709 IDiv => {
710         op_flags  => "F|L",
711         state     => "exc_pinned",
712         reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
713                        out => [ "eax", "flags", "none", "edx", "none" ] },
714         ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
715         outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
716         am        => "source,unary",
717         emit      => ". idiv%M %unop3",
718         latency   => 25,
719         units     => [ "GP" ],
720         modified_flags => $status_flags
721 },
722
723 Div => {
724         op_flags  => "F|L",
725         state     => "exc_pinned",
726         reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
727                        out => [ "eax", "flags", "none", "edx", "none" ] },
728         ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
729         outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
730         am        => "source,unary",
731         emit      => ". div%M %unop3",
732         latency   => 25,
733         units     => [ "GP" ],
734         modified_flags => $status_flags
735 },
736
737 Shl => {
738         irn_flags => "R",
739         reg_req   => { in => [ "gp", "ecx" ],
740                        out => [ "in_r1 !in_r2", "flags" ] },
741         ins       => [ "val", "count" ],
742         outs      => [ "res", "flags" ],
743         emit      => '. shl%M %SB1, %S0',
744         units     => [ "GP" ],
745         latency   => 1,
746         mode      => $mode_gp,
747         modified_flags => $status_flags
748 },
749
750 ShlMem => {
751         irn_flags => "R",
752         state     => "exc_pinned",
753         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
754         ins       => [ "base", "index", "mem", "count" ],
755         emit      => '. shl%M %SB3, %AM',
756         units     => [ "GP" ],
757         latency   => 1,
758         mode      => "mode_M",
759         modified_flags => $status_flags
760 },
761
762 l_ShlDep => {
763         cmp_attr => "return 1;",
764         reg_req  => { in => [ "none", "none", "none" ], out => [ "none" ] },
765         ins      => [ "val", "count", "dep" ],
766 },
767
768 ShlD => {
769         irn_flags => "R",
770         reg_req   => { in => [ "gp", "gp", "ecx" ],
771                        out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
772         ins       => [ "val_high", "val_low", "count" ],
773         outs      => [ "res", "flags" ],
774         emit      => ". shld%M %SB2, %S1, %D0",
775         latency   => 6,
776         units     => [ "GP" ],
777         mode      => $mode_gp,
778         modified_flags => $status_flags
779 },
780
781 l_ShlD => {
782         cmp_attr  => "return 1;",
783         reg_req  => { in => [ "none", "none", "none" ], out => [ "none" ] },
784         ins       => [ "val_high", "val_low", "count" ],
785 },
786
787 Shr => {
788         irn_flags => "R",
789         reg_req   => { in => [ "gp", "ecx" ],
790                        out => [ "in_r1 !in_r2", "flags" ] },
791         ins       => [ "val", "count" ],
792         outs      => [ "res", "flags" ],
793         emit      => '. shr%M %SB1, %S0',
794         units     => [ "GP" ],
795         mode      => $mode_gp,
796         latency   => 1,
797         modified_flags => $status_flags
798 },
799
800 ShrMem => {
801         irn_flags => "R",
802         state     => "exc_pinned",
803         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
804         ins       => [ "base", "index", "mem", "count" ],
805         emit      => '. shr%M %SB3, %AM',
806         units     => [ "GP" ],
807         mode      => "mode_M",
808         latency   => 1,
809         modified_flags => $status_flags
810 },
811
812 l_ShrDep => {
813         cmp_attr  => "return 1;",
814         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
815         ins       => [ "val", "count", "dep" ],
816 },
817
818 ShrD => {
819         irn_flags => "R",
820         reg_req   => { in => [ "gp", "gp", "ecx" ],
821                        out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
822         ins       => [ "val_high", "val_low", "count" ],
823         outs      => [ "res", "flags" ],
824         emit      => ". shrd%M %SB2, %S1, %D0",
825         latency   => 6,
826         units     => [ "GP" ],
827         mode      => $mode_gp,
828         modified_flags => $status_flags
829 },
830
831 l_ShrD => {
832         cmp_attr  => "return 1;",
833         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
834         ins       => [ "val_high", "val_low", "count" ],
835 },
836
837 Sar => {
838         irn_flags => "R",
839         reg_req   => { in => [ "gp", "ecx" ],
840                        out => [ "in_r1 !in_r2", "flags" ] },
841         ins       => [ "val", "count" ],
842         outs      => [ "res", "flags" ],
843         emit      => '. sar%M %SB1, %S0',
844         units     => [ "GP" ],
845         latency   => 1,
846         mode      => $mode_gp,
847         modified_flags => $status_flags
848 },
849
850 SarMem => {
851         irn_flags => "R",
852         state     => "exc_pinned",
853         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
854         ins       => [ "base", "index", "mem", "count" ],
855         emit      => '. sar%M %SB3, %AM',
856         units     => [ "GP" ],
857         latency   => 1,
858         mode      => "mode_M",
859         modified_flags => $status_flags
860 },
861
862 l_SarDep => {
863         cmp_attr  => "return 1;",
864         ins       => [ "val", "count", "dep" ],
865         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
866 },
867
868 Ror => {
869         irn_flags => "R",
870         reg_req   => { in => [ "gp", "ecx" ],
871                        out => [ "in_r1 !in_r2", "flags" ] },
872         ins       => [ "val", "count" ],
873         outs      => [ "res", "flags" ],
874         emit      => '. ror%M %SB1, %S0',
875         units     => [ "GP" ],
876         latency   => 1,
877         mode      => $mode_gp,
878         modified_flags => $status_flags
879 },
880
881 RorMem => {
882         irn_flags => "R",
883         state     => "exc_pinned",
884         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
885         ins       => [ "base", "index", "mem", "count" ],
886         emit      => '. ror%M %SB3, %AM',
887         units     => [ "GP" ],
888         latency   => 1,
889         mode      => "mode_M",
890         modified_flags => $status_flags
891 },
892
893 Rol => {
894         irn_flags => "R",
895         reg_req   => { in => [ "gp", "ecx" ],
896                        out => [ "in_r1 !in_r2", "flags" ] },
897         ins       => [ "val", "count" ],
898         outs      => [ "res", "flags" ],
899         emit      => '. rol%M %SB1, %S0',
900         units     => [ "GP" ],
901         latency   => 1,
902         mode      => $mode_gp,
903         modified_flags => $status_flags
904 },
905
906 RolMem => {
907         irn_flags => "R",
908         state     => "exc_pinned",
909         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
910         ins       => [ "base", "index", "mem", "count" ],
911         emit      => '. rol%M %SB3, %AM',
912         units     => [ "GP" ],
913         latency   => 1,
914         mode      => "mode_M",
915         modified_flags => $status_flags
916 },
917
918 # unary operations
919
920 Neg => {
921         irn_flags => "R",
922         reg_req   => { in => [ "gp" ],
923                        out => [ "in_r1", "flags" ] },
924         emit      => '. neg%M %S0',
925         ins       => [ "val" ],
926         outs      => [ "res", "flags" ],
927         units     => [ "GP" ],
928         latency   => 1,
929         mode      => $mode_gp,
930         modified_flags => $status_flags
931 },
932
933 NegMem => {
934         irn_flags => "R",
935         state     => "exc_pinned",
936         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
937         ins       => [ "base", "index", "mem" ],
938         emit      => '. neg%M %AM',
939         units     => [ "GP" ],
940         latency   => 1,
941         mode      => "mode_M",
942         modified_flags => $status_flags
943 },
944
945 Minus64Bit => {
946         irn_flags => "R",
947         reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1", "in_r2" ] },
948         outs      => [ "low_res", "high_res" ],
949         units     => [ "GP" ],
950         latency   => 3,
951         modified_flags => $status_flags
952 },
953
954
955 Inc => {
956         irn_flags => "R",
957         reg_req   => { in => [ "gp" ],
958                        out => [ "in_r1", "flags" ] },
959         ins       => [ "val" ],
960         outs      => [ "res", "flags" ],
961         emit      => '. inc%M %S0',
962         units     => [ "GP" ],
963         mode      => $mode_gp,
964         latency   => 1,
965         modified_flags => $status_flags_wo_cf
966 },
967
968 IncMem => {
969         irn_flags => "R",
970         state     => "exc_pinned",
971         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
972         ins       => [ "base", "index", "mem" ],
973         emit      => '. inc%M %AM',
974         units     => [ "GP" ],
975         mode      => "mode_M",
976         latency   => 1,
977         modified_flags => $status_flags_wo_cf
978 },
979
980 Dec => {
981         irn_flags => "R",
982         reg_req   => { in => [ "gp" ],
983                        out => [ "in_r1", "flags" ] },
984         ins       => [ "val" ],
985         outs      => [ "res", "flags" ],
986         emit      => '. dec%M %S0',
987         units     => [ "GP" ],
988         mode      => $mode_gp,
989         latency   => 1,
990         modified_flags => $status_flags_wo_cf
991 },
992
993 DecMem => {
994         irn_flags => "R",
995         state     => "exc_pinned",
996         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
997         ins       => [ "base", "index", "mem" ],
998         emit      => '. dec%M %AM',
999         units     => [ "GP" ],
1000         mode      => "mode_M",
1001         latency   => 1,
1002         modified_flags => $status_flags_wo_cf
1003 },
1004
1005 Not => {
1006         irn_flags => "R",
1007         reg_req   => { in => [ "gp" ],
1008                        out => [ "in_r1", "flags" ] },
1009         ins       => [ "val" ],
1010         outs      => [ "res", "flags" ],
1011         emit      => '. not%M %S0',
1012         units     => [ "GP" ],
1013         latency   => 1,
1014         mode      => $mode_gp,
1015         # no flags modified
1016 },
1017
1018 NotMem => {
1019         irn_flags => "R",
1020         state     => "exc_pinned",
1021         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1022         ins       => [ "base", "index", "mem" ],
1023         emit      => '. not%M %AM',
1024         units     => [ "GP" ],
1025         latency   => 1,
1026         mode      => "mode_M",
1027         # no flags modified
1028 },
1029
1030 Cmc => {
1031         reg_req => { in => [ "flags" ], out => [ "flags" ] },
1032         emit    => '.cmc',
1033         units     => [ "GP" ],
1034         latency   => 1,
1035         mode      => $mode_flags,
1036         modified_flags => $status_flags
1037 },
1038
1039 Stc => {
1040         reg_req => { out => [ "flags" ] },
1041         emit    => '.stc',
1042         units     => [ "GP" ],
1043         latency   => 1,
1044         mode      => $mode_flags,
1045         modified_flags => $status_flags
1046 },
1047
1048 # other operations
1049
1050 Cmp => {
1051         irn_flags => "R",
1052         state     => "exc_pinned",
1053         reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ],
1054                        out => [ "flags", "none", "none" ] },
1055         ins       => [ "base", "index", "mem", "left", "right" ],
1056         outs      => [ "eflags", "unused", "M" ],
1057         am        => "source,binary",
1058         emit      => '. cmp%M %binop',
1059         attr      => "int ins_permuted, int cmp_unsigned",
1060         init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
1061                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1062         latency   => 1,
1063         units     => [ "GP" ],
1064         mode      => $mode_flags,
1065         modified_flags => $status_flags
1066 },
1067
1068 Cmp8Bit => {
1069         irn_flags => "R",
1070         state     => "exc_pinned",
1071         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] ,
1072                        out => [ "flags", "none", "none" ] },
1073         ins       => [ "base", "index", "mem", "left", "right" ],
1074         outs      => [ "eflags", "unused", "M" ],
1075         am        => "source,binary",
1076         emit      => '. cmpb %binop',
1077         attr      => "int ins_permuted, int cmp_unsigned",
1078         init_attr => "attr->data.ins_permuted   = ins_permuted;\n".
1079                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1080         latency   => 1,
1081         units     => [ "GP" ],
1082         mode      => $mode_flags,
1083         modified_flags => $status_flags
1084 },
1085
1086 Test => {
1087         irn_flags => "R",
1088         state     => "exc_pinned",
1089         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ] ,
1090                        out => [ "flags", "none", "none" ] },
1091         ins       => [ "base", "index", "mem", "left", "right" ],
1092         outs      => [ "eflags", "unused", "M" ],
1093         am        => "source,binary",
1094         emit      => '. test%M %binop',
1095         attr      => "int ins_permuted, int cmp_unsigned",
1096         init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1097                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1098         latency   => 1,
1099         units     => [ "GP" ],
1100         mode      => $mode_flags,
1101         modified_flags => $status_flags
1102 },
1103
1104 Test8Bit => {
1105         irn_flags => "R",
1106         state     => "exc_pinned",
1107         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] ,
1108                        out => [ "flags", "none", "none" ] },
1109         ins       => [ "base", "index", "mem", "left", "right" ],
1110         outs      => [ "eflags", "unused", "M" ],
1111         am        => "source,binary",
1112         emit      => '. testb %binop',
1113         attr      => "int ins_permuted, int cmp_unsigned",
1114         init_attr => "attr->data.ins_permuted = ins_permuted;\n".
1115                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
1116         latency   => 1,
1117         units     => [ "GP" ],
1118         mode      => $mode_flags,
1119         modified_flags => $status_flags
1120 },
1121
1122 Set => {
1123         #irn_flags => "R",
1124         reg_req   => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
1125         ins       => [ "eflags" ],
1126         attr_type => "ia32_condcode_attr_t",
1127         attr      => "pn_Cmp pnc, int ins_permuted",
1128         init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1129                       "\tset_ia32_ls_mode(res, mode_Bu);\n",
1130         emit      => '. set%CMP0 %DB0',
1131         latency   => 1,
1132         units     => [ "GP" ],
1133         mode      => $mode_gp,
1134 },
1135
1136 SetMem => {
1137         #irn_flags => "R",
1138         state     => "exc_pinned",
1139         reg_req   => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
1140         ins       => [ "base", "index", "mem","eflags" ],
1141         attr_type => "ia32_condcode_attr_t",
1142         attr      => "pn_Cmp pnc, int ins_permuted",
1143         init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
1144                       "\tset_ia32_ls_mode(res, mode_Bu);\n",
1145         emit      => '. set%CMP3 %AM',
1146         latency   => 1,
1147         units     => [ "GP" ],
1148         mode      => 'mode_M',
1149 },
1150
1151 CMov => {
1152         #irn_flags => "R",
1153         # (note: leave the false,true order intact to make it compatible with other
1154         #  ia32_binary ops)
1155         state     => "exc_pinned",
1156         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ],
1157                        out => [ "in_r4 in_r5", "flags", "none" ] },
1158         ins       => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
1159         outs      => [ "res", "flags", "M" ],
1160         am        => "source,binary",
1161         attr_type => "ia32_condcode_attr_t",
1162         attr      => "int ins_permuted, pn_Cmp pnc",
1163         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
1164         latency   => 1,
1165         units     => [ "GP" ],
1166         mode      => $mode_gp,
1167 },
1168
1169 Jcc => {
1170         state     => "pinned",
1171         op_flags  => "L|X|Y",
1172         reg_req   => { in  => [ "eflags" ], out => [ "none", "none" ] },
1173         ins       => [ "eflags" ],
1174         outs      => [ "false", "true" ],
1175         attr_type => "ia32_condcode_attr_t",
1176         attr      => "pn_Cmp pnc",
1177         latency   => 2,
1178         units     => [ "BRANCH" ],
1179 },
1180
1181 SwitchJmp => {
1182         state     => "pinned",
1183         op_flags  => "L|X|Y",
1184         reg_req   => { in => [ "gp" ] },
1185         mode      => "mode_T",
1186         attr_type => "ia32_condcode_attr_t",
1187         attr      => "long pnc",
1188         latency   => 3,
1189         units     => [ "BRANCH" ],
1190         modified_flags => $status_flags,
1191         init_attr => "info->out_infos = NULL;",
1192 },
1193
1194 Jmp => {
1195         state    => "pinned",
1196         op_flags => "X",
1197         reg_req  => { out => [ "none" ] },
1198         latency  => 1,
1199         units    => [ "BRANCH" ],
1200         mode     => "mode_X",
1201 },
1202
1203 IJmp => {
1204         state     => "pinned",
1205         op_flags  => "X",
1206         reg_req   => { in => [ "gp", "gp", "none", "gp" ] },
1207         ins       => [ "base", "index", "mem", "target" ],
1208         am        => "source,unary",
1209         emit      => '. jmp *%unop3',
1210         latency   => 1,
1211         units     => [ "BRANCH" ],
1212         mode      => "mode_X",
1213 },
1214
1215 Const => {
1216         op_flags  => "c",
1217         irn_flags => "R",
1218         reg_req   => { out => [ "gp" ] },
1219         units     => [ "GP" ],
1220         attr      => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
1221         attr_type => "ia32_immediate_attr_t",
1222         latency   => 1,
1223         mode      => $mode_gp,
1224 },
1225
1226 GetEIP => {
1227         op_flags => "c",
1228         reg_req  => { out => [ "gp" ] },
1229         units    => [ "GP" ],
1230         latency  => 5,
1231         mode     => $mode_gp,
1232         modified_flags => $status_flags,
1233 },
1234
1235 Unknown_GP => {
1236         state     => "pinned",
1237         op_flags  => "c|NB",
1238         reg_req   => { out => [ "gp_UKNWN:I" ] },
1239         units     => [],
1240         emit      => "",
1241         latency   => 0,
1242         mode      => $mode_gp
1243 },
1244
1245 Unknown_VFP => {
1246         state     => "pinned",
1247         op_flags  => "c|NB",
1248         reg_req   => { out => [ "vfp_UKNWN:I" ] },
1249         units     => [],
1250         emit      => "",
1251         mode      => "mode_E",
1252         latency   => 0,
1253         attr_type => "ia32_x87_attr_t",
1254 },
1255
1256 Unknown_XMM => {
1257         state     => "pinned",
1258         op_flags  => "c|NB",
1259         reg_req   => { out => [ "xmm_UKNWN:I" ] },
1260         units     => [],
1261         emit      => "",
1262         latency   => 0,
1263         mode      => $mode_xmm
1264 },
1265
1266 NoReg_GP => {
1267         state     => "pinned",
1268         op_flags  => "c|NB|NI",
1269         reg_req   => { out => [ "gp_NOREG:I" ] },
1270         units     => [],
1271         emit      => "",
1272         latency   => 0,
1273         mode      => $mode_gp
1274 },
1275
1276 NoReg_VFP => {
1277         state     => "pinned",
1278         op_flags  => "c|NB|NI",
1279         reg_req   => { out => [ "vfp_NOREG:I" ] },
1280         units     => [],
1281         emit      => "",
1282         mode      => "mode_E",
1283         latency   => 0,
1284         attr_type => "ia32_x87_attr_t",
1285 },
1286
1287 NoReg_XMM => {
1288         state     => "pinned",
1289         op_flags  => "c|NB|NI",
1290         reg_req   => { out => [ "xmm_NOREG:I" ] },
1291         units     => [],
1292         emit      => "",
1293         latency   => 0,
1294         mode      => "mode_E"
1295 },
1296
1297 ChangeCW => {
1298         state     => "pinned",
1299         op_flags  => "c",
1300         reg_req   => { out => [ "fpcw:I" ] },
1301         mode      => $mode_fpcw,
1302         latency   => 3,
1303         units     => [ "GP" ],
1304         modified_flags => $fpcw_flags
1305 },
1306
1307 FldCW => {
1308         op_flags  => "L|F",
1309         state     => "pinned",
1310         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] },
1311         ins       => [ "base", "index", "mem" ],
1312         latency   => 5,
1313         emit      => ". fldcw %AM",
1314         mode      => $mode_fpcw,
1315         units     => [ "GP" ],
1316         modified_flags => $fpcw_flags
1317 },
1318
1319 FnstCW => {
1320         op_flags  => "L|F",
1321         state     => "pinned",
1322         reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1323         ins       => [ "base", "index", "mem", "fpcw" ],
1324         latency   => 5,
1325         emit      => ". fnstcw %AM",
1326         mode      => "mode_M",
1327         units     => [ "GP" ],
1328 },
1329
1330 FnstCWNOP => {
1331         op_flags  => "L|F",
1332         state     => "pinned",
1333         reg_req   => { in => [ "fp_cw" ], out => [ "none" ] },
1334         ins       => [ "fpcw" ],
1335         latency   => 0,
1336         emit      => "",
1337         mode      => "mode_M",
1338 },
1339
1340 Cltd => {
1341         # we should not rematrialize this node. It has very strict constraints.
1342         reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
1343         ins       => [ "val", "clobbered" ],
1344         emit      => '. cltd',
1345         latency   => 1,
1346         mode      => $mode_gp,
1347         units     => [ "GP" ],
1348 },
1349
1350 # Load / Store
1351 #
1352 # Note that we add additional latency values depending on address mode, so a
1353 # lateny of 0 for load is correct
1354
1355 Load => {
1356         op_flags  => "L|F",
1357         state     => "exc_pinned",
1358         reg_req   => { in => [ "gp", "gp", "none" ],
1359                        out => [ "gp", "none", "none", "none" ] },
1360         ins       => [ "base", "index", "mem" ],
1361         outs      => [ "res", "unused", "M", "X_exc" ],
1362         latency   => 0,
1363         emit      => ". mov%EX%.l %AM, %D0",
1364         units     => [ "GP" ],
1365 },
1366
1367 Store => {
1368         op_flags  => "L|F",
1369         state     => "exc_pinned",
1370         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] },
1371         ins       => [ "base", "index", "mem", "val" ],
1372         outs      => [ "M", "X_exc" ],
1373         emit      => '. mov%M %SI3, %AM',
1374         latency   => 2,
1375         units     => [ "GP" ],
1376         mode      => "mode_M",
1377 },
1378
1379 Store8Bit => {
1380         op_flags  => "L|F",
1381         state     => "exc_pinned",
1382         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] },
1383         ins       => [ "base", "index", "mem", "val" ],
1384         outs      => [ "M", "X_exc" ],
1385         emit      => '. mov%M %SB3, %AM',
1386         latency   => 2,
1387         units     => [ "GP" ],
1388         mode      => "mode_M",
1389 },
1390
1391 Lea => {
1392         irn_flags => "R",
1393         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
1394         ins       => [ "base", "index" ],
1395         emit      => '. leal %AM, %D0',
1396         latency   => 2,
1397         units     => [ "GP" ],
1398         mode      => $mode_gp,
1399 # lea doesn't modify the flags, but setting this seems advantageous since it
1400 # increases chances that the Lea is transformed back to an Add
1401         modified_flags => 1,
1402 },
1403
1404 Push => {
1405         state     => "exc_pinned",
1406         reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp:I|S", "none" ] },
1407         ins       => [ "base", "index", "mem", "val", "stack" ],
1408         emit      => '. push%M %unop3',
1409         outs      => [ "stack", "M" ],
1410         am        => "source,unary",
1411         latency   => 2,
1412         units     => [ "GP" ],
1413 },
1414
1415 Pop => {
1416         state     => "exc_pinned",
1417         reg_req   => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp:I|S" ] },
1418         ins       => [ "mem", "stack" ],
1419         outs      => [ "res", "M", "unused", "stack" ],
1420         emit      => '. pop%M %D0',
1421         latency   => 3, # Pop is more expensive than Push on Athlon
1422         units     => [ "GP" ],
1423 },
1424
1425 PopEbp => {
1426         state     => "exc_pinned",
1427         reg_req   => { in => [ "none", "esp" ], out => [ "ebp:I", "none", "none", "esp:I|S" ] },
1428         ins       => [ "mem", "stack" ],
1429         outs      => [ "res", "M", "unused", "stack" ],
1430         emit      => '. pop%M %D0',
1431         latency   => 3, # Pop is more expensive than Push on Athlon
1432         units     => [ "GP" ],
1433 },
1434
1435 PopMem => {
1436         state     => "exc_pinned",
1437         reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp:I|S" ] },
1438         ins       => [ "base", "index", "mem", "stack" ],
1439         outs      => [ "unused0", "M", "unused1", "stack" ],
1440         emit      => '. pop%M %AM',
1441         latency   => 3, # Pop is more expensive than Push on Athlon
1442         units     => [ "GP" ],
1443 },
1444
1445 Enter => {
1446         reg_req   => { in => [ "esp" ], out => [ "ebp", "esp:I|S", "none" ] },
1447         emit      => '. enter',
1448         outs      => [ "frame", "stack", "M" ],
1449         latency   => 15,
1450         units     => [ "GP" ],
1451 },
1452
1453 Leave => {
1454         reg_req   => { in => [ "ebp" ], out => [ "ebp:I", "esp:I|S" ] },
1455         emit      => '. leave',
1456         outs      => [ "frame", "stack" ],
1457         latency   => 3,
1458         units     => [ "GP" ],
1459 },
1460
1461 AddSP => {
1462         state     => "pinned",
1463         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "none" ] },
1464         ins       => [ "base", "index", "mem", "stack", "size" ],
1465         am        => "source,binary",
1466         emit      => '. addl %binop',
1467         latency   => 1,
1468         outs      => [ "stack", "M" ],
1469         units     => [ "GP" ],
1470         modified_flags => $status_flags
1471 },
1472
1473 SubSP => {
1474         state     => "pinned",
1475         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "gp", "none" ] },
1476         ins       => [ "base", "index", "mem", "stack", "size" ],
1477         am        => "source,binary",
1478         emit      => ". subl %binop\n".
1479                      ". movl %%esp, %D1",
1480         latency   => 2,
1481         outs      => [ "stack", "addr", "M" ],
1482         units     => [ "GP" ],
1483         modified_flags => $status_flags
1484 },
1485
1486 RepPrefix => {
1487         op_flags  => "K",
1488         state     => "pinned",
1489         mode      => "mode_M",
1490         emit      => ". rep",
1491         latency   => 0,
1492 },
1493
1494 LdTls => {
1495         irn_flags => "R",
1496         reg_req   => { out => [ "gp" ] },
1497         units     => [ "GP" ],
1498         latency   => 1,
1499 },
1500
1501 #
1502 # BT supports source address mode, but this is unused yet
1503 #
1504 Bt => {
1505         irn_flags => "R",
1506         state     => "exc_pinned",
1507         reg_req   => { in => [ "gp", "gp" ], out => [ "flags" ] },
1508         ins       => [ "left", "right" ],
1509         emit      => '. bt%M %S1, %S0',
1510         units     => [ "GP" ],
1511         latency   => 1,
1512         mode      => $mode_flags,
1513         modified_flags => $status_flags  # only CF is set, but the other flags are undefined
1514 },
1515
1516 Bsf => {
1517         irn_flags => "R",
1518         state     => "exc_pinned",
1519         reg_req   => { in => [ "gp", "gp", "none", "gp" ],
1520                        out => [ "gp", "flags", "none" ] },
1521         ins       => [ "base", "index", "mem", "operand" ],
1522         outs      => [ "res", "flags", "M" ],
1523         am        => "source,binary",
1524         emit      => '. bsf%M %unop3, %D0',
1525         units     => [ "GP" ],
1526         latency   => 1,
1527         mode      => $mode_gp,
1528         modified_flags => $status_flags
1529 },
1530
1531 Bsr => {
1532         irn_flags => "R",
1533         state     => "exc_pinned",
1534         reg_req   => { in => [ "gp", "gp", "none", "gp" ],
1535                        out => [ "gp", "flags", "none" ] },
1536         ins       => [ "base", "index", "mem", "operand" ],
1537         outs      => [ "res", "flags", "M" ],
1538         am        => "source,binary",
1539         emit      => '. bsr%M %unop3, %D0',
1540         units     => [ "GP" ],
1541         latency   => 1,
1542         mode      => $mode_gp,
1543         modified_flags => $status_flags
1544 },
1545
1546 #
1547 # SSE4.2 or SSE4a popcnt instruction
1548 #
1549 Popcnt => {
1550         irn_flags => "R",
1551         state     => "exc_pinned",
1552         reg_req   => { in => [ "gp", "gp", "none", "gp" ],
1553                        out => [ "gp", "flags", "none" ] },
1554         ins       => [ "base", "index", "mem", "operand" ],
1555         outs      => [ "res", "flags", "M" ],
1556         am        => "source,binary",
1557         emit      => '. popcnt%M %unop3, %D0',
1558         units     => [ "GP" ],
1559         latency   => 1,
1560         mode      => $mode_gp,
1561         modified_flags => $status_flags
1562 },
1563
1564 Call => {
1565         state     => "exc_pinned",
1566         reg_req   => {
1567                 in  => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ],
1568                 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" ]
1569         },
1570         ins       => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ],
1571         outs      => [ "stack", "fpcw", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ],
1572         attr_type => "ia32_call_attr_t",
1573         attr      => "unsigned pop, ir_type *call_tp",
1574         am        => "source,unary",
1575         units     => [ "BRANCH" ],
1576         latency   => 4, # random number
1577         modified_flags => $status_flags
1578 },
1579
1580 #
1581 # a Helper node for frame-climbing, needed for __builtin_(frame|return)_address
1582 #
1583 # PS: try gcc __builtin_frame_address(100000) :-)
1584 #
1585 ClimbFrame => {
1586         reg_req   => { in => [ "gp", "gp", "gp"], out => [ "in_r3" ] },
1587         ins       => [ "frame", "cnt", "tmp" ],
1588         outs      => [ "res" ],
1589         latency   => 4, # random number
1590         attr_type => "ia32_climbframe_attr_t",
1591         attr      => "unsigned count",
1592         units     => [ "GP" ],
1593         mode      => $mode_gp
1594 },
1595
1596 #
1597 # bswap
1598 #
1599 Bswap => {
1600         irn_flags => "R",
1601         reg_req   => { in => [ "gp" ],
1602                        out => [ "in_r1" ] },
1603         emit      => '. bswap%M %S0',
1604         ins       => [ "val" ],
1605         units     => [ "GP" ],
1606         latency   => 1,
1607         mode      => $mode_gp,
1608 },
1609
1610 #
1611 # bswap16, use xchg here
1612 #
1613 Bswap16 => {
1614         irn_flags => "R",
1615         reg_req   => { in => [ "eax ebx ecx edx" ],
1616                        out => [ "in_r1" ] },
1617         emit      => '. xchg %SB0, %SH0',
1618         ins       => [ "val" ],
1619         units     => [ "GP" ],
1620         latency   => 1,
1621         mode      => $mode_gp,
1622 },
1623
1624 #
1625 # BreakPoint
1626 #
1627 Breakpoint => {
1628         state     => "pinned",
1629         reg_req   => { in => [ "none" ], out => [ "none" ] },
1630         ins       => [ "mem" ],
1631         latency   => 0,
1632         emit      => ". int3",
1633         units     => [ "GP" ],
1634         mode      => mode_M,
1635 },
1636
1637 #
1638 # Undefined Instruction on ALL x86 CPU's
1639 #
1640 UD2 => {
1641         state     => "pinned",
1642         reg_req   => { in => [ "none" ], out => [ "none" ] },
1643         ins       => [ "mem" ],
1644         latency   => 0,
1645         emit      => ". .value  0x0b0f",
1646         units     => [ "GP" ],
1647         mode      => mode_M,
1648 },
1649
1650 #
1651 # outport
1652 #
1653 Outport => {
1654         irn_flags => "R",
1655         state     => "pinned",
1656         reg_req   => { in => [ "edx", "eax", "none" ], out => [ "none" ] },
1657         ins       => [ "port", "value", "mem" ],
1658         emit      => '. out%M %SS0, %SI1',
1659         units     => [ "GP" ],
1660         latency   => 1,
1661         mode      => mode_M,
1662         modified_flags => $status_flags
1663 },
1664
1665 #
1666 # inport
1667 #
1668 Inport => {
1669         irn_flags => "R",
1670         state     => "pinned",
1671         reg_req   => { in => [ "edx", "none" ], out => [ "eax", "none" ] },
1672         ins       => [ "port", "mem" ],
1673         outs      => [ "res", "M" ],
1674         emit      => '. in%M %DS0, %SS0',
1675         units     => [ "GP" ],
1676         latency   => 1,
1677         mode      => mode_T,
1678         modified_flags => $status_flags
1679 },
1680
1681 #
1682 # Intel style prefetching
1683 #
1684 Prefetch0 => {
1685         op_flags  => "L|F",
1686         state     => "exc_pinned",
1687         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1688         ins       => [ "base", "index", "mem" ],
1689         outs      => [ "M" ],
1690         latency   => 0,
1691         emit      => ". prefetcht0 %AM",
1692         units     => [ "GP" ],
1693 },
1694
1695 Prefetch1 => {
1696         op_flags  => "L|F",
1697         state     => "exc_pinned",
1698         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1699         ins       => [ "base", "index", "mem" ],
1700         outs      => [ "M" ],
1701         latency   => 0,
1702         emit      => ". prefetcht1 %AM",
1703         units     => [ "GP" ],
1704 },
1705
1706 Prefetch2 => {
1707         op_flags  => "L|F",
1708         state     => "exc_pinned",
1709         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1710         ins       => [ "base", "index", "mem" ],
1711         outs      => [ "M" ],
1712         latency   => 0,
1713         emit      => ". prefetcht2 %AM",
1714         units     => [ "GP" ],
1715 },
1716
1717 PrefetchNTA => {
1718         op_flags  => "L|F",
1719         state     => "exc_pinned",
1720         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1721         ins       => [ "base", "index", "mem" ],
1722         outs      => [ "M" ],
1723         latency   => 0,
1724         emit      => ". prefetchnta %AM",
1725         units     => [ "GP" ],
1726 },
1727
1728 #
1729 # 3DNow! prefetch instructions
1730 #
1731 Prefetch => {
1732         op_flags  => "L|F",
1733         state     => "exc_pinned",
1734         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1735         ins       => [ "base", "index", "mem" ],
1736         outs      => [ "M" ],
1737         latency   => 0,
1738         emit      => ". prefetch %AM",
1739         units     => [ "GP" ],
1740 },
1741
1742 PrefetchW => {
1743         op_flags  => "L|F",
1744         state     => "exc_pinned",
1745         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
1746         ins       => [ "base", "index", "mem" ],
1747         outs      => [ "M" ],
1748         latency   => 0,
1749         emit      => ". prefetchw %AM",
1750         units     => [ "GP" ],
1751 },
1752
1753 #-----------------------------------------------------------------------------#
1754 #   _____ _____ ______    __ _             _                     _            #
1755 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
1756 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1757 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1758 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1759 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1760 #-----------------------------------------------------------------------------#
1761
1762 # produces a 0/+0.0
1763 xZero => {
1764         irn_flags => "R",
1765         reg_req   => { out => [ "xmm" ] },
1766         emit      => '. xorp%XSD %D0, %D0',
1767         latency   => 3,
1768         units     => [ "SSE" ],
1769         mode      => $mode_xmm
1770 },
1771
1772 xPzero => {
1773         irn_flags => "R",
1774         reg_req   => { out => [ "xmm" ] },
1775         emit      => '. pxor %D0, %D0',
1776         latency   => 3,
1777         units     => [ "SSE" ],
1778         mode      => $mode_xmm
1779 },
1780
1781 # produces all 1 bits
1782 xAllOnes => {
1783         irn_flags => "R",
1784         reg_req   => { out => [ "xmm" ] },
1785         emit      => '. pcmpeqb %D0, %D0',
1786         latency   => 3,
1787         units     => [ "SSE" ],
1788         mode      => $mode_xmm
1789 },
1790
1791 # integer shift left, dword
1792 xPslld => {
1793         irn_flags => "R",
1794         reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1795         emit      => '. pslld %SI1, %D0',
1796         latency   => 3,
1797         units     => [ "SSE" ],
1798         mode      => $mode_xmm
1799 },
1800
1801 # integer shift left, qword
1802 xPsllq => {
1803         irn_flags => "R",
1804         reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1805         emit      => '. psllq %SI1, %D0',
1806         latency   => 3,
1807         units     => [ "SSE" ],
1808         mode      => $mode_xmm
1809 },
1810
1811 # integer shift right, dword
1812 xPsrld => {
1813         irn_flags => "R",
1814         reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
1815         emit      => '. psrld %SI1, %D0',
1816         latency   => 1,
1817         units     => [ "SSE" ],
1818         mode      => $mode_xmm
1819 },
1820
1821 # mov from integer to SSE register
1822 xMovd  => {
1823         irn_flags => "R",
1824         reg_req   => { in => [ "gp" ], out => [ "xmm" ] },
1825         emit      => '. movd %S0, %D0',
1826         latency   => 1,
1827         units     => [ "SSE" ],
1828         mode      => $mode_xmm
1829 },
1830
1831 # commutative operations
1832
1833 xAdd => {
1834         irn_flags => "R",
1835         state     => "exc_pinned",
1836         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1837                        out => [ "in_r4 in_r5", "flags", "none" ] },
1838         ins       => [ "base", "index", "mem", "left", "right" ],
1839         outs      => [ "res", "flags", "M" ],
1840         am        => "source,binary",
1841         emit      => '. add%XXM %binop',
1842         latency   => 4,
1843         units     => [ "SSE" ],
1844         mode      => $mode_xmm
1845 },
1846
1847 xMul => {
1848         irn_flags => "R",
1849         state     => "exc_pinned",
1850         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1851                        out => [ "in_r4 in_r5", "flags", "none" ] },
1852         ins       => [ "base", "index", "mem", "left", "right" ],
1853         outs      => [ "res", "flags", "M" ],
1854         am        => "source,binary",
1855         emit      => '. mul%XXM %binop',
1856         latency   => 4,
1857         units     => [ "SSE" ],
1858         mode      => $mode_xmm
1859 },
1860
1861 xMax => {
1862         irn_flags => "R",
1863         state     => "exc_pinned",
1864         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1865                        out => [ "in_r4 in_r5", "flags", "none" ] },
1866         ins       => [ "base", "index", "mem", "left", "right" ],
1867         outs      => [ "res", "flags", "M" ],
1868         am        => "source,binary",
1869         emit      => '. max%XXM %binop',
1870         latency   => 2,
1871         units     => [ "SSE" ],
1872         mode      => $mode_xmm
1873 },
1874
1875 xMin => {
1876         irn_flags => "R",
1877         state     => "exc_pinned",
1878         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1879                        out => [ "in_r4 in_r5", "flags", "none" ] },
1880         ins       => [ "base", "index", "mem", "left", "right" ],
1881         outs      => [ "res", "flags", "M" ],
1882         am        => "source,binary",
1883         emit      => '. min%XXM %binop',
1884         latency   => 2,
1885         units     => [ "SSE" ],
1886         mode      => $mode_xmm
1887 },
1888
1889 xAnd => {
1890         irn_flags => "R",
1891         state     => "exc_pinned",
1892         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1893                        out => [ "in_r4 in_r5", "flags", "none" ] },
1894         ins       => [ "base", "index", "mem", "left", "right" ],
1895         outs      => [ "res", "flags", "M" ],
1896         am        => "source,binary",
1897         emit      => '. andp%XSD %binop',
1898         latency   => 3,
1899         units     => [ "SSE" ],
1900         mode      => $mode_xmm
1901 },
1902
1903 xOr => {
1904         irn_flags => "R",
1905         state     => "exc_pinned",
1906         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1907                        out => [ "in_r4 in_r5", "flags", "none" ] },
1908         ins       => [ "base", "index", "mem", "left", "right" ],
1909         outs      => [ "res", "flags", "M" ],
1910         am        => "source,binary",
1911         emit      => '. orp%XSD %binop',
1912         latency   => 3,
1913         units     => [ "SSE" ],
1914         mode      => $mode_xmm
1915 },
1916
1917 xXor => {
1918         irn_flags => "R",
1919         state     => "exc_pinned",
1920         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1921                        out => [ "in_r4 in_r5", "flags", "none" ] },
1922         ins       => [ "base", "index", "mem", "left", "right" ],
1923         outs      => [ "res", "flags", "M" ],
1924         am        => "source,binary",
1925         emit      => '. xorp%XSD %binop',
1926         latency   => 3,
1927         units     => [ "SSE" ],
1928         mode      => $mode_xmm
1929 },
1930
1931 # not commutative operations
1932
1933 xAndNot => {
1934         irn_flags => "R",
1935         state     => "exc_pinned",
1936         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1937                        out => [ "in_r4 !in_r5", "flags", "none" ] },
1938         ins       => [ "base", "index", "mem", "left", "right" ],
1939         outs      => [ "res", "flags", "M" ],
1940         am        => "source,binary",
1941         emit      => '. andnp%XSD %binop',
1942         latency   => 3,
1943         units     => [ "SSE" ],
1944         mode      => $mode_xmm
1945 },
1946
1947 xSub => {
1948         irn_flags => "R",
1949         state     => "exc_pinned",
1950         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1951                        out => [ "in_r4", "flags", "none" ] },
1952         ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
1953         outs      => [ "res", "flags", "M" ],
1954         am        => "source,binary",
1955         emit      => '. sub%XXM %binop',
1956         latency   => 4,
1957         units     => [ "SSE" ],
1958         mode      => $mode_xmm
1959 },
1960
1961 xDiv => {
1962         irn_flags => "R",
1963         state     => "exc_pinned",
1964         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1965                        out => [ "in_r4 !in_r5", "flags", "none" ] },
1966         ins       => [ "base", "index", "mem", "dividend", "divisor" ],
1967         outs      => [ "res", "flags", "M" ],
1968         am        => "source,binary",
1969         emit      => '. div%XXM %binop',
1970         latency   => 16,
1971         units     => [ "SSE" ],
1972 },
1973
1974 # other operations
1975
1976 Ucomi => {
1977         irn_flags => "R",
1978         state     => "exc_pinned",
1979         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ],
1980                        out => [ "eflags" ] },
1981         ins       => [ "base", "index", "mem", "left", "right" ],
1982         outs      => [ "flags" ],
1983         am        => "source,binary",
1984         attr      => "int ins_permuted",
1985         init_attr => "attr->data.ins_permuted = ins_permuted;",
1986         emit      => ' .ucomi%XXM %binop',
1987         latency   => 3,
1988         units     => [ "SSE" ],
1989         mode      => $mode_flags,
1990         modified_flags => 1,
1991 },
1992
1993 # Load / Store
1994
1995 xLoad => {
1996         op_flags  => "L|F",
1997         state     => "exc_pinned",
1998         reg_req   => { in => [ "gp", "gp", "none" ],
1999                        out => [ "xmm", "none", "none", "none" ] },
2000         ins       => [ "base", "index", "mem" ],
2001         outs      => [ "res", "unused", "M", "X_exc" ],
2002         emit      => '. mov%XXM %AM, %D0',
2003         attr      => "ir_mode *load_mode",
2004         init_attr => "attr->ls_mode = load_mode;",
2005         latency   => 0,
2006         units     => [ "SSE" ],
2007 },
2008
2009 xStore => {
2010         op_flags => "L|F",
2011         state    => "exc_pinned",
2012         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] },
2013         ins       => [ "base", "index", "mem", "val" ],
2014         outs      => [ "M", "X_exc" ],
2015         emit     => '. mov%XXM %S3, %AM',
2016         latency  => 0,
2017         units    => [ "SSE" ],
2018         mode     => "mode_M",
2019 },
2020
2021 xStoreSimple => {
2022         op_flags => "L|F",
2023         state    => "exc_pinned",
2024         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none" ] },
2025         ins      => [ "base", "index", "mem", "val" ],
2026         outs     => [ "M" ],
2027         emit     => '. mov%XXM %S3, %AM',
2028         latency  => 0,
2029         units    => [ "SSE" ],
2030         mode     => "mode_M",
2031 },
2032
2033 CvtSI2SS => {
2034         op_flags => "L|F",
2035         state     => "exc_pinned",
2036         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
2037         ins      => [ "base", "index", "mem", "val" ],
2038         am       => "source,unary",
2039         emit     => '. cvtsi2ss %unop3, %D0',
2040         latency  => 2,
2041         units    => [ "SSE" ],
2042         mode     => $mode_xmm
2043 },
2044
2045 CvtSI2SD => {
2046         op_flags => "L|F",
2047         state     => "exc_pinned",
2048         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
2049         ins      => [ "base", "index", "mem", "val" ],
2050         am       => "source,unary",
2051         emit     => '. cvtsi2sd %unop3, %D0',
2052         latency  => 2,
2053         units    => [ "SSE" ],
2054         mode     => $mode_xmm
2055 },
2056
2057
2058 l_LLtoFloat => {
2059         op_flags => "L|F",
2060         cmp_attr => "return 1;",
2061         ins      => [ "val_high", "val_low" ],
2062         reg_req  => { in => [ "none", "none" ], out => [ "none" ] }
2063 },
2064
2065 l_FloattoLL => {
2066         op_flags => "L|F",
2067         cmp_attr => "return 1;",
2068         ins      => [ "val" ],
2069         outs     => [ "res_high", "res_low" ],
2070         reg_req  => { in => [ "none" ], out => [ "none", "none" ] }
2071 },
2072
2073 # CopyB
2074
2075 CopyB => {
2076         op_flags  => "F|H",
2077         state     => "pinned",
2078         reg_req   => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
2079         outs      => [ "DST", "SRC", "CNT", "M" ],
2080         attr_type => "ia32_copyb_attr_t",
2081         attr      => "unsigned size",
2082         units     => [ "GP" ],
2083         latency  => 3,
2084 # we don't care about this flag, so no need to mark this node
2085 #       modified_flags => [ "DF" ]
2086 },
2087
2088 CopyB_i => {
2089         op_flags  => "F|H",
2090         state     => "pinned",
2091         reg_req   => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
2092         outs      => [ "DST", "SRC", "M" ],
2093         attr_type => "ia32_copyb_attr_t",
2094         attr      => "unsigned size",
2095         units     => [ "GP" ],
2096         latency  => 3,
2097 # we don't care about this flag, so no need to mark this node
2098 #       modified_flags => [ "DF" ]
2099 },
2100
2101 # Conversions
2102
2103 Cwtl => {
2104         state     => "exc_pinned",
2105         reg_req   => { in => [ "eax" ], out => [ "eax" ] },
2106         ins       => [ "val" ],
2107         outs      => [ "res" ],
2108         emit      => '. cwtl',
2109         units     => [ "GP" ],
2110         latency   => 1,
2111         mode      => $mode_gp,
2112 },
2113
2114 Conv_I2I => {
2115         state     => "exc_pinned",
2116         reg_req   => { in => [ "gp", "gp", "none", "gp" ],
2117                        out => [ "gp", "none", "none" ] },
2118         ins       => [ "base", "index", "mem", "val" ],
2119         outs      => [ "res", "flags", "M" ],
2120         am        => "source,unary",
2121         units     => [ "GP" ],
2122         latency   => 1,
2123         attr      => "ir_mode *smaller_mode",
2124         init_attr => "attr->ls_mode = smaller_mode;",
2125         mode      => $mode_gp,
2126 },
2127
2128 Conv_I2I8Bit => {
2129         state     => "exc_pinned",
2130         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ],
2131                        out => [ "gp", "none", "none" ] },
2132         ins       => [ "base", "index", "mem", "val" ],
2133         outs      => [ "res", "flags", "M" ],
2134         am        => "source,unary",
2135         units     => [ "GP" ],
2136         latency   => 1,
2137         attr      => "ir_mode *smaller_mode",
2138         init_attr => "attr->ls_mode = smaller_mode;",
2139         mode      => $mode_gp,
2140 },
2141
2142 Conv_I2FP => {
2143         state     => "exc_pinned",
2144         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
2145         ins       => [ "base", "index", "mem", "val" ],
2146         am        => "source,unary",
2147         latency   => 10,
2148         units     => [ "SSE" ],
2149         mode      => $mode_xmm,
2150 },
2151
2152 Conv_FP2I => {
2153         state     => "exc_pinned",
2154         reg_req   => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
2155         ins       => [ "base", "index", "mem", "val" ],
2156         am        => "source,unary",
2157         latency   => 10,
2158         units     => [ "SSE" ],
2159         mode      => $mode_gp,
2160 },
2161
2162 Conv_FP2FP => {
2163         state     => "exc_pinned",
2164         reg_req   => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
2165         ins       => [ "base", "index", "mem", "val" ],
2166         am        => "source,unary",
2167         latency   => 8,
2168         units     => [ "SSE" ],
2169         mode      => $mode_xmm,
2170 },
2171
2172 #----------------------------------------------------------#
2173 #        _      _               _    __ _             _    #
2174 #       (_)    | |             | |  / _| |           | |   #
2175 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
2176 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
2177 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
2178 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
2179 #                 | |                                      #
2180 #  _ __   ___   __| | ___  ___                             #
2181 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
2182 # | | | | (_) | (_| |  __/\__ \                            #
2183 # |_| |_|\___/ \__,_|\___||___/                            #
2184 #----------------------------------------------------------#
2185
2186 # rematerialisation disabled for all float nodes for now, because the fpcw
2187 # handler runs before spilling and we might end up with wrong fpcw then
2188
2189 vfadd => {
2190 #       irn_flags => "R",
2191         state     => "exc_pinned",
2192         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2193         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
2194         am        => "source,binary",
2195         latency   => 4,
2196         units     => [ "VFP" ],
2197         mode      => "mode_E",
2198         attr_type => "ia32_x87_attr_t",
2199 },
2200
2201 vfmul => {
2202 #       irn_flags => "R",
2203         state     => "exc_pinned",
2204         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2205         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
2206         am        => "source,binary",
2207         latency   => 4,
2208         units     => [ "VFP" ],
2209         mode      => "mode_E",
2210         attr_type => "ia32_x87_attr_t",
2211 },
2212
2213 vfsub => {
2214 #       irn_flags => "R",
2215         state     => "exc_pinned",
2216         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2217         ins       => [ "base", "index", "mem", "minuend", "subtrahend", "fpcw" ],
2218         am        => "source,binary",
2219         latency   => 4,
2220         units     => [ "VFP" ],
2221         mode      => "mode_E",
2222         attr_type => "ia32_x87_attr_t",
2223 },
2224
2225 vfdiv => {
2226         state     => "exc_pinned",
2227         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
2228         ins       => [ "base", "index", "mem", "dividend", "divisor", "fpcw" ],
2229         am        => "source,binary",
2230         outs      => [ "res", "M" ],
2231         latency   => 20,
2232         units     => [ "VFP" ],
2233         attr_type => "ia32_x87_attr_t",
2234 },
2235
2236 vfprem => {
2237         reg_req   => { in => [ "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
2238         ins       => [ "left", "right", "fpcw" ],
2239         latency   => 20,
2240         units     => [ "VFP" ],
2241         mode      => "mode_E",
2242         attr_type => "ia32_x87_attr_t",
2243 },
2244
2245 vfabs => {
2246         irn_flags => "R",
2247         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2248         ins       => [ "value" ],
2249         latency   => 2,
2250         units     => [ "VFP" ],
2251         mode      => "mode_E",
2252         attr_type => "ia32_x87_attr_t",
2253 },
2254
2255 vfchs => {
2256         irn_flags => "R",
2257         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2258         ins       => [ "value" ],
2259         latency   => 2,
2260         units     => [ "VFP" ],
2261         mode      => "mode_E",
2262         attr_type => "ia32_x87_attr_t",
2263 },
2264
2265 # virtual Load and Store
2266
2267 vfld => {
2268         irn_flags => "R",
2269         op_flags  => "L|F",
2270         state     => "exc_pinned",
2271         reg_req   => { in => [ "gp", "gp", "none" ],
2272                        out => [ "vfp", "none", "none", "none" ] },
2273         ins       => [ "base", "index", "mem" ],
2274         outs      => [ "res", "unused", "M", "X_exc" ],
2275         attr      => "ir_mode *load_mode",
2276         init_attr => "attr->attr.ls_mode = load_mode;",
2277         latency   => 2,
2278         units     => [ "VFP" ],
2279         attr_type => "ia32_x87_attr_t",
2280 },
2281
2282 vfst => {
2283         irn_flags => "R",
2284         op_flags  => "L|F",
2285         state     => "exc_pinned",
2286         reg_req   => { in => [ "gp", "gp", "none", "vfp" ],
2287                        out => [ "none", "none" ] },
2288         ins       => [ "base", "index", "mem", "val" ],
2289         outs      => [ "M", "X_exc" ],
2290         attr      => "ir_mode *store_mode",
2291         init_attr => "attr->attr.ls_mode = store_mode;",
2292         latency   => 2,
2293         units     => [ "VFP" ],
2294         mode      => "mode_M",
2295         attr_type => "ia32_x87_attr_t",
2296 },
2297
2298 # Conversions
2299
2300 vfild => {
2301         state     => "exc_pinned",
2302         reg_req   => { in => [ "gp", "gp", "none" ],
2303                        out => [ "vfp", "none", "none" ] },
2304         outs      => [ "res", "unused", "M" ],
2305         ins       => [ "base", "index", "mem" ],
2306         latency   => 4,
2307         units     => [ "VFP" ],
2308         attr_type => "ia32_x87_attr_t",
2309 },
2310
2311 vfist => {
2312         state     => "exc_pinned",
2313         reg_req   => { in => [ "gp", "gp", "none", "vfp", "fpcw" ], out => [ "none" ] },
2314         ins       => [ "base", "index", "mem", "val", "fpcw" ],
2315         outs      => [ "M" ],
2316         latency   => 4,
2317         units     => [ "VFP" ],
2318         mode      => "mode_M",
2319         attr_type => "ia32_x87_attr_t",
2320 },
2321
2322 # SSE3 fisttp instruction
2323 vfisttp => {
2324         state     => "exc_pinned",
2325         reg_req   => { in => [ "gp", "gp", "none", "vfp" ], out => [ "in_r4", "none" ]},
2326         ins       => [ "base", "index", "mem", "val" ],
2327         outs      => [ "res", "M" ],
2328         latency   => 4,
2329         units     => [ "VFP" ],
2330         attr_type => "ia32_x87_attr_t",
2331 },
2332
2333
2334 # constants
2335
2336 vfldz => {
2337         irn_flags => "R",
2338         reg_req   => { out => [ "vfp" ] },
2339         outs      => [ "res" ],
2340         latency   => 4,
2341         units     => [ "VFP" ],
2342         mode      => "mode_E",
2343         attr_type => "ia32_x87_attr_t",
2344 },
2345
2346 vfld1 => {
2347         irn_flags => "R",
2348         reg_req   => { out => [ "vfp" ] },
2349         outs      => [ "res" ],
2350         latency   => 4,
2351         units     => [ "VFP" ],
2352         mode      => "mode_E",
2353         attr_type => "ia32_x87_attr_t",
2354 },
2355
2356 vfldpi => {
2357         irn_flags => "R",
2358         reg_req   => { out => [ "vfp" ] },
2359         outs      => [ "res" ],
2360         latency   => 4,
2361         units     => [ "VFP" ],
2362         mode      => "mode_E",
2363         attr_type => "ia32_x87_attr_t",
2364 },
2365
2366 vfldln2 => {
2367         irn_flags => "R",
2368         reg_req   => { out => [ "vfp" ] },
2369         outs      => [ "res" ],
2370         latency   => 4,
2371         units     => [ "VFP" ],
2372         mode      => "mode_E",
2373         attr_type => "ia32_x87_attr_t",
2374 },
2375
2376 vfldlg2 => {
2377         irn_flags => "R",
2378         reg_req   => { out => [ "vfp" ] },
2379         outs      => [ "res" ],
2380         latency   => 4,
2381         units     => [ "VFP" ],
2382         mode      => "mode_E",
2383         attr_type => "ia32_x87_attr_t",
2384 },
2385
2386 vfldl2t => {
2387         irn_flags => "R",
2388         reg_req   => { out => [ "vfp" ] },
2389         outs      => [ "res" ],
2390         latency   => 4,
2391         units     => [ "VFP" ],
2392         mode      => "mode_E",
2393         attr_type => "ia32_x87_attr_t",
2394 },
2395
2396 vfldl2e => {
2397         irn_flags => "R",
2398         reg_req   => { out => [ "vfp" ] },
2399         outs      => [ "res" ],
2400         latency   => 4,
2401         units     => [ "VFP" ],
2402         mode      => "mode_E",
2403         attr_type => "ia32_x87_attr_t",
2404 },
2405
2406 # other
2407
2408 vFucomFnstsw => {
2409 # we can't allow to rematerialize this node so we don't have
2410 #  accidently produce Phi(Fucom, Fucom(ins_permuted))
2411 #       irn_flags => "R",
2412         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
2413         ins       => [ "left", "right" ],
2414         outs      => [ "flags" ],
2415         attr      => "int ins_permuted",
2416         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2417         latency   => 3,
2418         units     => [ "VFP" ],
2419         attr_type => "ia32_x87_attr_t",
2420         mode      => $mode_gp
2421 },
2422
2423 vFucomi => {
2424         irn_flags => "R",
2425         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
2426         ins       => [ "left", "right" ],
2427         outs      => [ "flags" ],
2428         attr      => "int ins_permuted",
2429         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2430         latency   => 3,
2431         units     => [ "VFP" ],
2432         attr_type => "ia32_x87_attr_t",
2433         mode      => $mode_gp
2434 },
2435
2436 vFtstFnstsw => {
2437 #       irn_flags => "R",
2438         reg_req   => { in => [ "vfp" ], out => [ "eax" ] },
2439         ins       => [ "left" ],
2440         outs      => [ "flags" ],
2441         attr      => "int ins_permuted",
2442         init_attr => "attr->attr.data.ins_permuted = ins_permuted;",
2443         latency   => 3,
2444         units     => [ "VFP" ],
2445         attr_type => "ia32_x87_attr_t",
2446         mode      => $mode_gp
2447 },
2448
2449 Sahf => {
2450         irn_flags => "R",
2451         reg_req   => { in => [ "eax" ], out => [ "eflags" ] },
2452         ins       => [ "val" ],
2453         outs      => [ "flags" ],
2454         emit      => '. sahf',
2455         latency   => 1,
2456         units     => [ "GP" ],
2457         mode      => $mode_flags,
2458 },
2459
2460 #------------------------------------------------------------------------#
2461 #       ___ _____    __ _             _                     _            #
2462 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
2463 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
2464 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
2465 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
2466 #------------------------------------------------------------------------#
2467
2468 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
2469 #       are swapped, we work this around in the emitter...
2470
2471 fadd => {
2472         state     => "exc_pinned",
2473         rd_constructor => "NONE",
2474         reg_req   => { },
2475         emit      => '. fadd%XM %x87_binop',
2476         latency   => 4,
2477         attr_type => "ia32_x87_attr_t",
2478 },
2479
2480 faddp => {
2481         state     => "exc_pinned",
2482         rd_constructor => "NONE",
2483         reg_req   => { },
2484         emit      => '. faddp%XM %x87_binop',
2485         latency   => 4,
2486         attr_type => "ia32_x87_attr_t",
2487 },
2488
2489 fmul => {
2490         state     => "exc_pinned",
2491         rd_constructor => "NONE",
2492         reg_req   => { },
2493         emit      => '. fmul%XM %x87_binop',
2494         latency   => 4,
2495         attr_type => "ia32_x87_attr_t",
2496 },
2497
2498 fmulp => {
2499         state     => "exc_pinned",
2500         rd_constructor => "NONE",
2501         reg_req   => { },
2502         emit      => '. fmulp%XM %x87_binop',,
2503         latency   => 4,
2504         attr_type => "ia32_x87_attr_t",
2505 },
2506
2507 fsub => {
2508         state     => "exc_pinned",
2509         rd_constructor => "NONE",
2510         reg_req   => { },
2511         emit      => '. fsub%XM %x87_binop',
2512         latency   => 4,
2513         attr_type => "ia32_x87_attr_t",
2514 },
2515
2516 fsubp => {
2517         state     => "exc_pinned",
2518         rd_constructor => "NONE",
2519         reg_req   => { },
2520 # see note about gas bugs
2521         emit      => '. fsubrp%XM %x87_binop',
2522         latency   => 4,
2523         attr_type => "ia32_x87_attr_t",
2524 },
2525
2526 fsubr => {
2527         state     => "exc_pinned",
2528         rd_constructor => "NONE",
2529         irn_flags => "R",
2530         reg_req   => { },
2531         emit      => '. fsubr%XM %x87_binop',
2532         latency   => 4,
2533         attr_type => "ia32_x87_attr_t",
2534 },
2535
2536 fsubrp => {
2537         state     => "exc_pinned",
2538         rd_constructor => "NONE",
2539         irn_flags => "R",
2540         reg_req   => { },
2541 # see note about gas bugs
2542         emit      => '. fsubp%XM %x87_binop',
2543         latency   => 4,
2544         attr_type => "ia32_x87_attr_t",
2545 },
2546
2547 fprem => {
2548         rd_constructor => "NONE",
2549         reg_req   => { },
2550         emit      => '. fprem1',
2551         latency   => 20,
2552         attr_type => "ia32_x87_attr_t",
2553 },
2554
2555 # this node is just here, to keep the simulator running
2556 # we can omit this when a fprem simulation function exists
2557 fpremp => {
2558         rd_constructor => "NONE",
2559         reg_req   => { },
2560         emit      => '. fprem1\n'.
2561                      '. fstp %X0',
2562         latency   => 20,
2563         attr_type => "ia32_x87_attr_t",
2564 },
2565
2566 fdiv => {
2567         state     => "exc_pinned",
2568         rd_constructor => "NONE",
2569         reg_req   => { },
2570         emit      => '. fdiv%XM %x87_binop',
2571         latency   => 20,
2572         attr_type => "ia32_x87_attr_t",
2573 },
2574
2575 fdivp => {
2576         state     => "exc_pinned",
2577         rd_constructor => "NONE",
2578         reg_req   => { },
2579 # see note about gas bugs
2580         emit      => '. fdivrp%XM %x87_binop',
2581         latency   => 20,
2582         attr_type => "ia32_x87_attr_t",
2583 },
2584
2585 fdivr => {
2586         state     => "exc_pinned",
2587         rd_constructor => "NONE",
2588         reg_req   => { },
2589         emit      => '. fdivr%XM %x87_binop',
2590         latency   => 20,
2591         attr_type => "ia32_x87_attr_t",
2592 },
2593
2594 fdivrp => {
2595         state     => "exc_pinned",
2596         rd_constructor => "NONE",
2597         reg_req   => { },
2598 # see note about gas bugs
2599         emit      => '. fdivp%XM %x87_binop',
2600         latency   => 20,
2601         attr_type => "ia32_x87_attr_t",
2602 },
2603
2604 fabs => {
2605         rd_constructor => "NONE",
2606         reg_req   => { },
2607         emit      => '. fabs',
2608         latency   => 4,
2609         attr_type => "ia32_x87_attr_t",
2610 },
2611
2612 fchs => {
2613         op_flags  => "R|K",
2614         rd_constructor => "NONE",
2615         reg_req   => { },
2616         emit      => '. fchs',
2617         latency   => 4,
2618         attr_type => "ia32_x87_attr_t",
2619 },
2620
2621 # x87 Load and Store
2622
2623 fld => {
2624         rd_constructor => "NONE",
2625         op_flags  => "R|L|F",
2626         state     => "exc_pinned",
2627         reg_req   => { },
2628         emit      => '. fld%XM %AM',
2629         attr_type => "ia32_x87_attr_t",
2630         latency   => 2,
2631 },
2632
2633 fst => {
2634         rd_constructor => "NONE",
2635         op_flags  => "R|L|F",
2636         state     => "exc_pinned",
2637         reg_req   => { },
2638         emit      => '. fst%XM %AM',
2639         mode      => "mode_M",
2640         attr_type => "ia32_x87_attr_t",
2641         latency   => 2,
2642 },
2643
2644 fstp => {
2645         rd_constructor => "NONE",
2646         op_flags  => "R|L|F",
2647         state     => "exc_pinned",
2648         reg_req   => { },
2649         emit      => '. fstp%XM %AM',
2650         mode      => "mode_M",
2651         attr_type => "ia32_x87_attr_t",
2652         latency   => 2,
2653 },
2654
2655 # Conversions
2656
2657 fild => {
2658         state     => "exc_pinned",
2659         rd_constructor => "NONE",
2660         reg_req   => { },
2661         emit      => '. fild%XM %AM',
2662         attr_type => "ia32_x87_attr_t",
2663         latency   => 2,
2664 },
2665
2666 fist => {
2667         state     => "exc_pinned",
2668         rd_constructor => "NONE",
2669         reg_req   => { },
2670         emit      => '. fist%XM %AM',
2671         mode      => "mode_M",
2672         attr_type => "ia32_x87_attr_t",
2673         latency   => 2,
2674 },
2675
2676 fistp => {
2677         state     => "exc_pinned",
2678         rd_constructor => "NONE",
2679         reg_req   => { },
2680         emit      => '. fistp%XM %AM',
2681         mode      => "mode_M",
2682         attr_type => "ia32_x87_attr_t",
2683         latency   => 2,
2684 },
2685
2686 # SSE3 fisttp instruction
2687 fisttp => {
2688         state     => "exc_pinned",
2689         rd_constructor => "NONE",
2690         reg_req   => { },
2691         emit      => '. fisttp%XM %AM',
2692         mode      => "mode_M",
2693         attr_type => "ia32_x87_attr_t",
2694         latency   => 2,
2695 },
2696
2697 # constants
2698
2699 fldz => {
2700         op_flags  => "R|c|K",
2701         irn_flags => "R",
2702         reg_req   => { out => [ "vfp" ] },
2703         emit      => '. fldz',
2704         attr_type => "ia32_x87_attr_t",
2705         latency   => 2,
2706 },
2707
2708 fld1 => {
2709         op_flags  => "R|c|K",
2710         irn_flags => "R",
2711         reg_req   => { out => [ "vfp" ] },
2712         emit      => '. fld1',
2713         attr_type => "ia32_x87_attr_t",
2714         latency   => 2,
2715 },
2716
2717 fldpi => {
2718         op_flags  => "R|c|K",
2719         irn_flags => "R",
2720         reg_req   => { out => [ "vfp" ] },
2721         emit      => '. fldpi',
2722         attr_type => "ia32_x87_attr_t",
2723         latency   => 2,
2724 },
2725
2726 fldln2 => {
2727         op_flags  => "R|c|K",
2728         irn_flags => "R",
2729         reg_req   => { out => [ "vfp" ] },
2730         emit      => '. fldln2',
2731         attr_type => "ia32_x87_attr_t",
2732         latency   => 2,
2733 },
2734
2735 fldlg2 => {
2736         op_flags  => "R|c|K",
2737         irn_flags => "R",
2738         reg_req   => { out => [ "vfp" ] },
2739         emit      => '. fldlg2',
2740         attr_type => "ia32_x87_attr_t",
2741         latency   => 2,
2742 },
2743
2744 fldl2t => {
2745         op_flags  => "R|c|K",
2746         irn_flags => "R",
2747         reg_req   => { out => [ "vfp" ] },
2748         emit      => '. fldll2t',
2749         attr_type => "ia32_x87_attr_t",
2750         latency   => 2,
2751 },
2752
2753 fldl2e => {
2754         op_flags  => "R|c|K",
2755         irn_flags => "R",
2756         reg_req   => { out => [ "vfp" ] },
2757         emit      => '. fldl2e',
2758         attr_type => "ia32_x87_attr_t",
2759         latency   => 2,
2760 },
2761
2762 # fxch, fpush, fpop
2763 # Note that it is NEVER allowed to do CSE on these nodes
2764 # Moreover, note the virtual register requierements!
2765
2766 fxch => {
2767         op_flags  => "R|K",
2768         reg_req   => { out => [ "none" ] },
2769         cmp_attr  => "return 1;",
2770         emit      => '. fxch %X0',
2771         attr_type => "ia32_x87_attr_t",
2772         mode      => "mode_ANY",
2773         latency   => 1,
2774 },
2775
2776 fpush => {
2777         op_flags  => "R|K",
2778         reg_req   => { out => [ "none" ] },
2779         cmp_attr  => "return 1;",
2780         emit      => '. fld %X0',
2781         attr_type => "ia32_x87_attr_t",
2782         mode      => "mode_ANY",
2783         latency   => 1,
2784 },
2785
2786 fpushCopy => {
2787         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2788         cmp_attr  => "return 1;",
2789         emit      => '. fld %X0',
2790         attr_type => "ia32_x87_attr_t",
2791         latency   => 1,
2792 },
2793
2794 fpop => {
2795         op_flags  => "K",
2796         reg_req   => { out => [ "none" ] },
2797         cmp_attr  => "return 1;",
2798         emit      => '. fstp %X0',
2799         attr_type => "ia32_x87_attr_t",
2800         mode      => "mode_ANY",
2801         latency   => 1,
2802 },
2803
2804 ffreep => {
2805         op_flags  => "K",
2806         reg_req   => { out => [ "none" ] },
2807         cmp_attr  => "return 1;",
2808         emit      => '. ffreep %X0',
2809         attr_type => "ia32_x87_attr_t",
2810         mode      => "mode_ANY",
2811         latency   => 1,
2812 },
2813
2814 emms => {
2815         op_flags  => "K",
2816         reg_req   => { out => [ "none" ] },
2817         cmp_attr  => "return 1;",
2818         emit      => '. emms',
2819         attr_type => "ia32_x87_attr_t",
2820         mode      => "mode_ANY",
2821         latency   => 3,
2822 },
2823
2824 femms => {
2825         op_flags  => "K",
2826         reg_req   => { out => [ "none" ] },
2827         cmp_attr  => "return 1;",
2828         emit      => '. femms',
2829         attr_type => "ia32_x87_attr_t",
2830         mode      => "mode_ANY",
2831         latency   => 3,
2832 },
2833
2834 # compare
2835
2836 FucomFnstsw => {
2837         reg_req   => { },
2838         emit      => ". fucom %X1\n".
2839                      ". fnstsw %%ax",
2840         attr_type => "ia32_x87_attr_t",
2841         latency   => 2,
2842 },
2843
2844 FucompFnstsw => {
2845         reg_req   => { },
2846         emit      => ". fucomp %X1\n".
2847                      ". fnstsw %%ax",
2848         attr_type => "ia32_x87_attr_t",
2849         latency   => 2,
2850 },
2851
2852 FucomppFnstsw => {
2853         reg_req   => { },
2854         emit      => ". fucompp\n".
2855                      ". fnstsw %%ax",
2856         attr_type => "ia32_x87_attr_t",
2857         latency   => 2,
2858 },
2859
2860 Fucomi => {
2861         reg_req   => { },
2862         emit      => '. fucomi %X1',
2863         attr_type => "ia32_x87_attr_t",
2864         latency   => 1,
2865 },
2866
2867 Fucompi => {
2868         reg_req   => { },
2869         emit      => '. fucompi %X1',
2870         attr_type => "ia32_x87_attr_t",
2871         latency   => 1,
2872 },
2873
2874 FtstFnstsw => {
2875         reg_req   => { },
2876         emit      => ". ftst\n".
2877                      ". fnstsw %%ax",
2878         attr_type => "ia32_x87_attr_t",
2879         latency   => 2,
2880 },
2881
2882
2883 # -------------------------------------------------------------------------------- #
2884 #  ____ ____  _____                  _                               _             #
2885 # / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
2886 # \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
2887 #  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
2888 # |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
2889 #                                                                                  #
2890 # -------------------------------------------------------------------------------- #
2891
2892
2893 # Spilling and reloading of SSE registers, hardcoded, not generated #
2894
2895 xxLoad => {
2896         op_flags  => "L|F",
2897         state     => "exc_pinned",
2898         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2899         emit      => '. movdqu %D0, %AM',
2900         outs      => [ "res", "M" ],
2901         units     => [ "SSE" ],
2902         latency   => 1,
2903 },
2904
2905 xxStore => {
2906         op_flags => "L|F",
2907         state    => "exc_pinned",
2908         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
2909         ins      => [ "base", "index", "mem", "val" ],
2910         emit     => '. movdqu %binop',
2911         units    => [ "SSE" ],
2912         latency   => 1,
2913         mode     => "mode_M",
2914 },
2915
2916 ); # end of %nodes
2917
2918 # Include the generated SIMD node specification written by the SIMD optimization
2919 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2920 unless ($return = do $my_script_name) {
2921         warn "couldn't parse $my_script_name: $@" if $@;
2922         warn "couldn't do $my_script_name: $!"    unless defined $return;
2923         warn "couldn't run $my_script_name"       unless $return;
2924 }
2925
2926 # Transform some attributes
2927 foreach my $op (keys(%nodes)) {
2928         my $node         = $nodes{$op};
2929         my $op_attr_init = $node->{op_attr_init};
2930
2931         if(defined($op_attr_init)) {
2932                 $op_attr_init .= "\n\t";
2933         } else {
2934                 $op_attr_init = "";
2935         }
2936
2937         if(!defined($node->{latency})) {
2938                 if($op =~ m/^l_/) {
2939                         $node->{latency} = 0;
2940                 } else {
2941                         die("Latency missing for op $op");
2942                 }
2943         }
2944         $op_attr_init .= "attr->latency = ".$node->{latency} . ";";
2945
2946         $node->{op_attr_init} = $op_attr_init;
2947 }
2948
2949 print "";