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