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