ac5f7c62844102cae4b4988930f8c40dbf026908
[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"
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 # },
37 #
38 # ... # (all nodes you need to describe)
39 #
40 # ); # close the %nodes initializer
41
42 # op_flags: flags for the operation, OPTIONAL (default is "N")
43 # the op_flags correspond to the firm irop_flags:
44 #   N   irop_flag_none
45 #   L   irop_flag_labeled
46 #   C   irop_flag_commutative
47 #   X   irop_flag_cfopcode
48 #   I   irop_flag_ip_cfopcode
49 #   F   irop_flag_fragile
50 #   Y   irop_flag_forking
51 #   H   irop_flag_highlevel
52 #   c   irop_flag_constlike
53 #   K   irop_flag_keep
54 #
55 # irn_flags: special node flags, OPTIONAL (default is 0)
56 # following irn_flags are supported:
57 #   R   rematerializeable
58 #   N   not spillable
59 #   I   ignore for register allocation
60 #
61 # state: state of the operation, OPTIONAL (default is "floats")
62 #
63 # arity: arity of the operation, MUST NOT BE OMITTED
64 #
65 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
66 #        are always the first 3 arguments and are always autmatically
67 #        created)
68 #        If this key is missing the following arguments will be created:
69 #        for i = 1 .. arity: ir_node *op_i
70 #        ir_mode *mode
71 #
72 # outs:  if a node defines more than one output, the names of the projections
73 #        nodes having outs having automatically the mode mode_T
74 #
75 # comment: OPTIONAL comment for the node constructor
76 #
77 # rd_constructor: for every operation there will be a
78 #      new_rd_<arch>_<op-name> function with the arguments from above
79 #      which creates the ir_node corresponding to the defined operation
80 #      you can either put the complete source code of this function here
81 #
82 #      This key is OPTIONAL. If omitted, the following constructor will
83 #      be created:
84 #      if (!op_<arch>_<op-name>) assert(0);
85 #      for i = 1 to arity
86 #         set in[i] = op_i
87 #      done
88 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
89 #      return res
90 #
91 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
92
93 # register types:
94 #   0 - no special type
95 #   1 - caller save (register must be saved by the caller of a function)
96 #   2 - callee save (register must be saved by the called function)
97 #   4 - ignore (do not assign this register)
98 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
99 %reg_classes = (
100   "gp" => [
101             { "name" => "eax", "type" => 1 },
102             { "name" => "edx", "type" => 1 },
103             { "name" => "ebx", "type" => 2 },
104             { "name" => "ecx", "type" => 1 },
105             { "name" => "esi", "type" => 2 },
106             { "name" => "edi", "type" => 2 },
107             { "name" => "ebp", "type" => 2 },
108             { "name" => "esp", "type" => 4 },
109             { "name" => "gp_NOREG", "type" => 6 },  # we need a dummy register for NoReg nodes
110             { "name" => "gp_UKNWN", "type" => 6 },  # we need a dummy register for Unknown nodes
111                         { "mode" => "mode_P" }
112           ],
113   "xmm" => [
114             { "name" => "xmm0", "type" => 1 },
115             { "name" => "xmm1", "type" => 1 },
116             { "name" => "xmm2", "type" => 1 },
117             { "name" => "xmm3", "type" => 1 },
118             { "name" => "xmm4", "type" => 1 },
119             { "name" => "xmm5", "type" => 1 },
120             { "name" => "xmm6", "type" => 1 },
121             { "name" => "xmm7", "type" => 1 },
122             { "name" => "xmm_NOREG", "type" => 6 },  # we need a dummy register for NoReg nodes
123             { "name" => "xmm_UKNWN", "type" => 6 },  # we need a dummy register for Unknown nodes
124                         { "mode" => "mode_D" }
125           ],
126   "vfp" => [
127             { "name" => "vf0", "type" => 1 },
128             { "name" => "vf1", "type" => 1 },
129             { "name" => "vf2", "type" => 1 },
130             { "name" => "vf3", "type" => 1 },
131             { "name" => "vf4", "type" => 1 },
132             { "name" => "vf5", "type" => 1 },
133             { "name" => "vf6", "type" => 1 },
134             { "name" => "vf7", "type" => 1 },
135             { "name" => "vfp_NOREG", "type" => 6 },  # we need a dummy register for NoReg nodes
136             { "name" => "vfp_UKNWN", "type" => 6 },  # we need a dummy register for Unknown nodes
137                         { "mode" => "mode_E" }
138           ],
139   "st" => [
140             { "name" => "st0", "type" => 1 },
141             { "name" => "st1", "type" => 1 },
142             { "name" => "st2", "type" => 1 },
143             { "name" => "st3", "type" => 1 },
144             { "name" => "st4", "type" => 1 },
145             { "name" => "st5", "type" => 1 },
146             { "name" => "st6", "type" => 1 },
147             { "name" => "st7", "type" => 1 },
148                         { "mode" => "mode_E" }
149           ]
150 ); # %reg_classes
151
152 #--------------------------------------------------#
153 #                        _                         #
154 #                       (_)                        #
155 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
156 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
157 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
158 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
159 #                                      | |         #
160 #                                      |_|         #
161 #--------------------------------------------------#
162
163 %operands = (
164 );
165
166 %nodes = (
167
168 #-----------------------------------------------------------------#
169 #  _       _                                         _            #
170 # (_)     | |                                       | |           #
171 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
172 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
173 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
174 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
175 #                   __/ |                                         #
176 #                  |___/                                          #
177 #-----------------------------------------------------------------#
178
179 # commutative operations
180
181 # NOTE:
182 # All nodes supporting Addressmode have 5 INs:
183 # 1 - base    r1 == NoReg in case of no AM or no base
184 # 2 - index   r2 == NoReg in case of no AM or no index
185 # 3 - op1     r3 == always present
186 # 4 - op2     r4 == NoReg in case of immediate operation
187 # 5 - mem     NoMem in case of no AM otherwise it takes the mem from the Load
188
189 "Add" => {
190   "irn_flags" => "R",
191   "comment"   => "construct Add: Add(a, b) = Add(b, a) = a + b",
192   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
193   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
194   "emit"      => '. add %ia32_emit_binop /* Add(%A1, %A2) -> %D1 */',
195   "outs"      => [ "res", "M" ],
196 },
197
198 "Mul" => {
199   "irn_flags" => "R",
200   "comment"   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
201   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
202   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
203   "emit"      => '. imul %ia32_emit_binop /* Mul(%A1, %A2) -> %D1 */',
204   "outs"      => [ "res", "M" ],
205 },
206
207 # Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX
208 "Mulh" => {
209   "comment"   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
210   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
211   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax in_r3", "edx in_r4" ] },
212   "emit"      => '. imul %ia32_emit_binop /* Mulh(%A1, %A2) -> %D1 */',
213   "outs"      => [ "EAX", "EDX", "M" ],
214 },
215
216 "And" => {
217   "irn_flags" => "R",
218   "comment"   => "construct And: And(a, b) = And(b, a) = a AND b",
219   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
220   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
221   "emit"      => '. and %ia32_emit_binop /* And(%A1, %A2) -> %D1 */',
222   "outs"      => [ "res", "M" ],
223 },
224
225 "Or" => {
226   "irn_flags" => "R",
227   "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
228   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
229   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
230   "emit"      => '. or %ia32_emit_binop /* Or(%A1, %A2) -> %D1 */',
231   "outs"      => [ "res", "M" ],
232 },
233
234 "Eor" => {
235   "irn_flags" => "R",
236   "comment"   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
237   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
238   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
239   "emit"      => '. xor %ia32_emit_binop /* Xor(%A1, %A2) -> %D1 */',
240   "outs"      => [ "res", "M" ],
241 },
242
243 "Max" => {
244   "irn_flags" => "R",
245   "comment"   => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
246   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
247   "emit"      =>
248 '2. cmp %S1, %S2 /* prepare Max (%S1 - %S2), (%A1, %A2) */
249   if (mode_is_signed(get_irn_mode(n))) {
250 4.  cmovl %D1, %S2 /* %S1 is less %S2 */
251   }
252   else {
253 4.  cmovb %D1, %S2 /* %S1 is below %S2 */
254   }
255 '
256 },
257
258 "Min" => {
259   "irn_flags" => "R",
260   "comment"   => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b",
261   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
262   "emit"      =>
263 '2. cmp %S1, %S2 /* prepare Min (%S1 - %S2), (%A1, %A2) */
264   if (mode_is_signed(get_irn_mode(n))) {
265 2.  cmovg %D1, %S2 /* %S1 is greater %S2 */
266   }
267   else {
268 2.  cmova %D1, %S2, %D1 /* %S1 is above %S2 */
269   }
270 '
271 },
272
273 "CMov" => {
274   "irn_flags" => "R",
275   "comment"   => "construct Mux: Mux(sel, a, b) == sel ? a : b",
276   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp" ], "out" => [ "in_r4" ] }
277 },
278
279 # not commutative operations
280
281 "Sub" => {
282   "irn_flags" => "R",
283   "comment"   => "construct Sub: Sub(a, b) = a - b",
284   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
285   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
286   "emit"      => '. sub %ia32_emit_binop /* Sub(%A1, %A2) -> %D1 */',
287   "outs"      => [ "res", "M" ],
288 },
289
290 "DivMod" => {
291   "op_flags"  => "F|L",
292   "state"     => "exc_pinned",
293   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
294   "attr"      => "ia32_op_flavour_t dm_flav",
295   "init_attr" => "  attr->data.op_flav = dm_flav;",
296   "cmp_attr"  => "  return attr_a->data.op_flav != attr_b->data.op_flav;\n",
297   "emit"      =>
298 '  if (mode_is_signed(get_irn_mode(n))) {
299 4.  idiv %S2 /* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
300   }
301   else {
302 4.  div %S2 /* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
303   }
304 ',
305   "outs"      => [ "div_res", "mod_res", "M" ],
306 },
307
308 "Shl" => {
309   "irn_flags" => "R",
310   "comment"   => "construct Shl: Shl(a, b) = a << b",
311   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
312   "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
313   "emit"      => '. shl %ia32_emit_binop /* Shl(%A1, %A2) -> %D1 */',
314   "outs"      => [ "res", "M" ],
315 },
316
317 "Shr" => {
318   "irn_flags" => "R",
319   "comment"   => "construct Shr: Shr(a, b) = a >> b",
320   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
321   "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
322   "emit"      => '. shr %ia32_emit_binop /* Shr(%A1, %A2) -> %D1 */',
323   "outs"      => [ "res", "M" ],
324 },
325
326 "Shrs" => {
327   "irn_flags" => "R",
328   "comment"   => "construct Shrs: Shrs(a, b) = a >> b",
329   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
330   "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
331   "emit"      => '. sar %ia32_emit_binop /* Shrs(%A1, %A2) -> %D1 */',
332   "outs"      => [ "res", "M" ],
333 },
334
335 "RotR" => {
336   "irn_flags" => "R",
337   "comment"     => "construct RotR: RotR(a, b) = a ROTR b",
338   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
339   "reg_req"     => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
340   "emit"        => '. ror %ia32_emit_binop /* RotR(%A1, %A2) -> %D1 */',
341   "outs"      => [ "res", "M" ],
342 },
343
344 "RotL" => {
345   "irn_flags" => "R",
346   "comment"   => "construct RotL: RotL(a, b) = a ROTL b",
347   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
348   "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
349   "emit"      => '. rol %ia32_emit_binop /* RotL(%A1, %A2) -> %D1 */',
350   "outs"      => [ "res", "M" ],
351 },
352
353 # unary operations
354
355 "Minus" => {
356   "irn_flags" => "R",
357   "comment"   => "construct Minus: Minus(a) = -a",
358   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
359   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
360   "emit"      => '. neg %ia32_emit_unop /* Neg(%A1) -> %D1, (%A1) */',
361   "outs"      => [ "res", "M" ],
362 },
363
364 "Inc" => {
365   "irn_flags" => "R",
366   "comment"   => "construct Increment: Inc(a) = a++",
367   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
368   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
369   "emit"      => '. inc %ia32_emit_unop /* Inc(%S1) -> %D1, (%A1) */',
370   "outs"      => [ "res", "M" ],
371 },
372
373 "Dec" => {
374   "irn_flags" => "R",
375   "comment"   => "construct Decrement: Dec(a) = a--",
376   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
377   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
378   "emit"      => '. dec %ia32_emit_unop /* Dec(%S1) -> %D1, (%A1) */',
379   "outs"      => [ "res", "M" ],
380 },
381
382 "Not" => {
383   "irn_flags" => "R",
384   "comment"   => "construct Not: Not(a) = !a",
385   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
386   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
387   "emit"      => '. not %ia32_emit_unop /* Not(%S1) -> %D1, (%A1) */',
388   "outs"      => [ "res", "M" ],
389 },
390
391 # other operations
392
393 "CondJmp" => {
394   "op_flags"  => "L|X|Y",
395   "comment"   => "construct conditional jump: CMP A, B && JMPxx LABEL",
396   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
397   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ] },
398   "outs"      => [ "false", "true" ],
399 },
400
401 "TestJmp" => {
402   "op_flags"  => "L|X|Y",
403   "comment"   => "construct conditional jump: TEST A, B && JMPxx LABEL",
404   "reg_req"  => { "in" => [ "gp", "gp" ] },
405   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
406   "outs"      => [ "false", "true" ],
407 },
408
409 "CJmpAM" => {
410   "op_flags"  => "L|X|Y",
411   "comment"   => "construct conditional jump without CMP (replaces CondJmp): JMPxx LABEL",
412   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
413   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "none", "none" ] },
414   "outs"      => [ "false", "true" ],
415 },
416
417 "CJmp" => {
418   "op_flags"  => "L|X|Y",
419   "comment"   => "construct conditional jump without CMP (replaces TestJmp): JMPxx LABEL",
420   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
421   "reg_req"   => { "in" => [ "gp", "gp" ] },
422 },
423
424 "SwitchJmp" => {
425   "op_flags"  => "L|X|Y",
426   "comment"   => "construct switch",
427   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
428   "reg_req"   => { "in" => [ "gp" ], "out" => [ "none" ] },
429 },
430
431 "Const" => {
432   "op_flags"  => "c",
433   "irn_flags" => "R",
434   "comment"   => "represents an integer constant",
435   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
436   "reg_req"   => { "in" => [ "none" ], "out" => [ "gp" ] },
437 },
438
439 "Cdq" => {
440   "irn_flags" => "R",
441   "comment"   => "construct CDQ: sign extend EAX -> EDX:EAX",
442   "reg_req"   => { "in" => [ "gp" ], "out" => [ "eax in_r1", "edx" ] },
443   "emit"      => '. cdq /* sign extend EAX -> EDX:EAX, (%A1) */',
444   "outs"      => [ "EAX", "EDX" ],
445 },
446
447 # Load / Store
448
449 "Load" => {
450   "op_flags"  => "L|F",
451   "irn_flags" => "R",
452   "state"     => "exc_pinned",
453   "comment"   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
454   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
455   "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp" ] },
456   "emit"      =>
457 '  if (get_mode_size_bits(get_ia32_ls_mode(n)) < 32) {
458 4.   mov%Mx %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */
459   }
460   else {
461 4.   mov %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */
462   }
463 ',
464   "outs"      => [ "res", "M" ],
465 },
466
467 "Store" => {
468   "op_flags"  => "L|F",
469   "state"     => "exc_pinned",
470   "comment"   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
471   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
472   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ] },
473   "emit"      => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */',
474   "outs"      => [ "M" ],
475 },
476
477 "Store8Bit" => {
478   "op_flags"  => "L|F",
479   "state"     => "exc_pinned",
480   "comment"   => "construct 8Bit Store: Store(ptr, val, mem) = ST ptr,val",
481   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
482   "reg_req"   => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ] },
483   "emit"      => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */',
484   "outs"      => [ "M" ],
485 },
486
487 "Lea" => {
488   "irn_flags" => "R",
489   "comment"   => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8",
490   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
491   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
492   "emit"      => '. lea %D1, %ia32_emit_am /* LEA(%A1, %A2) */'
493 },
494
495 "Push" => {
496   "comment"   => "push a gp register on the stack",
497   "reg_req"   => { "in" => [ "esp", "gp", "none" ], "out" => [ "esp" ] },
498   "emit"      => '
499 if (get_ia32_id_cnst(n)) {
500         if (get_ia32_immop_type(n) == ia32_ImmConst) {
501 . push %C /* Push(%A2) */
502         } else {
503 . push OFFSET FLAT:%C /* Push(%A2) */
504         }
505 }
506 else {
507 . push %S2 /* Push(%A2) */
508 }
509 ',
510   "outs"      => [ "stack", "M" ],
511 },
512
513 "Pop" => {
514   "comment"   => "pop a gp register from the stack",
515   "reg_req"   => { "in" => [ "esp", "none" ], "out" => [ "gp", "esp" ] },
516   "emit"      => '. pop %D1 /* Pop -> %D1 */',
517   "outs"      => [ "res", "stack", "M" ],
518 },
519
520 "Enter" => {
521   "comment"   => "create stack frame",
522   "reg_req"   => { "in" => [ "esp" ], "out" => [ "ebp", "esp" ] },
523   "emit"      => '. enter /* Enter */',
524   "outs"      => [ "frame", "stack", "M" ],
525 },
526
527 "Leave" => {
528   "comment"   => "destroy stack frame",
529   "reg_req"   => { "in" => [ "esp", "ebp" ], "out" => [ "ebp", "esp" ] },
530   "emit"      => '. leave /* Leave */',
531   "outs"      => [ "frame", "stack", "M" ],
532 },
533
534 #-----------------------------------------------------------------------------#
535 #   _____ _____ ______    __ _             _                     _            #
536 #  / ____/ ____|  ____|  / _| |           | |                   | |           #
537 # | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
538 #  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
539 #  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
540 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
541 #-----------------------------------------------------------------------------#
542
543 # commutative operations
544
545 "xAdd" => {
546   "irn_flags" => "R",
547   "comment"   => "construct SSE Add: Add(a, b) = Add(b, a) = a + b",
548   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
549   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
550   "emit"      => '. adds%M %ia32_emit_binop /* SSE Add(%A3, %A4) -> %D1 */',
551   "outs"      => [ "res", "M" ],
552 },
553
554 "xMul" => {
555   "irn_flags" => "R",
556   "comment"   => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b",
557   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
558   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
559   "emit"      => '. muls%M %ia32_emit_binop /* SSE Mul(%A3, %A4) -> %D1 */',
560   "outs"      => [ "res", "M" ],
561 },
562
563 "xMax" => {
564   "irn_flags" => "R",
565   "comment"   => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
566   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
567   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
568   "emit"      => '. maxs%M %ia32_emit_binop /* SSE Max(%A3, %A4) -> %D1 */',
569   "outs"      => [ "res", "M" ],
570 },
571
572 "xMin" => {
573   "irn_flags" => "R",
574   "comment"   => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
575   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
576   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
577   "emit"      => '. mins%M %ia32_emit_binop /* SSE Min(%A3, %A4) -> %D1 */',
578   "outs"      => [ "res", "M" ],
579 },
580
581 "xAnd" => {
582   "irn_flags" => "R",
583   "comment"   => "construct SSE And: And(a, b) = a AND b",
584   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
585   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
586   "emit"      => '. andp%M %ia32_emit_binop /* SSE And(%A3, %A4) -> %D1 */',
587   "outs"      => [ "res", "M" ],
588 },
589
590 "xOr" => {
591   "irn_flags" => "R",
592   "comment"   => "construct SSE Or: Or(a, b) = a OR b",
593   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
594   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
595   "emit"      => '. orp%M %ia32_emit_binop /* SSE Or(%A3, %A4) -> %D1 */',
596   "outs"      => [ "res", "M" ],
597 },
598
599 "xEor" => {
600   "irn_flags" => "R",
601   "comment"   => "construct SSE Eor: Eor(a, b) = a XOR b",
602   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
603   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
604   "emit"      => '. xorp%M %ia32_emit_binop /* SSE Xor(%A3, %A4) -> %D1 */',
605   "outs"      => [ "res", "M" ],
606 },
607
608 # not commutative operations
609
610 "xSub" => {
611   "irn_flags" => "R",
612   "comment"   => "construct SSE Sub: Sub(a, b) = a - b",
613   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
614   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
615   "emit"      => '. subs%M %ia32_emit_binop /* SSE Sub(%A1, %A2) -> %D1 */',
616   "outs"      => [ "res", "M" ],
617 },
618
619 "xDiv" => {
620   "irn_flags" => "R",
621   "comment"   => "construct SSE Div: Div(a, b) = a / b",
622   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
623   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3 !in_r4" ] },
624   "emit"      => '. divs%M %ia32_emit_binop /* SSE Div(%A1, %A2) -> %D1 */',
625   "outs"      => [ "res", "M" ],
626 },
627
628 # other operations
629
630 "xCondJmp" => {
631   "op_flags"  => "L|X|Y",
632   "comment"   => "construct conditional jump: UCOMIS A, B && JMPxx LABEL",
633   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
634   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "none", "none" ] },
635   "outs"      => [ "false", "true" ],
636 },
637
638 "xConst" => {
639   "op_flags"  => "c",
640   "irn_flags" => "R",
641   "comment"   => "represents a SSE constant",
642   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
643   "reg_req"   => { "in" => [ "none" ], "out" => [ "xmm" ] },
644   "emit"      => '. movs%M %D1, %C /* Load fConst into register */',
645 },
646
647 # Load / Store
648
649 "xLoad" => {
650   "op_flags"  => "L|F",
651   "irn_flags" => "R",
652   "state"     => "exc_pinned",
653   "comment"   => "construct SSE Load: Load(ptr, mem) = LD ptr",
654   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
655   "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "xmm" ] },
656   "emit"      => '. movs%M %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */',
657   "outs"      => [ "res", "M" ],
658 },
659
660 "xStore" => {
661   "op_flags" => "L|F",
662   "state"    => "exc_pinned",
663   "comment"  => "construct Store: Store(ptr, val, mem) = ST ptr,val",
664   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
665   "reg_req"  => { "in" => [ "gp", "gp", "xmm", "none" ] },
666   "emit"     => '. movs%M %ia32_emit_binop /* Store(%S3) -> (%A1) */',
667   "outs"      => [ "M" ],
668 },
669
670 # CopyB
671
672 "CopyB" => {
673   "op_flags" => "F|H",
674   "state"    => "pinned",
675   "comment"  => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
676   "reg_req"  => { "in" => [ "edi", "esi", "ecx", "none" ], "out" => [ "none" ] },
677 },
678
679 "CopyB_i" => {
680   "op_flags" => "F|H",
681   "state"    => "pinned",
682   "comment"  => "implements a memcopy: CopyB(dst, src, mem) == memcpy(dst, src, attr(size))",
683   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
684   "reg_req"  => { "in" => [ "edi", "esi", "none" ], "out" => [ "none" ] },
685 },
686
687 # Conversions
688
689 "Conv_I2I" => {
690   "reg_req"  => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3", "none" ] },
691   "cmp_attr"  => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
692   "comment"  => "construct Conv Int -> Int",
693   "outs"      => [ "res", "M" ],
694 },
695
696 "Conv_I2I8Bit" => {
697   "reg_req"  => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ], "out" => [ "in_r3", "none" ] },
698   "cmp_attr"  => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
699   "comment"  => "construct Conv Int -> Int",
700   "outs"      => [ "res", "M" ],
701 },
702
703 "Conv_I2FP" => {
704   "reg_req"  => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "xmm", "none" ] },
705   "cmp_attr"  => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
706   "comment"  => "construct Conv Int -> Floating Point",
707   "outs"      => [ "res", "M" ],
708 },
709
710 "Conv_FP2I" => {
711   "reg_req"  => { "in" => [ "gp", "gp", "xmm", "none" ], "out" => [ "gp", "none" ] },
712   "cmp_attr"  => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
713   "comment"  => "construct Conv Floating Point -> Int",
714   "outs"      => [ "res", "M" ],
715 },
716
717 "Conv_FP2FP" => {
718   "reg_req"  => { "in" => [ "gp", "gp", "xmm", "none" ], "out" => [ "xmm", "none" ] },
719   "cmp_attr"  => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
720   "comment"  => "construct Conv Floating Point -> Floating Point",
721   "outs"      => [ "res", "M" ],
722 },
723
724 #----------------------------------------------------------#
725 #        _      _               _    __ _             _    #
726 #       (_)    | |             | |  / _| |           | |   #
727 # __   ___ _ __| |_ _   _  __ _| | | |_| | ___   __ _| |_  #
728 # \ \ / / | '__| __| | | |/ _` | | |  _| |/ _ \ / _` | __| #
729 #  \ V /| | |  | |_| |_| | (_| | | | | | | (_) | (_| | |_  #
730 #   \_/ |_|_|   \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
731 #                 | |                                      #
732 #  _ __   ___   __| | ___  ___                             #
733 # | '_ \ / _ \ / _` |/ _ \/ __|                            #
734 # | | | | (_) | (_| |  __/\__ \                            #
735 # |_| |_|\___/ \__,_|\___||___/                            #
736 #----------------------------------------------------------#
737
738 "vfadd" => {
739   "irn_flags" => "R",
740   "comment"   => "virtual fp Add: Add(a, b) = Add(b, a) = a + b",
741   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
742   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
743   "outs"      => [ "res", "M" ],
744 },
745
746 "vfmul" => {
747   "irn_flags" => "R",
748   "comment"   => "virtual fp Mul: Mul(a, b) = Mul(b, a) = a + b",
749   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
750   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
751   "outs"      => [ "res", "M" ],
752 },
753
754 "vfsub" => {
755   "irn_flags" => "R",
756   "comment"   => "virtual fp Sub: Sub(a, b) = a - b",
757   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
758   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
759   "outs"      => [ "res", "M" ],
760 },
761
762 "vfdiv" => {
763   "comment"   => "virtual fp Div: Div(a, b) = a / b",
764   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
765   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
766   "outs"      => [ "res", "M" ],
767 },
768
769 "vfabs" => {
770   "irn_flags" => "R",
771   "comment"   => "virtual fp Abs: Abs(a) = |a|",
772   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
773 },
774
775 "vfchs" => {
776   "irn_flags" => "R",
777   "comment"   => "virtual fp Chs: Chs(a) = -a",
778   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
779 },
780
781 "vfsin" => {
782   "irn_flags" => "R",
783   "comment"   => "virtual fp Sin: Sin(a) = sin(a)",
784   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
785 },
786
787 "vfcos" => {
788   "irn_flags" => "R",
789   "comment"   => "virtual fp Cos: Cos(a) = cos(a)",
790   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
791 },
792
793 "vfsqrt" => {
794   "irn_flags" => "R",
795   "comment"   => "virtual fp Sqrt: Sqrt(a) = a ^ 0.5",
796   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
797 },
798
799 # virtual Load and Store
800
801 "vfld" => {
802   "op_flags"  => "L|F",
803   "irn_flags" => "R",
804   "state"     => "exc_pinned",
805   "comment"   => "virtual fp Load: Load(ptr, mem) = LD ptr -> reg",
806   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
807   "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "vfp", "none" ] },
808   "outs"      => [ "res", "M" ],
809 },
810
811 "vfst" => {
812   "op_flags"  => "L|F",
813   "state"     => "exc_pinned",
814   "comment"   => "virtual fp Store: Store(ptr, val, mem) = ST ptr,val",
815   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
816   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "none" ] },
817   "outs"      => [ "M" ],
818 },
819
820 # Conversions
821
822 "vfild" => {
823   "irn_flags" => "R",
824   "comment"   => "virtual fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
825   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
826   "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "vfp", "none" ] },
827   "outs"      => [ "res", "M" ],
828 },
829
830 "vfist" => {
831   "comment"   => "virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val",
832   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
833   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "none" ] },
834   "outs"      => [ "M" ],
835 },
836
837 # constants
838
839 "vfldz" => {
840   "irn_flags" => "R",
841   "comment"   => "virtual fp Load 0.0: Ld 0.0 -> reg",
842   "reg_req"   => { "out" => [ "vfp" ] },
843 },
844
845 "vfld1" => {
846   "irn_flags" => "R",
847   "comment"   => "virtual fp Load 1.0: Ld 1.0 -> reg",
848   "reg_req"   => { "out" => [ "vfp" ] },
849 },
850
851 "vfldpi" => {
852   "irn_flags" => "R",
853   "comment"   => "virtual fp Load pi: Ld pi -> reg",
854   "reg_req"   => { "out" => [ "vfp" ] },
855 },
856
857 "vfldln2" => {
858   "irn_flags" => "R",
859   "comment"   => "virtual fp Load ln 2: Ld ln 2 -> reg",
860   "reg_req"   => { "out" => [ "vfp" ] },
861 },
862
863 "vfldlg2" => {
864   "irn_flags" => "R",
865   "comment"   => "virtual fp Load lg 2: Ld lg 2 -> reg",
866   "reg_req"   => { "out" => [ "vfp" ] },
867 },
868
869 "vfldl2t" => {
870   "irn_flags" => "R",
871   "comment"   => "virtual fp Load ld 10: Ld ld 10 -> reg",
872   "reg_req"   => { "out" => [ "vfp" ] },
873 },
874
875 "vfldl2e" => {
876   "irn_flags" => "R",
877   "comment"   => "virtual fp Load ld e: Ld ld e -> reg",
878   "reg_req"   => { "out" => [ "vfp" ] },
879 },
880
881 "vfConst" => {
882   "op_flags"  => "c",
883   "irn_flags" => "R",
884   "init_attr" => "  set_ia32_ls_mode(res, mode);",
885   "comment"   => "represents a virtual floating point constant",
886   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
887   "reg_req"   => { "in" => [ "none" ], "out" => [ "vfp" ] },
888 },
889
890 # other
891
892 "vfCondJmp" => {
893   "op_flags"  => "L|X|Y",
894   "comment"   => "represents a virtual floating point compare",
895   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
896   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "none", "none", "eax" ] },
897   "outs"      => [ "false", "true", "temp_reg_eax" ],
898 },
899
900 #------------------------------------------------------------------------#
901 #       ___ _____    __ _             _                     _            #
902 # __  _( _ )___  |  / _| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
903 # \ \/ / _ \  / /  | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
904 #  >  < (_) |/ /   |  _| | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
905 # /_/\_\___//_/    |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
906 #------------------------------------------------------------------------#
907
908 "fadd" => {
909   "op_flags"  => "R",
910   "rd_constructor" => "NONE",
911   "comment"   => "x87 Add: Add(a, b) = Add(b, a) = a + b",
912   "reg_req"   => { },
913   "emit"      => '. fadd %ia32_emit_x87_binop /* x87 fadd(%A1, %A2) -> %D1 */',
914 },
915
916 "faddp" => {
917   "op_flags"  => "R",
918   "rd_constructor" => "NONE",
919   "comment"   => "x87 Add: Add(a, b) = Add(b, a) = a + b",
920   "reg_req"   => { },
921   "emit"      => '. faddp %ia32_emit_x87_binop /* x87 fadd(%A1, %A2) -> %D1 */',
922 },
923
924 "fmul" => {
925   "op_flags"  => "R",
926   "rd_constructor" => "NONE",
927   "comment"   => "x87 fp Mul: Mul(a, b) = Mul(b, a) = a + b",
928   "reg_req"   => { },
929   "emit"      => '. fmul %ia32_emit_x87_binop /* x87 fmul(%A1, %A2) -> %D1 */',
930 },
931
932 "fmulp" => {
933   "op_flags"  => "R",
934   "rd_constructor" => "NONE",
935   "comment"   => "x87 fp Mul: Mul(a, b) = Mul(b, a) = a + b",
936   "reg_req"   => { },
937   "emit"      => '. fmulp %ia32_emit_x87_binop /* x87 fmul(%A1, %A2) -> %D1 */',,
938 },
939
940 "fsub" => {
941   "op_flags"  => "R",
942   "rd_constructor" => "NONE",
943   "comment"   => "x87 fp Sub: Sub(a, b) = a - b",
944   "reg_req"   => { },
945   "emit"      => '. fsub %ia32_emit_x87_binop /* x87 fsub(%A1, %A2) -> %D1 */',
946 },
947
948 "fsubp" => {
949   "op_flags"  => "R",
950   "rd_constructor" => "NONE",
951   "comment"   => "x87 fp Sub: Sub(a, b) = a - b",
952   "reg_req"   => { },
953   "emit"      => '. fsubp %ia32_emit_x87_binop /* x87 fsub(%A1, %A2) -> %D1 */',
954 },
955
956 "fsubr" => {
957   "op_flags"  => "R",
958   "rd_constructor" => "NONE",
959   "irn_flags" => "R",
960   "comment"   => "x87 fp SubR: SubR(a, b) = b - a",
961   "reg_req"   => { },
962   "emit"      => '. fsubr %ia32_emit_x87_binop /* x87 fsubr(%A1, %A2) -> %D1 */',
963 },
964
965 "fsubrp" => {
966   "op_flags"  => "R",
967   "rd_constructor" => "NONE",
968   "irn_flags" => "R",
969   "comment"   => "x87 fp SubR: SubR(a, b) = b - a",
970   "reg_req"   => { },
971   "emit"      => '. fsubrp %ia32_emit_x87_binop /* x87 fsubr(%A1, %A2) -> %D1 */',
972 },
973
974 "fdiv" => {
975   "op_flags"  => "R",
976   "rd_constructor" => "NONE",
977   "comment"   => "x87 fp Div: Div(a, b) = a / b",
978   "reg_req"   => { },
979   "emit"      => '. fdiv %ia32_emit_x87_binop /* x87 fdiv(%A1, %A2) -> %D1 */',
980 },
981
982 "fdivp" => {
983   "op_flags"  => "R",
984   "rd_constructor" => "NONE",
985   "comment"   => "x87 fp Div: Div(a, b) = a / b",
986   "reg_req"   => { },
987   "emit"      => '. fdivp %ia32_emit_x87_binop /* x87 fdiv(%A1, %A2) -> %D1 */',
988 },
989
990 "fdivr" => {
991   "op_flags"  => "R",
992   "rd_constructor" => "NONE",
993   "comment"   => "x87 fp DivR: DivR(a, b) = b / a",
994   "reg_req"   => { },
995   "emit"      => '. fdivr %ia32_emit_x87_binop /* x87 fdivr(%A1, %A2) -> %D1 */',
996 },
997
998 "fdivrp" => {
999   "op_flags"  => "R",
1000   "rd_constructor" => "NONE",
1001   "comment"   => "x87 fp DivR: DivR(a, b) = b / a",
1002   "reg_req"   => { },
1003   "emit"      => '. fdivrp %ia32_emit_x87_binop /* x87 fdivr(%A1, %A2) -> %D1 */',
1004 },
1005
1006 "fabs" => {
1007   "op_flags"  => "R",
1008   "rd_constructor" => "NONE",
1009   "comment"   => "x87 fp Abs: Abs(a) = |a|",
1010   "reg_req"   => { },
1011   "emit"      => '. fabs /* x87 fabs(%S1) -> %D1 */',
1012 },
1013
1014 "fchs" => {
1015   "op_flags"  => "R",
1016   "rd_constructor" => "NONE",
1017   "comment"   => "x87 fp Chs: Chs(a) = -a",
1018   "reg_req"   => { },
1019   "emit"      => '. fchs /* x87 fchs(%S1) -> %D1 */',
1020 },
1021
1022 "fsin" => {
1023   "op_flags"  => "R",
1024   "rd_constructor" => "NONE",
1025   "comment"   => "x87 fp Sin: Sin(a) = sin(a)",
1026   "reg_req"   => { },
1027   "emit"      => '. fsin /* x87 sin(%S1) -> %D1 */',
1028 },
1029
1030 "fcos" => {
1031   "op_flags"  => "R",
1032   "rd_constructor" => "NONE",
1033   "comment"   => "x87 fp Cos: Cos(a) = cos(a)",
1034   "reg_req"   => { },
1035   "emit"      => '. fcos /* x87 cos(%S1) -> %D1 */',
1036 },
1037
1038 "fsqrt" => {
1039   "op_flags"  => "R",
1040   "rd_constructor" => "NONE",
1041   "comment"   => "x87 fp Sqrt: Sqrt(a) = a ^ 0.5",
1042   "reg_req"   => { },
1043   "emit"      => '. fsqrt $ /* x87 sqrt(%S1) -> %D1 */',
1044 },
1045
1046 # x87 Load and Store
1047
1048 "fld" => {
1049   "rd_constructor" => "NONE",
1050   "op_flags"  => "R|L|F",
1051   "state"     => "exc_pinned",
1052   "comment"   => "x87 fp Load: Load(ptr, mem) = LD ptr -> reg",
1053   "reg_req"   => { },
1054   "emit"      => '. fld %ia32_emit_am /* Load((%A1)) -> %D1 */',
1055 },
1056
1057 "fst" => {
1058   "rd_constructor" => "NONE",
1059   "op_flags"  => "R|L|F",
1060   "state"     => "exc_pinned",
1061   "comment"   => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val",
1062   "reg_req"   => { },
1063   "emit"      => '. fst %ia32_emit_am /* Store(%A3) -> (%A1) */',
1064 },
1065
1066 "fstp" => {
1067   "rd_constructor" => "NONE",
1068   "op_flags"  => "R|L|F",
1069   "state"     => "exc_pinned",
1070   "comment"   => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val",
1071   "reg_req"   => { },
1072   "emit"      => '. fstp %ia32_emit_am /* Store(%A3) -> (%A1) and pop */',
1073 },
1074
1075 # Conversions
1076
1077 "fild" => {
1078   "op_flags"  => "R",
1079   "irn_flags" => "R",
1080   "rd_constructor" => "NONE",
1081   "comment"   => "x87 fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
1082   "reg_req"   => { },
1083   "emit"      => '. fild %ia32_emit_am /* integer Load((%A1)) -> %D1 */',
1084 },
1085
1086 "fist" => {
1087   "op_flags"  => "R",
1088   "rd_constructor" => "NONE",
1089   "comment"   => "x87 fp integer Store: Store(ptr, val, mem) = iST ptr,val",
1090   "reg_req"   => { },
1091   "emit"      => '. fist %ia32_emit_am /* integer Store(%A3) -> (%A1) */',
1092 },
1093
1094 "fistp" => {
1095   "op_flags"  => "R",
1096   "rd_constructor" => "NONE",
1097   "comment"   => "x87 fp integer Store: Store(ptr, val, mem) = iST ptr,val",
1098   "reg_req"   => { },
1099   "emit"      => '. fistp %ia32_emit_am /* integer Store(%A3) -> (%A1) and pop */',
1100 },
1101
1102 # constants
1103
1104 "fldz" => {
1105   "op_flags"  => "R",
1106   "rd_constructor" => "NONE",
1107   "comment"   => "x87 fp Load 0.0: Ld 0.0 -> reg",
1108   "reg_req"   => { },
1109   "emit"      => '. fldz /* x87 0.0 -> %D1 */',
1110 },
1111
1112 "fld1" => {
1113   "op_flags"  => "R",
1114   "rd_constructor" => "NONE",
1115   "comment"   => "x87 fp Load 1.0: Ld 1.0 -> reg",
1116   "reg_req"   => { },
1117   "emit"      => '. fld1 /* x87 1.0 -> %D1 */',
1118 },
1119
1120 "fldpi" => {
1121   "op_flags"  => "R",
1122   "rd_constructor" => "NONE",
1123   "comment"   => "x87 fp Load pi: Ld pi -> reg",
1124   "reg_req"   => { },
1125   "emit"      => '. fldpi /* x87 pi -> %D1 */',
1126 },
1127
1128 "fldln2" => {
1129   "op_flags"  => "R",
1130   "rd_constructor" => "NONE",
1131   "comment"   => "x87 fp Load ln 2: Ld ln 2 -> reg",
1132   "reg_req"   => { },
1133   "emit"      => '. fldln2 /* x87 ln(2) -> %D1 */',
1134 },
1135
1136 "fldlg2" => {
1137   "op_flags"  => "R",
1138   "rd_constructor" => "NONE",
1139   "comment"   => "x87 fp Load lg 2: Ld lg 2 -> reg",
1140   "reg_req"   => { },
1141   "emit"      => '. fldlg2 /* x87 log(2) -> %D1 */',
1142 },
1143
1144 "fldl2t" => {
1145   "op_flags"  => "R",
1146   "rd_constructor" => "NONE",
1147   "comment"   => "x87 fp Load ld 10: Ld ld 10 -> reg",
1148   "reg_req"   => { },
1149   "emit"      => '. fldll2t /* x87 ld(10) -> %D1 */',
1150 },
1151
1152 "fldl2e" => {
1153   "op_flags"  => "R",
1154   "rd_constructor" => "NONE",
1155   "comment"   => "x87 fp Load ld e: Ld ld e -> reg",
1156   "reg_req"   => { },
1157   "emit"      => '. fldl2e /* x87 ld(e) -> %D1 */',
1158 },
1159
1160 "fldConst" => {
1161   "op_flags"  => "R|c",
1162   "irn_flags" => "R",
1163   "rd_constructor" => "NONE",
1164   "comment"   => "represents a x87 constant",
1165   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
1166   "reg_req"   => { "out" => [ "st" ] },
1167   "emit"      => '. fld %ia32_emit_adr /* Load fConst into register -> %D1 */',
1168 },
1169
1170 # fxch, fpush, fpop
1171 # Note that it is NEVER allowed to do CSE on these nodes
1172
1173 "fxch" => {
1174   "op_flags"  => "R|K",
1175   "comment"   => "x87 stack exchange",
1176   "reg_req"   => { "in" => [ "st"], "out" => [ "st" ] },
1177   "cmp_attr"  => "  return 1;\n",
1178   "emit"      => '. fxch %X1 /* x87 swap %X1, %X3 */',
1179 },
1180
1181 "fpush" => {
1182   "op_flags"  => "R",
1183   "comment"   => "x87 stack push",
1184   "reg_req"   => { "in" => [ "st"], "out" => [ "st" ] },
1185   "cmp_attr"  => "  return 1;\n",
1186   "emit"      => '. fld %X1 /* x87 push %X1 */',
1187 },
1188
1189 "fpop" => {
1190   "op_flags"  => "R|K",
1191   "comment"   => "x87 stack pop",
1192   "reg_req"   => { "in" => [ "st"], "out" => [ "st" ] },
1193   "cmp_attr"  => "  return 1;\n",
1194   "emit"      => '. fstp %X1 /* x87 pop %X1 */',
1195 },
1196
1197 # compare
1198
1199 "fcomJmp" => {
1200   "op_flags"  => "L|X|Y",
1201   "comment"   => "floating point compare",
1202   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
1203   "reg_req"   => { },
1204 },
1205
1206 "fcompJmp" => {
1207   "op_flags"  => "L|X|Y",
1208   "comment"   => "floating point compare and pop",
1209   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
1210   "reg_req"   => { },
1211 },
1212
1213 "fcomppJmp" => {
1214   "op_flags"  => "L|X|Y",
1215   "comment"   => "floating point compare and pop twice",
1216   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
1217   "reg_req"   => { },
1218 },
1219
1220 "fcomrJmp" => {
1221   "op_flags"  => "L|X|Y",
1222   "comment"   => "floating point compare reverse",
1223   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
1224   "reg_req"   => { },
1225 },
1226
1227 "fcomrpJmp" => {
1228   "op_flags"  => "L|X|Y",
1229   "comment"   => "floating point compare reverse and pop",
1230   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
1231   "reg_req"   => { },
1232 },
1233
1234 "fcomrppJmp" => {
1235   "op_flags"  => "L|X|Y",
1236   "comment"   => "floating point compare reverse and pop twice",
1237   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
1238   "reg_req"   => { },
1239 },
1240
1241 ); # end of %nodes