- workaround and document ShrD/ShlD problems correctly this time
[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         am        => "source,ternary",
613         emit      => ". idiv%M %unop5",
614         latency   => 25,
615         units     => [ "GP" ],
616         modified_flags => $status_flags
617 },
618
619 Div => {
620         op_flags  => "F|L",
621         state     => "exc_pinned",
622         reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
623         ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
624         outs      => [ "div_res", "mod_res", "M" ],
625         am        => "source,ternary",
626         emit      => ". div%M %unop5",
627         latency   => 25,
628         units     => [ "GP" ],
629         modified_flags => $status_flags
630 },
631
632 Shl => {
633         irn_flags => "R",
634         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
635         ins       => [ "left", "right" ],
636         am        => "dest,binary",
637         emit      => '. shl %SB1, %S0',
638         units     => [ "GP" ],
639         mode      => $mode_gp,
640         modified_flags => $status_flags
641 },
642
643 ShlMem => {
644         irn_flags => "R",
645         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
646         ins       => [ "base", "index", "mem", "count" ],
647         emit      => '. shl%M %SB3, %AM',
648         units     => [ "GP" ],
649         mode      => "mode_M",
650         modified_flags => $status_flags
651 },
652
653 l_ShlDep => {
654         cmp_attr  => "return 1;",
655         # value, cnt, dependency
656         arity     => 3
657 },
658
659 ShlD => {
660         irn_flags => "R",
661         # see ShrD about the strange out constraint
662         reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "!in" ] },
663         ins       => [ "left_high", "left_low", "right" ],
664         am        => "dest,ternary",
665         emit      => ". shld%M %SB2, %S1, %S0\n".
666                      ". movl %S0, %D0",
667         latency   => 6,
668         units     => [ "GP" ],
669         mode      => $mode_gp,
670         modified_flags => $status_flags
671 },
672
673 l_ShlD => {
674         cmp_attr  => "return 1;",
675         arity     => 3,
676 },
677
678 Shr => {
679         irn_flags => "R",
680         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
681         ins       => [ "val", "count" ],
682         am        => "dest,binary",
683         emit      => '. shr %SB1, %S0',
684         units     => [ "GP" ],
685         mode      => $mode_gp,
686         modified_flags => $status_flags
687 },
688
689 ShrMem => {
690         irn_flags => "R",
691         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
692         ins       => [ "base", "index", "mem", "count" ],
693         emit      => '. shr%M %SB3, %AM',
694         units     => [ "GP" ],
695         mode      => "mode_M",
696         modified_flags => $status_flags
697 },
698
699 l_ShrDep => {
700         cmp_attr  => "return 1;",
701         # value, cnt, dependency
702         arity     => 3
703 },
704
705 ShrD => {
706         # What's going on with the out constraint here? We would like to write
707         # "in_r2" and be done. However in firm we only support should_be_same
708         # constraints at the moment. Which means they could be non-fullfilled in
709         # some cases. Now when all values happen to live through the node, out
710         # is ecx and in_r2 not ecx, then we're screwed. Because in this case we
711         # need a 4th Register.
712         #
713         # The best solution for this is extending the register allocator to support
714         # must_be_same constraints which create a copy when the in_r2 value
715         # lives through (this ensures that we have the 4th register in the cases
716         # when we need it and can always fix the situation).
717         #
718         # For now I'm doing this ultra ugly !in hack which allocates 4 registers
719         # and creates an extra mov
720         irn_flags => "R",
721         reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "!in" ] },
722         ins       => [ "left_high", "left_low", "right" ],
723         am        => "dest,ternary",
724         emit      => ". shrd%M %SB2, %S1, %S0\n".
725                      ". movl   %S0, %D0",
726         latency   => 6,
727         units     => [ "GP" ],
728         mode      => $mode_gp,
729         modified_flags => $status_flags
730 },
731
732 l_ShrD => {
733         cmp_attr  => "return 1;",
734         arity     => 3
735 },
736
737 Sar => {
738         irn_flags => "R",
739         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
740         ins       => [ "val", "count" ],
741         am        => "dest,binary",
742         emit      => '. sar %SB1, %S0',
743         units     => [ "GP" ],
744         mode      => $mode_gp,
745         modified_flags => $status_flags
746 },
747
748 SarMem => {
749         irn_flags => "R",
750         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
751         ins       => [ "base", "index", "mem", "count" ],
752         emit      => '. sar%M %SB3, %AM',
753         units     => [ "GP" ],
754         mode      => "mode_M",
755         modified_flags => $status_flags
756 },
757
758 l_Sar => {
759         cmp_attr  => "return 1;",
760         # value, cnt
761         arity     => 2
762 },
763
764 l_SarDep => {
765         cmp_attr  => "return 1;",
766         # value, cnt, dependency
767         arity     => 3
768 },
769
770 Ror => {
771         irn_flags => "R",
772         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
773         ins       => [ "val", "count" ],
774         am        => "dest,binary",
775         emit      => '. ror %SB1, %S0',
776         units     => [ "GP" ],
777         mode      => $mode_gp,
778         modified_flags => $status_flags
779 },
780
781 RorMem => {
782         irn_flags => "R",
783         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
784         ins       => [ "base", "index", "mem", "count" ],
785         emit      => '. ror%M %SB3, %AM',
786         units     => [ "GP" ],
787         mode      => "mode_M",
788         modified_flags => $status_flags
789 },
790
791 Rol => {
792         irn_flags => "R",
793         reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
794         ins       => [ "val", "count" ],
795         am        => "dest,binary",
796         emit      => '. rol %SB1, %S0',
797         units     => [ "GP" ],
798         mode      => $mode_gp,
799         modified_flags => $status_flags
800 },
801
802 RolMem => {
803         irn_flags => "R",
804         reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
805         ins       => [ "base", "index", "mem", "count" ],
806         emit      => '. rol%M %SB3, %AM',
807         units     => [ "GP" ],
808         mode      => "mode_M",
809         modified_flags => $status_flags
810 },
811
812 # unary operations
813
814 Neg => {
815         irn_flags => "R",
816         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
817         emit      => '. neg %S0',
818         ins       => [ "val" ],
819         am        => "dest,unary",
820         units     => [ "GP" ],
821         mode      => $mode_gp,
822         modified_flags => $status_flags
823 },
824
825 NegMem => {
826         irn_flags => "R",
827         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
828         ins       => [ "base", "index", "mem" ],
829         emit      => '. neg%M %AM',
830         units     => [ "GP" ],
831         mode      => "mode_M",
832         modified_flags => $status_flags
833 },
834
835 Minus64Bit => {
836         irn_flags => "R",
837         reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] },
838         outs      => [ "low_res", "high_res" ],
839         units     => [ "GP" ],
840         modified_flags => $status_flags
841 },
842
843
844 l_Neg => {
845         cmp_attr  => "return 1;",
846         arity     => 1,
847 },
848
849 Inc => {
850         irn_flags => "R",
851         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
852         am        => "dest,unary",
853         emit      => '. inc %S0',
854         units     => [ "GP" ],
855         mode      => $mode_gp,
856         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
857 },
858
859 IncMem => {
860         irn_flags => "R",
861         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
862         ins       => [ "base", "index", "mem" ],
863         emit      => '. inc%M %AM',
864         units     => [ "GP" ],
865         mode      => "mode_M",
866         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
867 },
868
869 Dec => {
870         irn_flags => "R",
871         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
872         am        => "dest,unary",
873         emit      => '. dec %S0',
874         units     => [ "GP" ],
875         mode      => $mode_gp,
876         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
877 },
878
879 DecMem => {
880         irn_flags => "R",
881         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
882         ins       => [ "base", "index", "mem" ],
883         emit      => '. dec%M %AM',
884         units     => [ "GP" ],
885         mode      => "mode_M",
886         modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
887 },
888
889 Not => {
890         irn_flags => "R",
891         reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
892         ins       => [ "val" ],
893         am        => "dest,unary",
894         emit      => '. not %S0',
895         units     => [ "GP" ],
896         mode      => $mode_gp,
897 },
898
899 NotMem => {
900         irn_flags => "R",
901         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
902         ins       => [ "base", "index", "mem" ],
903         emit      => '. not%M %AM',
904         units     => [ "GP" ],
905         mode      => "mode_M",
906 },
907
908 # other operations
909
910 Cmp => {
911         irn_flags => "R",
912         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
913         ins       => [ "base", "index", "mem", "left", "right" ],
914         outs      => [ "eflags" ],
915         am        => "source,binary",
916         emit      => '. cmp%M %binop',
917         attr      => "int flipped, int cmp_unsigned",
918         init_attr => "attr->data.cmp_flipped = flipped;\n".
919                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
920         latency   => 1,
921         units     => [ "GP" ],
922         mode      => $mode_flags,
923         modified_flags => $status_flags
924 },
925
926 Cmp8Bit => {
927         irn_flags => "R",
928         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
929         ins       => [ "base", "index", "mem", "left", "right" ],
930         outs      => [ "eflags" ],
931         am        => "source,binary",
932         emit      => '. cmpb %binop',
933         attr      => "int flipped, int cmp_unsigned",
934         init_attr => "attr->data.cmp_flipped = flipped;\n".
935                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
936         latency   => 1,
937         units     => [ "GP" ],
938         mode      => $mode_flags,
939         modified_flags => $status_flags
940 },
941
942 Test => {
943         irn_flags => "R",
944         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
945         ins       => [ "base", "index", "mem", "left", "right" ],
946         outs      => [ "eflags" ],
947         am        => "source,binary",
948         emit      => '. test%M %binop',
949         attr      => "int flipped, int cmp_unsigned",
950         init_attr => "attr->data.cmp_flipped = flipped;\n".
951                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
952         latency   => 1,
953         units     => [ "GP" ],
954         mode      => $mode_flags,
955         modified_flags => $status_flags
956 },
957
958 Test8Bit => {
959         irn_flags => "R",
960         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] },
961         ins       => [ "base", "index", "mem", "left", "right" ],
962         outs      => [ "eflags" ],
963         am        => "source,binary",
964         emit      => '. testb %binop',
965         attr      => "int flipped, int cmp_unsigned",
966         init_attr => "attr->data.cmp_flipped = flipped;\n".
967                      "\tattr->data.cmp_unsigned = cmp_unsigned;\n",
968         latency   => 1,
969         units     => [ "GP" ],
970         mode      => $mode_flags,
971         modified_flags => $status_flags
972 },
973
974 Set => {
975         #irn_flags => "R",
976         reg_req   => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
977         ins       => [ "eflags" ],
978         am        => "dest,unary",
979         attr      => "pn_Cmp pnc",
980         init_attr => "attr->pn_code = pnc;\nset_ia32_ls_mode(res, mode_Bu);\n",
981         emit      => '. set%CMP0 %DB0',
982         latency   => 1,
983         units     => [ "GP" ],
984         mode      => $mode_gp,
985 },
986
987 CMov => {
988         #irn_flags => "R",
989         # (note: leave the false,true order intact to make it compatible with other
990         #  ia32_binary ops)
991         reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ], out => [ "in_r4 in_r5" ] },
992         ins       => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
993         am        => "source,binary",
994         attr      => "int flipped, pn_Cmp pn_code",
995         init_attr => "attr->pn_code          = pn_code;\n".
996                      "attr->data.cmp_flipped = flipped;",
997         latency   => 1,
998         units     => [ "GP" ],
999         mode      => $mode_gp,
1000 },
1001
1002 Jcc => {
1003         state     => "pinned",
1004         op_flags  => "L|X|Y",
1005         reg_req   => { in  => [ "eflags" ], out => [ "none", "none" ] },
1006         ins       => [ "eflags" ],
1007         outs      => [ "false", "true" ],
1008         attr      => "pn_Cmp pnc",
1009         init_attr => "attr->pn_code = pnc;",
1010         latency   => 2,
1011         units     => [ "BRANCH" ],
1012 },
1013
1014 SwitchJmp => {
1015         state     => "pinned",
1016         op_flags  => "L|X|Y",
1017         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1018         latency   => 3,
1019         units     => [ "BRANCH" ],
1020         mode      => "mode_T",
1021         modified_flags => $status_flags
1022 },
1023
1024 IJmp => {
1025         state     => "pinned",
1026         op_flags  => "X",
1027         reg_req   => { in => [ "gp" ] },
1028         emit      => '. jmp *%S0',
1029         units     => [ "BRANCH" ],
1030         mode      => "mode_X",
1031 },
1032
1033 Const => {
1034         op_flags  => "c",
1035         irn_flags => "R",
1036         reg_req   => { out => [ "gp" ] },
1037         units     => [ "GP" ],
1038         attr      => "ir_entity *symconst, int symconst_sign, long offset",
1039         attr_type => "ia32_immediate_attr_t",
1040         mode      => $mode_gp,
1041 # depends on the const and is set in ia32_transform
1042 # modified_flags => $status_flags
1043 },
1044
1045 Unknown_GP => {
1046         state     => "pinned",
1047         op_flags  => "c",
1048         irn_flags => "I",
1049         reg_req   => { out => [ "gp_UKNWN" ] },
1050         units     => [],
1051         emit      => "",
1052         mode      => $mode_gp
1053 },
1054
1055 Unknown_VFP => {
1056         state     => "pinned",
1057         op_flags  => "c",
1058         irn_flags => "I",
1059         reg_req   => { out => [ "vfp_UKNWN" ] },
1060         units     => [],
1061         emit      => "",
1062         mode      => "mode_E",
1063         attr_type => "ia32_x87_attr_t",
1064 },
1065
1066 Unknown_XMM => {
1067         state     => "pinned",
1068         op_flags  => "c",
1069         irn_flags => "I",
1070         reg_req   => { out => [ "xmm_UKNWN" ] },
1071         units     => [],
1072         emit      => "",
1073         mode      => "mode_E"
1074 },
1075
1076 NoReg_GP => {
1077         state     => "pinned",
1078         op_flags  => "c",
1079         irn_flags => "I",
1080         reg_req   => { out => [ "gp_NOREG" ] },
1081         units     => [],
1082         emit      => "",
1083         mode      => $mode_gp
1084 },
1085
1086 NoReg_VFP => {
1087         state     => "pinned",
1088         op_flags  => "c",
1089         irn_flags => "I",
1090         reg_req   => { out => [ "vfp_NOREG" ] },
1091         units     => [],
1092         emit      => "",
1093         mode      => "mode_E",
1094         attr_type => "ia32_x87_attr_t",
1095 },
1096
1097 NoReg_XMM => {
1098         state     => "pinned",
1099         op_flags  => "c",
1100         irn_flags => "I",
1101         reg_req   => { out => [ "xmm_NOREG" ] },
1102         units     => [],
1103         emit      => "",
1104         mode      => "mode_E"
1105 },
1106
1107 ChangeCW => {
1108         state     => "pinned",
1109         op_flags  => "c",
1110         irn_flags => "I",
1111         reg_req   => { out => [ "fp_cw" ] },
1112         mode      => $mode_fpcw,
1113         latency   => 3,
1114         units     => [ "GP" ],
1115         modified_flags => $fpcw_flags
1116 },
1117
1118 FldCW => {
1119         op_flags  => "L|F",
1120         state     => "pinned",
1121         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
1122         ins       => [ "base", "index", "mem" ],
1123         latency   => 5,
1124         emit      => ". fldcw %AM",
1125         mode      => $mode_fpcw,
1126         units     => [ "GP" ],
1127         modified_flags => $fpcw_flags
1128 },
1129
1130 FnstCW => {
1131         op_flags  => "L|F",
1132         state     => "pinned",
1133         reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
1134         ins       => [ "base", "index", "mem", "fpcw" ],
1135         latency   => 5,
1136         emit      => ". fnstcw %AM",
1137         mode      => "mode_M",
1138         units     => [ "GP" ],
1139 },
1140
1141 Cltd => {
1142         # we should not rematrialize this node. It has very strict constraints.
1143         reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
1144         ins       => [ "val", "globbered" ],
1145         emit      => '. cltd',
1146         mode      => $mode_gp,
1147         units     => [ "GP" ],
1148 },
1149
1150 # Load / Store
1151 #
1152 # Note that we add additional latency values depending on address mode, so a
1153 # lateny of 0 for load is correct
1154
1155 Load => {
1156         op_flags  => "L|F",
1157         state     => "exc_pinned",
1158         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
1159         ins       => [ "base", "index", "mem" ],
1160         outs      => [ "res", "M" ],
1161         latency   => 0,
1162         emit      => ". mov%SE%ME%.l %AM, %D0",
1163         units     => [ "GP" ],
1164 },
1165
1166 l_Load => {
1167         op_flags  => "L|F",
1168         cmp_attr  => "return 1;",
1169         outs      => [ "res", "M" ],
1170         arity     => 2,
1171 },
1172
1173 l_Store => {
1174         op_flags  => "L|F",
1175         cmp_attr  => "return 1;",
1176         state     => "exc_pinned",
1177         arity     => 3,
1178         mode      => "mode_M",
1179 },
1180
1181 Store => {
1182         op_flags  => "L|F",
1183         state     => "exc_pinned",
1184         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
1185         ins       => [ "base", "index", "mem", "val" ],
1186         emit      => '. mov%M %SI3, %AM',
1187         latency   => 2,
1188         units     => [ "GP" ],
1189         mode      => "mode_M",
1190 },
1191
1192 Store8Bit => {
1193         op_flags  => "L|F",
1194         state     => "exc_pinned",
1195         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none" ] },
1196         ins       => [ "base", "index", "mem", "val" ],
1197         emit      => '. mov%M %SB3, %AM',
1198         latency   => 2,
1199         units     => [ "GP" ],
1200         mode      => "mode_M",
1201 },
1202
1203 Lea => {
1204         irn_flags => "R",
1205         reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
1206         ins       => [ "base", "index" ],
1207         emit      => '. leal %AM, %D0',
1208         latency   => 2,
1209         units     => [ "GP" ],
1210         mode      => $mode_gp,
1211 # well this isn't true for Lea, but we often transform Lea back to Add, Inc
1212 # or Dec, so we set the flag
1213         modified_flags => 1,
1214 },
1215
1216 Push => {
1217         reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
1218         ins       => [ "base", "index", "mem", "val", "stack" ],
1219         emit      => '. push%M %unop3',
1220         outs      => [ "stack:I|S", "M" ],
1221         am        => "source,binary",
1222         latency   => 2,
1223         units     => [ "GP" ],
1224 },
1225
1226 Pop => {
1227         reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "esp", "gp", "none" ] },
1228         emit      => '. pop%M %DAM1',
1229         outs      => [ "stack:I|S", "res", "M" ],
1230         ins       => [ "base", "index", "mem", "stack" ],
1231         am        => "dest,unary",
1232         latency   => 3, # Pop is more expensive than Push on Athlon
1233         units     => [ "GP" ],
1234 },
1235
1236 Enter => {
1237         reg_req   => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] },
1238         emit      => '. enter',
1239         outs      => [ "frame:I", "stack:I|S", "M" ],
1240         latency   => 15,
1241         units     => [ "GP" ],
1242 },
1243
1244 Leave => {
1245         reg_req   => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
1246         emit      => '. leave',
1247         outs      => [ "frame:I", "stack:I|S" ],
1248         latency   => 3,
1249         units     => [ "GP" ],
1250 },
1251
1252 AddSP => {
1253         irn_flags => "I",
1254         state     => "pinned",
1255         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
1256         ins       => [ "base", "index", "mem", "stack", "size" ],
1257         am        => "source,binary",
1258         emit      => '. addl %binop',
1259         outs      => [ "stack:S", "M" ],
1260         units     => [ "GP" ],
1261         modified_flags => $status_flags
1262 },
1263
1264 SubSP => {
1265 #irn_flags => "I",
1266         state     => "pinned",
1267         reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
1268         ins       => [ "base", "index", "mem", "stack", "size" ],
1269         am        => "source,binary",
1270         emit      => ". subl %binop\n".
1271                      ". movl %%esp, %D1",
1272         outs      => [ "stack:I|S", "addr", "M" ],
1273         units     => [ "GP" ],
1274         modified_flags => $status_flags
1275 },
1276
1277 LdTls => {
1278         irn_flags => "R",
1279         reg_req   => { out => [ "gp" ] },
1280         units     => [ "GP" ],
1281 },
1282
1283 # the int instruction
1284 int => {
1285         reg_req   => { in => [ "gp" ], out => [ "none" ] },
1286         mode      => "mode_M",
1287         emit      => '. int %SI0',
1288         units     => [ "GP" ],
1289         cmp_attr  => "return 1;",
1290 },
1291
1292
1293 #-----------------------------------------------------------------------------#
1294 #   _____ _____ ______    __ _             _                     _            #
1295 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
1296 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1297 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1298 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1299 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1300 #-----------------------------------------------------------------------------#
1301
1302 xZero => {
1303         irn_flags => "R",
1304         reg_req   => { out => [ "xmm" ] },
1305         emit      => '. xorp%XSD %D0, %D0',
1306         latency   => 3,
1307         units     => [ "SSE" ],
1308         mode      => "mode_E",
1309 },
1310
1311 # commutative operations
1312
1313 xAdd => {
1314         irn_flags => "R",
1315         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1316         ins       => [ "base", "index", "mem", "left", "right" ],
1317         emit      => '. add%XXM %binop',
1318         latency   => 4,
1319         units     => [ "SSE" ],
1320         mode      => "mode_E",
1321 },
1322
1323 xMul => {
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      => '. mul%XXM %binop',
1328         latency   => 4,
1329         units     => [ "SSE" ],
1330         mode      => "mode_E",
1331 },
1332
1333 xMax => {
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      => '. max%XXM %binop',
1338         latency   => 2,
1339         units     => [ "SSE" ],
1340         mode      => "mode_E",
1341 },
1342
1343 xMin => {
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      => '. min%XXM %binop',
1348         latency   => 2,
1349         units     => [ "SSE" ],
1350         mode      => "mode_E",
1351 },
1352
1353 xAnd => {
1354         irn_flags => "R",
1355         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1356         ins       => [ "base", "index", "mem", "left", "right" ],
1357         emit      => '. andp%XSD %binop',
1358         latency   => 3,
1359         units     => [ "SSE" ],
1360         mode      => "mode_E",
1361 },
1362
1363 xOr => {
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      => '. orp%XSD %binop',
1368         units     => [ "SSE" ],
1369         mode      => "mode_E",
1370 },
1371
1372 xXor => {
1373         irn_flags => "R",
1374         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] },
1375         ins       => [ "base", "index", "mem", "left", "right" ],
1376         emit      => '. xorp%XSD %binop',
1377         latency   => 3,
1378         units     => [ "SSE" ],
1379         mode      => "mode_E",
1380 },
1381
1382 # not commutative operations
1383
1384 xAndNot => {
1385         irn_flags => "R",
1386         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
1387         ins       => [ "base", "index", "mem", "left", "right" ],
1388         emit      => '. andnp%XSD %binop',
1389         latency   => 3,
1390         units     => [ "SSE" ],
1391         mode      => "mode_E",
1392 },
1393
1394 xSub => {
1395         irn_flags => "R",
1396         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
1397         ins       => [ "base", "index", "mem", "left", "right" ],
1398         emit      => '. sub%XXM %binop',
1399         latency   => 4,
1400         units     => [ "SSE" ],
1401         mode      => "mode_E",
1402 },
1403
1404 xDiv => {
1405         irn_flags => "R",
1406         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
1407         ins       => [ "base", "index", "mem", "left", "right" ],
1408         outs      => [ "res", "M" ],
1409         emit      => '. div%XXM %binop',
1410         latency   => 16,
1411         units     => [ "SSE" ],
1412 },
1413
1414 # other operations
1415
1416 Ucomi => {
1417         irn_flags => "R",
1418         reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eflags" ] },
1419         ins       => [ "base", "index", "mem", "left", "right" ],
1420         outs      => [ "flags" ],
1421         am        => "source,binary",
1422         attr      => "int flipped",
1423         init_attr => "attr->data.cmp_flipped = flipped;",
1424         emit      => ' .ucomi%XXM %binop',
1425         latency   => 3,
1426         units     => [ "SSE" ],
1427         mode      => $mode_flags,
1428         modified_flags => 1,
1429 },
1430
1431 # Load / Store
1432
1433 xLoad => {
1434         op_flags  => "L|F",
1435         state     => "exc_pinned",
1436         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
1437         ins       => [ "base", "index", "mem" ],
1438         emit      => '. mov%XXM %AM, %D0',
1439         attr      => "ir_mode *load_mode",
1440         init_attr => "attr->ls_mode = load_mode;",
1441         outs      => [ "res", "M" ],
1442         latency   => 0,
1443         units     => [ "SSE" ],
1444 },
1445
1446 xStore => {
1447         op_flags => "L|F",
1448         state    => "exc_pinned",
1449         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1450         ins       => [ "base", "index", "mem", "val" ],
1451         emit     => '. mov%XXM %S3, %AM',
1452         latency  => 0,
1453         units    => [ "SSE" ],
1454         mode     => "mode_M",
1455 },
1456
1457 xStoreSimple => {
1458         op_flags => "L|F",
1459         state    => "exc_pinned",
1460         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
1461         ins      => [ "base", "index", "mem", "val" ],
1462         emit     => '. mov%XXM %S3, %AM',
1463         latency  => 0,
1464         units    => [ "SSE" ],
1465         mode     => "mode_M",
1466 },
1467
1468 CvtSI2SS => {
1469         op_flags => "L|F",
1470         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1471         ins      => [ "base", "index", "mem", "val" ],
1472         emit     => '. cvtsi2ss %unop3, %D0',
1473         latency  => 2,
1474         units    => [ "SSE" ],
1475         mode     => $mode_xmm
1476 },
1477
1478 CvtSI2SD => {
1479         op_flags => "L|F",
1480         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
1481         ins      => [ "base", "index", "mem", "val" ],
1482         emit     => '. cvtsi2sd %unop3, %D0',
1483         latency  => 2,
1484         units    => [ "SSE" ],
1485         mode     => $mode_xmm
1486 },
1487
1488
1489 l_X87toSSE => {
1490         op_flags => "L|F",
1491         cmp_attr => "return 1;",
1492         arity    => 3,
1493 },
1494
1495 l_SSEtoX87 => {
1496         op_flags => "L|F",
1497         cmp_attr => "return 1;",
1498         arity    => 3,
1499 },
1500
1501 # CopyB
1502
1503 CopyB => {
1504         op_flags => "F|H",
1505         state    => "pinned",
1506         reg_req  => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
1507         outs     => [ "DST", "SRC", "CNT", "M" ],
1508         units    => [ "GP" ],
1509 # we don't care about this flag, so no need to mark this node
1510 #       modified_flags => [ "DF" ]
1511 },
1512
1513 CopyB_i => {
1514         op_flags => "F|H",
1515         state    => "pinned",
1516         reg_req  => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
1517         outs     => [ "DST", "SRC", "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 # Conversions
1524
1525 Conv_I2I => {
1526         state     => "exc_pinned",
1527         reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] },
1528         ins       => [ "base", "index", "mem", "val" ],
1529         units     => [ "GP" ],
1530         attr      => "ir_mode *smaller_mode",
1531         init_attr => "attr->ls_mode = smaller_mode;",
1532         mode      => $mode_gp,
1533 },
1534
1535 Conv_I2I8Bit => {
1536         state     => "exc_pinned",
1537         reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], 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_I2FP => {
1546         reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
1547         ins      => [ "base", "index", "mem", "val" ],
1548         latency  => 10,
1549         units    => [ "SSE" ],
1550         mode     => "mode_E",
1551 },
1552
1553 Conv_FP2I => {
1554         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
1555         ins      => [ "base", "index", "mem", "val" ],
1556         latency  => 10,
1557         units    => [ "SSE" ],
1558         mode     => $mode_gp,
1559 },
1560
1561 Conv_FP2FP => {
1562         reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
1563         ins      => [ "base", "index", "mem", "val" ],
1564         latency  => 8,
1565         units    => [ "SSE" ],
1566         mode     => "mode_E",
1567 },
1568
1569 #----------------------------------------------------------#
1570 #        _      _               _    __ _             _    #
1571 #       (_)    | |             | |  / _| |           | |   #
1572 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
1573 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
1574 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
1575 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
1576 #                 | |                                      #
1577 #  _ __   ___   __| | ___  ___                             #
1578 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
1579 # | | | | (_) | (_| |  __/\__ \                            #
1580 # |_| |_|\___/ \__,_|\___||___/                            #
1581 #----------------------------------------------------------#
1582
1583 # spilling disabled for all float nodes for now, because the fpcw handler
1584 # runs before spilling and we might end up with wrong fpcw then
1585
1586 vfadd => {
1587 #       irn_flags => "R",
1588         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1589         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1590         latency   => 4,
1591         units     => [ "VFP" ],
1592         mode      => "mode_E",
1593         attr_type => "ia32_x87_attr_t",
1594 },
1595
1596 vfmul => {
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 l_vfmul => {
1607         op_flags  => "C",
1608         cmp_attr  => "return 1;",
1609         arity     => 2,
1610 },
1611
1612 vfsub => {
1613 #       irn_flags => "R",
1614         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1615         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1616         latency   => 4,
1617         units     => [ "VFP" ],
1618         mode      => "mode_E",
1619         attr_type => "ia32_x87_attr_t",
1620 },
1621
1622 l_vfsub => {
1623         cmp_attr  => "return 1;",
1624         arity     => 2,
1625 },
1626
1627 vfdiv => {
1628         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
1629         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1630         outs      => [ "res", "M" ],
1631         latency   => 20,
1632         units     => [ "VFP" ],
1633         attr_type => "ia32_x87_attr_t",
1634 },
1635
1636 l_vfdiv => {
1637         cmp_attr  => "return 1;",
1638         outs      => [ "res", "M" ],
1639         arity     => 2,
1640 },
1641
1642 vfprem => {
1643         reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
1644         ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
1645         latency   => 20,
1646         units     => [ "VFP" ],
1647         mode      => "mode_E",
1648         attr_type => "ia32_x87_attr_t",
1649 },
1650
1651 l_vfprem => {
1652         cmp_attr  => "return 1;",
1653         arity     => 2,
1654 },
1655
1656 vfabs => {
1657         irn_flags => "R",
1658         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
1659         ins       => [ "value" ],
1660         latency   => 2,
1661         units     => [ "VFP" ],
1662         mode      => "mode_E",
1663         attr_type => "ia32_x87_attr_t",
1664 },
1665
1666 vfchs => {
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 # virtual Load and Store
1677
1678 vfld => {
1679         op_flags  => "L|F",
1680         state     => "exc_pinned",
1681         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1682         ins       => [ "base", "index", "mem" ],
1683         outs      => [ "res", "M" ],
1684         attr      => "ir_mode *load_mode",
1685         init_attr => "attr->attr.ls_mode = load_mode;",
1686         latency   => 2,
1687         units     => [ "VFP" ],
1688         attr_type => "ia32_x87_attr_t",
1689 },
1690
1691 vfst => {
1692         op_flags  => "L|F",
1693         state     => "exc_pinned",
1694         reg_req   => { in => [ "gp", "gp", "none", "vfp" ] },
1695         ins       => [ "base", "index", "mem", "val" ],
1696         attr      => "ir_mode *store_mode",
1697         init_attr => "attr->attr.ls_mode = store_mode;",
1698         latency   => 2,
1699         units     => [ "VFP" ],
1700         mode      => "mode_M",
1701         attr_type => "ia32_x87_attr_t",
1702 },
1703
1704 # Conversions
1705
1706 vfild => {
1707         state     => "exc_pinned",
1708         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
1709         outs      => [ "res", "M" ],
1710         ins       => [ "base", "index", "mem" ],
1711         latency   => 4,
1712         units     => [ "VFP" ],
1713         attr_type => "ia32_x87_attr_t",
1714 },
1715
1716 l_vfild => {
1717         cmp_attr  => "return 1;",
1718         outs      => [ "res", "M" ],
1719         arity     => 2,
1720 },
1721
1722 vfist => {
1723         state     => "exc_pinned",
1724         reg_req   => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
1725         ins       => [ "base", "index", "mem", "val", "fpcw" ],
1726         latency   => 4,
1727         units     => [ "VFP" ],
1728         mode      => "mode_M",
1729         attr_type => "ia32_x87_attr_t",
1730 },
1731
1732 l_vfist => {
1733         cmp_attr  => "return 1;",
1734         state     => "exc_pinned",
1735         arity     => 3,
1736         mode      => "mode_M",
1737 },
1738
1739
1740 # constants
1741
1742 vfldz => {
1743         irn_flags => "R",
1744         reg_req   => { out => [ "vfp" ] },
1745         latency   => 4,
1746         units     => [ "VFP" ],
1747         mode      => "mode_E",
1748         attr_type => "ia32_x87_attr_t",
1749 },
1750
1751 vfld1 => {
1752         irn_flags => "R",
1753         reg_req   => { out => [ "vfp" ] },
1754         latency   => 4,
1755         units     => [ "VFP" ],
1756         mode      => "mode_E",
1757         attr_type => "ia32_x87_attr_t",
1758 },
1759
1760 vfldpi => {
1761         irn_flags => "R",
1762         reg_req   => { out => [ "vfp" ] },
1763         latency   => 4,
1764         units     => [ "VFP" ],
1765         mode      => "mode_E",
1766         attr_type => "ia32_x87_attr_t",
1767 },
1768
1769 vfldln2 => {
1770         irn_flags => "R",
1771         reg_req   => { out => [ "vfp" ] },
1772         latency   => 4,
1773         units     => [ "VFP" ],
1774         mode      => "mode_E",
1775         attr_type => "ia32_x87_attr_t",
1776 },
1777
1778 vfldlg2 => {
1779         irn_flags => "R",
1780         reg_req   => { out => [ "vfp" ] },
1781         latency   => 4,
1782         units     => [ "VFP" ],
1783         mode      => "mode_E",
1784         attr_type => "ia32_x87_attr_t",
1785 },
1786
1787 vfldl2t => {
1788         irn_flags => "R",
1789         reg_req   => { out => [ "vfp" ] },
1790         latency   => 4,
1791         units     => [ "VFP" ],
1792         mode      => "mode_E",
1793         attr_type => "ia32_x87_attr_t",
1794 },
1795
1796 vfldl2e => {
1797         irn_flags => "R",
1798         reg_req   => { out => [ "vfp" ] },
1799         latency   => 4,
1800         units     => [ "VFP" ],
1801         mode      => "mode_E",
1802         attr_type => "ia32_x87_attr_t",
1803 },
1804
1805 # other
1806
1807 vFucomFnstsw => {
1808 # we can't allow to rematerialize this node so we don't have
1809 #  accidently produce Phi(Fucom, Fucom(flipped))
1810 #       irn_flags => "R",
1811         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
1812         ins       => [ "left", "right" ],
1813         outs      => [ "flags" ],
1814         attr      => "int flipped",
1815         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1816         latency   => 3,
1817         units     => [ "VFP" ],
1818         attr_type => "ia32_x87_attr_t",
1819         mode      => $mode_gp
1820 },
1821
1822 vFucomi => {
1823         irn_flags => "R",
1824         reg_req   => { in => [ "vfp", "vfp" ], out => [ "eflags" ] },
1825         ins       => [ "left", "right" ],
1826         outs      => [ "flags" ],
1827         attr      => "int flipped",
1828         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1829         latency   => 3,
1830         units     => [ "VFP" ],
1831         attr_type => "ia32_x87_attr_t",
1832         mode      => $mode_gp
1833 },
1834
1835 vFtstFnstsw => {
1836 #       irn_flags => "R",
1837         reg_req   => { in => [ "vfp" ], out => [ "eax" ] },
1838         ins       => [ "left" ],
1839         outs      => [ "flags" ],
1840         attr      => "int flipped",
1841         init_attr => "attr->attr.data.cmp_flipped = flipped;",
1842         latency   => 3,
1843         units     => [ "VFP" ],
1844         attr_type => "ia32_x87_attr_t",
1845         mode      => $mode_gp
1846 },
1847
1848 Sahf => {
1849         irn_flags => "R",
1850         reg_req   => { in => [ "eax" ], out => [ "eflags" ] },
1851         ins       => [ "val" ],
1852         outs      => [ "flags" ],
1853         emit      => '. sahf',
1854         units     => [ "GP" ],
1855         mode      => $mode_flags,
1856 },
1857
1858 #------------------------------------------------------------------------#
1859 #       ___ _____    __ _             _                     _            #
1860 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
1861 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
1862 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
1863 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
1864 #------------------------------------------------------------------------#
1865
1866 # Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
1867 #       are swapped, we work this around in the emitter...
1868
1869 fadd => {
1870         op_flags  => "R",
1871         rd_constructor => "NONE",
1872         reg_req   => { },
1873         emit      => '. fadd%XM %x87_binop',
1874         attr_type => "ia32_x87_attr_t",
1875 },
1876
1877 faddp => {
1878         op_flags  => "R",
1879         rd_constructor => "NONE",
1880         reg_req   => { },
1881         emit      => '. faddp%XM %x87_binop',
1882         attr_type => "ia32_x87_attr_t",
1883 },
1884
1885 fmul => {
1886         op_flags  => "R",
1887         rd_constructor => "NONE",
1888         reg_req   => { },
1889         emit      => '. fmul%XM %x87_binop',
1890         attr_type => "ia32_x87_attr_t",
1891 },
1892
1893 fmulp => {
1894         op_flags  => "R",
1895         rd_constructor => "NONE",
1896         reg_req   => { },
1897         emit      => '. fmulp%XM %x87_binop',,
1898         attr_type => "ia32_x87_attr_t",
1899 },
1900
1901 fsub => {
1902         op_flags  => "R",
1903         rd_constructor => "NONE",
1904         reg_req   => { },
1905         emit      => '. fsub%XM %x87_binop',
1906         attr_type => "ia32_x87_attr_t",
1907 },
1908
1909 fsubp => {
1910         op_flags  => "R",
1911         rd_constructor => "NONE",
1912         reg_req   => { },
1913 # see note about gas bugs
1914         emit      => '. fsubrp%XM %x87_binop',
1915         attr_type => "ia32_x87_attr_t",
1916 },
1917
1918 fsubr => {
1919         op_flags  => "R",
1920         rd_constructor => "NONE",
1921         irn_flags => "R",
1922         reg_req   => { },
1923         emit      => '. fsubr%XM %x87_binop',
1924         attr_type => "ia32_x87_attr_t",
1925 },
1926
1927 fsubrp => {
1928         op_flags  => "R",
1929         rd_constructor => "NONE",
1930         irn_flags => "R",
1931         reg_req   => { },
1932 # see note about gas bugs
1933         emit      => '. fsubp%XM %x87_binop',
1934         attr_type => "ia32_x87_attr_t",
1935 },
1936
1937 fprem => {
1938         op_flags  => "R",
1939         rd_constructor => "NONE",
1940         reg_req   => { },
1941         emit      => '. fprem1',
1942         attr_type => "ia32_x87_attr_t",
1943 },
1944
1945 # this node is just here, to keep the simulator running
1946 # we can omit this when a fprem simulation function exists
1947 fpremp => {
1948         op_flags  => "R",
1949         rd_constructor => "NONE",
1950         reg_req   => { },
1951         emit      => '. fprem1',
1952         attr_type => "ia32_x87_attr_t",
1953 },
1954
1955 fdiv => {
1956         op_flags  => "R",
1957         rd_constructor => "NONE",
1958         reg_req   => { },
1959         emit      => '. fdiv%XM %x87_binop',
1960         attr_type => "ia32_x87_attr_t",
1961 },
1962
1963 fdivp => {
1964         op_flags  => "R",
1965         rd_constructor => "NONE",
1966         reg_req   => { },
1967 # see note about gas bugs
1968         emit      => '. fdivrp%XM %x87_binop',
1969         attr_type => "ia32_x87_attr_t",
1970 },
1971
1972 fdivr => {
1973         op_flags  => "R",
1974         rd_constructor => "NONE",
1975         reg_req   => { },
1976         emit      => '. fdivr%XM %x87_binop',
1977         attr_type => "ia32_x87_attr_t",
1978 },
1979
1980 fdivrp => {
1981         op_flags  => "R",
1982         rd_constructor => "NONE",
1983         reg_req   => { },
1984 # see note about gas bugs
1985         emit      => '. fdivp%XM %x87_binop',
1986         attr_type => "ia32_x87_attr_t",
1987 },
1988
1989 fabs => {
1990         op_flags  => "R",
1991         rd_constructor => "NONE",
1992         reg_req   => { },
1993         emit      => '. fabs',
1994         attr_type => "ia32_x87_attr_t",
1995 },
1996
1997 fchs => {
1998         op_flags  => "R|K",
1999         rd_constructor => "NONE",
2000         reg_req   => { },
2001         emit      => '. fchs',
2002         attr_type => "ia32_x87_attr_t",
2003 },
2004
2005 # x87 Load and Store
2006
2007 fld => {
2008         rd_constructor => "NONE",
2009         op_flags  => "R|L|F",
2010         state     => "exc_pinned",
2011         reg_req   => { },
2012         emit      => '. fld%XM %AM',
2013         attr_type => "ia32_x87_attr_t",
2014 },
2015
2016 fst => {
2017         rd_constructor => "NONE",
2018         op_flags  => "R|L|F",
2019         state     => "exc_pinned",
2020         reg_req   => { },
2021         emit      => '. fst%XM %AM',
2022         mode      => "mode_M",
2023         attr_type => "ia32_x87_attr_t",
2024 },
2025
2026 fstp => {
2027         rd_constructor => "NONE",
2028         op_flags  => "R|L|F",
2029         state     => "exc_pinned",
2030         reg_req   => { },
2031         emit      => '. fstp%XM %AM',
2032         mode      => "mode_M",
2033         attr_type => "ia32_x87_attr_t",
2034 },
2035
2036 # Conversions
2037
2038 fild => {
2039         op_flags  => "R",
2040         rd_constructor => "NONE",
2041         reg_req   => { },
2042         emit      => '. fild%M %AM',
2043         attr_type => "ia32_x87_attr_t",
2044 },
2045
2046 fist => {
2047         op_flags  => "R",
2048         state     => "exc_pinned",
2049         rd_constructor => "NONE",
2050         reg_req   => { },
2051         emit      => '. fist%M %AM',
2052         mode      => "mode_M",
2053         attr_type => "ia32_x87_attr_t",
2054 },
2055
2056 fistp => {
2057         op_flags  => "R",
2058         state     => "exc_pinned",
2059         rd_constructor => "NONE",
2060         reg_req   => { },
2061         emit      => '. fistp%M %AM',
2062         mode      => "mode_M",
2063         attr_type => "ia32_x87_attr_t",
2064 },
2065
2066 # constants
2067
2068 fldz => {
2069         op_flags  => "R|c|K",
2070         irn_flags => "R",
2071         reg_req   => { out => [ "vfp" ] },
2072         emit      => '. fldz',
2073         attr_type => "ia32_x87_attr_t",
2074 },
2075
2076 fld1 => {
2077         op_flags  => "R|c|K",
2078         irn_flags => "R",
2079         reg_req   => { out => [ "vfp" ] },
2080         emit      => '. fld1',
2081         attr_type => "ia32_x87_attr_t",
2082 },
2083
2084 fldpi => {
2085         op_flags  => "R|c|K",
2086         irn_flags => "R",
2087         reg_req   => { out => [ "vfp" ] },
2088         emit      => '. fldpi',
2089         attr_type => "ia32_x87_attr_t",
2090 },
2091
2092 fldln2 => {
2093         op_flags  => "R|c|K",
2094         irn_flags => "R",
2095         reg_req   => { out => [ "vfp" ] },
2096         emit      => '. fldln2',
2097         attr_type => "ia32_x87_attr_t",
2098 },
2099
2100 fldlg2 => {
2101         op_flags  => "R|c|K",
2102         irn_flags => "R",
2103         reg_req   => { out => [ "vfp" ] },
2104         emit      => '. fldlg2',
2105         attr_type => "ia32_x87_attr_t",
2106 },
2107
2108 fldl2t => {
2109         op_flags  => "R|c|K",
2110         irn_flags => "R",
2111         reg_req   => { out => [ "vfp" ] },
2112         emit      => '. fldll2t',
2113         attr_type => "ia32_x87_attr_t",
2114 },
2115
2116 fldl2e => {
2117         op_flags  => "R|c|K",
2118         irn_flags => "R",
2119         reg_req   => { out => [ "vfp" ] },
2120         emit      => '. fldl2e',
2121         attr_type => "ia32_x87_attr_t",
2122 },
2123
2124 # fxch, fpush, fpop
2125 # Note that it is NEVER allowed to do CSE on these nodes
2126 # Moreover, note the virtual register requierements!
2127
2128 fxch => {
2129         op_flags  => "R|K",
2130         reg_req   => { },
2131         cmp_attr  => "return 1;",
2132         emit      => '. fxch %X0',
2133         attr_type => "ia32_x87_attr_t",
2134         mode      => "mode_ANY",
2135 },
2136
2137 fpush => {
2138         op_flags  => "R|K",
2139         reg_req   => {},
2140         cmp_attr  => "return 1;",
2141         emit      => '. fld %X0',
2142         attr_type => "ia32_x87_attr_t",
2143         mode      => "mode_ANY",
2144 },
2145
2146 fpushCopy => {
2147         op_flags  => "R",
2148         reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
2149         cmp_attr  => "return 1;",
2150         emit      => '. fld %X0',
2151         attr_type => "ia32_x87_attr_t",
2152 },
2153
2154 fpop => {
2155         op_flags  => "K",
2156         reg_req   => { },
2157         cmp_attr  => "return 1;",
2158         emit      => '. fstp %X0',
2159         attr_type => "ia32_x87_attr_t",
2160         mode      => "mode_ANY",
2161 },
2162
2163 ffreep => {
2164         op_flags  => "K",
2165         reg_req   => { },
2166         cmp_attr  => "return 1;",
2167         emit      => '. ffreep %X0',
2168         attr_type => "ia32_x87_attr_t",
2169         mode      => "mode_ANY",
2170 },
2171
2172 emms => {
2173         op_flags  => "K",
2174         reg_req   => { },
2175         cmp_attr  => "return 1;",
2176         emit      => '. emms',
2177         attr_type => "ia32_x87_attr_t",
2178         mode      => "mode_ANY",
2179 },
2180
2181 femms => {
2182         op_flags  => "K",
2183         reg_req   => { },
2184         cmp_attr  => "return 1;",
2185         emit      => '. femms',
2186         attr_type => "ia32_x87_attr_t",
2187         mode      => "mode_ANY",
2188 },
2189
2190 # compare
2191
2192 FucomFnstsw => {
2193         reg_req   => { },
2194         emit      => ". fucom %X1\n".
2195                      ". fnstsw",
2196         attr_type => "ia32_x87_attr_t",
2197 },
2198
2199 FucompFnstsw => {
2200         reg_req   => { },
2201         emit      => ". fucomp %X1\n".
2202                      ". fnstsw",
2203         attr_type => "ia32_x87_attr_t",
2204 },
2205
2206 FucomppFnstsw => {
2207         reg_req   => { },
2208         emit      => ". fucompp\n".
2209                      ". fnstsw",
2210         attr_type => "ia32_x87_attr_t",
2211 },
2212
2213 Fucomi => {
2214         reg_req   => { },
2215         emit      => '. fucomi %X1',
2216         attr_type => "ia32_x87_attr_t",
2217 },
2218
2219 Fucompi => {
2220         reg_req   => { },
2221         emit      => '. fucompi %X1',
2222         attr_type => "ia32_x87_attr_t",
2223 },
2224
2225 FtstFnstsw => {
2226         reg_req   => { },
2227         emit      => ". ftst\n".
2228                      ". fnstsw",
2229         attr_type => "ia32_x87_attr_t",
2230 },
2231
2232
2233 # -------------------------------------------------------------------------------- #
2234 #  ____ ____  _____                  _                               _             #
2235 # / ___/ ___|| ____| __   _____  ___| |_ ___  _ __   _ __   ___   __| | ___  ___   #
2236 # \___ \___ \|  _|   \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __|  #
2237 #  ___) |__) | |___   \ V /  __/ (__| || (_) | |    | | | | (_) | (_| |  __/\__ \  #
2238 # |____/____/|_____|   \_/ \___|\___|\__\___/|_|    |_| |_|\___/ \__,_|\___||___/  #
2239 #                                                                                  #
2240 # -------------------------------------------------------------------------------- #
2241
2242
2243 # Spilling and reloading of SSE registers, hardcoded, not generated #
2244
2245 xxLoad => {
2246         op_flags  => "L|F",
2247         state     => "exc_pinned",
2248         reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
2249         emit      => '. movdqu %D0, %AM',
2250         outs      => [ "res", "M" ],
2251         units     => [ "SSE" ],
2252 },
2253
2254 xxStore => {
2255         op_flags => "L|F",
2256         state    => "exc_pinned",
2257         reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
2258         ins      => [ "base", "index", "mem", "val" ],
2259         emit     => '. movdqu %binop',
2260         units    => [ "SSE" ],
2261         mode     => "mode_M",
2262 },
2263
2264 ); # end of %nodes
2265
2266 # Include the generated SIMD node specification written by the SIMD optimization
2267 $my_script_name = dirname($myname) . "/../ia32/ia32_simd_spec.pl";
2268 unless ($return = do $my_script_name) {
2269         warn "couldn't parse $my_script_name: $@" if $@;
2270         warn "couldn't do $my_script_name: $!"    unless defined $return;
2271         warn "couldn't run $my_script_name"       unless $return;
2272 }