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