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