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