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