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