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