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