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