Annotate nodes with their AM capabilities.
[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|I|S"
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 #   emit      => "emit code with templates",
32 #   attr      => "attitional attribute arguments for constructor"
33 #   init_attr => "emit attribute initialization template"
34 #   rd_constructor => "c source code which constructs an ir_node"
35 #   latency   => "latency of this operation (can be float)"
36 #   attr_type => "name of the attribute struct",
37 # },
38 #
39 # ... # (all nodes you need to describe)
40 #
41 # ); # close the %nodes initializer
42
43 # op_flags: flags for the operation, OPTIONAL (default is "N")
44 # the op_flags correspond to the firm irop_flags:
45 #   N   irop_flag_none
46 #   L   irop_flag_labeled
47 #   C   irop_flag_commutative
48 #   X   irop_flag_cfopcode
49 #   I   irop_flag_ip_cfopcode
50 #   F   irop_flag_fragile
51 #   Y   irop_flag_forking
52 #   H   irop_flag_highlevel
53 #   c   irop_flag_constlike
54 #   K   irop_flag_keep
55 #
56 # irn_flags: special node flags, OPTIONAL (default is 0)
57 # following irn_flags are supported:
58 #   R   rematerializeable
59 #   N   not spillable
60 #   I   ignore for register allocation
61 #   S   modifies stack pointer
62 #
63 # state: state of the operation, OPTIONAL (default is "floats")
64 #
65 # arity: arity of the operation, MUST NOT BE OMITTED
66 #
67 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
68 #        are always the first 3 arguments and are always autmatically
69 #        created)
70 #        If this key is missing the following arguments will be created:
71 #        for i = 1 .. arity: ir_node *op_i
72 #        ir_mode *mode
73 #
74 # outs:  if a node defines more than one output, the names of the projections
75 #        nodes having outs having automatically the mode mode_T
76 #        One can also annotate some flags for each out, additional to irn_flags.
77 #        They are separated from name with a colon ':', and concatenated by pipe '|'
78 #        Only I and S are available at the moment (same meaning as in irn_flags).
79 #        example: [ "frame:I", "stack:I|S", "M" ]
80 #
81 # comment: OPTIONAL comment for the node constructor
82 #
83 # rd_constructor: for every operation there will be a
84 #      new_rd_<arch>_<op-name> function with the arguments from above
85 #      which creates the ir_node corresponding to the defined operation
86 #      you can either put the complete source code of this function here
87 #
88 #      This key is OPTIONAL. If omitted, the following constructor will
89 #      be created:
90 #      if (!op_<arch>_<op-name>) assert(0);
91 #      for i = 1 to arity
92 #         set in[i] = op_i
93 #      done
94 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
95 #      return res
96 #
97 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
98 #
99 # latency: the latency of the operation, default is 1
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 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 | 16 },
151                 { name => "vf1", type => 1 | 16 },
152                 { name => "vf2", type => 1 | 16 },
153                 { name => "vf3", type => 1 | 16 },
154                 { name => "vf4", type => 1 | 16 },
155                 { name => "vf5", type => 1 | 16 },
156                 { name => "vf6", type => 1 | 16 },
157                 { name => "vf7", type => 1 | 16 },
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         SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
201         SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
202         SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
203         SI0 => "${arch}_emit_source_register_or_immediate(node, 0);",
204         SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
205         SI2 => "${arch}_emit_source_register_or_immediate(node, 2);",
206         SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
207         D0 => "${arch}_emit_dest_register(node, 0);",
208         D1 => "${arch}_emit_dest_register(node, 1);",
209         DB0 => "${arch}_emit_8bit_dest_register(node, 0);",
210         X0 => "${arch}_emit_x87_register(node, 0);",
211         X1 => "${arch}_emit_x87_register(node, 1);",
212         SE => "${arch}_emit_extend_suffix(get_ia32_ls_mode(node));",
213         ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
214                    ia32_emit_mode_suffix(node);",
215         M  => "${arch}_emit_mode_suffix(node);",
216         XM => "${arch}_emit_x87_mode_suffix(node);",
217         XXM => "${arch}_emit_xmm_mode_suffix(node);",
218         XSD => "${arch}_emit_xmm_mode_suffix_s(node);",
219         AM => "${arch}_emit_am(node);",
220         unop3 => "${arch}_emit_unop(node, 3);",
221         unop4 => "${arch}_emit_unop(node, 4);",
222         unop5 => "${arch}_emit_unop(node, 5);",
223         DAM1  => "${arch}_emit_am_or_dest_register(node, 1);",
224         binop => "${arch}_emit_binop(node);",
225         x87_binop => "${arch}_emit_x87_binop(node);",
226         CMP0  => "${arch}_emit_cmp_suffix_node(node, 0);",
227 );
228
229 #--------------------------------------------------#
230 #                        _                         #
231 #                       (_)                        #
232 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
233 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
234 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
235 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
236 #                                      | |         #
237 #                                      |_|         #
238 #--------------------------------------------------#
239
240 $default_attr_type = "ia32_attr_t";
241 $default_copy_attr = "ia32_copy_attr";
242
243 sub ia32_custom_init_attr {
244         my $node = shift;
245         my $name = shift;
246         my $res = "";
247         if(defined($node->{modified_flags})) {
248                 $res .= "\tset_ia32_flags(res, get_ia32_flags(res) | arch_irn_flags_modify_flags);\n";
249         }
250         if(defined($node->{am})) {
251                 my $am = $node->{am};
252                 if($am eq "full,binary") {
253                         $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_binary);";
254                 } elsif($am eq "full,unary") {
255                         $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_unary);";
256                 } elsif($am eq "source,unary") {
257                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_unary);";
258                 } elsif($am eq "source,binary") {
259                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_binary);";
260                 } elsif($am eq "dest,unary") {
261                         $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_unary);";
262                 } elsif($am eq "dest,binary") {
263                         $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_binary);";
264                 } elsif($am eq "dest,ternary") {
265                         $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_ternary);";
266                 } elsif($am eq "source,ternary") {
267                         $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_ternary);";
268                 } elsif($am eq "none") {
269                         # nothing to do
270                 } else {
271                         die("Invalid address mode '$am' specified on op $name");
272                 }
273         }
274         return $res;
275 }
276 $custom_init_attr_func = \&ia32_custom_init_attr;
277
278 %init_attr = (
279         ia32_attr_t     => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
280         ia32_x87_attr_t =>
281                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
282                 "\tinit_ia32_x87_attributes(res);",
283         ia32_asm_attr_t =>
284                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
285                 "\tinit_ia32_x87_attributes(res);".
286                 "\tinit_ia32_asm_attributes(res);",
287         ia32_immediate_attr_t =>
288                 "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
289                 "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);"
290 );
291
292 %compare_attr = (
293         ia32_attr_t           => "ia32_compare_nodes_attr",
294         ia32_x87_attr_t       => "ia32_compare_x87_attr",
295         ia32_asm_attr_t       => "ia32_compare_asm_attr",
296         ia32_immediate_attr_t => "ia32_compare_immediate_attr",
297 );
298
299 %operands = (
300 );
301
302 $mode_xmm     = "mode_E";
303 $mode_gp      = "mode_Iu";
304 $mode_flags   = "mode_Iu";
305 $mode_fpcw    = "mode_fpcw";
306 $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
307 $fpcw_flags   = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
308                   "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
309
310 %nodes = (
311
312 Immediate => {
313         state     => "pinned",
314         op_flags  => "c",
315         irn_flags => "I",
316         reg_req   => { out => [ "gp_NOREG" ] },
317         attr      => "ir_entity *symconst, int symconst_sign, long offset",
318         attr_type => "ia32_immediate_attr_t",
319         latency   => 0,
320         mode      => $mode_gp,
321 },
322
323 Asm => {
324         mode      => "mode_T",
325         arity     => "variable",
326         out_arity => "variable",
327         attr_type => "ia32_asm_attr_t",
328         latency   => 100,
329 },
330
331 ProduceVal => {
332         op_flags  => "c",
333         irn_flags => "R",
334         reg_req   => { out => [ "gp" ] },
335         emit      => "",
336         units     => [ ],
337         latency   => 0,
338         mode      => $mode_gp,
339         cmp_attr  => "return 1;",
340 },
341
342 #-----------------------------------------------------------------#
343 #  _       _                                         _            #
344 # (_)     | |                                       | |           #
345 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
346 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
347 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
348 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
349 #                   __/ |                                         #
350 #                  |___/                                          #
351 #-----------------------------------------------------------------#
352
353 # commutative operations
354
355 Add => {
356         irn_flags => "R",
357         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5", "none", "flags" ] },
358         ins       => [ "base", "index", "mem", "left", "right" ],
359         emit      => '. add%M %binop',
360         am        => "full,binary",
361         units     => [ "GP" ],
362         mode      => $mode_gp,
363         modified_flags => $status_flags
364 },
365
366 AddMem => {
367         irn_flags => "R",
368         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
369         ins       => [ "base", "index", "mem", "val" ],
370         emit      => ". add%M %SI3, %AM",
371         units     => [ "GP" ],
372         mode      => "mode_M",
373         modified_flags => $status_flags
374 },
375
376 AddMem8Bit => {
377         irn_flags => "R",
378         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
379         ins       => [ "base", "index", "mem", "val" ],
380         emit      => ". add%M %SB3, %AM",
381         units     => [ "GP" ],
382         mode      => "mode_M",
383         modified_flags => $status_flags
384 },
385
386 Adc => {
387         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 in_r5" ] },
388         ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
389         emit      => '. adc%M %binop',
390         am        => "full,binary",
391         units     => [ "GP" ],
392         mode      => $mode_gp,
393         modified_flags => $status_flags
394 },
395
396 l_Add => {
397         op_flags  => "C",
398         reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
399         ins       => [ "left", "right" ],
400 },
401
402 l_Adc => {
403         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
404         ins       => [ "left", "right", "eflags" ],
405 },
406
407 Mul => {
408         # we should not rematrialize this node. It produces 2 results and has
409         # very strict constrains
410         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] },
411         ins       => [ "base", "index", "mem", "val_high", "val_low" ],
412         emit      => '. mul%M %unop4',
413         outs      => [ "EAX", "EDX", "M" ],
414         am        => "source,binary",
415         latency   => 10,
416         units     => [ "GP" ],
417         modified_flags => $status_flags
418 },
419
420 l_Mul => {
421         # we should not rematrialize this node. It produces 2 results and has
422         # very strict constrains
423         op_flags  => "C",
424         cmp_attr  => "return 1;",
425         outs      => [ "EAX", "EDX", "M" ],
426         arity     => 2
427 },
428
429 IMul => {
430         irn_flags => "R",
431         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
432         ins       => [ "base", "index", "mem", "left", "right" ],
433         emit      => '. imul%M %binop',
434         am        => "source,binary",
435         latency   => 5,
436         units     => [ "GP" ],
437         mode      => $mode_gp,
438         modified_flags => $status_flags
439 },
440
441 IMul1OP => {
442         irn_flags => "R",
443         reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] },
444         ins       => [ "base", "index", "mem", "val_high", "val_low" ],
445         emit      => '. imul%M %unop4',
446         outs      => [ "EAX", "EDX", "M" ],
447         am        => "source,binary",
448         latency   => 5,
449         units     => [ "GP" ],
450         modified_flags => $status_flags
451 },
452
453 l_IMul => {
454         # we should not rematrialize this node. It produces 2 results and has
455         # very strict constrains
456         op_flags  => "C",
457         cmp_attr  => "return 1;",
458         outs      => [ "EAX", "EDX", "M" ],
459         arity     => 2
460 },
461
462 And => {
463         irn_flags => "R",
464         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
465         ins       => [ "base", "index", "mem", "left", "right" ],
466         am        => "full,binary",
467         emit      => '. and%M %binop',
468         units     => [ "GP" ],
469         mode      => $mode_gp,
470         modified_flags => $status_flags
471 },
472
473 AndMem => {
474         irn_flags => "R",
475         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
476         ins       => [ "base", "index", "mem", "val" ],
477         emit      => '. and%M %SI3, %AM',
478         units     => [ "GP" ],
479         mode      => "mode_M",
480         modified_flags => $status_flags
481 },
482
483 AndMem8Bit => {
484         irn_flags => "R",
485         reg_req   => { in => [ "gp", "gp", "none",  "eax ebx ecx edx" ], out => [ "none" ] },
486         ins       => [ "base", "index", "mem", "val" ],
487         emit      => '. and%M %SB3, %AM',
488         units     => [ "GP" ],
489         mode      => "mode_M",
490         modified_flags => $status_flags
491 },
492
493 Or => {
494         irn_flags => "R",
495         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
496         ins       => [ "base", "index", "mem", "left", "right" ],
497         am        => "full,binary",
498         emit      => '. or%M %binop',
499         units     => [ "GP" ],
500         mode      => $mode_gp,
501         modified_flags => $status_flags
502 },
503
504 OrMem => {
505         irn_flags => "R",
506         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
507         ins       => [ "base", "index", "mem", "val" ],
508         emit      => '. or%M %SI3, %AM',
509         units     => [ "GP" ],
510         mode      => "mode_M",
511         modified_flags => $status_flags
512 },
513
514 OrMem8Bit => {
515         irn_flags => "R",
516         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
517         ins       => [ "base", "index", "mem", "val" ],
518         emit      => '. or%M %SB3, %AM',
519         units     => [ "GP" ],
520         mode      => "mode_M",
521         modified_flags => $status_flags
522 },
523
524 Xor => {
525         irn_flags => "R",
526         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
527         ins       => [ "base", "index", "mem", "left", "right" ],
528         am        => "full,binary",
529         emit      => '. xor%M %binop',
530         units     => [ "GP" ],
531         mode      => $mode_gp,
532         modified_flags => $status_flags
533 },
534
535 XorMem => {
536         irn_flags => "R",
537         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
538         ins       => [ "base", "index", "mem", "val" ],
539         emit      => '. xor%M %SI3, %AM',
540         units     => [ "GP" ],
541         mode      => "mode_M",
542         modified_flags => $status_flags
543 },
544
545 XorMem8Bit => {
546         irn_flags => "R",
547         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
548         ins       => [ "base", "index", "mem", "val" ],
549         emit      => '. xor%M %SB3, %AM',
550         units     => [ "GP" ],
551         mode      => "mode_M",
552         modified_flags => $status_flags
553 },
554
555 # not commutative operations
556
557 Sub => {
558         irn_flags => "R",
559         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] },
560         ins       => [ "base", "index", "mem", "left", "right" ],
561         am        => "full,binary",
562         emit      => '. sub%M %binop',
563         units     => [ "GP" ],
564         mode      => $mode_gp,
565         modified_flags => $status_flags
566 },
567
568 SubMem => {
569         irn_flags => "R",
570         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
571         ins       => [ "base", "index", "mem", "val" ],
572         emit      => '. sub%M %SI3, %AM',
573         units     => [ "GP" ],
574         mode      => 'mode_M',
575         modified_flags => $status_flags
576 },
577
578 SubMem8Bit => {
579         irn_flags => "R",
580         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
581         ins       => [ "base", "index", "mem", "val" ],
582         emit      => '. sub%M %SB3, %AM',
583         units     => [ "GP" ],
584         mode      => 'mode_M',
585         modified_flags => $status_flags
586 },
587
588 Sbb => {
589         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 !in_r5" ] },
590         ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
591         am        => "full,binary",
592         emit      => '. sbb%M %binop',
593         units     => [ "GP" ],
594         mode      => $mode_gp,
595         modified_flags => $status_flags
596 },
597
598 l_Sub => {
599         reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
600         ins       => [ "left", "right" ],
601 },
602
603 l_Sbb => {
604         reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
605         ins       => [ "left", "right", "eflags" ],
606 },
607
608 IDiv => {
609         op_flags  => "F|L",
610         state     => "exc_pinned",
611         reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
612         ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
613         outs      => [ "div_res", "mod_res", "M" ],
614         am        => "source,ternary",
615         emit      => ". idiv%M %unop5",
616         latency   => 25,
617         units     => [ "GP" ],
618         modified_flags => $status_flags
619 },
620
621 Div => {
622         op_flags  => "F|L",
623         state     => "exc_pinned",
624         reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
625         ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
626         outs      => [ "div_res", "mod_res", "M" ],
627         am        => "source,ternary",
628         emit      => ". div%M %unop5",
629         latency   => 25,
630         units     => [ "GP" ],
631         modified_flags => $status_flags
632 },
633
634 Shl => {
635         irn_flags => "R",
636         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
637         ins       => [ "left", "right" ],
638         am        => "dest,binary",
639         emit      => '. shl %SB1, %S0',
640         units     => [ "GP" ],
641         mode      => $mode_gp,
642         modified_flags => $status_flags
643 },
644
645 ShlMem => {
646         irn_flags => "R",
647         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
648         ins       => [ "base", "index", "mem", "count" ],
649         emit      => '. shl%M %SB3, %AM',
650         units     => [ "GP" ],
651         mode      => "mode_M",
652         modified_flags => $status_flags
653 },
654
655 l_ShlDep => {
656         cmp_attr  => "return 1;",
657         # value, cnt, dependency
658         arity     => 3
659 },
660
661 ShlD => {
662         irn_flags => "R",
663         # see ShrD about the strange out constraint
664         reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "!in" ] },
665         ins       => [ "left_high", "left_low", "right" ],
666         am        => "dest,ternary",
667         emit      => ". shld%M %SB2, %S1, %S0\n".
668                      ". movl %S0, %D0",
669         latency   => 6,
670         units     => [ "GP" ],
671         mode      => $mode_gp,
672         modified_flags => $status_flags
673 },
674
675 l_ShlD => {
676         cmp_attr  => "return 1;",
677         arity     => 3,
678 },
679
680 Shr => {
681         irn_flags => "R",
682         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
683         ins       => [ "val", "count" ],
684         am        => "dest,binary",
685         emit      => '. shr %SB1, %S0',
686         units     => [ "GP" ],
687         mode      => $mode_gp,
688         modified_flags => $status_flags
689 },
690
691 ShrMem => {
692         irn_flags => "R",
693         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
694         ins       => [ "base", "index", "mem", "count" ],
695         emit      => '. shr%M %SB3, %AM',
696         units     => [ "GP" ],
697         mode      => "mode_M",
698         modified_flags => $status_flags
699 },
700
701 l_ShrDep => {
702         cmp_attr  => "return 1;",
703         # value, cnt, dependency
704         arity     => 3
705 },
706
707 ShrD => {
708         # What's going on with the out constraint here? We would like to write
709         # "in_r2" and be done. However in firm we only support should_be_same
710         # constraints at the moment. Which means they could be non-fullfilled in
711         # some cases. Now when all values happen to live through the node, out
712         # is ecx and in_r2 not ecx, then we're screwed. Because in this case we
713         # need a 4th Register.
714         #
715         # The best solution for this is extending the register allocator to support
716         # must_be_same constraints which create a copy when the in_r2 value
717         # lives through (this ensures that we have the 4th register in the cases
718         # when we need it and can always fix the situation).
719         #
720         # For now I'm doing this ultra ugly !in hack which allocates 4 registers
721         # and creates an extra mov
722         irn_flags => "R",
723         reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "!in" ] },
724         ins       => [ "left_high", "left_low", "right" ],
725         am        => "dest,ternary",
726         emit      => ". shrd%M %SB2, %S1, %S0\n".
727                      ". movl   %S0, %D0",
728         latency   => 6,
729         units     => [ "GP" ],
730         mode      => $mode_gp,
731         modified_flags => $status_flags
732 },
733
734 l_ShrD => {
735         cmp_attr  => "return 1;",
736         arity     => 3
737 },
738
739 Sar => {
740         irn_flags => "R",
741         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
742         ins       => [ "val", "count" ],
743         am        => "dest,binary",
744         emit      => '. sar %SB1, %S0',
745         units     => [ "GP" ],
746         mode      => $mode_gp,
747         modified_flags => $status_flags
748 },
749
750 SarMem => {
751         irn_flags => "R",
752         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
753         ins       => [ "base", "index", "mem", "count" ],
754         emit      => '. sar%M %SB3, %AM',
755         units     => [ "GP" ],
756         mode      => "mode_M",
757         modified_flags => $status_flags
758 },
759
760 l_Sar => {
761         cmp_attr  => "return 1;",
762         # value, cnt
763         arity     => 2
764 },
765
766 l_SarDep => {
767         cmp_attr  => "return 1;",
768         # value, cnt, dependency
769         arity     => 3
770 },
771
772 Ror => {
773         irn_flags => "R",
774         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
775         ins       => [ "val", "count" ],
776         am        => "dest,binary",
777         emit      => '. ror %SB1, %S0',
778         units     => [ "GP" ],
779         mode      => $mode_gp,
780         modified_flags => $status_flags
781 },
782
783 RorMem => {
784         irn_flags => "R",
785         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
786         ins       => [ "base", "index", "mem", "count" ],
787         emit      => '. ror%M %SB3, %AM',
788         units     => [ "GP" ],
789         mode      => "mode_M",
790         modified_flags => $status_flags
791 },
792
793 Rol => {
794         irn_flags => "R",
795         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
796         ins       => [ "val", "count" ],
797         am        => "dest,binary",
798         emit      => '. rol %SB1, %S0',
799         units     => [ "GP" ],
800         mode      => $mode_gp,
801         modified_flags => $status_flags
802 },
803
804 RolMem => {
805         irn_flags => "R",
806         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
807         ins       => [ "base", "index", "mem", "count" ],
808         emit      => '. rol%M %SB3, %AM',
809         units     => [ "GP" ],
810         mode      => "mode_M",
811         modified_flags => $status_flags
812 },
813
814 # unary operations
815
816 Neg => {
817         irn_flags => "R",
818         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
819         emit      => '. neg %S0',
820         ins       => [ "val" ],
821         am        => "dest,unary",
822         units     => [ "GP" ],
823         mode      => $mode_gp,
824         modified_flags => $status_flags
825 },
826
827 NegMem => {
828         irn_flags => "R",
829         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
830         ins       => [ "base", "index", "mem" ],
831         emit      => '. neg%M %AM',
832         units     => [ "GP" ],
833         mode      => "mode_M",
834         modified_flags => $status_flags
835 },
836
837 Minus64Bit => {
838         irn_flags => "R",
839         reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] },
840         outs      => [ "low_res", "high_res" ],
841         units     => [ "GP" ],
842         modified_flags => $status_flags
843 },
844
845
846 l_Neg => {
847         cmp_attr  => "return 1;",
848         arity     => 1,
849 },
850
851 Inc => {
852         irn_flags => "R",
853         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
854         am        => "dest,unary",
855         emit      => '. inc %S0',
856         units     => [ "GP" ],
857         mode      => $mode_gp,
858         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
859 },
860
861 IncMem => {
862         irn_flags => "R",
863         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
864         ins       => [ "base", "index", "mem" ],
865         emit      => '. inc%M %AM',
866         units     => [ "GP" ],
867         mode      => "mode_M",
868         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
869 },
870
871 Dec => {
872         irn_flags => "R",
873         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
874         am        => "dest,unary",
875         emit      => '. dec %S0',
876         units     => [ "GP" ],
877         mode      => $mode_gp,
878         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
879 },
880
881 DecMem => {
882         irn_flags => "R",
883         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
884         ins       => [ "base", "index", "mem" ],
885         emit      => '. dec%M %AM',
886         units     => [ "GP" ],
887         mode      => "mode_M",
888         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
889 },
890
891 Not => {
892         irn_flags => "R",
893         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
894         ins       => [ "val" ],
895         am        => "dest,unary",
896         emit      => '. not %S0',
897         units     => [ "GP" ],
898         mode      => $mode_gp,
899 },
900
901 NotMem => {
902         irn_flags => "R",
903         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
904         ins       => [ "base", "index", "mem" ],
905         emit      => '. not%M %AM',
906         units     => [ "GP" ],
907         mode      => "mode_M",
908 },
909
910 # other operations
911
912 Cmp => {
913         irn_flags => "R",
914         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
915         ins       => [ "base", "index", "mem", "left", "right" ],
916         outs      => [ "eflags" ],
917         am        => "source,binary",
918         emit      => '. cmp%M %binop',
919         attr      => "int flipped, int cmp_unsigned",
920         init_attr => "attr->data.cmp_flipped = flipped;\n".
921                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
922         latency   => 1,
923         units     => [ "GP" ],
924         mode      => $mode_flags,
925         modified_flags => $status_flags
926 },
927
928 Cmp8Bit => {
929         irn_flags => "R",
930         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
931         ins       => [ "base", "index", "mem", "left", "right" ],
932         outs      => [ "eflags" ],
933         am        => "source,binary",
934         emit      => '. cmpb %binop',
935         attr      => "int flipped, int cmp_unsigned",
936         init_attr => "attr->data.cmp_flipped = flipped;\n".
937                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
938         latency   => 1,
939         units     => [ "GP" ],
940         mode      => $mode_flags,
941         modified_flags => $status_flags
942 },
943
944 Test => {
945         irn_flags => "R",
946         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
947         ins       => [ "base", "index", "mem", "left", "right" ],
948         outs      => [ "eflags" ],
949         am        => "source,binary",
950         emit      => '. test%M %binop',
951         attr      => "int flipped, int cmp_unsigned",
952         init_attr => "attr->data.cmp_flipped = flipped;\n".
953                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
954         latency   => 1,
955         units     => [ "GP" ],
956         mode      => $mode_flags,
957         modified_flags => $status_flags
958 },
959
960 Test8Bit => {
961         irn_flags => "R",
962         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
963         ins       => [ "base", "index", "mem", "left", "right" ],
964         outs      => [ "eflags" ],
965         am        => "source,binary",
966         emit      => '. testb %binop',
967         attr      => "int flipped, int cmp_unsigned",
968         init_attr => "attr->data.cmp_flipped = flipped;\n".
969                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
970         latency   => 1,
971         units     => [ "GP" ],
972         mode      => $mode_flags,
973         modified_flags => $status_flags
974 },
975
976 Set => {
977         #irn_flags => "R",
978         reg_req   => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
979         ins       => [ "eflags" ],
980         am        => "dest,unary",
981         attr      => "pn_Cmp pnc",
982         init_attr => "attr->pn_code = pnc;\nset_ia32_ls_mode(res, mode_Bu);\n",
983         emit      => '. set%CMP0 %DB0',
984         latency   => 1,
985         units     => [ "GP" ],
986         mode      => $mode_gp,
987 },
988
989 CMov => {
990         #irn_flags => "R",
991         # (note: leave the false,true order intact to make it compatible with other
992         #  ia32_binary ops)
993         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ], out => [ "in_r4 in_r5" ] },
994         ins       => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
995         am        => "source,binary",
996         attr      => "int flipped, pn_Cmp pn_code",
997         init_attr => "attr->pn_code          = pn_code;\n".
998                      "attr->data.cmp_flipped = flipped;",
999         latency   => 1,
1000         units     => [ "GP" ],
1001         mode      => $mode_gp,
1002 },
1003
1004 Jcc => {
1005         state     => "pinned",
1006         op_flags  => "L|X|Y",
1007         reg_req   => { in  => [ "eflags" ], out => [ "none", "none" ] },
1008         ins       => [ "eflags" ],
1009         outs      => [ "false", "true" ],
1010         attr      => "pn_Cmp pnc",
1011         init_attr => "attr->pn_code = pnc;",
1012         latency   => 2,
1013         units     => [ "BRANCH" ],
1014 },
1015
1016 SwitchJmp => {
1017         state     => "pinned",
1018         op_flags  => "L|X|Y",
1019         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1020         latency   => 3,
1021         units     => [ "BRANCH" ],
1022         mode      => "mode_T",
1023         modified_flags => $status_flags
1024 },
1025
1026 IJmp => {
1027         state     => "pinned",
1028         op_flags  => "X",
1029         reg_req   => { in => [ "gp" ] },
1030         emit      => '. jmp *%S0',
1031         units     => [ "BRANCH" ],
1032         mode      => "mode_X",
1033 },
1034
1035 Const => {
1036         op_flags  => "c",
1037         irn_flags => "R",
1038         reg_req   => { out => [ "gp" ] },
1039         units     => [ "GP" ],
1040         attr      => "ir_entity *symconst, int symconst_sign, long offset",
1041         attr_type => "ia32_immediate_attr_t",
1042         mode      => $mode_gp,
1043 # depends on the const and is set in ia32_transform
1044 # modified_flags => $status_flags
1045 },
1046
1047 Unknown_GP => {
1048         state     => "pinned",
1049         op_flags  => "c",
1050         irn_flags => "I",
1051         reg_req   => { out => [ "gp_UKNWN" ] },
1052         units     => [],
1053         emit      => "",
1054         mode      => $mode_gp
1055 },
1056
1057 Unknown_VFP => {
1058         state     => "pinned",
1059         op_flags  => "c",
1060         irn_flags => "I",
1061         reg_req   => { out => [ "vfp_UKNWN" ] },
1062         units     => [],
1063         emit      => "",
1064         mode      => "mode_E",
1065         attr_type => "ia32_x87_attr_t",
1066 },
1067
1068 Unknown_XMM => {
1069         state     => "pinned",
1070         op_flags  => "c",
1071         irn_flags => "I",
1072         reg_req   => { out => [ "xmm_UKNWN" ] },
1073         units     => [],
1074         emit      => "",
1075         mode      => "mode_E"
1076 },
1077
1078 NoReg_GP => {
1079         state     => "pinned",
1080         op_flags  => "c",
1081         irn_flags => "I",
1082         reg_req   => { out => [ "gp_NOREG" ] },
1083         units     => [],
1084         emit      => "",
1085         mode      => $mode_gp
1086 },
1087
1088 NoReg_VFP => {
1089         state     => "pinned",
1090         op_flags  => "c",
1091         irn_flags => "I",
1092         reg_req   => { out => [ "vfp_NOREG" ] },
1093         units     => [],
1094         emit      => "",
1095         mode      => "mode_E",
1096         attr_type => "ia32_x87_attr_t",
1097 },
1098
1099 NoReg_XMM => {
1100         state     => "pinned",
1101         op_flags  => "c",
1102         irn_flags => "I",
1103         reg_req   => { out => [ "xmm_NOREG" ] },
1104         units     => [],
1105         emit      => "",
1106         mode      => "mode_E"
1107 },
1108
1109 ChangeCW => {
1110         state     => "pinned",
1111         op_flags  => "c",
1112         irn_flags => "I",
1113         reg_req   => { out => [ "fp_cw" ] },
1114         mode      => $mode_fpcw,
1115         latency   => 3,
1116         units     => [ "GP" ],
1117         modified_flags => $fpcw_flags
1118 },
1119
1120 FldCW => {
1121         op_flags  => "L|F",
1122         state     => "pinned",
1123         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
1124         ins       => [ "base", "index", "mem" ],
1125         latency   => 5,
1126         emit      => ". fldcw %AM",
1127         mode      => $mode_fpcw,
1128         units     => [ "GP" ],
1129         modified_flags => $fpcw_flags
1130 },
1131
1132 FnstCW => {
1133         op_flags  => "L|F",
1134         state     => "pinned",
1135         reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1136         ins       => [ "base", "index", "mem", "fpcw" ],
1137         latency   => 5,
1138         emit      => ". fnstcw %AM",
1139         mode      => "mode_M",
1140         units     => [ "GP" ],
1141 },
1142
1143 Cltd => {
1144         # we should not rematrialize this node. It has very strict constraints.
1145         reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
1146         ins       => [ "val", "globbered" ],
1147         emit      => '. cltd',
1148         mode      => $mode_gp,
1149         units     => [ "GP" ],
1150 },
1151
1152 # Load / Store
1153 #
1154 # Note that we add additional latency values depending on address mode, so a
1155 # lateny of 0 for load is correct
1156
1157 Load => {
1158         op_flags  => "L|F",
1159         state     => "exc_pinned",
1160         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
1161         ins       => [ "base", "index", "mem" ],
1162         outs      => [ "res", "M" ],
1163         latency   => 0,
1164         emit      => ". mov%SE%ME%.l %AM, %D0",
1165         units     => [ "GP" ],
1166 },
1167
1168 l_Load => {
1169         op_flags  => "L|F",
1170         cmp_attr  => "return 1;",
1171         outs      => [ "res", "M" ],
1172         arity     => 2,
1173 },
1174
1175 l_Store => {
1176         op_flags  => "L|F",
1177         cmp_attr  => "return 1;",
1178         state     => "exc_pinned",
1179         arity     => 3,
1180         mode      => "mode_M",
1181 },
1182
1183 Store => {
1184         op_flags  => "L|F",
1185         state     => "exc_pinned",
1186         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
1187         ins       => [ "base", "index", "mem", "val" ],
1188         emit      => '. mov%M %SI3, %AM',
1189         latency   => 2,
1190         units     => [ "GP" ],
1191         mode      => "mode_M",
1192 },
1193
1194 Store8Bit => {
1195         op_flags  => "L|F",
1196         state     => "exc_pinned",
1197         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none" ] },
1198         ins       => [ "base", "index", "mem", "val" ],
1199         emit      => '. mov%M %SB3, %AM',
1200         latency   => 2,
1201         units     => [ "GP" ],
1202         mode      => "mode_M",
1203 },
1204
1205 Lea => {
1206         irn_flags => "R",
1207         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
1208         ins       => [ "base", "index" ],
1209         emit      => '. leal %AM, %D0',
1210         latency   => 2,
1211         units     => [ "GP" ],
1212         mode      => $mode_gp,
1213 # well this isn't true for Lea, but we often transform Lea back to Add, Inc
1214 # or Dec, so we set the flag
1215         modified_flags => 1,
1216 },
1217
1218 Push => {
1219         reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
1220         ins       => [ "base", "index", "mem", "val", "stack" ],
1221         emit      => '. push%M %unop3',
1222         outs      => [ "stack:I|S", "M" ],
1223         am        => "source,binary",
1224         latency   => 2,
1225         units     => [ "GP" ],
1226 },
1227
1228 Pop => {
1229         reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "esp", "gp", "none" ] },
1230         emit      => '. pop%M %DAM1',
1231         outs      => [ "stack:I|S", "res", "M" ],
1232         ins       => [ "base", "index", "mem", "stack" ],
1233         am        => "dest,unary",
1234         latency   => 3, # Pop is more expensive than Push on Athlon
1235         units     => [ "GP" ],
1236 },
1237
1238 Enter => {
1239         reg_req   => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
1240         emit      => '. enter',
1241         outs      => [ "frame:I", "stack:I|S", "M" ],
1242         latency   => 15,
1243         units     => [ "GP" ],
1244 },
1245
1246 Leave => {
1247         reg_req   => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
1248         emit      => '. leave',
1249         outs      => [ "frame:I", "stack:I|S" ],
1250         latency   => 3,
1251         units     => [ "GP" ],
1252 },
1253
1254 AddSP => {
1255         irn_flags => "I",
1256         state     => "pinned",
1257         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
1258         ins       => [ "base", "index", "mem", "stack", "size" ],
1259         am        => "source,binary",
1260         emit      => '. addl %binop',
1261         outs      => [ "stack:S", "M" ],
1262         units     => [ "GP" ],
1263         modified_flags => $status_flags
1264 },
1265
1266 SubSP => {
1267 #irn_flags => "I",
1268         state     => "pinned",
1269         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
1270         ins       => [ "base", "index", "mem", "stack", "size" ],
1271         am        => "source,binary",
1272         emit      => ". subl %binop\n".
1273                      ". movl %%esp, %D1",
1274         outs      => [ "stack:I|S", "addr", "M" ],
1275         units     => [ "GP" ],
1276         modified_flags => $status_flags
1277 },
1278
1279 LdTls => {
1280         irn_flags => "R",
1281         reg_req   => { out => [ "gp" ] },
1282         units     => [ "GP" ],
1283 },
1284
1285 # the int instruction
1286 int => {
1287         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1288         mode      => "mode_M",
1289         emit      => '. int %SI0',
1290         units     => [ "GP" ],
1291         cmp_attr  => "return 1;",
1292 },
1293
1294
1295 #-----------------------------------------------------------------------------#
1296 #   _____ _____ ______    __ _             _                     _            #
1297 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
1298 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1299 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1300 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1301 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1302 #-----------------------------------------------------------------------------#
1303
1304 xZero => {
1305         irn_flags => "R",
1306         reg_req   => { out => [ "xmm" ] },
1307         emit      => '. xorp%XSD %D0, %D0',
1308         latency   => 3,
1309         units     => [ "SSE" ],
1310         mode      => "mode_E",
1311 },
1312
1313 # commutative operations
1314
1315 xAdd => {
1316         irn_flags => "R",
1317         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1318         ins       => [ "base", "index", "mem", "left", "right" ],
1319         am        => "source,binary",
1320         emit      => '. add%XXM %binop',
1321         latency   => 4,
1322         units     => [ "SSE" ],
1323         mode      => "mode_E",
1324 },
1325
1326 xMul => {
1327         irn_flags => "R",
1328         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1329         ins       => [ "base", "index", "mem", "left", "right" ],
1330         am        => "source,binary",
1331         emit      => '. mul%XXM %binop',
1332         latency   => 4,
1333         units     => [ "SSE" ],
1334         mode      => "mode_E",
1335 },
1336
1337 xMax => {
1338         irn_flags => "R",
1339         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1340         ins       => [ "base", "index", "mem", "left", "right" ],
1341         am        => "source,binary",
1342         emit      => '. max%XXM %binop',
1343         latency   => 2,
1344         units     => [ "SSE" ],
1345         mode      => "mode_E",
1346 },
1347
1348 xMin => {
1349         irn_flags => "R",
1350         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1351         ins       => [ "base", "index", "mem", "left", "right" ],
1352         am        => "source,binary",
1353         emit      => '. min%XXM %binop',
1354         latency   => 2,
1355         units     => [ "SSE" ],
1356         mode      => "mode_E",
1357 },
1358
1359 xAnd => {
1360         irn_flags => "R",
1361         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1362         ins       => [ "base", "index", "mem", "left", "right" ],
1363         am        => "source,binary",
1364         emit      => '. andp%XSD %binop',
1365         latency   => 3,
1366         units     => [ "SSE" ],
1367         mode      => "mode_E",
1368 },
1369
1370 xOr => {
1371         irn_flags => "R",
1372         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1373         ins       => [ "base", "index", "mem", "left", "right" ],
1374         am        => "source,binary",
1375         emit      => '. orp%XSD %binop',
1376         units     => [ "SSE" ],
1377         mode      => "mode_E",
1378 },
1379
1380 xXor => {
1381         irn_flags => "R",
1382         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1383         ins       => [ "base", "index", "mem", "left", "right" ],
1384         am        => "source,binary",
1385         emit      => '. xorp%XSD %binop',
1386         latency   => 3,
1387         units     => [ "SSE" ],
1388         mode      => "mode_E",
1389 },
1390
1391 # not commutative operations
1392
1393 xAndNot => {
1394         irn_flags => "R",
1395         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1396         ins       => [ "base", "index", "mem", "left", "right" ],
1397         am        => "source,binary",
1398         emit      => '. andnp%XSD %binop',
1399         latency   => 3,
1400         units     => [ "SSE" ],
1401         mode      => "mode_E",
1402 },
1403
1404 xSub => {
1405         irn_flags => "R",
1406         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1407         ins       => [ "base", "index", "mem", "left", "right" ],
1408         am        => "source,binary",
1409         emit      => '. sub%XXM %binop',
1410         latency   => 4,
1411         units     => [ "SSE" ],
1412         mode      => "mode_E",
1413 },
1414
1415 xDiv => {
1416         irn_flags => "R",
1417         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
1418         ins       => [ "base", "index", "mem", "left", "right" ],
1419         am        => "source,binary",
1420         outs      => [ "res", "M" ],
1421         emit      => '. div%XXM %binop',
1422         latency   => 16,
1423         units     => [ "SSE" ],
1424 },
1425
1426 # other operations
1427
1428 Ucomi => {
1429         irn_flags => "R",
1430         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eflags" ] },
1431         ins       => [ "base", "index", "mem", "left", "right" ],
1432         outs      => [ "flags" ],
1433         am        => "source,binary",
1434         attr      => "int flipped",
1435         init_attr => "attr->data.cmp_flipped = flipped;",
1436         emit      => ' .ucomi%XXM %binop',
1437         latency   => 3,
1438         units     => [ "SSE" ],
1439         mode      => $mode_flags,
1440         modified_flags => 1,
1441 },
1442
1443 # Load / Store
1444
1445 xLoad => {
1446         op_flags  => "L|F",
1447         state     => "exc_pinned",
1448         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
1449         ins       => [ "base", "index", "mem" ],
1450         emit      => '. mov%XXM %AM, %D0',
1451         attr      => "ir_mode *load_mode",
1452         init_attr => "attr->ls_mode = load_mode;",
1453         outs      => [ "res", "M" ],
1454         latency   => 0,
1455         units     => [ "SSE" ],
1456 },
1457
1458 xStore => {
1459         op_flags => "L|F",
1460         state    => "exc_pinned",
1461         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1462         ins       => [ "base", "index", "mem", "val" ],
1463         emit     => '. mov%XXM %S3, %AM',
1464         latency  => 0,
1465         units    => [ "SSE" ],
1466         mode     => "mode_M",
1467 },
1468
1469 xStoreSimple => {
1470         op_flags => "L|F",
1471         state    => "exc_pinned",
1472         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1473         ins      => [ "base", "index", "mem", "val" ],
1474         emit     => '. mov%XXM %S3, %AM',
1475         latency  => 0,
1476         units    => [ "SSE" ],
1477         mode     => "mode_M",
1478 },
1479
1480 CvtSI2SS => {
1481         op_flags => "L|F",
1482         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1483         ins      => [ "base", "index", "mem", "val" ],
1484         am       => "source,unary",
1485         emit     => '. cvtsi2ss %unop3, %D0',
1486         latency  => 2,
1487         units    => [ "SSE" ],
1488         mode     => $mode_xmm
1489 },
1490
1491 CvtSI2SD => {
1492         op_flags => "L|F",
1493         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1494         ins      => [ "base", "index", "mem", "val" ],
1495         am       => "source,unary",
1496         emit     => '. cvtsi2sd %unop3, %D0',
1497         latency  => 2,
1498         units    => [ "SSE" ],
1499         mode     => $mode_xmm
1500 },
1501
1502
1503 l_X87toSSE => {
1504         op_flags => "L|F",
1505         cmp_attr => "return 1;",
1506         arity    => 3,
1507 },
1508
1509 l_SSEtoX87 => {
1510         op_flags => "L|F",
1511         cmp_attr => "return 1;",
1512         arity    => 3,
1513 },
1514
1515 # CopyB
1516
1517 CopyB => {
1518         op_flags => "F|H",
1519         state    => "pinned",
1520         reg_req  => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1521         outs     => [ "DST", "SRC", "CNT", "M" ],
1522         units    => [ "GP" ],
1523 # we don't care about this flag, so no need to mark this node
1524 #       modified_flags => [ "DF" ]
1525 },
1526
1527 CopyB_i => {
1528         op_flags => "F|H",
1529         state    => "pinned",
1530         reg_req  => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
1531         outs     => [ "DST", "SRC", "M" ],
1532         units    => [ "GP" ],
1533 # we don't care about this flag, so no need to mark this node
1534 #       modified_flags => [ "DF" ]
1535 },
1536
1537 # Conversions
1538
1539 Conv_I2I => {
1540         state     => "exc_pinned",
1541         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] },
1542         ins       => [ "base", "index", "mem", "val" ],
1543         am        => "source,unary",
1544         units     => [ "GP" ],
1545         attr      => "ir_mode *smaller_mode",
1546         init_attr => "attr->ls_mode = smaller_mode;",
1547         mode      => $mode_gp,
1548 },
1549
1550 Conv_I2I8Bit => {
1551         state     => "exc_pinned",
1552         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "gp", "none" ] },
1553         ins       => [ "base", "index", "mem", "val" ],
1554         am        => "source,unary",
1555         units     => [ "GP" ],
1556         attr      => "ir_mode *smaller_mode",
1557         init_attr => "attr->ls_mode = smaller_mode;",
1558         mode      => $mode_gp,
1559 },
1560
1561 Conv_I2FP => {
1562         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
1563         ins      => [ "base", "index", "mem", "val" ],
1564         am       => "source,unary",
1565         latency  => 10,
1566         units    => [ "SSE" ],
1567         mode     => "mode_E",
1568 },
1569
1570 Conv_FP2I => {
1571         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1572         ins      => [ "base", "index", "mem", "val" ],
1573         am       => "source,unary",
1574         latency  => 10,
1575         units    => [ "SSE" ],
1576         mode     => $mode_gp,
1577 },
1578
1579 Conv_FP2FP => {
1580         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1581         ins      => [ "base", "index", "mem", "val" ],
1582         am       => "source,unary",
1583         latency  => 8,
1584         units    => [ "SSE" ],
1585         mode     => "mode_E",
1586 },
1587
1588 #----------------------------------------------------------#
1589 #        _      _               _    __ _             _    #
1590 #       (_)    | |             | |  / _| |           | |   #
1591 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
1592 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
1593 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
1594 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1595 #                 | |                                      #
1596 #  _ __   ___   __| | ___  ___                             #
1597 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
1598 # | | | | (_) | (_| |  __/\__ \                            #
1599 # |_| |_|\___/ \__,_|\___||___/                            #
1600 #----------------------------------------------------------#
1601
1602 # spilling disabled for all float nodes for now, because the fpcw handler
1603 # runs before spilling and we might end up with wrong fpcw then
1604
1605 vfadd => {
1606 #       irn_flags => "R",
1607         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1608         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1609         am        => "source,binary",
1610         latency   => 4,
1611         units     => [ "VFP" ],
1612         mode      => "mode_E",
1613         attr_type => "ia32_x87_attr_t",
1614 },
1615
1616 vfmul => {
1617 #       irn_flags => "R",
1618         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1619         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1620         am        => "source,binary",
1621         latency   => 4,
1622         units     => [ "VFP" ],
1623         mode      => "mode_E",
1624         attr_type => "ia32_x87_attr_t",
1625 },
1626
1627 l_vfmul => {
1628         op_flags  => "C",
1629         cmp_attr  => "return 1;",
1630         arity     => 2,
1631 },
1632
1633 vfsub => {
1634 #       irn_flags => "R",
1635         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1636         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1637         am        => "source,binary",
1638         latency   => 4,
1639         units     => [ "VFP" ],
1640         mode      => "mode_E",
1641         attr_type => "ia32_x87_attr_t",
1642 },
1643
1644 l_vfsub => {
1645         cmp_attr  => "return 1;",
1646         arity     => 2,
1647 },
1648
1649 vfdiv => {
1650         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
1651         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1652         am        => "source,binary",
1653         outs      => [ "res", "M" ],
1654         latency   => 20,
1655         units     => [ "VFP" ],
1656         attr_type => "ia32_x87_attr_t",
1657 },
1658
1659 l_vfdiv => {
1660         cmp_attr  => "return 1;",
1661         outs      => [ "res", "M" ],
1662         arity     => 2,
1663 },
1664
1665 vfprem => {
1666         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1667         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1668         latency   => 20,
1669         units     => [ "VFP" ],
1670         mode      => "mode_E",
1671         attr_type => "ia32_x87_attr_t",
1672 },
1673
1674 l_vfprem => {
1675         cmp_attr  => "return 1;",
1676         arity     => 2,
1677 },
1678
1679 vfabs => {
1680         irn_flags => "R",
1681         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1682         ins       => [ "value" ],
1683         latency   => 2,
1684         units     => [ "VFP" ],
1685         mode      => "mode_E",
1686         attr_type => "ia32_x87_attr_t",
1687 },
1688
1689 vfchs => {
1690         irn_flags => "R",
1691         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1692         ins       => [ "value" ],
1693         latency   => 2,
1694         units     => [ "VFP" ],
1695         mode      => "mode_E",
1696         attr_type => "ia32_x87_attr_t",
1697 },
1698
1699 # virtual Load and Store
1700
1701 vfld => {
1702         op_flags  => "L|F",
1703         state     => "exc_pinned",
1704         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1705         ins       => [ "base", "index", "mem" ],
1706         outs      => [ "res", "M" ],
1707         attr      => "ir_mode *load_mode",
1708         init_attr => "attr->attr.ls_mode = load_mode;",
1709         latency   => 2,
1710         units     => [ "VFP" ],
1711         attr_type => "ia32_x87_attr_t",
1712 },
1713
1714 vfst => {
1715         op_flags  => "L|F",
1716         state     => "exc_pinned",
1717         reg_req   => { in => [ "gp", "gp", "none", "vfp" ] },
1718         ins       => [ "base", "index", "mem", "val" ],
1719         attr      => "ir_mode *store_mode",
1720         init_attr => "attr->attr.ls_mode = store_mode;",
1721         latency   => 2,
1722         units     => [ "VFP" ],
1723         mode      => "mode_M",
1724         attr_type => "ia32_x87_attr_t",
1725 },
1726
1727 # Conversions
1728
1729 vfild => {
1730         state     => "exc_pinned",
1731         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1732         outs      => [ "res", "M" ],
1733         ins       => [ "base", "index", "mem" ],
1734         latency   => 4,
1735         units     => [ "VFP" ],
1736         attr_type => "ia32_x87_attr_t",
1737 },
1738
1739 l_vfild => {
1740         cmp_attr  => "return 1;",
1741         outs      => [ "res", "M" ],
1742         arity     => 2,
1743 },
1744
1745 vfist => {
1746         state     => "exc_pinned",
1747         reg_req   => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
1748         ins       => [ "base", "index", "mem", "val", "fpcw" ],
1749         latency   => 4,
1750         units     => [ "VFP" ],
1751         mode      => "mode_M",
1752         attr_type => "ia32_x87_attr_t",
1753 },
1754
1755 l_vfist => {
1756         cmp_attr  => "return 1;",
1757         state     => "exc_pinned",
1758         arity     => 3,
1759         mode      => "mode_M",
1760 },
1761
1762
1763 # constants
1764
1765 vfldz => {
1766         irn_flags => "R",
1767         reg_req   => { out => [ "vfp" ] },
1768         latency   => 4,
1769         units     => [ "VFP" ],
1770         mode      => "mode_E",
1771         attr_type => "ia32_x87_attr_t",
1772 },
1773
1774 vfld1 => {
1775         irn_flags => "R",
1776         reg_req   => { out => [ "vfp" ] },
1777         latency   => 4,
1778         units     => [ "VFP" ],
1779         mode      => "mode_E",
1780         attr_type => "ia32_x87_attr_t",
1781 },
1782
1783 vfldpi => {
1784         irn_flags => "R",
1785         reg_req   => { out => [ "vfp" ] },
1786         latency   => 4,
1787         units     => [ "VFP" ],
1788         mode      => "mode_E",
1789         attr_type => "ia32_x87_attr_t",
1790 },
1791
1792 vfldln2 => {
1793         irn_flags => "R",
1794         reg_req   => { out => [ "vfp" ] },
1795         latency   => 4,
1796         units     => [ "VFP" ],
1797         mode      => "mode_E",
1798         attr_type => "ia32_x87_attr_t",
1799 },
1800
1801 vfldlg2 => {
1802         irn_flags => "R",
1803         reg_req   => { out => [ "vfp" ] },
1804         latency   => 4,
1805         units     => [ "VFP" ],
1806         mode      => "mode_E",
1807         attr_type => "ia32_x87_attr_t",
1808 },
1809
1810 vfldl2t => {
1811         irn_flags => "R",
1812         reg_req   => { out => [ "vfp" ] },
1813         latency   => 4,
1814         units     => [ "VFP" ],
1815         mode      => "mode_E",
1816         attr_type => "ia32_x87_attr_t",
1817 },
1818
1819 vfldl2e => {
1820         irn_flags => "R",
1821         reg_req   => { out => [ "vfp" ] },
1822         latency   => 4,
1823         units     => [ "VFP" ],
1824         mode      => "mode_E",
1825         attr_type => "ia32_x87_attr_t",
1826 },
1827
1828 # other
1829
1830 vFucomFnstsw => {
1831 # we can't allow to rematerialize this node so we don't have
1832 #  accidently produce Phi(Fucom, Fucom(flipped))
1833 #       irn_flags => "R",
1834         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
1835         ins       => [ "left", "right" ],
1836         outs      => [ "flags" ],
1837         attr      => "int flipped",
1838         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1839         latency   => 3,
1840         units     => [ "VFP" ],
1841         attr_type => "ia32_x87_attr_t",
1842         mode      => $mode_gp
1843 },
1844
1845 vFucomi => {
1846         irn_flags => "R",
1847         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
1848         ins       => [ "left", "right" ],
1849         outs      => [ "flags" ],
1850         attr      => "int flipped",
1851         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1852         latency   => 3,
1853         units     => [ "VFP" ],
1854         attr_type => "ia32_x87_attr_t",
1855         mode      => $mode_gp
1856 },
1857
1858 vFtstFnstsw => {
1859 #       irn_flags => "R",
1860         reg_req   => { in => [ "vfp" ], out => [ "eax" ] },
1861         ins       => [ "left" ],
1862         outs      => [ "flags" ],
1863         attr      => "int flipped",
1864         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1865         latency   => 3,
1866         units     => [ "VFP" ],
1867         attr_type => "ia32_x87_attr_t",
1868         mode      => $mode_gp
1869 },
1870
1871 Sahf => {
1872         irn_flags => "R",
1873         reg_req   => { in => [ "eax" ], out => [ "eflags" ] },
1874         ins       => [ "val" ],
1875         outs      => [ "flags" ],
1876         emit      => '. sahf',
1877         units     => [ "GP" ],
1878         mode      => $mode_flags,
1879 },
1880
1881 #------------------------------------------------------------------------#
1882 #       ___ _____    __ _             _                     _            #
1883 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1884 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1885 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1886 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1887 #------------------------------------------------------------------------#
1888
1889 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
1890 #       are swapped, we work this around in the emitter...
1891
1892 fadd => {
1893         op_flags  => "R",
1894         rd_constructor => "NONE",
1895         reg_req   => { },
1896         emit      => '. fadd%XM %x87_binop',
1897         attr_type => "ia32_x87_attr_t",
1898 },
1899
1900 faddp => {
1901         op_flags  => "R",
1902         rd_constructor => "NONE",
1903         reg_req   => { },
1904         emit      => '. faddp%XM %x87_binop',
1905         attr_type => "ia32_x87_attr_t",
1906 },
1907
1908 fmul => {
1909         op_flags  => "R",
1910         rd_constructor => "NONE",
1911         reg_req   => { },
1912         emit      => '. fmul%XM %x87_binop',
1913         attr_type => "ia32_x87_attr_t",
1914 },
1915
1916 fmulp => {
1917         op_flags  => "R",
1918         rd_constructor => "NONE",
1919         reg_req   => { },
1920         emit      => '. fmulp%XM %x87_binop',,
1921         attr_type => "ia32_x87_attr_t",
1922 },
1923
1924 fsub => {
1925         op_flags  => "R",
1926         rd_constructor => "NONE",
1927         reg_req   => { },
1928         emit      => '. fsub%XM %x87_binop',
1929         attr_type => "ia32_x87_attr_t",
1930 },
1931
1932 fsubp => {
1933         op_flags  => "R",
1934         rd_constructor => "NONE",
1935         reg_req   => { },
1936 # see note about gas bugs
1937         emit      => '. fsubrp%XM %x87_binop',
1938         attr_type => "ia32_x87_attr_t",
1939 },
1940
1941 fsubr => {
1942         op_flags  => "R",
1943         rd_constructor => "NONE",
1944         irn_flags => "R",
1945         reg_req   => { },
1946         emit      => '. fsubr%XM %x87_binop',
1947         attr_type => "ia32_x87_attr_t",
1948 },
1949
1950 fsubrp => {
1951         op_flags  => "R",
1952         rd_constructor => "NONE",
1953         irn_flags => "R",
1954         reg_req   => { },
1955 # see note about gas bugs
1956         emit      => '. fsubp%XM %x87_binop',
1957         attr_type => "ia32_x87_attr_t",
1958 },
1959
1960 fprem => {
1961         op_flags  => "R",
1962         rd_constructor => "NONE",
1963         reg_req   => { },
1964         emit      => '. fprem1',
1965         attr_type => "ia32_x87_attr_t",
1966 },
1967
1968 # this node is just here, to keep the simulator running
1969 # we can omit this when a fprem simulation function exists
1970 fpremp => {
1971         op_flags  => "R",
1972         rd_constructor => "NONE",
1973         reg_req   => { },
1974         emit      => '. fprem1',
1975         attr_type => "ia32_x87_attr_t",
1976 },
1977
1978 fdiv => {
1979         op_flags  => "R",
1980         rd_constructor => "NONE",
1981         reg_req   => { },
1982         emit      => '. fdiv%XM %x87_binop',
1983         attr_type => "ia32_x87_attr_t",
1984 },
1985
1986 fdivp => {
1987         op_flags  => "R",
1988         rd_constructor => "NONE",
1989         reg_req   => { },
1990 # see note about gas bugs
1991         emit      => '. fdivrp%XM %x87_binop',
1992         attr_type => "ia32_x87_attr_t",
1993 },
1994
1995 fdivr => {
1996         op_flags  => "R",
1997         rd_constructor => "NONE",
1998         reg_req   => { },
1999         emit      => '. fdivr%XM %x87_binop',
2000         attr_type => "ia32_x87_attr_t",
2001 },
2002
2003 fdivrp => {
2004         op_flags  => "R",
2005         rd_constructor => "NONE",
2006         reg_req   => { },
2007 # see note about gas bugs
2008         emit      => '. fdivp%XM %x87_binop',
2009         attr_type => "ia32_x87_attr_t",
2010 },
2011
2012 fabs => {
2013         op_flags  => "R",
2014         rd_constructor => "NONE",
2015         reg_req   => { },
2016         emit      => '. fabs',
2017         attr_type => "ia32_x87_attr_t",
2018 },
2019
2020 fchs => {
2021         op_flags  => "R|K",
2022         rd_constructor => "NONE",
2023         reg_req   => { },
2024         emit      => '. fchs',
2025         attr_type => "ia32_x87_attr_t",
2026 },
2027
2028 # x87 Load and Store
2029
2030 fld => {
2031         rd_constructor => "NONE",
2032         op_flags  => "R|L|F",
2033         state     => "exc_pinned",
2034         reg_req   => { },
2035         emit      => '. fld%XM %AM',
2036         attr_type => "ia32_x87_attr_t",
2037 },
2038
2039 fst => {
2040         rd_constructor => "NONE",
2041         op_flags  => "R|L|F",
2042         state     => "exc_pinned",
2043         reg_req   => { },
2044         emit      => '. fst%XM %AM',
2045         mode      => "mode_M",
2046         attr_type => "ia32_x87_attr_t",
2047 },
2048
2049 fstp => {
2050         rd_constructor => "NONE",
2051         op_flags  => "R|L|F",
2052         state     => "exc_pinned",
2053         reg_req   => { },
2054         emit      => '. fstp%XM %AM',
2055         mode      => "mode_M",
2056         attr_type => "ia32_x87_attr_t",
2057 },
2058
2059 # Conversions
2060
2061 fild => {
2062         op_flags  => "R",
2063         rd_constructor => "NONE",
2064         reg_req   => { },
2065         emit      => '. fild%M %AM',
2066         attr_type => "ia32_x87_attr_t",
2067 },
2068
2069 fist => {
2070         op_flags  => "R",
2071         state     => "exc_pinned",
2072         rd_constructor => "NONE",
2073         reg_req   => { },
2074         emit      => '. fist%M %AM',
2075         mode      => "mode_M",
2076         attr_type => "ia32_x87_attr_t",
2077 },
2078
2079 fistp => {
2080         op_flags  => "R",
2081         state     => "exc_pinned",
2082         rd_constructor => "NONE",
2083         reg_req   => { },
2084         emit      => '. fistp%M %AM',
2085         mode      => "mode_M",
2086         attr_type => "ia32_x87_attr_t",
2087 },
2088
2089 # constants
2090
2091 fldz => {
2092         op_flags  => "R|c|K",
2093         irn_flags => "R",
2094         reg_req   => { out => [ "vfp" ] },
2095         emit      => '. fldz',
2096         attr_type => "ia32_x87_attr_t",
2097 },
2098
2099 fld1 => {
2100         op_flags  => "R|c|K",
2101         irn_flags => "R",
2102         reg_req   => { out => [ "vfp" ] },
2103         emit      => '. fld1',
2104         attr_type => "ia32_x87_attr_t",
2105 },
2106
2107 fldpi => {
2108         op_flags  => "R|c|K",
2109         irn_flags => "R",
2110         reg_req   => { out => [ "vfp" ] },
2111         emit      => '. fldpi',
2112         attr_type => "ia32_x87_attr_t",
2113 },
2114
2115 fldln2 => {
2116         op_flags  => "R|c|K",
2117         irn_flags => "R",
2118         reg_req   => { out => [ "vfp" ] },
2119         emit      => '. fldln2',
2120         attr_type => "ia32_x87_attr_t",
2121 },
2122
2123 fldlg2 => {
2124         op_flags  => "R|c|K",
2125         irn_flags => "R",
2126         reg_req   => { out => [ "vfp" ] },
2127         emit      => '. fldlg2',
2128         attr_type => "ia32_x87_attr_t",
2129 },
2130
2131 fldl2t => {
2132         op_flags  => "R|c|K",
2133         irn_flags => "R",
2134         reg_req   => { out => [ "vfp" ] },
2135         emit      => '. fldll2t',
2136         attr_type => "ia32_x87_attr_t",
2137 },
2138
2139 fldl2e => {
2140         op_flags  => "R|c|K",
2141         irn_flags => "R",
2142         reg_req   => { out => [ "vfp" ] },
2143         emit      => '. fldl2e',
2144         attr_type => "ia32_x87_attr_t",
2145 },
2146
2147 # fxch, fpush, fpop
2148 # Note that it is NEVER allowed to do CSE on these nodes
2149 # Moreover, note the virtual register requierements!
2150
2151 fxch => {
2152         op_flags  => "R|K",
2153         reg_req   => { },
2154         cmp_attr  => "return 1;",
2155         emit      => '. fxch %X0',
2156         attr_type => "ia32_x87_attr_t",
2157         mode      => "mode_ANY",
2158 },
2159
2160 fpush => {
2161         op_flags  => "R|K",
2162         reg_req   => {},
2163         cmp_attr  => "return 1;",
2164         emit      => '. fld %X0',
2165         attr_type => "ia32_x87_attr_t",
2166         mode      => "mode_ANY",
2167 },
2168
2169 fpushCopy => {
2170         op_flags  => "R",
2171         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2172         cmp_attr  => "return 1;",
2173         emit      => '. fld %X0',
2174         attr_type => "ia32_x87_attr_t",
2175 },
2176
2177 fpop => {
2178         op_flags  => "K",
2179         reg_req   => { },
2180         cmp_attr  => "return 1;",
2181         emit      => '. fstp %X0',
2182         attr_type => "ia32_x87_attr_t",
2183         mode      => "mode_ANY",
2184 },
2185
2186 ffreep => {
2187         op_flags  => "K",
2188         reg_req   => { },
2189         cmp_attr  => "return 1;",
2190         emit      => '. ffreep %X0',
2191         attr_type => "ia32_x87_attr_t",
2192         mode      => "mode_ANY",
2193 },
2194
2195 emms => {
2196         op_flags  => "K",
2197         reg_req   => { },
2198         cmp_attr  => "return 1;",
2199         emit      => '. emms',
2200         attr_type => "ia32_x87_attr_t",
2201         mode      => "mode_ANY",
2202 },
2203
2204 femms => {
2205         op_flags  => "K",
2206         reg_req   => { },
2207         cmp_attr  => "return 1;",
2208         emit      => '. femms',
2209         attr_type => "ia32_x87_attr_t",
2210         mode      => "mode_ANY",
2211 },
2212
2213 # compare
2214
2215 FucomFnstsw => {
2216         reg_req   => { },
2217         emit      => ". fucom %X1\n".
2218                      ". fnstsw",
2219         attr_type => "ia32_x87_attr_t",
2220 },
2221
2222 FucompFnstsw => {
2223         reg_req   => { },
2224         emit      => ". fucomp %X1\n".
2225                      ". fnstsw",
2226         attr_type => "ia32_x87_attr_t",
2227 },
2228
2229 FucomppFnstsw => {
2230         reg_req   => { },
2231         emit      => ". fucompp\n".
2232                      ". fnstsw",
2233         attr_type => "ia32_x87_attr_t",
2234 },
2235
2236 Fucomi => {
2237         reg_req   => { },
2238         emit      => '. fucomi %X1',
2239         attr_type => "ia32_x87_attr_t",
2240 },
2241
2242 Fucompi => {
2243         reg_req   => { },
2244         emit      => '. fucompi %X1',
2245         attr_type => "ia32_x87_attr_t",
2246 },
2247
2248 FtstFnstsw => {
2249         reg_req   => { },
2250         emit      => ". ftst\n".
2251                      ". fnstsw",
2252         attr_type => "ia32_x87_attr_t",
2253 },
2254
2255
2256 # -------------------------------------------------------------------------------- #
2257 #  ____ ____  _____                  _                               _             #
2258 # / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
2259 # \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
2260 #  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
2261 # |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
2262 #                                                                                  #
2263 # -------------------------------------------------------------------------------- #
2264
2265
2266 # Spilling and reloading of SSE registers, hardcoded, not generated #
2267
2268 xxLoad => {
2269         op_flags  => "L|F",
2270         state     => "exc_pinned",
2271         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2272         emit      => '. movdqu %D0, %AM',
2273         outs      => [ "res", "M" ],
2274         units     => [ "SSE" ],
2275 },
2276
2277 xxStore => {
2278         op_flags => "L|F",
2279         state    => "exc_pinned",
2280         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
2281         ins      => [ "base", "index", "mem", "val" ],
2282         emit     => '. movdqu %binop',
2283         units    => [ "SSE" ],
2284         mode     => "mode_M",
2285 },
2286
2287 ); # end of %nodes
2288
2289 # Include the generated SIMD node specification written by the SIMD optimization
2290 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2291 unless ($return = do $my_script_name) {
2292         warn "couldn't parse $my_script_name: $@" if $@;
2293         warn "couldn't do $my_script_name: $!"    unless defined $return;
2294         warn "couldn't run $my_script_name"       unless $return;
2295 }