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