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