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