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