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