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