jumps have a special irn flag now so beirgmod can identify them
[libfirm] / ir / be / ppc32 / ppc32_spec.pl
1 # Creation: 2006/02/13
2 # $Id$
3 # This is a template specification for the Firm-Backend
4
5 # the cpu architecture (ia32, ia64, mips, sparc, ppc32, ...)
6
7 $arch = "ppc32";
8
9 # register types:
10 #   0 - no special type
11 #   1 - caller save (register must be saved by the caller of a function)
12 #   2 - callee save (register must be saved by the called function)
13 #   4 - ignore (do not assign this register)
14 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
15 %reg_classes = (
16   "gp" => [
17                          { "name" => "r0", "type" => 1 },
18                          { "name" => "r2", "type" => 1 },
19                          { "name" => "r3", "type" => 1 },
20                          { "name" => "r4", "type" => 1 },
21                          { "name" => "r5", "type" => 1 },
22                          { "name" => "r6", "type" => 1 },
23                          { "name" => "r7", "type" => 1 },
24                          { "name" => "r8", "type" => 1 },
25                          { "name" => "r9", "type" => 1 },
26                          { "name" => "r10", "type" => 1 },
27 #                        { "name" => "r11", "type" => 1 },
28 #                        { "name" => "r12", "type" => 1 },
29                          { "name" => "r13", "type" => 2 },
30                          { "name" => "r14", "type" => 2 },
31                          { "name" => "r15", "type" => 2 },
32 #                        { "name" => "r16", "type" => 2 },
33 #                        { "name" => "r17", "type" => 2 },
34 #                        { "name" => "r18", "type" => 2 },
35 #                        { "name" => "r19", "type" => 2 },
36 #                        { "name" => "r20", "type" => 2 },
37 #                        { "name" => "r21", "type" => 2 },
38 #                        { "name" => "r22", "type" => 2 },
39 #                        { "name" => "r23", "type" => 2 },
40 #                        { "name" => "r24", "type" => 2 },
41 #                        { "name" => "r25", "type" => 2 },
42 #                        { "name" => "r26", "type" => 2 },
43 #                        { "name" => "r27", "type" => 2 },
44 #                        { "name" => "r28", "type" => 2 },
45 #                        { "name" => "r29", "type" => 2 },
46 #                        { "name" => "r30", "type" => 2 },
47                          { "name" => "r31", "type" => 2 },
48                          { "name" => "r1", "type" => 6 }, # this is our stackpointer
49                          { "mode" => "mode_P" }
50                        ],
51   "fp"  => [
52 #                        { "name" => "f0", "type" => 1 }, # => reserved for FP Perm
53                          { "name" => "f1", "type" => 1 },
54                          { "name" => "f2", "type" => 1 },
55                          { "name" => "f3", "type" => 1 },
56                          { "name" => "f4", "type" => 1 },
57                          { "name" => "f5", "type" => 1 },
58                          { "name" => "f6", "type" => 1 },
59                          { "name" => "f7", "type" => 1 },
60                          { "name" => "f8", "type" => 1 },
61                          { "name" => "f9", "type" => 1 },
62                          { "name" => "f10", "type" => 1 },
63                          { "name" => "f11", "type" => 1 },
64                          { "name" => "f12", "type" => 1 },
65                          { "name" => "f13", "type" => 1 },
66                          { "name" => "f14", "type" => 2 },
67                          { "name" => "f15", "type" => 2 },
68                          { "name" => "f16", "type" => 2 },
69 #                        { "name" => "f17", "type" => 2 },
70 #                        { "name" => "f18", "type" => 2 },
71 #                        { "name" => "f19", "type" => 2 },
72 #                        { "name" => "f20", "type" => 2 },
73 #                        { "name" => "f21", "type" => 2 },
74 #                        { "name" => "f22", "type" => 2 },
75 #                        { "name" => "f23", "type" => 2 },
76 #                        { "name" => "f24", "type" => 2 },
77 #                        { "name" => "f25", "type" => 2 },
78 #                        { "name" => "f26", "type" => 2 },
79 #                        { "name" => "f27", "type" => 2 },
80 #                        { "name" => "f28", "type" => 2 },
81 #                        { "name" => "f29", "type" => 2 },
82 #                        { "name" => "f30", "type" => 2 },
83 #                        { "name" => "f31", "type" => 2 },
84                          { "mode" => "mode_D" }
85                        ],
86   "condition" => [
87                          { "name" => "cr0", "type" => 1 },
88                          { "name" => "cr1", "type" => 1 },
89                          { "name" => "cr2", "type" => 2 },
90                          { "name" => "cr3", "type" => 2 },
91                          { "name" => "cr4", "type" => 2 },
92                          { "name" => "cr5", "type" => 1 },
93                          { "name" => "cr6", "type" => 1 },
94 #                        { "name" => "cr7", "type" => 1 }, # => reserved for Condition Perm
95                          { "mode" => "mode_P" } # real mode is 4 bit, but doesn't matter ...
96                        ],
97   "link" => [
98                          { "name" => "lr", "type" => 4 }, # 3
99                          { "mode" => "mode_P" }
100                        ],
101   "count" => [
102                          { "name" => "ctr", "type" => 1 },
103                          { "mode" => "mode_P" }
104                        ]
105 ); # %reg_classes
106
107 %emit_templates = (
108     S0 => "${arch}_emit_source_register(node, 0);",
109     S1 => "${arch}_emit_source_register(node, 1);",
110     S2 => "${arch}_emit_source_register(node, 2);",
111     D0 => "${arch}_emit_dest_register(node, 0);",
112     D1 => "${arch}_emit_dest_register(node, 1);",
113     D2 => "${arch}_emit_dest_register(node, 2);",
114         O  => "${arch}_emit_offset(node);",
115         C  => "${arch}_emit_immediate(node);",
116         RLWIMI => "${arch}_emit_rlwimi_helper(node);",
117 );
118
119 $default_cmp_attr = "NULL";
120
121 #--------------------------------------------------#
122 #                        _                         #
123 #                       (_)                        #
124 #  _ __   _____      __  _ _ __    ___  _ __  ___  #
125 # | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
126 # | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
127 # |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
128 #                                      | |         #
129 #                                      |_|         #
130 #--------------------------------------------------#
131
132 %nodes = (
133
134 #-----------------------------------------------------------------#
135 #  _       _                                         _            #
136 # (_)     | |                                       | |           #
137 #  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
138 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
139 # | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
140 # |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
141 #                   __/ |                                         #
142 #                  |___/                                          #
143 #-----------------------------------------------------------------#
144
145 # commutative operations
146
147 "Add" => {
148   "op_flags"  => "C",
149   "irn_flags" => "R",
150   "comment"   => "construct Add: Add(a, b) = Add(b, a) = a + b",
151   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
152   "emit"      => '. add     %D0, %S0, %S1',
153 },
154
155 "Addi" => {
156   "irn_flags" => "R",
157   "comment"   => "construct Add: Addi(a, const) = Addi(const, a) = a + const",
158   "reg_req"   => { "in" => [ "!r0" ], "out" => [ "gp" ] },
159 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
160   "emit"      => '. addi    %D0, %S0, %C',
161   "cmp_attr"  =>
162 '
163         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
164 ',
165 },
166
167
168 "Mullw" => {
169   "op_flags"  => "C",
170   "irn_flags" => "R",
171   "comment"   => "construct Mul: Mullw(a, b) = Mullw(b, a) = lo32(a * b)",
172   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
173   "emit"      => '. mullw   %D0, %S0, %S1',
174 },
175
176 "Mulhw" => {
177   "op_flags"  => "C",
178   "irn_flags" => "R",
179   "comment"   => "construct Mul: Mulhw(a, b) = Mulhw(b, a) = hi32(a * b)",
180   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
181   "emit"      => '. mulhw   %D0, %S0, %S1',
182 },
183
184 "Mulhwu" => {
185   "op_flags"  => "C",
186   "irn_flags" => "R",
187   "comment"   => "construct Mul: Mulhwu(a, b) = Mulhwu(b, a) = hi32(a * b)",
188   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
189   "emit"      => '. mulhwu  %D0, %S0, %S1',
190 },
191
192 #"Mul_i" => {
193 #  "irn_flags" => "R",
194 #  "comment"   => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
195 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
196 #  "emit"      => '. mul %S0, %C, %D0',
197 #},
198
199 "And" => {
200   "op_flags"  => "C",
201   "irn_flags" => "R",
202   "comment"   => "construct And: And(a, b) = And(b, a) = a AND b",
203   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
204   "emit"      => '. and     %D0, %S0, %S1',
205 },
206
207 #"And_i" => {
208 #  "irn_flags" => "R",
209 #  "comment"   => "construct And: And(a, const) = And(const, a) = a AND const",
210 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
211 #  "emit"      => '. and %S0, %C, %D0',
212 #},
213
214 "Or" => {
215   "op_flags"  => "C",
216   "irn_flags" => "R",
217   "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
218   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
219   "emit"      => '. or      %D0, %S0, %S1',
220 },
221
222 #"Or_i" => {
223 #  "op_flags"  => "C",
224 #  "irn_flags" => "R",
225 #  "comment"   => "construct Or: Or(a, const) = Or(const, a) = a OR const",
226 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
227 #  "emit"      => '. or %S0, %C, %D0',
228 #},
229
230 "Xor" => {
231   "op_flags"  => "C",
232   "irn_flags" => "R",
233   "comment"   => "construct Xor: Xor(a, b) = Xor(b, a) = a XOR b",
234   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
235   "emit"      => '. xor     %D0, %S0, %S1',
236 },
237
238 #"Xor_i" => {
239 #  "irn_flags" => "R",
240 #  "comment"   => "construct Xor: Xor(a, const) = Xor(const, a) = a EOR const",
241 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
242 #  "emit"      => '. xor %S0, %C, %D0',
243 #},
244
245 # not commutative operations
246
247 "Sub" => {
248   "irn_flags" => "R",
249   "comment"   => "construct Sub: Sub(a, b) = a - b",
250   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
251   "emit"      => '. sub %D0, %S0, %S1',
252 },
253
254 #"Sub_i" => {
255 #  "irn_flags" => "R",
256 #  "comment"   => "construct Sub: Sub(a, const) = a - const",
257 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
258 #  "emit"      => '. subl %S0, %C, %D0',
259 #},
260
261 "Slw" => {
262   "irn_flags" => "R",
263   "comment"   => "construct Shl: Shl(a, b) = a << b",
264   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
265   "emit"      => '. slw %D0, %S0, %S1',
266 },
267
268 #"Shl_i" => {
269 #  "irn_flags" => "R",
270 #  "comment"   => "construct Shl: Shl(a, const) = a << const",
271 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
272 #  "emit"      => '. shl %S0, %C, %D0',
273 #},
274
275 "Srw" => {
276   "irn_flags" => "R",
277   "comment"   => "construct Shr: Srw(a, b): c = a >> b",
278   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
279   "emit"      => '. srw     %D0, %S0, %S1',
280 },
281
282 #"Shr_i" => {
283 #  "irn_flags" => "R",
284 #  "comment"   => "construct Shr: Shr(a, const) = a >> const",
285 #  "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
286 #  "emit"      => '. shr %S0, %C, %D0',
287 #},
288
289 "Sraw" => {
290   "irn_flags" => "R",
291   "comment"   => "construct Shrs: Sraw(a, b): c = a >> b",
292   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
293   "emit"      => '. sraw %D0, %S0, %S1',
294 },
295
296 "Srawi" => {
297   "irn_flags" => "R",
298   "comment"   => "construct Shrs: Srawi(a, const): c = a >> const",
299   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
300   "emit"      => '. sraw %D0, %S0, %C',
301   "cmp_attr"  =>
302 '
303         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
304 ',
305
306 },
307
308 "Rlwnm" => {
309   "irn_flags" => "R",
310   "comment"   => "construct ???: Rlwnm(a, b): c = a ROTL b",
311   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
312   "emit"      => '. rlwnm %D0, %S0, %S1',
313 },
314
315 "Rlwinm" => {
316   "irn_flags" => "R",
317   "comment"   => "construct ???: Rlwinm(a, b_const, c_const, d_const): (m = MASK(c, d)) e = (a ROTL b) & m",
318   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
319   "emit"      => '. rlwinm %D0, %S0, %RLWIMI',
320   "cmp_attr"  =>
321 '
322         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
323 ',
324 },
325
326
327 "Neg" => {
328   "irn_flags" => "R",
329   "comment"   => "construct Minus: Neg(a) = -a",
330   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
331   "emit"      => '. neg %D0, %S0',
332 },
333
334 "Not" => {
335   "irn_flags" => "R",
336   "comment"   => "construct Not: Not(a) = !a",
337   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
338   "emit"      => '. nor %D0, %S0, %S0',
339 },
340
341 "Extsb" => {
342   "irn_flags" => "R",
343   "comment"   => "construct Sign extension of byte: Extsb(char a) = (int) a",
344   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
345   "emit"      => '. extsb %D0, %S0',
346 },
347
348 "Extsh" => {
349   "irn_flags" => "R",
350   "comment"   => "construct Sign extension of halfword: Extsh(char a) = (short) a",
351   "reg_req"   => { "in" => [ "gp" ], "out" => [ "gp" ] },
352   "emit"      => '. extsh %D0, %S0',
353 },
354
355 "Divw" => {
356   "irn_flags" => "R",
357   "comment"   => "construct Div (signed): Div(a, b) = a div b",
358   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
359   "emit"      => '. divw %D0, %S0, %S1',
360 },
361
362 "Divwu" => {
363   "irn_flags" => "R",
364   "comment"   => "construct Div (unsigned): Div(a, b) = a div b",
365   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
366   "emit"      => '. divwu %D0, %S0, %S1',
367 },
368
369 "Mtctr" => {
370   "irn_flags" => "R",
371   "comment"   => "construct Mtctr: Ctr = a",
372   "reg_req"   => { "in" => [ "gp" ], "out" => [ "count" ] },
373   "emit"      => '. mtctr %S0',
374 },
375
376
377 # other operations
378
379 "Const" => {
380   "op_flags"  => "c",
381   "irn_flags" => "R",
382   "comment"   => "Const (high-level node)",
383   "reg_req"   => { "out" => [ "gp" ] },
384   "cmp_attr"  =>
385 '
386         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
387 ',
388 },
389
390 "fConst" => {
391   "op_flags"  => "c",
392   "irn_flags" => "R",
393   "comment"   => "float Const (high-level node)",
394   "reg_req"   => { "out" => [ "fp" ] },
395   "cmp_attr"  =>
396 '
397         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
398 ',
399 },
400
401 "SymConst" => {
402   "op_flags"  => "c",
403   "irn_flags" => "R",
404   "comment"   => "SymConst (high-level node)",
405   "reg_req"   => { "out" => [ "gp" ] },
406   "cmp_attr"  =>
407 '
408         return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
409 ',
410 },
411
412 "Unknown" => {
413   "op_flags"  => "c",
414   "irn_flags" => "R",
415   "comment"   => "construct unknown register",
416   "reg_req"   => { "out" => [ "gp" ] },
417   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
418   "cmp_attr"  =>
419 '
420         return 1;
421 ',
422 },
423
424 "fUnknown" => {
425   "op_flags"  => "c",
426   "irn_flags" => "R",
427   "comment"   => "construct unknown float register",
428   "reg_req"   => { "out" => [ "fp" ] },
429   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
430   "cmp_attr"  =>
431 '
432         return 1;
433 ',
434 },
435
436 "cUnknown" => {
437   "op_flags"  => "c",
438   "irn_flags" => "R",
439   "comment"   => "construct unknown condition register",
440   "reg_req"   => { "out" => [ "condition" ] },
441   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
442   "cmp_attr"  =>
443 '
444         return 1;
445 ',
446 },
447
448 "Addi_zero" => {
449   "op_flags"  => "c",
450   "irn_flags" => "R",
451   "comment"   => "load constant (16bit with sign extension)",
452   "reg_req"   => { "out" => [ "gp" ] },
453   "emit"      => '. addi    %D0, 0, %C',
454   "cmp_attr"  =>
455 '
456         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
457 ',
458 },
459
460 "Branch" => {
461   "op_flags"  => "L|X|Y",
462   "comment"   => "branch somewhere",
463   "reg_req"   => { "in" => [ "condition" ], "out" => [ "none", "none" ] },
464   "cmp_attr"  =>
465 '
466         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
467 ',
468 },
469
470 "LoopCopy" => {
471   "irn_flags" => "R",
472   "comment"   => "construct LoopCopy(src, dest, count, mem): Copy count words from src to dest",
473   "reg_req"   => { "in" => [ "gp", "gp", "count", "none" ], "out" => [ "none", "in_r1", "in_r2", "in_r3", "gp" ] },
474 },
475
476 "Switch" => {
477   "op_flags" => "L|X|Y",
478   "comment"   => "construct Switch(selector): Jump to whatever",
479   "reg_req"   => { "in" => [ "gp", "gp", "condition" ], "out" => [ "none" ] },
480   "cmp_attr"  =>
481 '
482         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
483 ',
484 },
485
486 "Addis_zero" => {
487   "op_flags"  => "c",
488   "irn_flags" => "R",
489   "comment"   => "load the constant to higher 16 bit of register",
490   "reg_req"   => { "out" => [ "gp" ] },
491   "emit"      => '. addis %D0, 0, %C',
492   "attr"      => "ppc32_attr_offset_mode om, tarval *tv, ident *id",
493   "init_attr" =>
494 '
495         attr->offset_mode = om;
496         if (tv) {
497                 attr->content_type = ppc32_ac_Const;
498                 attr->data.constant_tarval = tv;
499         }
500         else if (id) {
501                 attr->content_type = ppc32_ac_SymConst;
502                 attr->data.symconst_ident = id;
503         }
504 ',
505   "cmp_attr"  =>
506 '
507         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
508 ',
509 },
510
511 "Ori" => {
512   "irn_flags" => "R",
513   "comment"   => "ors constant with register",
514   "reg_req"   => { "in" => [ "gp"], "out" => [ "gp" ] },
515   "emit"      => '. ori %D0, %S0, %C',
516   "cmp_attr"  =>
517 '
518         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
519 ',
520 },
521
522 "Andi_dot" => {
523   "irn_flags" => "R",
524   "comment"   => "ands constant with register with cr0 update",
525   "reg_req"   => { "in" => [ "gp"], "out" => [ "gp", "cr0" ] },
526   "emit"      => '. andi. %D0, %S0,%C',
527   "cmp_attr"  =>
528 '
529         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
530 ',
531 },
532
533 "Cmp" => {
534   "irn_flags" => "R",
535   "comment"   => "construct Cmp: Cmp(a, b) = Flags in crX",
536   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "condition" ] },
537   "emit"      => '. cmp %D0, 0, %S0, %S1',
538 },
539
540 "Cmpi" => {
541   "irn_flags" => "R",
542   "comment"   => "construct Cmp immediate: Cmpi(a, const) = Flags in crX",
543   "reg_req"   => { "in" => [ "gp" ], "out" => [ "condition" ] },
544   "emit"      => '. cmpi %D0, 0, %S0, %C',
545   "cmp_attr"  =>
546 '
547         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
548 ',
549 },
550
551
552 "Cmpl" => {
553   "irn_flags" => "R",
554   "comment"   => "construct Cmp logical: Cmpl(a, b) = Flags in crX",
555   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "condition" ] },
556   "emit"      => '. cmpl %D0, 0, %S0, %S1',
557 },
558
559 "Cmpli" => {
560   "irn_flags" => "R",
561   "comment"   => "construct Cmp logical immediate: Cmpli(a, const) = Flags in crX",
562   "reg_req"   => { "in" => [ "gp" ], "out" => [ "condition" ] },
563   "emit"      => '. cmpli %D0, 0, %S0, %C',
564   "cmp_attr"  =>
565 '
566         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
567 ',
568 },
569
570
571 # Load / Store
572
573 "Lbz" => {
574   "op_flags"  => "L|F",
575   "irn_flags" => "R",
576   "state"     => "exc_pinned",
577   "comment"   => "construct Load (byte unsigned): Load(ptr, mem) = LD ptr -> reg",
578   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
579   "emit"      => '. lbz %D0, %O(%S0)',
580   "cmp_attr"  =>
581 '
582         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
583 ',
584   "outs"      => [ "res", "M" ],
585 },
586
587 "Lhz" => {
588   "op_flags"  => "L|F",
589   "irn_flags" => "R",
590   "state"     => "exc_pinned",
591   "comment"   => "construct Load (halfword unsigned): Load(ptr, mem) = LD ptr -> reg",
592   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
593   "emit"      => '. lhz %D0, %O(%S0)',
594   "cmp_attr"  =>
595 '
596         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
597 ',
598   "outs"      => [ "res", "M" ],
599 },
600
601 "Lha" => {
602   "op_flags"  => "L|F",
603   "irn_flags" => "R",
604   "state"     => "exc_pinned",
605   "comment"   => "construct Load (halfword signed): Load(ptr, mem) = LD ptr -> reg",
606   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
607   "emit"      => '. lha %D0, %O(%S0)',
608   "cmp_attr"  =>
609 '
610         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
611 ',
612   "outs"      => [ "res", "M" ],
613 },
614
615 "Lwz" => {
616   "op_flags"  => "L|F",
617   "irn_flags" => "R",
618   "state"     => "exc_pinned",
619   "comment"   => "construct Load (word): Load(ptr, mem) = LD ptr -> reg",
620   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "none" ] },
621   "emit"      => '. lwz %D0, %O(%S0)',
622   "cmp_attr"  =>
623 '
624         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
625 ',
626   "outs"      => [ "res", "M" ],
627 },
628
629 "Lwzu" => {
630   "op_flags"  => "L|F",
631   "irn_flags" => "R",
632   "state"     => "exc_pinned",
633   "comment"   => "construct Load with update (word): Load(ptr, mem) = LD ptr -> reg",
634   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "gp", "in_r1", "none"] },
635   "emit"      => '. lwzu %D0, %O(%S0)',
636   "cmp_attr"  =>
637 '
638         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
639 ',
640   "outs"      => [ "res", "ptr", "M" ],
641 },
642
643 "Stb" => {
644   "op_flags"  => "L|F",
645   "state"     => "exc_pinned",
646   "comment"   => "construct Store: Store (byte) (ptr, val, mem) = ST ptr,val",
647   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
648   "emit"      => '. stb %S1, %O(%S0)',
649   "cmp_attr"  =>
650 '
651         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
652 ',
653   "outs"      => [ "M" ],
654 },
655
656 "Sth" => {
657   "op_flags"  => "L|F",
658   "state"     => "exc_pinned",
659   "comment"   => "construct Store: Store (halfword) (ptr, val, mem) = ST ptr,val",
660   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
661   "emit"      => '. sth %S1, %O(%S0)',
662   "cmp_attr"  =>
663 '
664         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
665 ',
666   "outs"      => [ "M" ],
667 },
668
669 "Stw" => {
670   "op_flags"  => "L|F",
671   "state"     => "exc_pinned",
672   "comment"   => "construct Store: Store (word) (ptr, val, mem) = ST ptr,val",
673   "reg_req"   => { "in" => [ "!r0", "gp", "none" ], "out" => [ "none" ] },
674   "emit"      => '. stw %S1, %O(%S0)',
675   "cmp_attr"  =>
676 '
677         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
678 ',
679   "outs"      => [ "M" ],
680 },
681
682 #--------------------------------------------------------#
683 #    __ _             _                     _            #
684 #   / _| |           | |                   | |           #
685 #  | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
686 #  |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
687 #  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
688 #  |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
689 #--------------------------------------------------------#
690
691 # commutative operations
692
693 "fAdd" => {
694   "op_flags"  => "C",
695   "irn_flags" => "R",
696   "comment"   => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
697   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
698   "emit"      => '. fadd %D0, %S0, %S1',
699 },
700
701 "fAdds" => {
702   "op_flags"  => "C",
703   "irn_flags" => "R",
704   "comment"   => "construct FP Add (single): Add(a, b) = Add(b, a) = a + b",
705   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
706   "emit"      => '. fadds %D0, %S0, %S1',
707 },
708
709 "fMul" => {
710   "op_flags"  => "C",
711   "comment"   => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
712   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
713   "emit"      => '. fmul %D0, %S0, %S1',
714 },
715
716 "fMuls" => {
717   "op_flags"  => "C",
718   "comment"   => "construct FP Mul (single): Mul(a, b) = Mul(b, a) = a * b",
719   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
720   "emit"      => '. fmuls %D0, %S0, %S1',
721 },
722
723 "fNeg" => {
724   "comment"   => "construct FP Negation: fNeg(a) = -a",
725   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
726   "emit"      => '. fneg %D0, %S0',
727 },
728
729
730 "fMax" => {
731   "op_flags"  => "C",
732   "irn_flags" => "R",
733   "comment"   => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
734   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
735   "emit"      => '. fmax %S0, %S1, %D0',
736 },
737
738 "fMin" => {
739   "op_flags"  => "C",
740   "irn_flags" => "R",
741   "comment"   => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
742   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
743   "emit"      => '. fmin %S0, %S1, %D0',
744 },
745
746 # not commutative operations
747
748 "fSub" => {
749   "irn_flags" => "R",
750   "comment"   => "construct FP Sub: Sub(a, b) = a - b",
751   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
752   "emit"      => '. fsub %D0, %S0, %S1',
753 },
754
755 "fSubs" => {
756   "irn_flags" => "R",
757   "comment"   => "construct FP Sub (single): Sub(a, b) = a - b",
758   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
759   "emit"      => '. fsubs %D0, %S0, %S1',
760 },
761
762 "fDiv" => {
763   "comment"   => "construct FP Div: Div(a, b) = a / b",
764   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
765   "emit"      => '. fdiv %D0, %S0, %S1',
766 },
767
768 "fDivs" => {
769   "comment"   => "construct FP Div (single): Div(a, b) = a / b",
770   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] },
771   "emit"      => '. fdivs %D0, %S0, %S1',
772 },
773
774 "fMinus" => {
775   "irn_flags" => "R",
776   "comment"   => "construct FP Minus: fMinus(a) = -a",
777   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
778   "emit"      => '. fneg %D0, %S0',
779 },
780
781 "fCtiw" => {
782   "irn_flags" => "R",
783   "comment"   => "construct FP Convert to integer word: fCtiw(a) = (int) a",
784   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
785   "emit"      => '. fctiw %D0, %S0',
786 },
787
788 "fRsp" => {
789   "irn_flags" => "R",
790   "comment"   => "construct FP Round to single: fRsp(a) = (float) a",
791   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
792   "emit"      => '. frsp %D0, %S0',
793 },
794
795 "fAbs" => {
796   "irn_flags" => "R",
797   "comment"   => "construct FP Abs: fAbs(a) = |a|",
798   "reg_req"   => { "in" => [ "fp" ], "out" => [ "fp" ] },
799   "emit"      => '. fabs %D0, %S0',
800 },
801
802 "fCmpu" => {
803   "irn_flags" => "R",
804   "comment"   => "construct FP Cmp unordered: fCmpu(a, b) = a ? b",
805   "reg_req"   => { "in" => [ "fp", "fp" ], "out" => [ "condition" ] },
806   "emit"      => '. fcmpu %D0, %S0, %S1',
807 },
808
809 # other operations
810
811 #"fConst" => {
812 #  "op_flags"  => "c",
813 #  "irn_flags" => "R",
814 #  "comment"   => "represents a FP constant",
815 #  "reg_req"   => { "out" => [ "fp" ] },
816 #  "emit"      => '. fmov %C, %D0',
817 #  "cmp_attr"  =>
818 #'
819 #       /* TODO: compare fConst attributes */
820 #       return 1;
821 #',
822 #},
823
824 "fUnknown" => {
825   "op_flags"  => "c",
826   "irn_flags" => "R",
827   "comment"   => "construct unknown floating point register",
828   "reg_req"   => { "out" => [ "fp" ] },
829   "emit"      => '. \t\t /* use %D0 as uninitialized value */',
830   "cmp_attr"  =>
831 '
832         return 1;
833 ',
834 },
835
836 # Load / Store
837
838 "Lfd" => {
839   "op_flags"  => "L|F",
840   "irn_flags" => "R",
841   "state"     => "exc_pinned",
842   "comment"   => "construct FP Load (double): Load(ptr, mem) = LD ptr",
843   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "fp", "none" ] },
844   "emit"      => '. lfd %D0, %O(%S0)',
845   "cmp_attr"  =>
846 '
847         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
848 ',
849   "outs"      => [ "res", "M" ],
850 },
851
852 "Lfs" => {
853   "op_flags"  => "L|F",
854   "irn_flags" => "R",
855   "state"     => "exc_pinned",
856   "comment"   => "construct FP Load (single): Load(ptr, mem) = LD ptr",
857   "reg_req"   => { "in" => [ "!r0", "none" ], "out" => [ "fp","none" ] },
858   "emit"      => '. lfs %D0, %O(%S0)',
859   "cmp_attr"  =>
860 '
861         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
862 ',
863   "outs"      => [ "res", "M" ],
864 },
865
866 "Stfd" => {
867   "op_flags"  => "L|F",
868   "state"     => "exc_pinned",
869   "comment"   => "construct Store (double): Store(ptr, val, mem)  = ST ptr,val",
870   "reg_req"   => { "in" => [ "!r0", "fp", "none" ], "out" => [ "none" ] },
871   "emit"      => '. stfd %S1, %O(%S0)',
872   "cmp_attr"  =>
873 '
874         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
875 ',
876   "outs"      => [ "M" ],
877 },
878
879 "Stfs" => {
880   "op_flags"  => "L|F",
881   "state"     => "exc_pinned",
882   "comment"   => "construct Store (single): Store(ptr, val, mem)  = ST ptr,val",
883   "reg_req"   => { "in" => [ "!r0", "fp", "none" ], "out" => [ "none" ] },
884   "emit"      => '. stfs %S1, %O(%S0)',
885   "cmp_attr"  =>
886 '
887         return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
888 ',
889   "outs"      => [ "M" ],
890 },
891
892 ); # end of %nodes