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