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