4a94ed0460d6be4d2f26017e06e2e37fc72b051c
[mesa.git] / src / gallium / auxiliary / rtasm / rtasm_ppc.c
1 /**************************************************************************
2 *
3 * Copyright (C) 2008 Tungsten Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 **************************************************************************/
23
24 /**
25 * PPC code generation.
26 * For reference, see http://www.power.org/resources/reading/PowerISA_V2.05.pdf
27 * ABI info: http://www.cs.utsa.edu/~whaley/teach/cs6463FHPO/LEC/lec12_ho.pdf
28 *
29 * Other PPC refs:
30 * http://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
31 * http://www.ibm.com/developerworks/eserver/library/es-archguide-v2.html
32 * http://www.freescale.com/files/product/doc/MPCFPE32B.pdf
33 *
34 * \author Brian Paul
35 */
36
37
38 #include <stdio.h>
39 #include "util/u_memory.h"
40 #include "pipe/p_debug.h"
41 #include "rtasm_ppc.h"
42
43
44 void
45 ppc_init_func(struct ppc_function *p, unsigned max_inst)
46 {
47 uint i;
48
49 p->store = align_malloc(max_inst * PPC_INST_SIZE, 16);
50 p->num_inst = 0;
51 p->max_inst = max_inst;
52 p->fp_used = ~0x0;
53 p->vec_used = ~0x0;
54
55 /* only allow using gp registers 7..12 for now */
56 p->reg_used = 0x0;
57 for (i = 7; i < 13; i++)
58 p->reg_used |= (1 << i);
59 }
60
61
62 void
63 ppc_release_func(struct ppc_function *p)
64 {
65 assert(p->num_inst <= p->max_inst);
66 if (p->store != NULL) {
67 align_free(p->store);
68 }
69 p->store = NULL;
70 }
71
72
73 void (*ppc_get_func(struct ppc_function *p))(void)
74 {
75 #if 0
76 DUMP_END();
77 if (DISASSEM && p->store)
78 debug_printf("disassemble %p %p\n", p->store, p->csr);
79
80 if (p->store == p->error_overflow)
81 return (void (*)(void)) NULL;
82 else
83 #endif
84 return (void (*)(void)) p->store;
85 }
86
87
88 void
89 ppc_dump_func(const struct ppc_function *p)
90 {
91 uint i;
92 for (i = 0; i < p->num_inst; i++) {
93 debug_printf("%3u: 0x%08x\n", i, p->store[i]);
94 }
95 }
96
97
98 /**
99 * Allocate a general purpose register.
100 * \return register index or -1 if none left.
101 */
102 int
103 ppc_allocate_register(struct ppc_function *p)
104 {
105 unsigned i;
106 for (i = 0; i < PPC_NUM_REGS; i++) {
107 const uint64_t mask = 1 << i;
108 if ((p->reg_used & mask) != 0) {
109 p->reg_used &= ~mask;
110 return i;
111 }
112 }
113 return -1;
114 }
115
116
117 /**
118 * Mark the given general purpose register as "unallocated".
119 */
120 void
121 ppc_release_register(struct ppc_function *p, int reg)
122 {
123 assert(reg < PPC_NUM_REGS);
124 assert((p->reg_used & (1 << reg)) == 0);
125 p->reg_used |= (1 << reg);
126 }
127
128
129 /**
130 * Allocate a floating point register.
131 * \return register index or -1 if none left.
132 */
133 int
134 ppc_allocate_fp_register(struct ppc_function *p)
135 {
136 unsigned i;
137 for (i = 0; i < PPC_NUM_FP_REGS; i++) {
138 const uint64_t mask = 1 << i;
139 if ((p->fp_used & mask) != 0) {
140 p->fp_used &= ~mask;
141 return i;
142 }
143 }
144 return -1;
145 }
146
147
148 /**
149 * Mark the given floating point register as "unallocated".
150 */
151 void
152 ppc_release_fp_register(struct ppc_function *p, int reg)
153 {
154 assert(reg < PPC_NUM_FP_REGS);
155 assert((p->fp_used & (1 << reg)) == 0);
156 p->fp_used |= (1 << reg);
157 }
158
159
160 /**
161 * Allocate a vector register.
162 * \return register index or -1 if none left.
163 */
164 int
165 ppc_allocate_vec_register(struct ppc_function *p)
166 {
167 unsigned i;
168 for (i = 0; i < PPC_NUM_VEC_REGS; i++) {
169 const uint64_t mask = 1 << i;
170 if ((p->vec_used & mask) != 0) {
171 p->vec_used &= ~mask;
172 return i;
173 }
174 }
175 return -1;
176 }
177
178
179 /**
180 * Mark the given vector register as "unallocated".
181 */
182 void
183 ppc_release_vec_register(struct ppc_function *p, int reg)
184 {
185 assert(reg < PPC_NUM_VEC_REGS);
186 assert((p->vec_used & (1 << reg)) == 0);
187 p->vec_used |= (1 << reg);
188 }
189
190
191
192 union vx_inst {
193 uint32_t bits;
194 struct {
195 unsigned op:6;
196 unsigned vD:5;
197 unsigned vA:5;
198 unsigned vB:5;
199 unsigned op2:11;
200 } inst;
201 };
202
203 static inline void
204 emit_vx(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB)
205 {
206 union vx_inst inst;
207 inst.inst.op = 4;
208 inst.inst.vD = vD;
209 inst.inst.vA = vA;
210 inst.inst.vB = vB;
211 inst.inst.op2 = op2;
212 p->store[p->num_inst++] = inst.bits;
213 assert(p->num_inst <= p->max_inst);
214 };
215
216
217 union vxr_inst {
218 uint32_t bits;
219 struct {
220 unsigned op:6;
221 unsigned vD:5;
222 unsigned vA:5;
223 unsigned vB:5;
224 unsigned rC:1;
225 unsigned op2:10;
226 } inst;
227 };
228
229 static inline void
230 emit_vxr(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB)
231 {
232 union vxr_inst inst;
233 inst.inst.op = 4;
234 inst.inst.vD = vD;
235 inst.inst.vA = vA;
236 inst.inst.vB = vB;
237 inst.inst.rC = 0;
238 inst.inst.op2 = op2;
239 p->store[p->num_inst++] = inst.bits;
240 assert(p->num_inst <= p->max_inst);
241 };
242
243
244 union va_inst {
245 uint32_t bits;
246 struct {
247 unsigned op:6;
248 unsigned vD:5;
249 unsigned vA:5;
250 unsigned vB:5;
251 unsigned vC:5;
252 unsigned op2:6;
253 } inst;
254 };
255
256 static inline void
257 emit_va(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB, uint vC)
258 {
259 union va_inst inst;
260 inst.inst.op = 4;
261 inst.inst.vD = vD;
262 inst.inst.vA = vA;
263 inst.inst.vB = vB;
264 inst.inst.vC = vC;
265 inst.inst.op2 = op2;
266 p->store[p->num_inst++] = inst.bits;
267 assert(p->num_inst <= p->max_inst);
268 };
269
270
271 union i_inst {
272 uint32_t bits;
273 struct {
274 unsigned op:6;
275 unsigned li:24;
276 unsigned aa:1;
277 unsigned lk:1;
278 } inst;
279 };
280
281 static INLINE void
282 emit_i(struct ppc_function *p, uint op, uint li, uint aa, uint lk)
283 {
284 union i_inst inst;
285 inst.inst.op = op;
286 inst.inst.li = li;
287 inst.inst.aa = aa;
288 inst.inst.lk = lk;
289 p->store[p->num_inst++] = inst.bits;
290 assert(p->num_inst <= p->max_inst);
291 }
292
293
294 union xl_inst {
295 uint32_t bits;
296 struct {
297 unsigned op:6;
298 unsigned bo:5;
299 unsigned bi:5;
300 unsigned unused:3;
301 unsigned bh:2;
302 unsigned op2:10;
303 unsigned lk:1;
304 } inst;
305 };
306
307 static INLINE void
308 emit_xl(struct ppc_function *p, uint op, uint bo, uint bi, uint bh,
309 uint op2, uint lk)
310 {
311 union xl_inst inst;
312 inst.inst.op = op;
313 inst.inst.bo = bo;
314 inst.inst.bi = bi;
315 inst.inst.unused = 0x0;
316 inst.inst.bh = bh;
317 inst.inst.op2 = op2;
318 inst.inst.lk = lk;
319 p->store[p->num_inst++] = inst.bits;
320 assert(p->num_inst <= p->max_inst);
321 }
322
323 static INLINE void
324 dump_xl(const char *name, uint inst)
325 {
326 union xl_inst i;
327
328 i.bits = inst;
329 debug_printf("%s = 0x%08x\n", name, inst);
330 debug_printf(" op: %d 0x%x\n", i.inst.op, i.inst.op);
331 debug_printf(" bo: %d 0x%x\n", i.inst.bo, i.inst.bo);
332 debug_printf(" bi: %d 0x%x\n", i.inst.bi, i.inst.bi);
333 debug_printf(" unused: %d 0x%x\n", i.inst.unused, i.inst.unused);
334 debug_printf(" bh: %d 0x%x\n", i.inst.bh, i.inst.bh);
335 debug_printf(" op2: %d 0x%x\n", i.inst.op2, i.inst.op2);
336 debug_printf(" lk: %d 0x%x\n", i.inst.lk, i.inst.lk);
337 }
338
339
340 union x_inst {
341 uint32_t bits;
342 struct {
343 unsigned op:6;
344 unsigned vrs:5;
345 unsigned ra:5;
346 unsigned rb:5;
347 unsigned op2:10;
348 unsigned unused:1;
349 } inst;
350 };
351
352 static INLINE void
353 emit_x(struct ppc_function *p, uint op, uint vrs, uint ra, uint rb, uint op2)
354 {
355 union x_inst inst;
356 inst.inst.op = op;
357 inst.inst.vrs = vrs;
358 inst.inst.ra = ra;
359 inst.inst.rb = rb;
360 inst.inst.op2 = op2;
361 inst.inst.unused = 0x0;
362 p->store[p->num_inst++] = inst.bits;
363 assert(p->num_inst <= p->max_inst);
364 }
365
366
367 union d_inst {
368 uint32_t bits;
369 struct {
370 unsigned op:6;
371 unsigned rt:5;
372 unsigned ra:5;
373 unsigned si:16;
374 } inst;
375 };
376
377 static inline void
378 emit_d(struct ppc_function *p, uint op, uint rt, uint ra, int si)
379 {
380 union d_inst inst;
381 assert(si >= -32768);
382 assert(si <= 32767);
383 inst.inst.op = op;
384 inst.inst.rt = rt;
385 inst.inst.ra = ra;
386 inst.inst.si = (unsigned) (si & 0xffff);
387 p->store[p->num_inst++] = inst.bits;
388 assert(p->num_inst <= p->max_inst);
389 };
390
391
392 union a_inst {
393 uint32_t bits;
394 struct {
395 unsigned op:6;
396 unsigned frt:5;
397 unsigned fra:5;
398 unsigned frb:5;
399 unsigned unused:5;
400 unsigned op2:5;
401 unsigned rc:1;
402 } inst;
403 };
404
405 static inline void
406 emit_a(struct ppc_function *p, uint op, uint frt, uint fra, uint frb, uint op2,
407 uint rc)
408 {
409 union a_inst inst;
410 inst.inst.op = op;
411 inst.inst.frt = frt;
412 inst.inst.fra = fra;
413 inst.inst.frb = frb;
414 inst.inst.unused = 0x0;
415 inst.inst.op2 = op2;
416 inst.inst.rc = rc;
417 p->store[p->num_inst++] = inst.bits;
418 assert(p->num_inst <= p->max_inst);
419 };
420
421
422 union xo_inst {
423 uint32_t bits;
424 struct {
425 unsigned op:6;
426 unsigned rt:5;
427 unsigned ra:5;
428 unsigned rb:5;
429 unsigned oe:1;
430 unsigned op2:9;
431 unsigned rc:1;
432 } inst;
433 };
434
435 static INLINE void
436 emit_xo(struct ppc_function *p, uint op, uint rt, uint ra, uint rb, uint oe,
437 uint op2, uint rc)
438 {
439 union xo_inst inst;
440 inst.inst.op = op;
441 inst.inst.rt = rt;
442 inst.inst.ra = ra;
443 inst.inst.rb = rb;
444 inst.inst.oe = oe;
445 inst.inst.op2 = op2;
446 inst.inst.rc = rc;
447 p->store[p->num_inst++] = inst.bits;
448 assert(p->num_inst <= p->max_inst);
449 }
450
451
452
453
454
455 /**
456 ** float vector arithmetic
457 **/
458
459 /** vector float add */
460 void
461 ppc_vaddfp(struct ppc_function *p, uint vD, uint vA, uint vB)
462 {
463 emit_vx(p, 10, vD, vA, vB);
464 }
465
466 /** vector float substract */
467 void
468 ppc_vsubfp(struct ppc_function *p, uint vD, uint vA, uint vB)
469 {
470 emit_vx(p, 74, vD, vA, vB);
471 }
472
473 /** vector float min */
474 void
475 ppc_vminfp(struct ppc_function *p, uint vD, uint vA, uint vB)
476 {
477 emit_vx(p, 1098, vD, vA, vB);
478 }
479
480 /** vector float max */
481 void
482 ppc_vmaxfp(struct ppc_function *p, uint vD, uint vA, uint vB)
483 {
484 emit_vx(p, 1034, vD, vA, vB);
485 }
486
487 /** vector float mult add: vD = vA * vB + vC */
488 void
489 ppc_vmaddfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
490 {
491 emit_va(p, 46, vD, vA, vC, vB); /* note arg order */
492 }
493
494 /** vector float compare greater than */
495 void
496 ppc_vcmpgtfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
497 {
498 emit_vxr(p, 710, vD, vA, vB);
499 }
500
501 /** vector float compare greater than or equal to */
502 void
503 ppc_vcmpgefpx(struct ppc_function *p, uint vD, uint vA, uint vB)
504 {
505 emit_vxr(p, 454, vD, vA, vB);
506 }
507
508 /** vector float compare equal */
509 void
510 ppc_vcmpeqfpx(struct ppc_function *p, uint vD, uint vA, uint vB)
511 {
512 emit_vxr(p, 198, vD, vA, vB);
513 }
514
515 /** vector float 2^x */
516 void
517 ppc_vexptefp(struct ppc_function *p, uint vD, uint vB)
518 {
519 emit_vx(p, 394, vD, 0, vB);
520 }
521
522 /** vector float log2(x) */
523 void
524 ppc_vlogefp(struct ppc_function *p, uint vD, uint vB)
525 {
526 emit_vx(p, 458, vD, 0, vB);
527 }
528
529 /** vector float reciprocol */
530 void
531 ppc_vrefp(struct ppc_function *p, uint vD, uint vB)
532 {
533 emit_vx(p, 266, vD, 0, vB);
534 }
535
536 /** vector float reciprocol sqrt estimate */
537 void
538 ppc_vrsqrtefp(struct ppc_function *p, uint vD, uint vB)
539 {
540 emit_vx(p, 330, vD, 0, vB);
541 }
542
543 /** vector float round to negative infinity */
544 void
545 ppc_vrfim(struct ppc_function *p, uint vD, uint vB)
546 {
547 emit_vx(p, 714, vD, 0, vB);
548 }
549
550 /** vector float round to positive infinity */
551 void
552 ppc_vrfip(struct ppc_function *p, uint vD, uint vB)
553 {
554 emit_vx(p, 650, vD, 0, vB);
555 }
556
557 /** vector float round to nearest int */
558 void
559 ppc_vrfin(struct ppc_function *p, uint vD, uint vB)
560 {
561 emit_vx(p, 522, vD, 0, vB);
562 }
563
564 /** vector float round to int toward zero */
565 void
566 ppc_vrfiz(struct ppc_function *p, uint vD, uint vB)
567 {
568 emit_vx(p, 586, vD, 0, vB);
569 }
570
571 /** vector store: store vR at mem[vA+vB] */
572 void
573 ppc_stvx(struct ppc_function *p, uint vR, uint vA, uint vB)
574 {
575 emit_x(p, 31, vR, vA, vB, 231);
576 }
577
578 /** vector load: vR = mem[vA+vB] */
579 void
580 ppc_lvx(struct ppc_function *p, uint vR, uint vA, uint vB)
581 {
582 emit_x(p, 31, vR, vA, vB, 103);
583 }
584
585
586
587 /**
588 ** vector bitwise operations
589 **/
590
591 /** vector and */
592 void
593 ppc_vand(struct ppc_function *p, uint vD, uint vA, uint vB)
594 {
595 emit_vx(p, 1028, vD, vA, vB);
596 }
597
598 /** vector and complement */
599 void
600 ppc_vandc(struct ppc_function *p, uint vD, uint vA, uint vB)
601 {
602 emit_vx(p, 1092, vD, vA, vB);
603 }
604
605 /** vector or */
606 void
607 ppc_vor(struct ppc_function *p, uint vD, uint vA, uint vB)
608 {
609 emit_vx(p, 1156, vD, vA, vB);
610 }
611
612 /** vector nor */
613 void
614 ppc_vnor(struct ppc_function *p, uint vD, uint vA, uint vB)
615 {
616 emit_vx(p, 1284, vD, vA, vB);
617 }
618
619 /** vector xor */
620 void
621 ppc_vxor(struct ppc_function *p, uint vD, uint vA, uint vB)
622 {
623 emit_vx(p, 1220, vD, vA, vB);
624 }
625
626 /** Pseudo-instruction: vector move */
627 void
628 ppc_vecmove(struct ppc_function *p, uint vD, uint vA)
629 {
630 ppc_vor(p, vD, vA, vA);
631 }
632
633
634
635 /**
636 ** Vector shuffle / select / splat / etc
637 **/
638
639 /** vector permute */
640 void
641 ppc_vperm(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
642 {
643 emit_va(p, 43, vD, vA, vB, vC);
644 }
645
646 /** vector select */
647 void
648 ppc_vsel(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC)
649 {
650 emit_va(p, 42, vD, vA, vB, vC);
651 }
652
653 /** vector splat byte */
654 void
655 ppc_vspltb(struct ppc_function *p, uint vD, uint vB, uint imm)
656 {
657 emit_vx(p, 42, vD, imm, vB);
658 }
659
660 /** vector splat half word */
661 void
662 ppc_vsplthw(struct ppc_function *p, uint vD, uint vB, uint imm)
663 {
664 emit_vx(p, 588, vD, imm, vB);
665 }
666
667 /** vector splat word */
668 void
669 ppc_vspltw(struct ppc_function *p, uint vD, uint vB, uint imm)
670 {
671 emit_vx(p, 652, vD, imm, vB);
672 }
673
674 /** vector splat signed immediate word */
675 void
676 ppc_vspltisw(struct ppc_function *p, uint vD, int imm)
677 {
678 assert(imm >= -16);
679 assert(imm < 15);
680 emit_vx(p, 908, vD, imm, 0);
681 }
682
683 /** vector shift left word: vD[word] = vA[word] << (vB[word] & 0x1f) */
684 void
685 ppc_vslw(struct ppc_function *p, uint vD, uint vA, uint vB)
686 {
687 emit_vx(p, 388, vD, vA, vB);
688 }
689
690
691
692
693 /**
694 ** integer arithmetic
695 **/
696
697 /** rt = ra + imm */
698 void
699 ppc_addi(struct ppc_function *p, uint rt, uint ra, int imm)
700 {
701 emit_d(p, 14, rt, ra, imm);
702 }
703
704 /** rt = ra + (imm << 16) */
705 void
706 ppc_addis(struct ppc_function *p, uint rt, uint ra, int imm)
707 {
708 emit_d(p, 15, rt, ra, imm);
709 }
710
711 /** rt = ra + rb */
712 void
713 ppc_add(struct ppc_function *p, uint rt, uint ra, uint rb)
714 {
715 emit_xo(p, 31, rt, ra, rb, 0, 266, 0);
716 }
717
718 /** rt = ra AND ra */
719 void
720 ppc_and(struct ppc_function *p, uint rt, uint ra, uint rb)
721 {
722 emit_x(p, 31, ra, rt, rb, 28); /* note argument order */
723 }
724
725 /** rt = ra AND imm */
726 void
727 ppc_andi(struct ppc_function *p, uint rt, uint ra, int imm)
728 {
729 emit_d(p, 28, ra, rt, imm); /* note argument order */
730 }
731
732 /** rt = ra OR ra */
733 void
734 ppc_or(struct ppc_function *p, uint rt, uint ra, uint rb)
735 {
736 emit_x(p, 31, ra, rt, rb, 444); /* note argument order */
737 }
738
739 /** rt = ra OR imm */
740 void
741 ppc_ori(struct ppc_function *p, uint rt, uint ra, int imm)
742 {
743 emit_d(p, 24, ra, rt, imm); /* note argument order */
744 }
745
746 /** rt = ra XOR ra */
747 void
748 ppc_xor(struct ppc_function *p, uint rt, uint ra, uint rb)
749 {
750 emit_x(p, 31, ra, rt, rb, 316); /* note argument order */
751 }
752
753 /** rt = ra XOR imm */
754 void
755 ppc_xori(struct ppc_function *p, uint rt, uint ra, int imm)
756 {
757 emit_d(p, 26, ra, rt, imm); /* note argument order */
758 }
759
760 /** pseudo instruction: move: rt = ra */
761 void
762 ppc_mr(struct ppc_function *p, uint rt, uint ra)
763 {
764 ppc_or(p, rt, ra, ra);
765 }
766
767 /** pseudo instruction: load immediate: rt = imm */
768 void
769 ppc_li(struct ppc_function *p, uint rt, int imm)
770 {
771 ppc_addi(p, rt, 0, imm);
772 }
773
774 /** rt = imm << 16 */
775 void
776 ppc_lis(struct ppc_function *p, uint rt, int imm)
777 {
778 ppc_addis(p, rt, 0, imm);
779 }
780
781 /** rt = imm */
782 void
783 ppc_load_int(struct ppc_function *p, uint rt, int imm)
784 {
785 ppc_lis(p, rt, (imm >> 16)); /* rt = imm >> 16 */
786 ppc_ori(p, rt, rt, (imm & 0xffff)); /* rt = rt | (imm & 0xffff) */
787 }
788
789
790
791
792 /**
793 ** integer load/store
794 **/
795
796 /** store rs at memory[(ra)+d],
797 * then update ra = (ra)+d
798 */
799 void
800 ppc_stwu(struct ppc_function *p, uint rs, uint ra, int d)
801 {
802 emit_d(p, 37, rs, ra, d);
803 }
804
805 /** store rs at memory[(ra)+d] */
806 void
807 ppc_stw(struct ppc_function *p, uint rs, uint ra, int d)
808 {
809 emit_d(p, 36, rs, ra, d);
810 }
811
812 /** Load rt = mem[(ra)+d]; then zero set high 32 bits to zero. */
813 void
814 ppc_lwz(struct ppc_function *p, uint rt, uint ra, int d)
815 {
816 emit_d(p, 32, rt, ra, d);
817 }
818
819
820
821 /**
822 ** Float (non-vector) arithmetic
823 **/
824
825 /** add: frt = fra + frb */
826 void
827 ppc_fadd(struct ppc_function *p, uint frt, uint fra, uint frb)
828 {
829 emit_a(p, 63, frt, fra, frb, 21, 0);
830 }
831
832 /** sub: frt = fra - frb */
833 void
834 ppc_fsub(struct ppc_function *p, uint frt, uint fra, uint frb)
835 {
836 emit_a(p, 63, frt, fra, frb, 20, 0);
837 }
838
839 /** convert to int: rt = (int) ra */
840 void
841 ppc_fctiwz(struct ppc_function *p, uint rt, uint fra)
842 {
843 emit_x(p, 63, rt, 0, fra, 15);
844 }
845
846 /** store frs at mem[(ra)+offset] */
847 void
848 ppc_stfs(struct ppc_function *p, uint frs, uint ra, int offset)
849 {
850 emit_d(p, 52, frs, ra, offset);
851 }
852
853 /** store frs at mem[(ra)+(rb)] */
854 void
855 ppc_stfiwx(struct ppc_function *p, uint frs, uint ra, uint rb)
856 {
857 emit_x(p, 31, frs, ra, rb, 983);
858 }
859
860 /** load frt = mem[(ra)+offset] */
861 void
862 ppc_lfs(struct ppc_function *p, uint frt, uint ra, int offset)
863 {
864 emit_d(p, 48, frt, ra, offset);
865 }
866
867
868
869
870
871 /**
872 ** branch instructions
873 **/
874
875 /** BLR: Branch to link register (p. 35) */
876 void
877 ppc_blr(struct ppc_function *p)
878 {
879 emit_i(p, 18, 0, 0, 1);
880 }
881
882 /** Branch Conditional to Link Register (p. 36) */
883 void
884 ppc_bclr(struct ppc_function *p, uint condOp, uint branchHint, uint condReg)
885 {
886 emit_xl(p, 19, condOp, condReg, branchHint, 16, 0);
887 }
888
889 /** Pseudo instruction: return from subroutine */
890 void
891 ppc_return(struct ppc_function *p)
892 {
893 ppc_bclr(p, BRANCH_COND_ALWAYS, BRANCH_HINT_SUB_RETURN, 0);
894 }