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