add assert for not getting bad out regs, and fix some bugs related to this
[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_r1 !in_r3" ] },
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_r1 !in_r3" ] },
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" ] },
1003         ins       => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
1004         am        => "source,binary",
1005         attr      => "pn_Cmp pn_code",
1006         init_attr => "attr->pn_code = pn_code;",
1007         latency   => 1,
1008         units     => [ "GP" ],
1009         mode      => $mode_gp,
1010 },
1011
1012 Jcc => {
1013         state     => "pinned",
1014         op_flags  => "L|X|Y",
1015         reg_req   => { in  => [ "eflags" ], out => [ "none", "none" ] },
1016         ins       => [ "eflags" ],
1017         outs      => [ "false", "true" ],
1018         attr      => "pn_Cmp pnc",
1019         init_attr => "attr->pn_code = pnc;",
1020         latency   => 2,
1021         units     => [ "BRANCH" ],
1022 },
1023
1024 SwitchJmp => {
1025         state     => "pinned",
1026         op_flags  => "L|X|Y",
1027         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1028         latency   => 3,
1029         units     => [ "BRANCH" ],
1030         mode      => "mode_T",
1031         modified_flags => $status_flags
1032 },
1033
1034 IJmp => {
1035         state     => "pinned",
1036         op_flags  => "X",
1037         reg_req   => { in => [ "gp" ] },
1038         emit      => '. jmp *%S0',
1039         units     => [ "BRANCH" ],
1040         mode      => "mode_X",
1041 },
1042
1043 Const => {
1044         op_flags  => "c",
1045         irn_flags => "R",
1046         reg_req   => { out => [ "gp" ] },
1047         units     => [ "GP" ],
1048         attr      => "ir_entity *symconst, int symconst_sign, long offset",
1049         attr_type => "ia32_immediate_attr_t",
1050         mode      => $mode_gp,
1051 # depends on the const and is set in ia32_transform
1052 # modified_flags => $status_flags
1053 },
1054
1055 Unknown_GP => {
1056         state     => "pinned",
1057         op_flags  => "c",
1058         irn_flags => "I",
1059         reg_req   => { out => [ "gp_UKNWN" ] },
1060         units     => [],
1061         emit      => "",
1062         mode      => $mode_gp
1063 },
1064
1065 Unknown_VFP => {
1066         state     => "pinned",
1067         op_flags  => "c",
1068         irn_flags => "I",
1069         reg_req   => { out => [ "vfp_UKNWN" ] },
1070         units     => [],
1071         emit      => "",
1072         mode      => "mode_E",
1073         attr_type => "ia32_x87_attr_t",
1074 },
1075
1076 Unknown_XMM => {
1077         state     => "pinned",
1078         op_flags  => "c",
1079         irn_flags => "I",
1080         reg_req   => { out => [ "xmm_UKNWN" ] },
1081         units     => [],
1082         emit      => "",
1083         mode      => "mode_E"
1084 },
1085
1086 NoReg_GP => {
1087         state     => "pinned",
1088         op_flags  => "c",
1089         irn_flags => "I",
1090         reg_req   => { out => [ "gp_NOREG" ] },
1091         units     => [],
1092         emit      => "",
1093         mode      => $mode_gp
1094 },
1095
1096 NoReg_VFP => {
1097         state     => "pinned",
1098         op_flags  => "c",
1099         irn_flags => "I",
1100         reg_req   => { out => [ "vfp_NOREG" ] },
1101         units     => [],
1102         emit      => "",
1103         mode      => "mode_E",
1104         attr_type => "ia32_x87_attr_t",
1105 },
1106
1107 NoReg_XMM => {
1108         state     => "pinned",
1109         op_flags  => "c",
1110         irn_flags => "I",
1111         reg_req   => { out => [ "xmm_NOREG" ] },
1112         units     => [],
1113         emit      => "",
1114         mode      => "mode_E"
1115 },
1116
1117 ChangeCW => {
1118         state     => "pinned",
1119         op_flags  => "c",
1120         irn_flags => "I",
1121         reg_req   => { out => [ "fp_cw" ] },
1122         mode      => $mode_fpcw,
1123         latency   => 3,
1124         units     => [ "GP" ],
1125         modified_flags => $fpcw_flags
1126 },
1127
1128 FldCW => {
1129         op_flags  => "L|F",
1130         state     => "pinned",
1131         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
1132         ins       => [ "base", "index", "mem" ],
1133         latency   => 5,
1134         emit      => ". fldcw %AM",
1135         mode      => $mode_fpcw,
1136         units     => [ "GP" ],
1137         modified_flags => $fpcw_flags
1138 },
1139
1140 FnstCW => {
1141         op_flags  => "L|F",
1142         state     => "pinned",
1143         reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1144         ins       => [ "base", "index", "mem", "fpcw" ],
1145         latency   => 5,
1146         emit      => ". fnstcw %AM",
1147         mode      => "mode_M",
1148         units     => [ "GP" ],
1149 },
1150
1151 Cltd => {
1152         # we should not rematrialize this node. It has very strict constraints.
1153         reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
1154         ins       => [ "val", "globbered" ],
1155         emit      => '. cltd',
1156         mode      => $mode_gp,
1157         units     => [ "GP" ],
1158 },
1159
1160 # Load / Store
1161 #
1162 # Note that we add additional latency values depending on address mode, so a
1163 # lateny of 0 for load is correct
1164
1165 Load => {
1166         op_flags  => "L|F",
1167         state     => "exc_pinned",
1168         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
1169         ins       => [ "base", "index", "mem" ],
1170         outs      => [ "res", "M" ],
1171         latency   => 0,
1172         emit      => ". mov%SE%ME%.l %AM, %D0",
1173         units     => [ "GP" ],
1174 },
1175
1176 l_Load => {
1177         op_flags  => "L|F",
1178         cmp_attr  => "return 1;",
1179         outs      => [ "res", "M" ],
1180         arity     => 2,
1181 },
1182
1183 l_Store => {
1184         op_flags  => "L|F",
1185         cmp_attr  => "return 1;",
1186         state     => "exc_pinned",
1187         arity     => 3,
1188         mode      => "mode_M",
1189 },
1190
1191 Store => {
1192         op_flags  => "L|F",
1193         state     => "exc_pinned",
1194         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
1195         ins       => [ "base", "index", "mem", "val" ],
1196         emit      => '. mov%M %SI3, %AM',
1197         latency   => 2,
1198         units     => [ "GP" ],
1199         mode      => "mode_M",
1200 },
1201
1202 Store8Bit => {
1203         op_flags  => "L|F",
1204         state     => "exc_pinned",
1205         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none" ] },
1206         ins       => [ "base", "index", "mem", "val" ],
1207         emit      => '. mov%M %SB3, %AM',
1208         latency   => 2,
1209         units     => [ "GP" ],
1210         mode      => "mode_M",
1211 },
1212
1213 Lea => {
1214         irn_flags => "R",
1215         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
1216         ins       => [ "base", "index" ],
1217         emit      => '. leal %AM, %D0',
1218         latency   => 2,
1219         units     => [ "GP" ],
1220         mode      => $mode_gp,
1221 # well this isn't true for Lea, but we often transform Lea back to Add, Inc
1222 # or Dec, so we set the flag
1223         modified_flags => 1,
1224 },
1225
1226 Push => {
1227         reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
1228         ins       => [ "base", "index", "mem", "val", "stack" ],
1229         emit      => '. push%M %unop3',
1230         outs      => [ "stack:I|S", "M" ],
1231         am        => "source,binary",
1232         latency   => 2,
1233         units     => [ "GP" ],
1234 },
1235
1236 Pop => {
1237         reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "esp", "gp", "none" ] },
1238         emit      => '. pop%M %DAM1',
1239         outs      => [ "stack:I|S", "res", "M" ],
1240         ins       => [ "base", "index", "mem", "stack" ],
1241         am        => "dest,unary",
1242         latency   => 3, # Pop is more expensive than Push on Athlon
1243         units     => [ "GP" ],
1244 },
1245
1246 Enter => {
1247         reg_req   => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
1248         emit      => '. enter',
1249         outs      => [ "frame:I", "stack:I|S", "M" ],
1250         latency   => 15,
1251         units     => [ "GP" ],
1252 },
1253
1254 Leave => {
1255         reg_req   => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
1256         emit      => '. leave',
1257         outs      => [ "frame:I", "stack:I|S" ],
1258         latency   => 3,
1259         units     => [ "GP" ],
1260 },
1261
1262 AddSP => {
1263         irn_flags => "I",
1264         state     => "pinned",
1265         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
1266         ins       => [ "base", "index", "mem", "stack", "size" ],
1267         am        => "source,binary",
1268         emit      => '. addl %binop',
1269         outs      => [ "stack:S", "M" ],
1270         units     => [ "GP" ],
1271         modified_flags => $status_flags
1272 },
1273
1274 SubSP => {
1275 #irn_flags => "I",
1276         state     => "pinned",
1277         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
1278         ins       => [ "base", "index", "mem", "stack", "size" ],
1279         am        => "source,binary",
1280         emit      => ". subl %binop\n".
1281                      ". movl %%esp, %D1",
1282         outs      => [ "stack:I|S", "addr", "M" ],
1283         units     => [ "GP" ],
1284         modified_flags => $status_flags
1285 },
1286
1287 LdTls => {
1288         irn_flags => "R",
1289         reg_req   => { out => [ "gp" ] },
1290         units     => [ "GP" ],
1291 },
1292
1293 # the int instruction
1294 int => {
1295         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1296         mode      => "mode_M",
1297         emit      => '. int %SI0',
1298         units     => [ "GP" ],
1299         cmp_attr  => "return 1;",
1300 },
1301
1302
1303 #-----------------------------------------------------------------------------#
1304 #   _____ _____ ______    __ _             _                     _            #
1305 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
1306 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1307 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1308 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1309 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1310 #-----------------------------------------------------------------------------#
1311
1312 xZero => {
1313         irn_flags => "R",
1314         reg_req   => { out => [ "xmm" ] },
1315         emit      => '. xorp%XSD %D0, %D0',
1316         latency   => 3,
1317         units     => [ "SSE" ],
1318         mode      => "mode_E",
1319 },
1320
1321 # commutative operations
1322
1323 xAdd => {
1324         irn_flags => "R",
1325         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1326         ins       => [ "base", "index", "mem", "left", "right" ],
1327         emit      => '. add%XXM %binop',
1328         latency   => 4,
1329         units     => [ "SSE" ],
1330         mode      => "mode_E",
1331 },
1332
1333 xMul => {
1334         irn_flags => "R",
1335         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1336         ins       => [ "base", "index", "mem", "left", "right" ],
1337         emit      => '. mul%XXM %binop',
1338         latency   => 4,
1339         units     => [ "SSE" ],
1340         mode      => "mode_E",
1341 },
1342
1343 xMax => {
1344         irn_flags => "R",
1345         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1346         ins       => [ "base", "index", "mem", "left", "right" ],
1347         emit      => '. max%XXM %binop',
1348         latency   => 2,
1349         units     => [ "SSE" ],
1350         mode      => "mode_E",
1351 },
1352
1353 xMin => {
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         emit      => '. min%XXM %binop',
1358         latency   => 2,
1359         units     => [ "SSE" ],
1360         mode      => "mode_E",
1361 },
1362
1363 xAnd => {
1364         irn_flags => "R",
1365         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1366         ins       => [ "base", "index", "mem", "left", "right" ],
1367         emit      => '. andp%XSD %binop',
1368         latency   => 3,
1369         units     => [ "SSE" ],
1370         mode      => "mode_E",
1371 },
1372
1373 xOr => {
1374         irn_flags => "R",
1375         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1376         ins       => [ "base", "index", "mem", "left", "right" ],
1377         emit      => '. orp%XSD %binop',
1378         units     => [ "SSE" ],
1379         mode      => "mode_E",
1380 },
1381
1382 xXor => {
1383         irn_flags => "R",
1384         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1385         ins       => [ "base", "index", "mem", "left", "right" ],
1386         emit      => '. xorp%XSD %binop',
1387         latency   => 3,
1388         units     => [ "SSE" ],
1389         mode      => "mode_E",
1390 },
1391
1392 # not commutative operations
1393
1394 xAndNot => {
1395         irn_flags => "R",
1396         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1397         ins       => [ "base", "index", "mem", "left", "right" ],
1398         emit      => '. andnp%XSD %binop',
1399         latency   => 3,
1400         units     => [ "SSE" ],
1401         mode      => "mode_E",
1402 },
1403
1404 xSub => {
1405         irn_flags => "R",
1406         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1407         ins       => [ "base", "index", "mem", "left", "right" ],
1408         emit      => '. sub%XXM %binop',
1409         latency   => 4,
1410         units     => [ "SSE" ],
1411         mode      => "mode_E",
1412 },
1413
1414 xDiv => {
1415         irn_flags => "R",
1416         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
1417         ins       => [ "base", "index", "mem", "left", "right" ],
1418         outs      => [ "res", "M" ],
1419         emit      => '. div%XXM %binop',
1420         latency   => 16,
1421         units     => [ "SSE" ],
1422 },
1423
1424 # other operations
1425
1426 Ucomi => {
1427         irn_flags => "R",
1428         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eflags" ] },
1429         ins       => [ "base", "index", "mem", "left", "right" ],
1430         outs      => [ "flags" ],
1431         am        => "source,binary",
1432         attr      => "int flipped",
1433         init_attr => "attr->data.cmp_flipped = flipped;",
1434         emit      => ' .ucomi%XXM %binop',
1435         latency   => 3,
1436         units     => [ "SSE" ],
1437         mode      => $mode_flags,
1438         modified_flags => 1,
1439 },
1440
1441 # Load / Store
1442
1443 xLoad => {
1444         op_flags  => "L|F",
1445         state     => "exc_pinned",
1446         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
1447         ins       => [ "base", "index", "mem" ],
1448         emit      => '. mov%XXM %AM, %D0',
1449         attr      => "ir_mode *load_mode",
1450         init_attr => "attr->ls_mode = load_mode;",
1451         outs      => [ "res", "M" ],
1452         latency   => 0,
1453         units     => [ "SSE" ],
1454 },
1455
1456 xStore => {
1457         op_flags => "L|F",
1458         state    => "exc_pinned",
1459         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1460         ins       => [ "base", "index", "mem", "val" ],
1461         emit     => '. mov%XXM %S3, %AM',
1462         latency  => 0,
1463         units    => [ "SSE" ],
1464         mode     => "mode_M",
1465 },
1466
1467 xStoreSimple => {
1468         op_flags => "L|F",
1469         state    => "exc_pinned",
1470         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1471         ins      => [ "base", "index", "mem", "val" ],
1472         emit     => '. mov%XXM %S3, %AM',
1473         latency  => 0,
1474         units    => [ "SSE" ],
1475         mode     => "mode_M",
1476 },
1477
1478 CvtSI2SS => {
1479         op_flags => "L|F",
1480         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1481         ins      => [ "base", "index", "mem", "val" ],
1482         emit     => '. cvtsi2ss %unop3, %D0',
1483         latency  => 2,
1484         units    => [ "SSE" ],
1485         mode     => $mode_xmm
1486 },
1487
1488 CvtSI2SD => {
1489         op_flags => "L|F",
1490         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1491         ins      => [ "base", "index", "mem", "val" ],
1492         emit     => '. cvtsi2sd %unop3, %D0',
1493         latency  => 2,
1494         units    => [ "SSE" ],
1495         mode     => $mode_xmm
1496 },
1497
1498
1499 l_X87toSSE => {
1500         op_flags => "L|F",
1501         cmp_attr => "return 1;",
1502         arity    => 3,
1503 },
1504
1505 l_SSEtoX87 => {
1506         op_flags => "L|F",
1507         cmp_attr => "return 1;",
1508         arity    => 3,
1509 },
1510
1511 # CopyB
1512
1513 CopyB => {
1514         op_flags => "F|H",
1515         state    => "pinned",
1516         reg_req  => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1517         outs     => [ "DST", "SRC", "CNT", "M" ],
1518         units    => [ "GP" ],
1519 # we don't care about this flag, so no need to mark this node
1520 #       modified_flags => [ "DF" ]
1521 },
1522
1523 CopyB_i => {
1524         op_flags => "F|H",
1525         state    => "pinned",
1526         reg_req  => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
1527         outs     => [ "DST", "SRC", "M" ],
1528         units    => [ "GP" ],
1529 # we don't care about this flag, so no need to mark this node
1530 #       modified_flags => [ "DF" ]
1531 },
1532
1533 # Conversions
1534
1535 Conv_I2I => {
1536         state     => "exc_pinned",
1537         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] },
1538         ins       => [ "base", "index", "mem", "val" ],
1539         units     => [ "GP" ],
1540         attr      => "ir_mode *smaller_mode",
1541         init_attr => "attr->ls_mode = smaller_mode;",
1542         mode      => $mode_gp,
1543 },
1544
1545 Conv_I2I8Bit => {
1546         state     => "exc_pinned",
1547         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "gp", "none" ] },
1548         ins       => [ "base", "index", "mem", "val" ],
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         latency  => 10,
1559         units    => [ "SSE" ],
1560         mode     => "mode_E",
1561 },
1562
1563 Conv_FP2I => {
1564         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1565         ins      => [ "base", "index", "mem", "val" ],
1566         latency  => 10,
1567         units    => [ "SSE" ],
1568         mode     => $mode_gp,
1569 },
1570
1571 Conv_FP2FP => {
1572         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1573         ins      => [ "base", "index", "mem", "val" ],
1574         latency  => 8,
1575         units    => [ "SSE" ],
1576         mode     => "mode_E",
1577 },
1578
1579 #----------------------------------------------------------#
1580 #        _      _               _    __ _             _    #
1581 #       (_)    | |             | |  / _| |           | |   #
1582 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
1583 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
1584 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
1585 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1586 #                 | |                                      #
1587 #  _ __   ___   __| | ___  ___                             #
1588 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
1589 # | | | | (_) | (_| |  __/\__ \                            #
1590 # |_| |_|\___/ \__,_|\___||___/                            #
1591 #----------------------------------------------------------#
1592
1593 # spilling disabled for all float nodes for now, because the fpcw handler
1594 # runs before spilling and we might end up with wrong fpcw then
1595
1596 vfadd => {
1597 #       irn_flags => "R",
1598         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1599         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1600         latency   => 4,
1601         units     => [ "VFP" ],
1602         mode      => "mode_E",
1603         attr_type => "ia32_x87_attr_t",
1604 },
1605
1606 vfmul => {
1607 #       irn_flags => "R",
1608         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1609         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1610         latency   => 4,
1611         units     => [ "VFP" ],
1612         mode      => "mode_E",
1613         attr_type => "ia32_x87_attr_t",
1614 },
1615
1616 l_vfmul => {
1617         op_flags  => "C",
1618         cmp_attr  => "return 1;",
1619         arity     => 2,
1620 },
1621
1622 vfsub => {
1623 #       irn_flags => "R",
1624         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1625         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1626         latency   => 4,
1627         units     => [ "VFP" ],
1628         mode      => "mode_E",
1629         attr_type => "ia32_x87_attr_t",
1630 },
1631
1632 l_vfsub => {
1633         cmp_attr  => "return 1;",
1634         arity     => 2,
1635 },
1636
1637 vfdiv => {
1638         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
1639         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1640         outs      => [ "res", "M" ],
1641         latency   => 20,
1642         units     => [ "VFP" ],
1643         attr_type => "ia32_x87_attr_t",
1644 },
1645
1646 l_vfdiv => {
1647         cmp_attr  => "return 1;",
1648         outs      => [ "res", "M" ],
1649         arity     => 2,
1650 },
1651
1652 vfprem => {
1653         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1654         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1655         latency   => 20,
1656         units     => [ "VFP" ],
1657         mode      => "mode_E",
1658         attr_type => "ia32_x87_attr_t",
1659 },
1660
1661 l_vfprem => {
1662         cmp_attr  => "return 1;",
1663         arity     => 2,
1664 },
1665
1666 vfabs => {
1667         irn_flags => "R",
1668         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1669         ins       => [ "value" ],
1670         latency   => 2,
1671         units     => [ "VFP" ],
1672         mode      => "mode_E",
1673         attr_type => "ia32_x87_attr_t",
1674 },
1675
1676 vfchs => {
1677         irn_flags => "R",
1678         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1679         ins       => [ "value" ],
1680         latency   => 2,
1681         units     => [ "VFP" ],
1682         mode      => "mode_E",
1683         attr_type => "ia32_x87_attr_t",
1684 },
1685
1686 # virtual Load and Store
1687
1688 vfld => {
1689         op_flags  => "L|F",
1690         state     => "exc_pinned",
1691         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1692         ins       => [ "base", "index", "mem" ],
1693         outs      => [ "res", "M" ],
1694         attr      => "ir_mode *load_mode",
1695         init_attr => "attr->attr.ls_mode = load_mode;",
1696         latency   => 2,
1697         units     => [ "VFP" ],
1698         attr_type => "ia32_x87_attr_t",
1699 },
1700
1701 vfst => {
1702         op_flags  => "L|F",
1703         state     => "exc_pinned",
1704         reg_req   => { in => [ "gp", "gp", "none", "vfp" ] },
1705         ins       => [ "base", "index", "mem", "val" ],
1706         attr      => "ir_mode *store_mode",
1707         init_attr => "attr->attr.ls_mode = store_mode;",
1708         latency   => 2,
1709         units     => [ "VFP" ],
1710         mode      => "mode_M",
1711         attr_type => "ia32_x87_attr_t",
1712 },
1713
1714 # Conversions
1715
1716 vfild => {
1717         state     => "exc_pinned",
1718         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1719         outs      => [ "res", "M" ],
1720         ins       => [ "base", "index", "mem" ],
1721         latency   => 4,
1722         units     => [ "VFP" ],
1723         attr_type => "ia32_x87_attr_t",
1724 },
1725
1726 l_vfild => {
1727         cmp_attr  => "return 1;",
1728         outs      => [ "res", "M" ],
1729         arity     => 2,
1730 },
1731
1732 vfist => {
1733         state     => "exc_pinned",
1734         reg_req   => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
1735         ins       => [ "base", "index", "mem", "val", "fpcw" ],
1736         latency   => 4,
1737         units     => [ "VFP" ],
1738         mode      => "mode_M",
1739         attr_type => "ia32_x87_attr_t",
1740 },
1741
1742 l_vfist => {
1743         cmp_attr  => "return 1;",
1744         state     => "exc_pinned",
1745         arity     => 3,
1746         mode      => "mode_M",
1747 },
1748
1749
1750 # constants
1751
1752 vfldz => {
1753         irn_flags => "R",
1754         reg_req   => { out => [ "vfp" ] },
1755         latency   => 4,
1756         units     => [ "VFP" ],
1757         mode      => "mode_E",
1758         attr_type => "ia32_x87_attr_t",
1759 },
1760
1761 vfld1 => {
1762         irn_flags => "R",
1763         reg_req   => { out => [ "vfp" ] },
1764         latency   => 4,
1765         units     => [ "VFP" ],
1766         mode      => "mode_E",
1767         attr_type => "ia32_x87_attr_t",
1768 },
1769
1770 vfldpi => {
1771         irn_flags => "R",
1772         reg_req   => { out => [ "vfp" ] },
1773         latency   => 4,
1774         units     => [ "VFP" ],
1775         mode      => "mode_E",
1776         attr_type => "ia32_x87_attr_t",
1777 },
1778
1779 vfldln2 => {
1780         irn_flags => "R",
1781         reg_req   => { out => [ "vfp" ] },
1782         latency   => 4,
1783         units     => [ "VFP" ],
1784         mode      => "mode_E",
1785         attr_type => "ia32_x87_attr_t",
1786 },
1787
1788 vfldlg2 => {
1789         irn_flags => "R",
1790         reg_req   => { out => [ "vfp" ] },
1791         latency   => 4,
1792         units     => [ "VFP" ],
1793         mode      => "mode_E",
1794         attr_type => "ia32_x87_attr_t",
1795 },
1796
1797 vfldl2t => {
1798         irn_flags => "R",
1799         reg_req   => { out => [ "vfp" ] },
1800         latency   => 4,
1801         units     => [ "VFP" ],
1802         mode      => "mode_E",
1803         attr_type => "ia32_x87_attr_t",
1804 },
1805
1806 vfldl2e => {
1807         irn_flags => "R",
1808         reg_req   => { out => [ "vfp" ] },
1809         latency   => 4,
1810         units     => [ "VFP" ],
1811         mode      => "mode_E",
1812         attr_type => "ia32_x87_attr_t",
1813 },
1814
1815 # other
1816
1817 vFucomFnstsw => {
1818 # we can't allow to rematerialize this node so we don't have
1819 #  accidently produce Phi(Fucom, Fucom(flipped))
1820 #       irn_flags => "R",
1821         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
1822         ins       => [ "left", "right" ],
1823         outs      => [ "flags" ],
1824         attr      => "int flipped",
1825         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1826         latency   => 3,
1827         units     => [ "VFP" ],
1828         attr_type => "ia32_x87_attr_t",
1829         mode      => $mode_gp
1830 },
1831
1832 vFucomi => {
1833         irn_flags => "R",
1834         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
1835         ins       => [ "left", "right" ],
1836         outs      => [ "flags" ],
1837         attr      => "int flipped",
1838         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1839         latency   => 3,
1840         units     => [ "VFP" ],
1841         attr_type => "ia32_x87_attr_t",
1842         mode      => $mode_gp
1843 },
1844
1845 vFtstFnstsw => {
1846 #       irn_flags => "R",
1847         reg_req   => { in => [ "vfp" ], out => [ "eax" ] },
1848         ins       => [ "left" ],
1849         outs      => [ "flags" ],
1850         attr      => "int flipped",
1851         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1852         latency   => 3,
1853         units     => [ "VFP" ],
1854         attr_type => "ia32_x87_attr_t",
1855         mode      => $mode_gp
1856 },
1857
1858 Sahf => {
1859         irn_flags => "R",
1860         reg_req   => { in => [ "eax" ], out => [ "eflags" ] },
1861         ins       => [ "val" ],
1862         outs      => [ "flags" ],
1863         emit      => '. sahf',
1864         units     => [ "GP" ],
1865         mode      => $mode_flags,
1866 },
1867
1868 #------------------------------------------------------------------------#
1869 #       ___ _____    __ _             _                     _            #
1870 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1871 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1872 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1873 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1874 #------------------------------------------------------------------------#
1875
1876 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
1877 #       are swapped, we work this around in the emitter...
1878
1879 fadd => {
1880         op_flags  => "R",
1881         rd_constructor => "NONE",
1882         reg_req   => { },
1883         emit      => '. fadd%XM %x87_binop',
1884         attr_type => "ia32_x87_attr_t",
1885 },
1886
1887 faddp => {
1888         op_flags  => "R",
1889         rd_constructor => "NONE",
1890         reg_req   => { },
1891         emit      => '. faddp%XM %x87_binop',
1892         attr_type => "ia32_x87_attr_t",
1893 },
1894
1895 fmul => {
1896         op_flags  => "R",
1897         rd_constructor => "NONE",
1898         reg_req   => { },
1899         emit      => '. fmul%XM %x87_binop',
1900         attr_type => "ia32_x87_attr_t",
1901 },
1902
1903 fmulp => {
1904         op_flags  => "R",
1905         rd_constructor => "NONE",
1906         reg_req   => { },
1907         emit      => '. fmulp%XM %x87_binop',,
1908         attr_type => "ia32_x87_attr_t",
1909 },
1910
1911 fsub => {
1912         op_flags  => "R",
1913         rd_constructor => "NONE",
1914         reg_req   => { },
1915         emit      => '. fsub%XM %x87_binop',
1916         attr_type => "ia32_x87_attr_t",
1917 },
1918
1919 fsubp => {
1920         op_flags  => "R",
1921         rd_constructor => "NONE",
1922         reg_req   => { },
1923 # see note about gas bugs
1924         emit      => '. fsubrp%XM %x87_binop',
1925         attr_type => "ia32_x87_attr_t",
1926 },
1927
1928 fsubr => {
1929         op_flags  => "R",
1930         rd_constructor => "NONE",
1931         irn_flags => "R",
1932         reg_req   => { },
1933         emit      => '. fsubr%XM %x87_binop',
1934         attr_type => "ia32_x87_attr_t",
1935 },
1936
1937 fsubrp => {
1938         op_flags  => "R",
1939         rd_constructor => "NONE",
1940         irn_flags => "R",
1941         reg_req   => { },
1942 # see note about gas bugs
1943         emit      => '. fsubp%XM %x87_binop',
1944         attr_type => "ia32_x87_attr_t",
1945 },
1946
1947 fprem => {
1948         op_flags  => "R",
1949         rd_constructor => "NONE",
1950         reg_req   => { },
1951         emit      => '. fprem1',
1952         attr_type => "ia32_x87_attr_t",
1953 },
1954
1955 # this node is just here, to keep the simulator running
1956 # we can omit this when a fprem simulation function exists
1957 fpremp => {
1958         op_flags  => "R",
1959         rd_constructor => "NONE",
1960         reg_req   => { },
1961         emit      => '. fprem1',
1962         attr_type => "ia32_x87_attr_t",
1963 },
1964
1965 fdiv => {
1966         op_flags  => "R",
1967         rd_constructor => "NONE",
1968         reg_req   => { },
1969         emit      => '. fdiv%XM %x87_binop',
1970         attr_type => "ia32_x87_attr_t",
1971 },
1972
1973 fdivp => {
1974         op_flags  => "R",
1975         rd_constructor => "NONE",
1976         reg_req   => { },
1977 # see note about gas bugs
1978         emit      => '. fdivrp%XM %x87_binop',
1979         attr_type => "ia32_x87_attr_t",
1980 },
1981
1982 fdivr => {
1983         op_flags  => "R",
1984         rd_constructor => "NONE",
1985         reg_req   => { },
1986         emit      => '. fdivr%XM %x87_binop',
1987         attr_type => "ia32_x87_attr_t",
1988 },
1989
1990 fdivrp => {
1991         op_flags  => "R",
1992         rd_constructor => "NONE",
1993         reg_req   => { },
1994 # see note about gas bugs
1995         emit      => '. fdivp%XM %x87_binop',
1996         attr_type => "ia32_x87_attr_t",
1997 },
1998
1999 fabs => {
2000         op_flags  => "R",
2001         rd_constructor => "NONE",
2002         reg_req   => { },
2003         emit      => '. fabs',
2004         attr_type => "ia32_x87_attr_t",
2005 },
2006
2007 fchs => {
2008         op_flags  => "R|K",
2009         rd_constructor => "NONE",
2010         reg_req   => { },
2011         emit      => '. fchs',
2012         attr_type => "ia32_x87_attr_t",
2013 },
2014
2015 # x87 Load and Store
2016
2017 fld => {
2018         rd_constructor => "NONE",
2019         op_flags  => "R|L|F",
2020         state     => "exc_pinned",
2021         reg_req   => { },
2022         emit      => '. fld%XM %AM',
2023         attr_type => "ia32_x87_attr_t",
2024 },
2025
2026 fst => {
2027         rd_constructor => "NONE",
2028         op_flags  => "R|L|F",
2029         state     => "exc_pinned",
2030         reg_req   => { },
2031         emit      => '. fst%XM %AM',
2032         mode      => "mode_M",
2033         attr_type => "ia32_x87_attr_t",
2034 },
2035
2036 fstp => {
2037         rd_constructor => "NONE",
2038         op_flags  => "R|L|F",
2039         state     => "exc_pinned",
2040         reg_req   => { },
2041         emit      => '. fstp%XM %AM',
2042         mode      => "mode_M",
2043         attr_type => "ia32_x87_attr_t",
2044 },
2045
2046 # Conversions
2047
2048 fild => {
2049         op_flags  => "R",
2050         rd_constructor => "NONE",
2051         reg_req   => { },
2052         emit      => '. fild%M %AM',
2053         attr_type => "ia32_x87_attr_t",
2054 },
2055
2056 fist => {
2057         op_flags  => "R",
2058         state     => "exc_pinned",
2059         rd_constructor => "NONE",
2060         reg_req   => { },
2061         emit      => '. fist%M %AM',
2062         mode      => "mode_M",
2063         attr_type => "ia32_x87_attr_t",
2064 },
2065
2066 fistp => {
2067         op_flags  => "R",
2068         state     => "exc_pinned",
2069         rd_constructor => "NONE",
2070         reg_req   => { },
2071         emit      => '. fistp%M %AM',
2072         mode      => "mode_M",
2073         attr_type => "ia32_x87_attr_t",
2074 },
2075
2076 # constants
2077
2078 fldz => {
2079         op_flags  => "R|c|K",
2080         irn_flags => "R",
2081         emit      => '. fldz',
2082         attr_type => "ia32_x87_attr_t",
2083 },
2084
2085 fld1 => {
2086         op_flags  => "R|c|K",
2087         irn_flags => "R",
2088         reg_req   => { out => [ "vfp" ] },
2089         emit      => '. fld1',
2090         attr_type => "ia32_x87_attr_t",
2091 },
2092
2093 fldpi => {
2094         op_flags  => "R|c|K",
2095         irn_flags => "R",
2096         reg_req   => { out => [ "vfp" ] },
2097         emit      => '. fldpi',
2098         attr_type => "ia32_x87_attr_t",
2099 },
2100
2101 fldln2 => {
2102         op_flags  => "R|c|K",
2103         irn_flags => "R",
2104         reg_req   => { out => [ "vfp" ] },
2105         emit      => '. fldln2',
2106         attr_type => "ia32_x87_attr_t",
2107 },
2108
2109 fldlg2 => {
2110         op_flags  => "R|c|K",
2111         irn_flags => "R",
2112         reg_req   => { out => [ "vfp" ] },
2113         emit      => '. fldlg2',
2114         attr_type => "ia32_x87_attr_t",
2115 },
2116
2117 fldl2t => {
2118         op_flags  => "R|c|K",
2119         irn_flags => "R",
2120         reg_req   => { out => [ "vfp" ] },
2121         emit      => '. fldll2t',
2122         attr_type => "ia32_x87_attr_t",
2123 },
2124
2125 fldl2e => {
2126         op_flags  => "R|c|K",
2127         irn_flags => "R",
2128         reg_req   => { out => [ "vfp" ] },
2129         emit      => '. fldl2e',
2130         attr_type => "ia32_x87_attr_t",
2131 },
2132
2133 # fxch, fpush, fpop
2134 # Note that it is NEVER allowed to do CSE on these nodes
2135 # Moreover, note the virtual register requierements!
2136
2137 fxch => {
2138         op_flags  => "R|K",
2139         reg_req   => { },
2140         cmp_attr  => "return 1;",
2141         emit      => '. fxch %X0',
2142         attr_type => "ia32_x87_attr_t",
2143         mode      => "mode_ANY",
2144 },
2145
2146 fpush => {
2147         op_flags  => "R|K",
2148         reg_req   => {},
2149         cmp_attr  => "return 1;",
2150         emit      => '. fld %X0',
2151         attr_type => "ia32_x87_attr_t",
2152         mode      => "mode_ANY",
2153 },
2154
2155 fpushCopy => {
2156         op_flags  => "R",
2157         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2158         cmp_attr  => "return 1;",
2159         emit      => '. fld %X0',
2160         attr_type => "ia32_x87_attr_t",
2161 },
2162
2163 fpop => {
2164         op_flags  => "K",
2165         reg_req   => { },
2166         cmp_attr  => "return 1;",
2167         emit      => '. fstp %X0',
2168         attr_type => "ia32_x87_attr_t",
2169         mode      => "mode_ANY",
2170 },
2171
2172 ffreep => {
2173         op_flags  => "K",
2174         reg_req   => { },
2175         cmp_attr  => "return 1;",
2176         emit      => '. ffreep %X0',
2177         attr_type => "ia32_x87_attr_t",
2178         mode      => "mode_ANY",
2179 },
2180
2181 emms => {
2182         op_flags  => "K",
2183         reg_req   => { },
2184         cmp_attr  => "return 1;",
2185         emit      => '. emms',
2186         attr_type => "ia32_x87_attr_t",
2187         mode      => "mode_ANY",
2188 },
2189
2190 femms => {
2191         op_flags  => "K",
2192         reg_req   => { },
2193         cmp_attr  => "return 1;",
2194         emit      => '. femms',
2195         attr_type => "ia32_x87_attr_t",
2196         mode      => "mode_ANY",
2197 },
2198
2199 # compare
2200
2201 FucomFnstsw => {
2202         reg_req   => { },
2203         emit      => ". fucom %X1\n".
2204                      ". fnstsw",
2205         attr_type => "ia32_x87_attr_t",
2206 },
2207
2208 FucompFnstsw => {
2209         reg_req   => { },
2210         emit      => ". fucomp %X1\n".
2211                      ". fnstsw",
2212         attr_type => "ia32_x87_attr_t",
2213 },
2214
2215 FucomppFnstsw => {
2216         reg_req   => { },
2217         emit      => ". fucompp\n".
2218                      ". fnstsw",
2219         attr_type => "ia32_x87_attr_t",
2220 },
2221
2222 Fucomi => {
2223         reg_req   => { },
2224         emit      => '. fucomi %X1',
2225         attr_type => "ia32_x87_attr_t",
2226 },
2227
2228 Fucompi => {
2229         reg_req   => { },
2230         emit      => '. fucompi %X1',
2231         attr_type => "ia32_x87_attr_t",
2232 },
2233
2234 FtstFnstsw => {
2235         reg_req   => { },
2236         emit      => ". ftst\n".
2237                      ". fnstsw",
2238         attr_type => "ia32_x87_attr_t",
2239 },
2240
2241
2242 # -------------------------------------------------------------------------------- #
2243 #  ____ ____  _____                  _                               _             #
2244 # / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
2245 # \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
2246 #  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
2247 # |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
2248 #                                                                                  #
2249 # -------------------------------------------------------------------------------- #
2250
2251
2252 # Spilling and reloading of SSE registers, hardcoded, not generated #
2253
2254 xxLoad => {
2255         op_flags  => "L|F",
2256         state     => "exc_pinned",
2257         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2258         emit      => '. movdqu %D0, %AM',
2259         outs      => [ "res", "M" ],
2260         units     => [ "SSE" ],
2261 },
2262
2263 xxStore => {
2264         op_flags => "L|F",
2265         state    => "exc_pinned",
2266         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
2267         ins      => [ "base", "index", "mem", "val" ],
2268         emit     => '. movdqu %binop',
2269         units    => [ "SSE" ],
2270         mode     => "mode_M",
2271 },
2272
2273 ); # end of %nodes
2274
2275 # Include the generated SIMD node specification written by the SIMD optimization
2276 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2277 unless ($return = do $my_script_name) {
2278         warn "couldn't parse $my_script_name: $@" if $@;
2279         warn "couldn't do $my_script_name: $!"    unless defined $return;
2280         warn "couldn't run $my_script_name"       unless $return;
2281 }