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