4 # the cpu architecture (ia32, ia64, mips, sparc, ppc32, ...)
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
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" }
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 },
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 ...
97 { name => "lr", type => 4 }, # 3
101 { name => "ctr", type => 1 },
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);",
118 $default_cmp_attr = "NULL";
120 #--------------------------------------------------#
123 # _ __ _____ __ _ _ __ ___ _ __ ___ #
124 # | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| #
125 # | | | | __/\ V V / | | | | (_) | |_) \__ \ #
126 # |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ #
129 #--------------------------------------------------#
133 #-----------------------------------------------------------------#
136 # _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ #
137 # | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
138 # | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ #
139 # |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ #
142 #-----------------------------------------------------------------#
144 # commutative operations
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',
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',
162 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
169 comment => "construct Mul: Mullw(a, b) = Mullw(b, a) = lo32(a * b)",
170 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
171 emit => '. mullw %D0, %S0, %S1',
177 comment => "construct Mul: Mulhw(a, b) = Mulhw(b, a) = hi32(a * b)",
178 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
179 emit => '. mulhw %D0, %S0, %S1',
185 comment => "construct Mul: Mulhwu(a, b) = Mulhwu(b, a) = hi32(a * b)",
186 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
187 emit => '. mulhwu %D0, %S0, %S1',
192 # comment => "construct Mul: Mul(a, const) = Mul(const, a) = a * const",
193 # reg_req => { in => [ "gp" ], out => [ "gp" ] },
194 # emit => '. mul %S0, %C, %D0',
200 comment => "construct And: And(a, b) = And(b, a) = a AND b",
201 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
202 emit => '. and %D0, %S0, %S1',
207 # comment => "construct And: And(a, const) = And(const, a) = a AND const",
208 # reg_req => { in => [ "gp" ], out => [ "gp" ] },
209 # emit => '. and %S0, %C, %D0',
215 comment => "construct Or: Or(a, b) = Or(b, a) = a OR b",
216 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
217 emit => '. or %D0, %S0, %S1',
223 # comment => "construct Or: Or(a, const) = Or(const, a) = a OR const",
224 # reg_req => { in => [ "gp" ], out => [ "gp" ] },
225 # emit => '. or %S0, %C, %D0',
231 comment => "construct Xor: Xor(a, b) = Xor(b, a) = a XOR b",
232 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
233 emit => '. xor %D0, %S0, %S1',
238 # comment => "construct Xor: Xor(a, const) = Xor(const, a) = a EOR const",
239 # reg_req => { in => [ "gp" ], out => [ "gp" ] },
240 # emit => '. xor %S0, %C, %D0',
243 # not commutative operations
247 comment => "construct Sub: Sub(a, b) = a - b",
248 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
249 emit => '. sub %D0, %S0, %S1',
254 # comment => "construct Sub: Sub(a, const) = a - const",
255 # reg_req => { in => [ "gp" ], out => [ "gp" ] },
256 # emit => '. subl %S0, %C, %D0',
261 comment => "construct Shl: Shl(a, b) = a << b",
262 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
263 emit => '. slw %D0, %S0, %S1',
268 # comment => "construct Shl: Shl(a, const) = a << const",
269 # reg_req => { in => [ "gp" ], out => [ "gp" ] },
270 # emit => '. shl %S0, %C, %D0',
275 comment => "construct Shr: Srw(a, b): c = a >> b",
276 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
277 emit => '. srw %D0, %S0, %S1',
282 # comment => "construct Shr: Shr(a, const) = a >> const",
283 # reg_req => { in => [ "gp" ], out => [ "gp" ] },
284 # emit => '. shr %S0, %C, %D0',
289 comment => "construct Shrs: Sraw(a, b): c = a >> b",
290 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
291 emit => '. sraw %D0, %S0, %S1',
296 comment => "construct Shrs: Srawi(a, const): c = a >> const",
297 reg_req => { in => [ "gp" ], out => [ "gp" ] },
298 emit => '. sraw %D0, %S0, %C',
301 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
308 comment => "construct ???: Rlwnm(a, b): c = a ROTL b",
309 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
310 emit => '. rlwnm %D0, %S0, %S1',
315 comment => "construct ???: Rlwinm(a, b_const, c_const, d_const): (m = MASK(c, d)) e = (a ROTL b) & m",
316 reg_req => { in => [ "gp" ], out => [ "gp" ] },
317 emit => '. rlwinm %D0, %S0, %RLWIMI',
320 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
326 comment => "construct Minus: Neg(a) = -a",
327 reg_req => { in => [ "gp" ], out => [ "gp" ] },
328 emit => '. neg %D0, %S0',
333 comment => "construct Not: Not(a) = !a",
334 reg_req => { in => [ "gp" ], out => [ "gp" ] },
335 emit => '. nor %D0, %S0, %S0',
340 comment => "construct Sign extension of byte: Extsb(char a) = (int) a",
341 reg_req => { in => [ "gp" ], out => [ "gp" ] },
342 emit => '. extsb %D0, %S0',
347 comment => "construct Sign extension of halfword: Extsh(char a) = (short) a",
348 reg_req => { in => [ "gp" ], out => [ "gp" ] },
349 emit => '. extsh %D0, %S0',
354 comment => "construct Div (signed): Div(a, b) = a div b",
355 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
356 emit => '. divw %D0, %S0, %S1',
361 comment => "construct Div (unsigned): Div(a, b) = a div b",
362 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
363 emit => '. divwu %D0, %S0, %S1',
368 comment => "construct Mtctr: Ctr = a",
369 reg_req => { in => [ "gp" ], out => [ "count" ] },
370 emit => '. mtctr %S0',
379 comment => "Const (high-level node)",
380 reg_req => { out => [ "gp" ] },
383 return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
390 comment => "float Const (high-level node)",
391 reg_req => { out => [ "fp" ] },
394 return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
401 comment => "SymConst (high-level node)",
402 reg_req => { out => [ "gp" ] },
405 return attr_a->data.constant_tarval != attr_b->data.constant_tarval;
412 comment => "construct unknown register",
413 reg_req => { out => [ "gp" ] },
414 emit => '. \t\t /* use %D0 as uninitialized value */',
424 comment => "construct unknown float register",
425 reg_req => { out => [ "fp" ] },
426 emit => '. \t\t /* use %D0 as uninitialized value */',
436 comment => "construct unknown condition register",
437 reg_req => { out => [ "condition" ] },
438 emit => '. \t\t /* use %D0 as uninitialized value */',
448 comment => "load constant (16bit with sign extension)",
449 reg_req => { out => [ "gp" ] },
450 emit => '. addi %D0, 0, %C',
453 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
459 comment => "branch somewhere",
460 reg_req => { in => [ "condition" ], out => [ "none", "none" ] },
463 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
469 comment => "construct LoopCopy(src, dest, count, mem): Copy count words from src to dest",
470 reg_req => { in => [ "gp", "gp", "count", "none" ], out => [ "none", "in_r1", "in_r2", "in_r3", "gp" ] },
475 comment => "construct Switch(selector): Jump to whatever",
476 reg_req => { in => [ "gp", "gp", "condition" ], out => [ "none" ] },
479 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
486 comment => "load the constant to higher 16 bit of register",
487 reg_req => { out => [ "gp" ] },
488 emit => '. addis %D0, 0, %C',
489 "attr" => "ppc32_attr_offset_mode om, tarval *tv, ident *id",
492 attr->offset_mode = om;
494 attr->content_type = ppc32_ac_Const;
495 attr->data.constant_tarval = tv;
498 attr->content_type = ppc32_ac_SymConst;
499 attr->data.symconst_ident = id;
504 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
510 comment => "ors constant with register",
511 reg_req => { in => [ "gp"], out => [ "gp" ] },
512 emit => '. ori %D0, %S0, %C',
515 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
521 comment => "ands constant with register with cr0 update",
522 reg_req => { in => [ "gp"], out => [ "gp", "cr0" ] },
523 emit => '. andi. %D0, %S0,%C',
526 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
532 comment => "construct Cmp: Cmp(a, b) = Flags in crX",
533 reg_req => { in => [ "gp", "gp" ], out => [ "condition" ] },
534 emit => '. cmp %D0, 0, %S0, %S1',
539 comment => "construct Cmp immediate: Cmpi(a, const) = Flags in crX",
540 reg_req => { in => [ "gp" ], out => [ "condition" ] },
541 emit => '. cmpi %D0, 0, %S0, %C',
544 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
550 comment => "construct Cmp logical: Cmpl(a, b) = Flags in crX",
551 reg_req => { in => [ "gp", "gp" ], out => [ "condition" ] },
552 emit => '. cmpl %D0, 0, %S0, %S1',
557 comment => "construct Cmp logical immediate: Cmpli(a, const) = Flags in crX",
558 reg_req => { in => [ "gp" ], out => [ "condition" ] },
559 emit => '. cmpli %D0, 0, %S0, %C',
562 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
572 state => "exc_pinned",
573 comment => "construct Load (byte unsigned): Load(ptr, mem) = LD ptr -> reg",
574 reg_req => { in => [ "!r0", "none" ], out => [ "gp", "none" ] },
575 emit => '. lbz %D0, %O(%S0)',
578 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
580 outs => [ "res", "M" ],
586 state => "exc_pinned",
587 comment => "construct Load (halfword unsigned): Load(ptr, mem) = LD ptr -> reg",
588 reg_req => { in => [ "!r0", "none" ], out => [ "gp", "none" ] },
589 emit => '. lhz %D0, %O(%S0)',
592 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
594 outs => [ "res", "M" ],
600 state => "exc_pinned",
601 comment => "construct Load (halfword signed): Load(ptr, mem) = LD ptr -> reg",
602 reg_req => { in => [ "!r0", "none" ], out => [ "gp", "none" ] },
603 emit => '. lha %D0, %O(%S0)',
606 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
608 outs => [ "res", "M" ],
614 state => "exc_pinned",
615 comment => "construct Load (word): Load(ptr, mem) = LD ptr -> reg",
616 reg_req => { in => [ "!r0", "none" ], out => [ "gp", "none" ] },
617 emit => '. lwz %D0, %O(%S0)',
620 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
622 outs => [ "res", "M" ],
628 state => "exc_pinned",
629 comment => "construct Load with update (word): Load(ptr, mem) = LD ptr -> reg",
630 reg_req => { in => [ "!r0", "none" ], out => [ "gp", "in_r1", "none"] },
631 emit => '. lwzu %D0, %O(%S0)',
634 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
636 outs => [ "res", "ptr", "M" ],
641 state => "exc_pinned",
642 comment => "construct Store: Store (byte) (ptr, val, mem) = ST ptr,val",
643 reg_req => { in => [ "!r0", "gp", "none" ], out => [ "none" ] },
644 emit => '. stb %S1, %O(%S0)',
647 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
654 state => "exc_pinned",
655 comment => "construct Store: Store (halfword) (ptr, val, mem) = ST ptr,val",
656 reg_req => { in => [ "!r0", "gp", "none" ], out => [ "none" ] },
657 emit => '. sth %S1, %O(%S0)',
660 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
667 state => "exc_pinned",
668 comment => "construct Store: Store (word) (ptr, val, mem) = ST ptr,val",
669 reg_req => { in => [ "!r0", "gp", "none" ], out => [ "none" ] },
670 emit => '. stw %S1, %O(%S0)',
673 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
678 #--------------------------------------------------------#
681 # | |_| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
682 # | _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
683 # | | | | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
684 # |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
685 #--------------------------------------------------------#
687 # commutative operations
692 comment => "construct FP Add: Add(a, b) = Add(b, a) = a + b",
693 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
694 emit => '. fadd %D0, %S0, %S1',
700 comment => "construct FP Add (single): Add(a, b) = Add(b, a) = a + b",
701 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
702 emit => '. fadds %D0, %S0, %S1',
707 comment => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b",
708 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
709 emit => '. fmul %D0, %S0, %S1',
714 comment => "construct FP Mul (single): Mul(a, b) = Mul(b, a) = a * b",
715 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
716 emit => '. fmuls %D0, %S0, %S1',
720 comment => "construct FP Negation: fNeg(a) = -a",
721 reg_req => { in => [ "fp" ], out => [ "fp" ] },
722 emit => '. fneg %D0, %S0',
728 comment => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b",
729 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
730 emit => '. fmax %S0, %S1, %D0',
736 comment => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b",
737 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
738 emit => '. fmin %S0, %S1, %D0',
741 # not commutative operations
745 comment => "construct FP Sub: Sub(a, b) = a - b",
746 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
747 emit => '. fsub %D0, %S0, %S1',
752 comment => "construct FP Sub (single): Sub(a, b) = a - b",
753 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
754 emit => '. fsubs %D0, %S0, %S1',
758 comment => "construct FP Div: Div(a, b) = a / b",
759 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
760 emit => '. fdiv %D0, %S0, %S1',
764 comment => "construct FP Div (single): Div(a, b) = a / b",
765 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
766 emit => '. fdivs %D0, %S0, %S1',
771 comment => "construct FP Minus: fMinus(a) = -a",
772 reg_req => { in => [ "fp" ], out => [ "fp" ] },
773 emit => '. fneg %D0, %S0',
778 comment => "construct FP Convert to integer word: fCtiw(a) = (int) a",
779 reg_req => { in => [ "fp" ], out => [ "fp" ] },
780 emit => '. fctiw %D0, %S0',
785 comment => "construct FP Round to single: fRsp(a) = (float) a",
786 reg_req => { in => [ "fp" ], out => [ "fp" ] },
787 emit => '. frsp %D0, %S0',
792 comment => "construct FP Abs: fAbs(a) = |a|",
793 reg_req => { in => [ "fp" ], out => [ "fp" ] },
794 emit => '. fabs %D0, %S0',
799 comment => "construct FP Cmp unordered: fCmpu(a, b) = a ? b",
800 reg_req => { in => [ "fp", "fp" ], out => [ "condition" ] },
801 emit => '. fcmpu %D0, %S0, %S1',
809 # comment => "represents a FP constant",
810 # reg_req => { out => [ "fp" ] },
811 # emit => '. fmov %C, %D0',
814 # /* TODO: compare fConst attributes */
822 comment => "construct unknown floating point register",
823 reg_req => { out => [ "fp" ] },
824 emit => '. \t\t /* use %D0 as uninitialized value */',
836 state => "exc_pinned",
837 comment => "construct FP Load (double): Load(ptr, mem) = LD ptr",
838 reg_req => { in => [ "!r0", "none" ], out => [ "fp", "none" ] },
839 emit => '. lfd %D0, %O(%S0)',
842 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
844 outs => [ "res", "M" ],
850 state => "exc_pinned",
851 comment => "construct FP Load (single): Load(ptr, mem) = LD ptr",
852 reg_req => { in => [ "!r0", "none" ], out => [ "fp","none" ] },
853 emit => '. lfs %D0, %O(%S0)',
856 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
858 outs => [ "res", "M" ],
863 state => "exc_pinned",
864 comment => "construct Store (double): Store(ptr, val, mem) = ST ptr,val",
865 reg_req => { in => [ "!r0", "fp", "none" ], out => [ "none" ] },
866 emit => '. stfd %S1, %O(%S0)',
869 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);
876 state => "exc_pinned",
877 comment => "construct Store (single): Store(ptr, val, mem) = ST ptr,val",
878 reg_req => { in => [ "!r0", "fp", "none" ], out => [ "none" ] },
879 emit => '. stfs %S1, %O(%S0)',
882 return (attr_a->data.constant_tarval != attr_b->data.constant_tarval);