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