fixed indents
[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
7 $arch = "ia32";
8
9 # The node description is done as a perl hash initializer with the
10 # following structure:
11 #
12 # %nodes = (
13 #
14 # <op-name> => {
15 #   "op_flags" => "N|L|C|X|I|F|Y|H|c",
16 #   "arity"    => "0|1|2|3|variable|dynamic|all",
17 #   "state"    => "floats|pinned",
18 #   "args"     => [
19 #                   { "type" => "type 1", "name" => "name 1" },
20 #                   { "type" => "type 2", "name" => "name 2" },
21 #                   ...
22 #                 ],
23 #   "comment"  => "any comment for constructor",
24 #   "rd_constructor" => "c source code which constructs an ir_node"
25 # },
26 #
27 # ... # (all nodes you need to describe)
28 #
29 # ); # close the %nodes initializer
30
31 # the op_flags correspond to the firm irop_flags:
32 #   N   irop_flag_none
33 #   L   irop_flag_labeled
34 #   C   irop_flag_commutative
35 #   X   irop_flag_cfopcode
36 #   I   irop_flag_ip_cfopcode
37 #   F   irop_flag_fragile
38 #   Y   irop_flag_forking
39 #   H   irop_flag_highlevel
40 #   c   irop_flag_constlike
41 #
42 # op_flags: flags for the operation, OPTIONAL (default is "N")
43 #
44 # state: state of the operation, OPTIONAL (default is "pinned")
45 #
46 # arity: arity of the operation, MUST NOT BE OMITTED
47 #
48 # args:  the OPTIONAL arguments of the node constructor (debug, irg and block
49 #        are always the first 3 arguments and are always autmatically
50 #        created)
51 #        If this key is missing the following arguments will be created:
52 #        for i = 1 .. arity: ir_node *op_i
53 #        ir_mode *mode
54 #
55 # comment: OPTIONAL comment for the node constructor
56 #
57 # rd_constructor: for every operation there will be a
58 #      new_rd_<arch>_<op-name> function with the arguments from above
59 #      which creates the ir_node corresponding to the defined operation
60 #      you can either put the complete source code of this function here
61 #
62 #      This key is OPTIONAL. If omitted, the following constructor will
63 #      be created:
64 #      if (!op_<arch>_<op-name>) assert(0);
65 #      for i = 1 to arity
66 #         set in[i] = op_i
67 #      done
68 #      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
69 #      return res
70 #
71 # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
72
73 %reg_classes = (
74   "general_purpose" => [
75                          { "name" => "eax", "type" => 0 },
76                          { "name" => "ebx", "type" => 0 },
77                          { "name" => "ecx", "type" => 0 },
78                          { "name" => "edx", "type" => 0 },
79                          { "name" => "edi", "type" => 0 },
80                          { "name" => "esi", "type" => 0 },
81                          { "name" => "ebp", "type" => 0 }
82                        ],
83   "floating_point"  => [
84                          { "name" => "xmm0", "type" => 0 },
85                          { "name" => "xmm1", "type" => 0 },
86                          { "name" => "xmm2", "type" => 0 },
87                          { "name" => "xmm3", "type" => 0 },
88                          { "name" => "xmm4", "type" => 0 },
89                          { "name" => "xmm5", "type" => 0 },
90                          { "name" => "xmm6", "type" => 0 },
91                          { "name" => "xmm7", "type" => 0 },
92                        ],
93   "flag_register"   => [
94                          { "name" => "eflags", "type" => 0 }
95                        ]
96 ); # %reg_classes
97
98 #--------------------------------------------------#
99 #                        _                         #
100 #                       (_)                        #
101 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
102 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
103 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
104 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
105 #                                      | |         #
106 #                                      |_|         #
107 #--------------------------------------------------#
108
109 %nodes = (
110
111 #-----------------------------------------------------------------#
112 #  _       _                                         _            #
113 # (_)     | |                                       | |           #
114 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
115 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
116 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
117 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
118 #                   __/ |                                         #
119 #                  |___/                                          #
120 #-----------------------------------------------------------------#
121
122 # commutative operations
123
124 "Add" => {
125   "op_flags"    => "C",
126   "arity"       => 2,
127   "remat"       => 1,
128   "comment"     => "construct Add: Add(a, b) = Add(b, a) = a + b",
129   "check_inout" => 1,
130   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
131   "emit"        => '. addl %s2, %d1\t\t\t/* Add(%s1, %s2) -> %d1, (%a1, %a2) */'
132 },
133
134 "Add_i" => {
135   "arity"       => 1,
136   "remat"       => 1,
137   "comment"     => "construct Add: Add(a, const) = Add(const, a) = a + const",
138   "check_inout" => 1,
139   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
140   "emit"        => '. addl %c, %d1\t\t\t/* Add(%c, %s1) -> %d1, (%a1, const) */'
141 },
142
143 "Mul" => {
144   "op_flags"    => "C",
145   "arity"       => 2,
146   "comment"     => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
147   "reg_req"     => { "in" => [ "eax", "general_purpose" ], "out" => [ "eax" ] },
148   "emit"        =>
149 '  if (mode_is_signed(get_irn_mode(n))) {
150 4. imull %s2\t\t\t/* signed Mul(%s1, %s2) -> %d1, (%a1, %a2) */
151   }
152   else {
153 4. mull %s2\t\t\t/* unsigned Mul(%s1, %s2) -> %d1, (%a1, %a2) */
154   }
155 '
156 },
157
158 "Mul_i" => {
159   "state"       => "pinned",
160   "arity"       => 1,
161   "comment"     => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
162   "reg_req"     => { "in" => [ "eax" ], "out" => [ "eax" ] },
163   "emit"        =>
164 '  if (mode_is_signed(get_irn_mode(n))) {
165 4. imull %c\t\t\t/* signed Mul(%c, %s1) -> %d1, (%a1, const) */
166   }
167   else {
168 4. mull %c\t\t\t/* unsigned Mul(%c, %s1) -> %d1, (%a1, const) */
169   }
170 '
171 },
172
173 "Mulh" => {
174   "op_flags"    => "C",
175   "arity"       => 2,
176   "comment"     => "construct Mulh: Mulh(a, b) = Mulh(b, a) = get_32_highest_bits(a * b)",
177   "reg_req"     => { "in" => [ "eax", "general_purpose" ], "out" => [ "edx" ] },
178   "emit"        =>
179 '  if (mode_is_signed(get_irn_mode(n))) {
180 4. imull %s2\t\t\t/* signed Mulh(%s1, %s2) -> %d1, (%a1, %a2) */
181   }
182   else {
183 4. mull %s2\t\t\t/* unsigned Mulh(%s1, %s2) -> %d1, (%a1, %a2) */
184   }
185 '
186 },
187
188 "Mulh_i" => {
189   "state"       => "pinned",
190   "arity"       => 1,
191   "comment"     => "construct Mulh: Mulh(a, const) = Mulh(const, a) = get_32_highest_bits(a * const)",
192   "reg_req"     => { "in" => [ "eax" ], "out" => [ "edx" ] },
193   "emit"        =>
194 '  if (mode_is_signed(get_irn_mode(n))) {
195 4. imull %c\t\t\t/* signed Mulh(%c, %s1) -> %d1, (%a1, const) */
196   }
197   else {
198 4. mull %c\t\t\t/* unsigned Mulh(%c, %s1) -> %d1, (%a1, const) */
199   }
200 '
201 },
202
203 "And" => {
204   "op_flags"    => "C",
205   "arity"       => 2,
206   "remat"       => 1,
207   "comment"     => "construct And: And(a, b) = And(b, a) = a AND b",
208   "check_inout" => 1,
209   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
210   "emit"        => '. andl %s2, %d1\t\t\t/* And(%s1, %s2) -> %d1, (%a1, %a2) */'
211 },
212
213 "And_i" => {
214   "arity"       => 1,
215   "remat"       => 1,
216   "comment"     => "construct And: And(a, const) = And(const, a) = a AND const",
217   "check_inout" => 1,
218   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
219   "emit"        => '. andl %c, %d1\t\t\t/* And(%c, %s1) -> %d1, (%a1, const) */'
220 },
221
222 "Or" => {
223   "op_flags"    => "C",
224   "arity"       => 2,
225   "remat"       => 1,
226   "comment"     => "construct Or: Or(a, b) = Or(b, a) = a OR b",
227   "check_inout" => 1,
228   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
229   "emit"        => '. orl %s2, %d1\t\t\t/* Or(%s1, %s2) -> %d1, (%a1, %a2) */'
230 },
231
232 "Or_i" => {
233   "arity"       => 1,
234   "remat"       => 1,
235   "comment"     => "construct Or: Or(a, const) = Or(const, a) = a OR const",
236   "check_inout" => 1,
237   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
238   "emit"        => '. orl %c, %d1\t\t\t/* Or(%c, %s1) -> %d1, (%a1, const) */'
239 },
240
241 "Eor" => {
242   "op_flags"    => "C",
243   "arity"       => 2,
244   "remat"       => 1,
245   "comment"     => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
246   "check_inout" => 1,
247   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
248   "emit"        => '. xorl %s2, %d1\t\t\t/* Xor(%s1, %s2) -> %d1, (%a1, %a2) */'
249 },
250
251 "Eor_i" => {
252   "arity"       => 1,
253   "remat"       => 1,
254   "comment"     => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const",
255   "check_inout" => 1,
256   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
257   "emit"        => '. xorl %c, %d1\t\t\t/* Xor(%c, %s1) -> %d1, (%a1, const) */'
258 },
259
260 "Max" => {
261   "op_flags"    => "C",
262   "arity"       => 2,
263   "remat"       => 1,
264   "comment"     => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
265   "check_inout" => 1,
266   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
267   "emit"        =>
268 '2. cmpl %s2, %s1\t\t\t/* prepare Max (%s1 should be %d1), (%a1, %a2) */
269   if (mode_is_signed(get_irn_mode(n))) {
270 4.  cmovl %s2, %d1\t\t\t/* %s1 is less %s2 */
271   }
272   else {
273 4.  cmovb %s2, %d1\t\t\t/* %s1 is below %s2 */
274   }
275 '
276 },
277
278 "Min" => {
279   "op_flags"    => "C",
280   "arity"       => 2,
281   "remat"       => 1,
282   "comment"     => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b",
283   "check_inout" => 1,
284   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
285   "emit"        =>
286 '2. cmpl %s2, %s1\t\t\t/* prepare Min (%s1 should be %d1), (%a1, %a2) */
287   if (mode_is_signed(get_irn_mode(n))) {
288 2.  cmovg %s2, %d1\t\t\t/* %s1 is greater %s2 */
289   }
290   else {
291 2.  cmova %s2, %d1\t\t\t/* %s1 is above %s2 */
292   }
293 '
294 },
295
296 # not commutative operations
297
298 "Sub" => {
299   "arity"       => 2,
300   "remat"       => 1,
301   "comment"     => "construct Sub: Sub(a, b) = a - b",
302   "check_inout" => 1,
303   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
304   "emit"        => '. subl %s2, %d1\t\t\t/* Sub(%s1, %s2) -> %d1, (%a1, %a2) */'
305 },
306
307 "Sub_i" => {
308   "arity"       => 1,
309   "remat"       => 1,
310   "comment"     => "construct Sub: Sub(a, const) = a - const",
311   "check_inout" => 1,
312   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
313   "emit"        => '. subl %c, %d1\t\t\t/* Sub(%s1, %c) -> %d1, (%a1, const) */'
314 },
315
316 "DivMod" => {
317   "op_flags"    => "F|L",
318   "state"       => "exc_pinned",
319   "arity"       => 4,
320   "comment"     => "construct DivMod: DivMod(a,b) = (a / b, a % b)",
321   "emit"        =>
322 '  if (mode_is_signed(get_irn_mode(n))) {
323 4.  idivl %s2\t\t\t/* signed Mod(%s1, %s2) -> %d1, (%a2, %a3, %4) */
324   }
325   else {
326 4.  divl %s2\t\t\t/* unsigned Mod(%s1, %s2) -> %d1, (%a2, %a3, %a4) */
327   }
328 ',
329   "args"     => [
330                   { "type" => "ir_node *",        "name" => "dividend" },
331                   { "type" => "ir_node *",        "name" => "divisor" },
332                   { "type" => "ir_node *",        "name" => "mem" },
333                   { "type" => "divmod_flavour_t", "name" => "dm_flav" },   # flavours (flavour_Div, flavour_Mod, flavour_DivMod)
334                   { "type" => "ir_mode *",        "name" => "mode" },
335                 ],
336   "rd_constructor" =>
337 "  ir_node *res;
338   ir_node *in[4];
339   asmop_attr *attr;
340
341   if (!op_ia32_DivMod) assert(0);
342
343   in[1] = divisor;
344   in[3] = mem;
345
346   if (mode_is_signed(mode)) {
347     ir_node *cltd;
348     /* in signed mode , we need to sign extend the dividend */
349     cltd  = new_rd_ia32_Cltd(db, current_ir_graph, block, divisor, mode_T);
350     in[0] = new_rd_Proj(db, current_ir_graph, block, cltd, mode_Is, pn_EAX);
351     in[2] = new_rd_Proj(db, current_ir_graph, block, cltd, mode_Is, pn_EDX);
352   }
353   else {
354     in[0] = dividend;
355     in[2] = new_rd_ia32_Const(db, current_ir_graph, block, mode_Iu);
356     set_ia32_Const_type(in[2], asmop_Const);
357     set_ia32_Immop_tarval(in[2], get_tarval_null(mode_Iu));
358   }
359
360   res = new_ir_node(db, irg, block, op_ia32_DivMod, mode, 4, in);
361
362   set_ia32_DivMod_flavour(res, dm_flav);
363   set_ia32_n_res(res, 2);
364
365   attr = get_ia32_attr(res);
366
367   attr->in_req    = calloc(4, sizeof(arch_register_req_t *));
368   attr->in_req[0] = &ia32_default_req_ia32_general_purpose_eax;
369   attr->in_req[1] = &ia32_default_req_ia32_general_purpose;
370   attr->in_req[2] = &ia32_default_req_ia32_general_purpose_edx;
371   attr->in_req[3] = &ia32_default_req_none;
372
373   attr->out_req    = calloc(2, sizeof(arch_register_req_t *));
374   attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
375   attr->out_req[1] = &ia32_default_req_ia32_general_purpose_edx;
376
377   attr->slots = calloc(2, sizeof(arch_register_t *));
378
379   return res;
380 "
381 },
382
383 "Shl" => {
384   "arity"       => 2,
385   "remat"       => 1,
386   "comment"     => "construct Shl: Shl(a, b) = a << b",
387   "check_inout" => 1,
388   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
389   "emit"        => '. shll %s2, %d1\t\t\t/* Shl(%s1, %s2) -> %d1, (%a1, %a2) */'
390 },
391
392 "Shl_i" => {
393   "arity"       => 1,
394   "remat"       => 1,
395   "comment"     => "construct Shl: Shl(a, const) = a << const",
396   "check_inout" => 1,
397   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
398   "emit"        => '. shll %c, %d1\t\t\t/* Shl(%s1, %c) -> %d1, (%a1, const) */'
399 },
400
401 "Shr" => {
402   "arity"       => 2,
403   "remat"       => 1,
404   "comment"     => "construct Shr: Shr(a, b) = a >> b",
405   "check_inout" => 1,
406   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
407   "emit"        => '. shrl %s2, %d1\t\t\t/* Shr(%s1, %s2) -> %d1, (%a1, %a2) */'
408 },
409
410 "Shr_i" => {
411   "arity"       => 1,
412   "remat"       => 1,
413   "comment"     => "construct Shr: Shr(a, const) = a >> const",
414   "check_inout" => 1,
415   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
416   "emit"        => '. shrl %c, %d1\t\t\t/* Shr(%s1, %c) -> %d1, (%a1, const) */'
417 },
418
419 "Shrs" => {
420   "arity"       => 2,
421   "remat"       => 1,
422   "comment"     => "construct Shrs: Shrs(a, b) = a >> b",
423   "check_inout" => 1,
424   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
425   "emit"        => '. sarl %s2, %d1\t\t\t/* Shrs(%s1, %s2) -> %d1, (%a1, %a2) */'
426 },
427
428 "Shrs_i" => {
429   "arity"       => 1,
430   "remat"       => 1,
431   "comment"     => "construct Shrs: Shrs(a, const) = a >> const",
432   "check_inout" => 1,
433   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
434   "emit"        => '. sarl %c, %d1\t\t\t/* Shrs(%s1, %c) -> %d1, (%a1, const) */'
435 },
436
437 "RotR" => {
438   "arity"       => 2,
439   "remat"       => 1,
440   "comment"     => "construct RotR: RotR(a, b) = a ROTR b",
441   "check_inout" => 1,
442   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
443   "emit"        => '. rorl %s2, %d1\t\t\t/* RotR(%s1, %s2) -> %d1, (%a1, %a2) */'
444 },
445
446 "RotL" => {
447   "arity"       => 2,
448   "remat"       => 1,
449   "comment"     => "construct RotL: RotL(a, b) = a ROTL b",
450   "check_inout" => 1,
451   "reg_req"     => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_s1" ] },
452   "emit"        => '. roll %s2, %d1\t\t\t/* RotL(%s1, %s2) -> %d1, (%a1, %a2) */'
453 },
454
455 "RotL_i" => {
456   "arity"       => 1,
457   "remat"       => 1,
458   "comment"     => "construct RotL: RotL(a, const) = a ROTL const",
459   "check_inout" => 1,
460   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
461   "emit"        => '. roll %c, %d1\t\t\t/* RotL(%s1, %c) -> %d1, (%a1, const) */'
462 },
463
464 "Minus" => {
465   "arity"       => 1,
466   "remat"       => 1,
467   "comment"     => "construct Minus: Minus(a) = -a",
468   "check_inout" => 1,
469   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
470   "emit"        => '. negl %d1\t\t\t/* Neg(%s1) -> %d1, (%a1) */'
471 },
472
473 "Inc" => {
474   "arity"       => 1,
475   "remat"       => 1,
476   "comment"     => "construct Increment: Inc(a) = a++",
477   "check_inout" => 1,
478   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
479   "emit"        => '. incl %d1\t\t\t/* Inc(%s1) -> %d1, (%a1) */'
480 },
481
482 "Dec" => {
483   "arity"       => 1,
484   "remat"       => 1,
485   "comment"     => "construct Decrement: Dec(a) = a--",
486   "check_inout" => 1,
487   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
488   "emit"        => '. decl %d1\t\t\t/* Dec(%s1) -> %d1, (%a1) */'
489 },
490
491 "Not" => {
492   "arity"       => 1,
493   "remat"       => 1,
494   "comment"     => "construct Not: Not(a) = !a",
495   "check_inout" => 1,
496   "reg_req"     => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
497   "emit"        => '. notl %d1\t\t\t/* Not(%s1) -> %d1, (%a1) */'
498 },
499
500 # other operations
501
502 "Conv" => {
503   "arity"    => 1,
504   "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
505   "comment"  => "construct Conv: Conv(a) = (conv)a"
506 },
507
508 "CondJmp" => {
509   "op_flags" => "C|L|X|Y",
510   "arity"    => 2,
511   "comment"  => "construct conditional jump: CMP A, B && JMPxx LABEL",
512   "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "flag_register" ] },
513 },
514
515 "CondJmp_i" => {
516   "op_flags" => "L|X|Y",
517   "arity"    => 1,
518   "comment"  => "construct conditional jump: CMP A, const && JMPxx LABEL",
519   "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "none", "flag_register" ] },
520 },
521
522 "SwitchJmp" => {
523   "op_flags" => "L|X|Y",
524   "arity"    => 1,
525   "comment"  => "construct switch",
526   "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "flag_register" ] },
527 },
528
529 "Const" => {
530   "op_flags" => "c",
531   "arity"    => "0",
532   "remat"    => 1,
533   "comment"  => "represents an integer constant",
534   "reg_req"  => { "out" => [ "general_purpose" ] },
535   "emit"     => '. movl %c, %d1\t\t\t/* Mov Const into register */',
536   "cmp_attr" =>
537 '
538   if (attr_a->tp == attr_b->tp) {
539     if (attr_a->tp == asmop_SymConst) {
540       if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
541         return 1;
542       else
543         return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
544     }
545     else {
546       if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
547         return 1;
548
549       if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
550         return 0;
551       else
552         return 1;
553     }
554   }
555   else
556     return 1;
557 '
558 },
559
560 "Cltd" => {
561   "arity"       => 1,
562   "remat"       => 1,
563   "comment"     => "construct Cltd: sign extend EAX -> EDX:EAX",
564   "reg_req"     => { "in" => [ "eax" ], "out" => [ "eax", "edx" ] },
565   "emit"        => '. cltd\t\t\t/* sign extend EAX -> EDX:EAX, (%a1) */'
566 },
567
568 # Load / Store
569
570 "Load" => {
571   "op_flags" => "L|F",
572   "state"    => "exc_pinned",
573   "arity"    => 2,
574   "remat"    => 1,
575   "comment"  => "construct Load: Load(ptr, mem) = LD ptr -> reg",
576   "reg_req"  => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] },
577   "emit"     => '. movl (%s1), %d1\t\t\t/* Load((%s1)) -> %d1, (%a1) */'
578 },
579
580 "Store" => {
581   "op_flags" => "L|F",
582   "state"    => "exc_pinned",
583   "arity"    => 3,
584   "remat"    => 1,
585   "comment"  => "construct Store: Store(ptr, val, mem) = ST ptr,val",
586   "reg_req"  => { "in" => [ "general_purpose", "general_purpose", "none" ] },
587   "emit"     => '. movl %s2, (%s1)\t\t\t/* Store(%s1) -> (%s2), (%a1, %a2) */'
588 },
589
590 "Lea" => {
591   "arity"    => 2,
592   "comment"  => "construct Lea: Lea(a,b) = lea offs(a,b,const) | res = a + b * const + offs with const = 0,1,2,4,8",
593   "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] },
594   "emit"     => '. leal %o(%s1, %s2, %c), %d1\t\t/* %d1 = %s1 + %s2 << %c + %o, (%a1, %a2) */'
595 },
596
597 "Lea_i" => {
598   "arity"    => 1,
599   "comment"  => "construct Lea: Lea(a) = lea offs(a) | res = a + offs",
600   "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] },
601   "emit"     => '. leal %c(%s1), %d1\t\t\t/* %d1 = %s1 + %c, (%a1)*/'
602 },
603
604 "RegParam" => {
605   "arity"    => 1,
606   "comment"  => "constructs a Register Parameter to cover parameters passed in register",
607   "reg_req"  => { "in" => [ "none" ], "out" => [ "none" ] },
608   "cmp_attr" =>
609 '
610   return (attr_a->pn_code != attr_b->pn_code);
611 '
612 },
613
614 "StackParam" => {
615   "arity"    => 1,
616   "comment"  => "constructs a Stack Parameter to retrieve a parameter from Stack",
617   "reg_req"  => { "in" => [ "none" ], "out" => [ "general_purpose" ] },
618   "cmp_attr" =>
619 '
620   return (attr_a->pn_code != attr_b->pn_code);
621 '
622 },
623
624 "StackArg" => {
625   "arity"    => 2,
626   "comment"  => "constructs a Stack Argument to pass an argument on Stack",
627   "reg_req"  => { "in" => [ "none", "general_purpose" ], "out" => [ "none" ] },
628   "cmp_attr" =>
629 '
630   return (attr_a->pn_code != attr_b->pn_code);
631 '
632 },
633
634 #--------------------------------------------------------#
635 #    __ _             _                     _            #
636 #   / _| |           | |                   | |           #
637 #  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
638 #  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
639 #  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
640 #  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
641 #--------------------------------------------------------#
642
643 # commutative operations
644
645 "fAdd" => {
646   "op_flags"    => "C",
647   "arity"       => 2,
648   "remat"       => 1,
649   "check_inout" => 1,
650   "comment"     => "construct SSE Add: Add(a, b) = Add(b, a) = a + b",
651   "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_s1" ] },
652   "emit"        => '. add%m %s2, %d1\t\t\t/* SSE Add(%s1, %s2) -> %d1 */'
653 },
654
655 "fMul" => {
656   "op_flags"    => "C",
657   "arity"       => 2,
658   "check_inout" => 1,
659   "comment"     => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b",
660   "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_s1" ] },
661   "emit"        =>'. muls%m %s2, %d1\t\t\t/* SSE Mul(%s1, %s2) -> %d1 */'
662 },
663
664 "fMax" => {
665   "op_flags"    => "C",
666   "arity"       => 2,
667   "remat"       => 1,
668   "check_inout" => 1,
669   "comment"     => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
670   "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_s1" ] },
671   "emit"        =>'. maxs%m %s2, %d1\t\t\t/* SSE Max(%s1, %s2) -> %d1 */'
672 },
673
674 "fMin" => {
675   "op_flags"    => "C",
676   "arity"       => 2,
677   "remat"       => 1,
678   "check_inout" => 1,
679   "comment"     => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
680   "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_s1" ] },
681   "emit"        =>'. mins%m %s2, %d1\t\t\t/* SSE Min(%s1, %s2) -> %d1 */'
682 },
683
684 # not commutative operations
685
686 "fSub" => {
687   "arity"       => 2,
688   "remat"       => 1,
689   "check_inout" => 1,
690   "comment"     => "construct SSE Sub: Sub(a, b) = a - b",
691   "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_s1" ] },
692   "emit"        => '. subs%m %s2, %d1\t\t\t/* SSE Sub(%s1, %s2) -> %d1 */'
693 },
694
695 "fDiv" => {
696   "arity"       => 2,
697   "remat"       => 1,
698   "check_inout" => 1,
699   "comment"     => "construct SSE Div: Div(a, b) = a / b",
700   "reg_req"     => { "in" => [ "floating_point", "floating_point" ], "out" => [ "in_s1" ] },
701   "emit"        => '. divs%m %s2, %d1\t\t\t/* SSE Div(%s1, %s2) -> %d1 */'
702 },
703
704 "fMinus" => {
705   "arity"       => 1,
706   "remat"       => 1,
707   "check_inout" => 1,
708   "comment"     => "construct SSE Minus: Minus(a) = -a",
709   "reg_req"     => { "in" => [ "floating_point" ], "out" => [ "in_s1" ] },
710   "emit"        => '. xorp%m c %d1\t\t\t/* SSE Minus(%s1) -> %d1 */'
711 },
712
713 # other operations
714
715 "fConv" => {
716   "arity"    => 1,
717   "reg_req"  => { "in" => [ "general_purpose" ], "out" => [ "in_s1" ] },
718   "comment"  => "construct Conv: Conv(a) = (conv)a"
719 },
720
721 "fCondJmp" => {
722   "op_flags" => "C|L|X|Y",
723   "arity"    => 2,
724   "comment"  => "construct conditional jump: CMP A, B && JMPxx LABEL",
725   "reg_req"  => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "flag_register" ] },
726 },
727
728 "fConst" => {
729   "op_flags" => "c",
730   "arity"    => "0",
731   "remat"    => 1,
732   "comment"  => "represents a SSE constant",
733   "reg_req"  => { "out" => [ "floating_point" ] },
734   "emit"     => '. mov%m %c, %d1\t\t\t/* Mov fConst into register */',
735   "cmp_attr" =>
736 '
737   if (attr_a->tp == attr_b->tp) {
738     if (attr_a->tp == asmop_SymConst) {
739       if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
740         return 1;
741       else
742         return strcmp(get_sc_name(attr_a->old_ir), get_sc_name(attr_b->old_ir));
743     }
744     else {
745       if (attr_a->old_ir == NULL || attr_b->old_ir == NULL)
746         return 1;
747
748       if (tarval_cmp(attr_a->tv, attr_b->tv) == pn_Cmp_Eq)
749         return 0;
750       else
751         return 1;
752     }
753   }
754   else
755     return 1;
756 '
757 },
758
759 # Load / Store
760
761 "fLoad" => {
762   "op_flags" => "L|F",
763   "state"    => "exc_pinned",
764   "arity"    => 2,
765   "remat"    => 1,
766   "comment"  => "construct SSE Load: Load(ptr, mem) = LD ptr",
767   "reg_req"  => { "in" => [ "general_purpose", "none" ], "out" => [ "floating_point" ] },
768   "emit"     => '. movl (%s1), %d1\t\t\t/* Load((%s1)) -> %d1 */'
769 },
770
771 "fStore" => {
772   "op_flags" => "L|F",
773   "state"    => "exc_pinned",
774   "arity"    => 3,
775   "remat"    => 1,
776   "comment"  => "construct Store: Store(ptr, val, mem) = ST ptr,val",
777   "reg_req"  => { "in" => [ "general_purpose", "floating_point", "none" ] },
778   "emit"     => '. movl %s2, (%s1)\t\t\t/* Store(%s2) -> (%s1), (%a1, %a2) */'
779 },
780
781 "fStackParam" => {
782   "arity"    => 1,
783   "comment"  => "constructs a Stack Parameter to retrieve a SSE parameter from Stack",
784   "reg_req"  => { "in" => [ "none" ], "out" => [ "floating_point" ] },
785   "cmp_attr" =>
786 '
787   return (attr_a->pn_code != attr_b->pn_code);
788 '
789 },
790
791 "fStackArg" => {
792   "arity"    => 2,
793   "comment"  => "constructs a Stack Argument to pass an argument on Stack",
794   "reg_req"  => { "in" => [ "none", "floating_point" ], "out" => [ "none" ] },
795   "cmp_attr" =>
796 '
797   return (attr_a->pn_code != attr_b->pn_code);
798 '
799 },
800
801 # Call
802
803 "Call" => {
804   "op_flags" => "L|F",
805   "state"    => "mem_pinned",
806   "arity"    => "variable",
807   "spill"    => 0,
808   "comment"  => "construct Call: Call(...)",
809   "args"     => [
810                   { "type" => "int",        "name" => "n" },
811                   { "type" => "ir_node **", "name" => "in" }
812                 ],
813   "rd_constructor" =>
814 "  if (!op_ia32_Call) assert(0);
815   return new_ir_node(db, irg, block, op_ia32_Call, mode_T, n, in);
816 "
817 }
818
819 ); # end of %nodes