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