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