4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* VIS floating point instruction simulator for Sparc FPU simulator. */
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/fpu/fpusystm.h>
31 #include <sys/fpu/fpu_simulator.h>
32 #include <sys/vis_simulator.h>
33 #include <sys/fpu/globals.h>
34 #include <sys/privregs.h>
35 #include <sys/sun4asi.h>
36 #include <sys/machasi.h>
37 #include <sys/debug.h>
38 #include <sys/cpu_module.h>
39 #include <sys/systm.h>
41 #define FPU_REG_FIELD uint32_reg /* Coordinate with FPU_REGS_TYPE. */
42 #define FPU_DREG_FIELD uint64_reg /* Coordinate with FPU_DREGS_TYPE. */
43 #define FPU_FSR_FIELD uint64_reg /* Coordinate with V9_FPU_FSR_TYPE. */
45 extern uint_t
get_subcc_ccr(uint64_t, uint64_t);
47 static enum ftt_type
vis_array(fp_simd_type
*, vis_inst_type
, struct regs
*,
49 static enum ftt_type
vis_alignaddr(fp_simd_type
*, vis_inst_type
,
50 struct regs
*, void *, kfpu_t
*);
51 static enum ftt_type
vis_edge(fp_simd_type
*, vis_inst_type
, struct regs
*,
53 static enum ftt_type
vis_faligndata(fp_simd_type
*, fp_inst_type
,
55 static enum ftt_type
vis_bmask(fp_simd_type
*, vis_inst_type
, struct regs
*,
57 static enum ftt_type
vis_bshuffle(fp_simd_type
*, fp_inst_type
,
59 static enum ftt_type
vis_siam(fp_simd_type
*, vis_inst_type
, kfpu_t
*);
60 static enum ftt_type
vis_fcmp(fp_simd_type
*, vis_inst_type
, struct regs
*,
62 static enum ftt_type
vis_fmul(fp_simd_type
*, vis_inst_type
);
63 static enum ftt_type
vis_fpixel(fp_simd_type
*, vis_inst_type
, kfpu_t
*);
64 static enum ftt_type
vis_fpaddsub(fp_simd_type
*, vis_inst_type
);
65 static enum ftt_type
vis_pdist(fp_simd_type
*, fp_inst_type
, struct regs
*,
67 static enum ftt_type
vis_prtl_fst(fp_simd_type
*, vis_inst_type
, struct regs
*,
69 static enum ftt_type
vis_short_fls(fp_simd_type
*, vis_inst_type
,
70 struct regs
*, void *, uint_t
);
71 static enum ftt_type
vis_blk_fldst(fp_simd_type
*, vis_inst_type
,
72 struct regs
*, void *, uint_t
);
75 * Simulator for VIS instructions with op3 == 0x36 that get fp_disabled
80 fp_simd_type
*pfpsd
, /* FPU simulator data. */
81 fp_inst_type pinst
, /* FPU instruction to simulate. */
82 struct regs
*pregs
, /* Pointer to PCB image of registers. */
83 void *prw
, /* Pointer to locals and ins. */
84 kfpu_t
*fp
) /* Need to fp to access gsr reg */
86 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
88 uint64_t lus1
, lus2
, lusr
;
89 enum ftt_type ftt
= ftt_none
;
95 ASSERT(USERMODE(pregs
->r_tstate
));
100 if ((f
.inst
.opf
& 1) == 0) { /* double precision */
101 if ((nrs1
& 1) == 1) /* fix register encoding */
102 nrs1
= (nrs1
& 0x1e) | 0x20;
104 nrs2
= (nrs2
& 0x1e) | 0x20;
106 nrd
= (nrd
& 0x1e) | 0x20;
109 switch (f
.inst
.opf
) {
110 /* these instr's do not use fp regs */
123 ftt
= vis_edge(pfpsd
, f
.inst
, pregs
, prw
);
128 ftt
= vis_array(pfpsd
, f
.inst
, pregs
, prw
);
132 ftt
= vis_alignaddr(pfpsd
, f
.inst
, pregs
, prw
, fp
);
135 ftt
= vis_bmask(pfpsd
, f
.inst
, pregs
, prw
, fp
);
145 ftt
= vis_fcmp(pfpsd
, f
.inst
, pregs
, prw
);
154 ftt
= vis_fmul(pfpsd
, f
.inst
);
161 ftt
= vis_fpixel(pfpsd
, f
.inst
, fp
);
165 ftt
= vis_pdist(pfpsd
, pinst
, pregs
, prw
, f
.inst
.opf
);
168 ftt
= vis_faligndata(pfpsd
, pinst
, fp
);
171 ftt
= vis_bshuffle(pfpsd
, pinst
, fp
);
181 ftt
= vis_fpaddsub(pfpsd
, f
.inst
);
185 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
189 _fp_pack_word(pfpsd
, &usr
, nrd
);
192 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
193 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
194 lusr
= ~(lus1
| lus2
);
195 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
198 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
199 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
201 _fp_pack_word(pfpsd
, &usr
, nrd
);
204 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
205 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
206 lusr
= (lus1
& ~lus2
);
207 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
210 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
211 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
213 _fp_pack_word(pfpsd
, &usr
, nrd
);
216 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
218 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
221 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
223 _fp_pack_word(pfpsd
, &usr
, nrd
);
226 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
227 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
228 lusr
= (~lus1
& lus2
);
229 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
232 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
233 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
235 _fp_pack_word(pfpsd
, &usr
, nrd
);
238 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
240 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
243 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
245 _fp_pack_word(pfpsd
, &usr
, nrd
);
248 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
249 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
250 lusr
= (lus1
^ lus2
);
251 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
254 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
255 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
257 _fp_pack_word(pfpsd
, &usr
, nrd
);
260 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
261 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
262 lusr
= ~(lus1
& lus2
);
263 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
266 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
267 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
269 _fp_pack_word(pfpsd
, &usr
, nrd
);
272 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
273 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
274 lusr
= (lus1
& lus2
);
275 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
278 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
279 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
281 _fp_pack_word(pfpsd
, &usr
, nrd
);
284 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
285 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
286 lusr
= ~(lus1
^ lus2
);
287 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
290 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
291 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
293 _fp_pack_word(pfpsd
, &usr
, nrd
);
296 _fp_unpack_extword(pfpsd
, &lusr
, nrs1
);
297 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
300 _fp_unpack_word(pfpsd
, &usr
, nrs1
);
301 _fp_pack_word(pfpsd
, &usr
, nrd
);
304 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
305 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
306 lusr
= (lus1
| ~lus2
);
307 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
310 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
311 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
313 _fp_pack_word(pfpsd
, &usr
, nrd
);
316 _fp_unpack_extword(pfpsd
, &lusr
, nrs2
);
317 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
320 _fp_unpack_word(pfpsd
, &usr
, nrs2
);
321 _fp_pack_word(pfpsd
, &usr
, nrd
);
324 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
325 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
326 lusr
= (~lus1
| lus2
);
327 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
330 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
331 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
333 _fp_pack_word(pfpsd
, &usr
, nrd
);
336 _fp_unpack_extword(pfpsd
, &lus1
, nrs1
);
337 _fp_unpack_extword(pfpsd
, &lus2
, nrs2
);
338 lusr
= (lus1
| lus2
);
339 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
342 _fp_unpack_word(pfpsd
, &us1
, nrs1
);
343 _fp_unpack_word(pfpsd
, &us2
, nrs2
);
345 _fp_pack_word(pfpsd
, &usr
, nrd
);
348 lusr
= 0xffffffffffffffff;
349 _fp_pack_extword(pfpsd
, &lusr
, nrd
);
353 _fp_pack_word(pfpsd
, &usr
, nrd
);
356 ftt
= vis_siam(pfpsd
, f
.inst
, fp
);
359 return (ftt_unimplemented
);
362 pregs
->r_pc
= pregs
->r_npc
; /* Do not retry emulated instruction. */
368 * Simulator for edge instructions
372 fp_simd_type
*pfpsd
, /* FPU simulator data. */
373 vis_inst_type inst
, /* FPU instruction to simulate. */
374 struct regs
*pregs
, /* Pointer to PCB image of registers. */
375 void *prw
) /* Pointer to locals and ins. */
378 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
380 uint64_t addrl
, addrr
, mask
;
381 uint64_t ah61l
, ah61r
; /* Higher 61 bits of address */
382 int al3l
, al3r
; /* Lower 3 bits of address */
389 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &addrl
);
392 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &addrr
);
396 /* Test PSTATE.AM to determine 32-bit vs 64-bit addressing */
397 if ((pregs
->r_tstate
& TSTATE_AM
) != 0) {
398 ah61l
= addrl
& 0xfffffff8;
399 ah61r
= addrr
& 0xfffffff8;
401 ah61l
= addrl
& ~0x7;
402 ah61r
= addrr
& ~0x7;
415 if (inst
.opf
== edge8
) {
416 VISINFO_KSTAT(vis_edge8
);
418 VISINFO_KSTAT(vis_edge8n
);
421 if (ah61l
== ah61r
) {
423 mask
&= (0xff << (0x7 - al3r
)) & 0xff;
428 if (inst
.opf
== edge8l
) {
429 VISINFO_KSTAT(vis_edge8l
);
431 VISINFO_KSTAT(vis_edge8ln
);
433 mask
= (0xff << al3l
) & 0xff;
434 if (ah61l
== ah61r
) {
436 mask
&= 0xff >> (0x7 - al3r
);
450 if (inst
.opf
== edge16
) {
451 VISINFO_KSTAT(vis_edge16
);
454 VISINFO_KSTAT(vis_edge16n
);
457 if (ah61l
== ah61r
) {
460 mask
&= (0xf << (0x3 - al3r
)) & 0xf;
465 if (inst
.opf
== edge16l
) {
466 VISINFO_KSTAT(vis_edge16l
);
469 VISINFO_KSTAT(vis_edge16ln
);
472 mask
= (0xf << al3l
) & 0xf;
473 if (ah61l
== ah61r
) {
476 mask
&= 0xf >> (0x3 - al3r
);
491 if (inst
.opf
== edge32
) {
492 VISINFO_KSTAT(vis_edge32
);
495 VISINFO_KSTAT(vis_edge32n
);
498 if (ah61l
== ah61r
) {
501 mask
&= (0x3 << (0x1 - al3r
)) & 0x3;
506 if (inst
.opf
== edge32l
) {
507 VISINFO_KSTAT(vis_edge32l
);
510 VISINFO_KSTAT(vis_edge32ln
);
512 mask
= (0x3 << al3l
) & 0x3;
513 if (ah61l
== ah61r
) {
516 mask
&= 0x3 >> (0x1 - al3r
);
523 ftt
= write_iureg(pfpsd
, nrd
, pregs
, prw
, &mask
);
533 /* Update flags per SUBcc outcome */
534 pregs
->r_tstate
&= ~((uint64_t)TSTATE_CCR_MASK
535 << TSTATE_CCR_SHIFT
);
536 ccr
= get_subcc_ccr(addrl
, addrr
); /* get subcc cond. codes */
537 pregs
->r_tstate
|= ((uint64_t)ccr
<< TSTATE_CCR_SHIFT
);
545 * Simulator for three dimentional array addressing instructions.
549 fp_simd_type
*pfpsd
, /* FPU simulator data. */
550 vis_inst_type inst
, /* FPU instruction to simulate. */
551 struct regs
*pregs
, /* Pointer to PCB image of registers. */
552 void *prw
) /* Pointer to locals and ins. */
555 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
557 uint64_t laddr
, bsize
, baddr
;
565 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &laddr
);
568 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &bsize
);
575 nbit
= (1 << bsize
) - 1; /* Number of bits for XY<6+n-1:6> */
576 oy
= 17 + bsize
; /* Offset of Y<6+n-1:6> */
577 oz
= 17 + 2 * bsize
; /* Offset of Z<8:5> */
580 baddr
|= (laddr
>> (11 - 0)) & (0x03 << 0); /* X_integer<1:0> */
581 baddr
|= (laddr
>> (33 - 2)) & (0x03 << 2); /* Y_integer<1:0> */
582 baddr
|= (laddr
>> (55 - 4)) & (0x01 << 4); /* Z_integer<0> */
583 baddr
|= (laddr
>> (13 - 5)) & (0x0f << 5); /* X_integer<5:2> */
584 baddr
|= (laddr
>> (35 - 9)) & (0x0f << 9); /* Y_integer<5:2> */
585 baddr
|= (laddr
>> (56 - 13)) & (0x0f << 13); /* Z_integer<4:1> */
586 baddr
|= (laddr
>> (17 - 17)) & (nbit
<< 17); /* X_integer<6+n-1:6> */
587 baddr
|= (laddr
>> (39 - oy
)) & (nbit
<< oy
); /* Y_integer<6+n-1:6> */
588 baddr
|= (laddr
>> (60 - oz
)) & (0x0f << oz
); /* Z_integer<8:5> */
592 VISINFO_KSTAT(vis_array8
);
595 VISINFO_KSTAT(vis_array16
);
599 VISINFO_KSTAT(vis_array32
);
604 ftt
= write_iureg(pfpsd
, nrd
, pregs
, prw
, &baddr
);
610 * Simulator for alignaddr and alignaddrl instructions.
614 fp_simd_type
*pfpsd
, /* FPU simulator data. */
615 vis_inst_type inst
, /* FPU instruction to simulate. */
616 struct regs
*pregs
, /* Pointer to PCB image of registers. */
617 void *prw
, /* Pointer to locals and ins. */
618 kfpu_t
*fp
) /* Need to fp to access gsr reg */
620 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
622 uint64_t ea
, tea
, g
, r
;
629 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &ea
);
632 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &tea
);
636 r
= ea
& ~0x7; /* zero least 3 significant bits */
637 ftt
= write_iureg(pfpsd
, nrd
, pregs
, prw
, &r
);
640 g
= pfpsd
->fp_current_read_gsr(fp
);
641 g
&= ~(GSR_ALIGN_MASK
); /* zero the align offset */
643 if (inst
.opf
== alignaddrl
) {
644 s
= (short)(~r
); /* 2's complement for alignaddrl */
646 r
= (uint64_t)((s
+ 1) & 0x7);
648 r
= (uint64_t)(s
& 0x7);
650 g
|= (r
<< GSR_ALIGN_SHIFT
) & GSR_ALIGN_MASK
;
651 pfpsd
->fp_current_write_gsr(g
, fp
);
657 * Simulator for bmask instruction.
661 fp_simd_type
*pfpsd
, /* FPU simulator data. */
662 vis_inst_type inst
, /* FPU instruction to simulate. */
663 struct regs
*pregs
, /* Pointer to PCB image of registers. */
664 void *prw
, /* Pointer to locals and ins. */
665 kfpu_t
*fp
) /* Need to fp to access gsr reg */
667 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
671 VISINFO_KSTAT(vis_bmask
);
676 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &ea
);
679 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &tea
);
683 ftt
= write_iureg(pfpsd
, nrd
, pregs
, prw
, &ea
);
685 g
= pfpsd
->fp_current_read_gsr(fp
);
686 g
&= ~(GSR_MASK_MASK
); /* zero the mask offset */
688 /* Put the least significant 32 bits of ea in GSR.mask */
689 g
|= (ea
<< GSR_MASK_SHIFT
) & GSR_MASK_MASK
;
690 pfpsd
->fp_current_write_gsr(g
, fp
);
695 * Simulator for fp[add|sub]* instruction.
699 fp_simd_type
*pfpsd
, /* FPU simulator data. */
700 vis_inst_type inst
) /* FPU instruction to simulate. */
702 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
717 if ((inst
.opf
& 1) == 0) { /* double precision */
718 if ((nrs1
& 1) == 1) /* fix register encoding */
719 nrs1
= (nrs1
& 0x1e) | 0x20;
721 nrs2
= (nrs2
& 0x1e) | 0x20;
723 nrd
= (nrd
& 0x1e) | 0x20;
727 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
728 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
729 for (i
= 0; i
<= 3; i
++) {
730 lrd
.s
[i
] = lrs1
.s
[i
] + lrs2
.s
[i
];
732 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
735 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
736 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
737 for (i
= 0; i
<= 1; i
++) {
738 krd
.s
[i
] = krs1
.s
[i
] + krs2
.s
[i
];
740 _fp_pack_word(pfpsd
, &krd
.i
, nrd
);
743 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
744 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
745 for (i
= 0; i
<= 1; i
++) {
746 lrd
.i
[i
] = lrs1
.i
[i
] + lrs2
.i
[i
];
748 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
751 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
752 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
753 krd
.i
= krs1
.i
+ krs2
.i
;
754 _fp_pack_word(pfpsd
, &krd
.i
, nrd
);
757 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
758 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
759 for (i
= 0; i
<= 3; i
++) {
760 lrd
.s
[i
] = lrs1
.s
[i
] - lrs2
.s
[i
];
762 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
765 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
766 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
767 for (i
= 0; i
<= 1; i
++) {
768 krd
.s
[i
] = krs1
.s
[i
] - krs2
.s
[i
];
770 _fp_pack_word(pfpsd
, &krd
.i
, nrd
);
773 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
774 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
775 for (i
= 0; i
<= 1; i
++) {
776 lrd
.i
[i
] = lrs1
.i
[i
] - lrs2
.i
[i
];
778 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
781 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
782 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
783 krd
.i
= krs1
.i
- krs2
.i
;
784 _fp_pack_word(pfpsd
, &krd
.i
, nrd
);
791 * Simulator for fcmp* instruction.
795 fp_simd_type
*pfpsd
, /* FPU simulator data. */
796 vis_inst_type inst
, /* FPU instruction to simulate. */
797 struct regs
*pregs
, /* Pointer to PCB image of registers. */
798 void *prw
) /* Pointer to locals and ins. */
800 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
814 if ((nrs1
& 1) == 1) /* fix register encoding */
815 nrs1
= (nrs1
& 0x1e) | 0x20;
817 nrs2
= (nrs2
& 0x1e) | 0x20;
819 _fp_unpack_extword(pfpsd
, &krs1
.ll
, nrs1
);
820 _fp_unpack_extword(pfpsd
, &krs2
.ll
, nrs2
);
823 VISINFO_KSTAT(vis_fcmple16
);
824 for (i
= 0; i
<= 3; i
++) {
825 sr1
= (short)krs1
.s
[i
];
826 sr2
= (short)krs2
.s
[i
];
828 krd
.ll
+= (0x8 >> i
);
832 VISINFO_KSTAT(vis_fcmpne16
);
833 for (i
= 0; i
<= 3; i
++) {
834 sr1
= (short)krs1
.s
[i
];
835 sr2
= (short)krs2
.s
[i
];
837 krd
.ll
+= (0x8 >> i
);
841 VISINFO_KSTAT(vis_fcmpgt16
);
842 for (i
= 0; i
<= 3; i
++) {
843 sr1
= (short)krs1
.s
[i
];
844 sr2
= (short)krs2
.s
[i
];
846 krd
.ll
+= (0x8 >> i
);
850 VISINFO_KSTAT(vis_fcmpeq16
);
851 for (i
= 0; i
<= 3; i
++) {
852 sr1
= (short)krs1
.s
[i
];
853 sr2
= (short)krs2
.s
[i
];
855 krd
.ll
+= (0x8 >> i
);
859 VISINFO_KSTAT(vis_fcmple32
);
860 for (i
= 0; i
<= 1; i
++) {
861 ir1
= (int)krs1
.i
[i
];
862 ir2
= (int)krs2
.i
[i
];
864 krd
.ll
+= (0x2 >> i
);
868 VISINFO_KSTAT(vis_fcmpne32
);
869 for (i
= 0; i
<= 1; i
++) {
870 ir1
= (int)krs1
.i
[i
];
871 ir2
= (int)krs2
.i
[i
];
873 krd
.ll
+= (0x2 >> i
);
877 VISINFO_KSTAT(vis_fcmpgt32
);
878 for (i
= 0; i
<= 1; i
++) {
879 ir1
= (int)krs1
.i
[i
];
880 ir2
= (int)krs2
.i
[i
];
882 krd
.ll
+= (0x2 >> i
);
886 VISINFO_KSTAT(vis_fcmpeq32
);
887 for (i
= 0; i
<= 1; i
++) {
888 ir1
= (int)krs1
.i
[i
];
889 ir2
= (int)krs2
.i
[i
];
891 krd
.ll
+= (0x2 >> i
);
895 ftt
= write_iureg(pfpsd
, nrd
, pregs
, prw
, &krd
.ll
);
900 * Simulator for fmul* instruction.
904 fp_simd_type
*pfpsd
, /* FPU simulator data. */
905 vis_inst_type inst
) /* FPU instruction to simulate. */
907 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
927 if ((inst
.opf
& 1) == 0) { /* double precision */
928 if ((nrd
& 1) == 1) /* fix register encoding */
929 nrd
= (nrd
& 0x1e) | 0x20;
934 VISINFO_KSTAT(vis_fmul8x16
);
935 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
937 nrs2
= (nrs2
& 0x1e) | 0x20;
938 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
939 for (i
= 0; i
<= 3; i
++) {
940 us1
= (ushort_t
)krs1
.c
[i
];
941 s2
= (short)lrs2
.s
[i
];
943 sres
= (short)((kres
.c
[1] << 8) | kres
.c
[2]);
944 if (kres
.c
[3] >= 0x80)
948 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
951 VISINFO_KSTAT(vis_fmul8x16au
);
952 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
953 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
954 for (i
= 0; i
<= 3; i
++) {
955 us1
= (ushort_t
)krs1
.c
[i
];
956 s2
= (short)krs2
.s
[0];
958 sres
= (short)((kres
.c
[1] << 8) | kres
.c
[2]);
959 if (kres
.c
[3] >= 0x80)
963 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
966 VISINFO_KSTAT(vis_fmul8x16al
);
967 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
968 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
969 for (i
= 0; i
<= 3; i
++) {
970 us1
= (ushort_t
)krs1
.c
[i
];
971 s2
= (short)krs2
.s
[1];
973 sres
= (short)((kres
.c
[1] << 8) | kres
.c
[2]);
974 if (kres
.c
[3] >= 0x80)
978 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
981 VISINFO_KSTAT(vis_fmul8sux16
);
982 if ((nrs1
& 1) == 1) /* fix register encoding */
983 nrs1
= (nrs1
& 0x1e) | 0x20;
984 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
986 nrs2
= (nrs2
& 0x1e) | 0x20;
987 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
988 for (i
= 0; i
<= 3; i
++) {
990 s1
= (short)c1
; /* keeps the sign alive */
991 s2
= (short)lrs2
.s
[i
];
993 sres
= (short)((kres
.c
[1] << 8) | kres
.c
[2]);
994 if (kres
.c
[3] >= 0x80)
997 lrd
.s
[i
] = (sres
& 0xFFFF);
1001 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1004 VISINFO_KSTAT(vis_fmul8ulx16
);
1005 if ((nrs1
& 1) == 1) /* fix register encoding */
1006 nrs1
= (nrs1
& 0x1e) | 0x20;
1007 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
1008 if ((nrs2
& 1) == 1)
1009 nrs2
= (nrs2
& 0x1e) | 0x20;
1010 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
1011 for (i
= 0; i
<= 3; i
++) {
1012 us1
= (ushort_t
)lrs1
.c
[(i
*2)+1];
1013 s2
= (short)lrs2
.s
[i
];
1015 sres
= (short)kres
.s
[0];
1016 if (kres
.s
[1] >= 0x8000)
1020 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1023 VISINFO_KSTAT(vis_fmuld8sux16
);
1024 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
1025 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
1026 for (i
= 0; i
<= 1; i
++) {
1028 s1
= (short)c1
; /* keeps the sign alive */
1029 s2
= (short)krs2
.s
[i
];
1031 lrd
.i
[i
] = kres
.i
<< 8;
1033 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1036 VISINFO_KSTAT(vis_fmuld8ulx16
);
1037 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
1038 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
1039 for (i
= 0; i
<= 1; i
++) {
1040 us1
= (ushort_t
)krs1
.c
[(i
*2)+1];
1041 s2
= (short)krs2
.s
[i
];
1042 lrd
.i
[i
] = us1
* s2
;
1044 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1051 * Simulator for fpixel formatting instructions.
1053 static enum ftt_type
1055 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1056 vis_inst_type inst
, /* FPU instruction to simulate. */
1057 kfpu_t
*fp
) /* Need to fp to access gsr reg */
1059 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
1080 if ((inst
.opf
!= fpack16
) && (inst
.opf
!= fpackfix
)) {
1081 if ((nrd
& 1) == 1) /* fix register encoding */
1082 nrd
= (nrd
& 0x1e) | 0x20;
1087 VISINFO_KSTAT(vis_fpack16
);
1088 if ((nrs2
& 1) == 1) /* fix register encoding */
1089 nrs2
= (nrs2
& 0x1e) | 0x20;
1090 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
1091 r
= pfpsd
->fp_current_read_gsr(fp
);
1092 /* fpack16 ignores GSR.scale msb */
1093 sf
= (int)(GSR_SCALE(r
) & 0xf);
1094 for (i
= 0; i
<= 3; i
++) {
1095 s
= (short)lrs2
.s
[i
]; /* preserve the sign */
1100 } else if (k
> 255) {
1107 _fp_pack_word(pfpsd
, &krd
.i
, nrd
);
1110 VISINFO_KSTAT(vis_fpack32
);
1111 if ((nrs1
& 1) == 1) /* fix register encoding */
1112 nrs1
= (nrs1
& 0x1e) | 0x20;
1113 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
1114 if ((nrs2
& 1) == 1)
1115 nrs2
= (nrs2
& 0x1e) | 0x20;
1116 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
1118 r
= pfpsd
->fp_current_read_gsr(fp
);
1119 sf
= (int)GSR_SCALE(r
);
1120 lrd
.ll
= lrs1
.ll
<< 8;
1121 for (i
= 0, k
= 3; i
<= 1; i
++, k
+= 4) {
1122 j
= (int)lrs2
.i
[i
]; /* preserve the sign */
1123 l
= ((int64_t)j
<< sf
);
1127 } else if (m
> 255) {
1134 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1137 VISINFO_KSTAT(vis_fpackfix
);
1138 if ((nrs2
& 1) == 1)
1139 nrs2
= (nrs2
& 0x1e) | 0x20;
1140 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
1142 r
= pfpsd
->fp_current_read_gsr(fp
);
1143 sf
= (int)GSR_SCALE(r
);
1144 for (i
= 0; i
<= 1; i
++) {
1145 j
= (int)lrs2
.i
[i
]; /* preserve the sign */
1146 l
= ((int64_t)j
<< sf
);
1150 } else if (m
> 32767) {
1157 _fp_pack_word(pfpsd
, &krd
.i
, nrd
);
1160 VISINFO_KSTAT(vis_fexpand
);
1161 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
1162 for (i
= 0; i
<= 3; i
++) {
1164 lrd
.s
[i
] = (ushort_t
)(uc
<< 4);
1166 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1169 VISINFO_KSTAT(vis_fpmerge
);
1170 _fp_unpack_word(pfpsd
, &krs1
.i
, nrs1
);
1171 _fp_unpack_word(pfpsd
, &krs2
.i
, nrs2
);
1172 for (i
= 0, j
= 0; i
<= 3; i
++, j
+= 2) {
1173 lrd
.c
[j
] = krs1
.c
[i
];
1174 lrd
.c
[j
+1] = krs2
.c
[i
];
1176 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1183 * Simulator for pdist instruction.
1187 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1188 fp_inst_type pinst
, /* FPU instruction to simulate. */
1189 struct regs
*pregs
, /* Pointer to PCB image of registers. */
1190 void *prw
, /* Pointer to locals and ins. */
1191 uint_t op
) /* Opcode pdist or pdistn */
1193 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
1205 if ((nrs1
& 1) == 1) /* fix register encoding */
1206 nrs1
= (nrs1
& 0x1e) | 0x20;
1207 if ((nrs2
& 1) == 1)
1208 nrs2
= (nrs2
& 0x1e) | 0x20;
1210 nrd
= (nrd
& 0x1e) | 0x20;
1212 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
1213 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
1216 VISINFO_KSTAT(vis_pdist
);
1217 _fp_unpack_extword(pfpsd
, &lrd
.ll
, nrd
);
1220 VISINFO_KSTAT(vis_pdistn
);
1224 for (i
= 0; i
<= 7; i
++) {
1225 s
= (short)(lrs1
.c
[i
] - lrs2
.c
[i
]);
1232 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1235 (void) write_iureg(pfpsd
, nrd
, pregs
, prw
, &lrd
.ll
);
1240 * Simulator for faligndata instruction.
1242 static enum ftt_type
1244 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1245 fp_inst_type pinst
, /* FPU instruction to simulate. */
1246 kfpu_t
*fp
) /* Need to fp to access gsr reg */
1248 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
1259 if ((nrs1
& 1) == 1) /* fix register encoding */
1260 nrs1
= (nrs1
& 0x1e) | 0x20;
1261 if ((nrs2
& 1) == 1)
1262 nrs2
= (nrs2
& 0x1e) | 0x20;
1264 nrd
= (nrd
& 0x1e) | 0x20;
1266 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
1267 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
1269 r
= pfpsd
->fp_current_read_gsr(fp
);
1270 ao
= (int)GSR_ALIGN(r
);
1272 for (i
= 0, j
= ao
, k
= 0; i
<= 7; i
++)
1274 lrd
.c
[i
] = lrs1
.c
[j
++];
1276 lrd
.c
[i
] = lrs2
.c
[k
++];
1278 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1284 * Simulator for bshuffle instruction.
1286 static enum ftt_type
1288 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1289 fp_inst_type pinst
, /* FPU instruction to simulate. */
1290 kfpu_t
*fp
) /* Need to fp to access gsr reg */
1292 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
1300 VISINFO_KSTAT(vis_bshuffle
);
1304 if ((nrs1
& 1) == 1) /* fix register encoding */
1305 nrs1
= (nrs1
& 0x1e) | 0x20;
1306 if ((nrs2
& 1) == 1)
1307 nrs2
= (nrs2
& 0x1e) | 0x20;
1309 nrd
= (nrd
& 0x1e) | 0x20;
1311 _fp_unpack_extword(pfpsd
, &lrs1
.ll
, nrs1
);
1312 _fp_unpack_extword(pfpsd
, &lrs2
.ll
, nrs2
);
1314 r
= pfpsd
->fp_current_read_gsr(fp
);
1315 ao
= (int)GSR_MASK(r
);
1318 * BSHUFFLE Destination Byte Selection
1320 * 0 rs byte[GSR.mask<31..28>]
1321 * 1 rs byte[GSR.mask<27..24>]
1322 * 2 rs byte[GSR.mask<23..20>]
1323 * 3 rs byte[GSR.mask<19..16>]
1324 * 4 rs byte[GSR.mask<15..12>]
1325 * 5 rs byte[GSR.mask<11..8>]
1326 * 6 rs byte[GSR.mask<7..4>]
1327 * 7 rs byte[GSR.mask<3..0>]
1328 * P.S. rs1 is the upper half and rs2 is the lower half
1329 * Bytes in the source value are numbered from most to
1332 for (i
= 7; i
>= 0; i
--, ao
= (ao
>> 4)) {
1333 j
= ao
& 0xf; /* get byte number */
1335 lrd
.c
[i
] = lrs1
.c
[j
];
1337 lrd
.c
[i
] = lrs2
.c
[j
- 8];
1340 _fp_pack_extword(pfpsd
, &lrd
.ll
, nrd
);
1346 * Simulator for siam instruction.
1348 static enum ftt_type
1350 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1351 vis_inst_type inst
, /* FPU instruction to simulate. */
1352 kfpu_t
*fp
) /* Need to fp to access gsr reg */
1354 uint_t nrs2
; /* Register number fields. */
1358 g
= pfpsd
->fp_current_read_gsr(fp
);
1359 g
&= ~(GSR_IM_IRND_MASK
); /* zero the IM and IRND fields */
1360 r
= nrs2
& 0x7; /* get mode(3 bit) */
1361 g
|= (r
<< GSR_IRND_SHIFT
);
1362 pfpsd
->fp_current_write_gsr(g
, fp
);
1367 * Simulator for VIS loads and stores between floating-point unit and memory.
1371 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1372 fp_inst_type pinst
, /* FPU instruction to simulate. */
1373 struct regs
*pregs
, /* Pointer to PCB image of registers. */
1374 void *prw
, /* Pointer to locals and ins. */
1375 uint_t asi
) /* asi to emulate! */
1382 ASSERT(USERMODE(pregs
->r_tstate
));
1397 return (vis_prtl_fst(pfpsd
, i
.inst
, pregs
,
1407 return (vis_short_fls(pfpsd
, i
.inst
, pregs
,
1417 case ASI_BLK_COMMIT_P
:
1418 case ASI_BLK_COMMIT_S
:
1419 return (vis_blk_fldst(pfpsd
, i
.inst
, pregs
,
1422 return (ftt_unimplemented
);
1427 * Simulator for partial stores between floating-point unit and memory.
1429 static enum ftt_type
1431 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1432 vis_inst_type inst
, /* ISE instruction to simulate. */
1433 struct regs
*pregs
, /* Pointer to PCB image of registers. */
1434 void *prw
, /* Pointer to locals and ins. */
1435 uint_t asi
) /* asi to emulate! */
1437 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
1453 if ((nrd
& 1) == 1) /* fix register encoding */
1454 nrd
= (nrd
& 0x1e) | 0x20;
1457 if ((opf
& 0x100) == 0) { /* effective address = rs1 */
1458 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &ea
);
1459 if (ftt
!= ftt_none
)
1461 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &tmsk
);
1462 if (ftt
!= ftt_none
)
1466 pfpsd
->fp_trapaddr
= (caddr_t
)pregs
->r_pc
;
1467 return (ftt_unimplemented
);
1470 pfpsd
->fp_trapaddr
= (caddr_t
)ea
; /* setup bad addr in case we trap */
1471 if ((ea
& 0x3) != 0)
1472 return (ftt_alignment
); /* Require 32 bit-alignment. */
1477 ftt
= _fp_read_extword((uint64_t *)ea
, &l
.ll
, pfpsd
);
1478 if (ftt
!= ftt_none
)
1480 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1481 for (i
= 0, j
= 0x80; i
<= 7; i
++, j
>>= 1) {
1487 ftt
= _fp_write_extword((uint64_t *)ea
, res
.ll
, pfpsd
);
1488 if (ftt
!= ftt_none
)
1491 case ASI_PST8_PL
: /* little-endian */
1493 ftt
= _fp_read_extword((uint64_t *)ea
, &l
.ll
, pfpsd
);
1494 if (ftt
!= ftt_none
)
1496 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1497 for (h
= 7, i
= 0, j
= 1; i
<= 7; h
--, i
++, j
<<= 1) {
1503 ftt
= _fp_write_extword((uint64_t *)ea
, res
.ll
, pfpsd
);
1504 if (ftt
!= ftt_none
)
1509 ftt
= _fp_read_extword((uint64_t *)ea
, &l
.ll
, pfpsd
);
1510 if (ftt
!= ftt_none
)
1512 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1513 for (i
= 0, j
= 0x8; i
<= 3; i
++, j
>>= 1) {
1519 ftt
= _fp_write_extword((uint64_t *)ea
, res
.ll
, pfpsd
);
1520 if (ftt
!= ftt_none
)
1525 ftt
= _fp_read_extword((uint64_t *)ea
, &l
.ll
, pfpsd
);
1526 if (ftt
!= ftt_none
)
1528 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1529 for (h
= 7, i
= 0, j
= 1; i
<= 6; h
-= 2, i
+= 2, j
<<= 1) {
1530 if ((msk
& j
) == j
) {
1532 res
.c
[i
+1] = k
.c
[h
-1];
1535 res
.c
[i
+1] = l
.c
[i
+1];
1538 ftt
= _fp_write_extword((uint64_t *)ea
, res
.ll
, pfpsd
);
1539 if (ftt
!= ftt_none
)
1544 ftt
= _fp_read_extword((uint64_t *)ea
, &l
.ll
, pfpsd
);
1545 if (ftt
!= ftt_none
)
1547 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1548 for (i
= 0, j
= 0x2; i
<= 1; i
++, j
>>= 1) {
1554 ftt
= _fp_write_extword((uint64_t *)ea
, res
.ll
, pfpsd
);
1555 if (ftt
!= ftt_none
)
1560 ftt
= _fp_read_extword((uint64_t *)ea
, &l
.ll
, pfpsd
);
1561 if (ftt
!= ftt_none
)
1563 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1564 for (h
= 7, i
= 0, j
= 1; i
<= 4; h
-= 4, i
+= 4, j
<<= 1) {
1565 if ((msk
& j
) == j
) {
1567 res
.c
[i
+1] = k
.c
[h
-1];
1568 res
.c
[i
+2] = k
.c
[h
-2];
1569 res
.c
[i
+3] = k
.c
[h
-3];
1572 res
.c
[i
+1] = l
.c
[i
+1];
1573 res
.c
[i
+2] = l
.c
[i
+2];
1574 res
.c
[i
+3] = l
.c
[i
+3];
1577 ftt
= _fp_write_extword((uint64_t *)ea
, res
.ll
, pfpsd
);
1578 if (ftt
!= ftt_none
)
1583 pregs
->r_pc
= pregs
->r_npc
; /* Do not retry emulated instruction. */
1589 * Simulator for short load/stores between floating-point unit and memory.
1591 static enum ftt_type
1593 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1594 vis_inst_type inst
, /* ISE instruction to simulate. */
1595 struct regs
*pregs
, /* Pointer to PCB image of registers. */
1596 void *prw
, /* Pointer to locals and ins. */
1597 uint_t asi
) /* asi to emulate! */
1599 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
1613 enum ftt_type ftt
= ftt_none
;
1620 if ((nrd
& 1) == 1) /* fix register encoding */
1621 nrd
= (nrd
& 0x1e) | 0x20;
1624 if ((opf
& 0x100) == 0) { /* effective address = rs1 + rs2 */
1625 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &ea
);
1626 if (ftt
!= ftt_none
)
1628 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &tea
);
1629 if (ftt
!= ftt_none
)
1632 } else { /* effective address = rs1 + imm13 */
1634 ea
= (fp
.i
<< 19) >> 19; /* Extract simm13 field. */
1635 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &tea
);
1636 if (ftt
!= ftt_none
)
1640 if (get_udatamodel() == DATAMODEL_ILP32
)
1641 ea
= (uint64_t)(caddr32_t
)ea
;
1643 pfpsd
->fp_trapaddr
= (caddr_t
)ea
; /* setup bad addr in case we trap */
1647 case ASI_FL8_PL
: /* little-endian */
1649 if ((inst
.op3
& 7) == 3) { /* load byte */
1650 if (fuword8((void *)ea
, &uc
) == -1)
1654 _fp_pack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1655 } else { /* store byte */
1656 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1658 if (subyte((caddr_t
)ea
, uc
) == -1)
1665 return (ftt_alignment
);
1666 if ((inst
.op3
& 7) == 3) { /* load short */
1667 if (fuword16((void *)ea
, &us
) == -1)
1671 _fp_pack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1672 } else { /* store short */
1673 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1675 if (suword16((caddr_t
)ea
, us
) == -1)
1679 case ASI_FL16_PL
: /* little-endian */
1682 return (ftt_alignment
);
1683 if ((inst
.op3
& 7) == 3) { /* load short */
1684 if (fuword16((void *)ea
, &us
) == -1)
1687 k
.c
[6] = (uchar_t
)us
;
1688 k
.c
[7] = (uchar_t
)((us
& 0xff00) >> 8);
1689 _fp_pack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1690 } else { /* store short */
1691 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
, nrd
);
1693 us
= (ushort_t
)((uc
<< 8) | k
.c
[6]);
1694 if (suword16((void *)ea
, us
) == -1)
1700 pregs
->r_pc
= pregs
->r_npc
; /* Do not retry emulated instruction. */
1706 * Simulator for block loads and stores between floating-point unit and memory.
1707 * We pass the addrees of ea to sync_data_memory() to flush the Ecache.
1708 * Sync_data_memory() calls platform dependent code to flush the Ecache.
1710 static enum ftt_type
1712 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1713 vis_inst_type inst
, /* ISE instruction to simulate. */
1714 struct regs
*pregs
, /* Pointer to PCB image of registers. */
1715 void *prw
, /* Pointer to locals and ins. */
1716 uint_t asi
) /* asi to emulate! */
1718 uint_t nrs1
, nrs2
, nrd
; /* Register number fields. */
1719 uint_t opf
, h
, i
, j
;
1731 boolean_t little_endian
= B_FALSE
;
1736 if ((nrd
& 1) == 1) /* fix register encoding */
1737 nrd
= (nrd
& 0x1e) | 0x20;
1739 /* ensure register is 8-double precision aligned */
1740 if ((nrd
& 0xf) != 0)
1741 return (ftt_unimplemented
);
1744 if ((opf
& 0x100) == 0) { /* effective address = rs1 + rs2 */
1745 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &ea
);
1746 if (ftt
!= ftt_none
)
1748 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &tea
);
1749 if (ftt
!= ftt_none
)
1752 } else { /* effective address = rs1 + imm13 */
1754 ea
= (fp
.i
<< 19) >> 19; /* Extract simm13 field. */
1755 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &tea
);
1756 if (ftt
!= ftt_none
)
1760 if ((ea
& 0x3F) != 0) /* Require 64 byte-alignment. */
1761 return (ftt_alignment
);
1763 pfpsd
->fp_trapaddr
= (caddr_t
)ea
; /* setup bad addr in case we trap */
1769 little_endian
= B_TRUE
;
1775 case ASI_BLK_COMMIT_P
:
1776 case ASI_BLK_COMMIT_S
:
1777 if ((inst
.op3
& 7) == 3) { /* lddf */
1778 for (i
= 0; i
< 8; i
++, nrd
+= 2) {
1779 ftt
= _fp_read_extword((uint64_t *)ea
, &k
.ll
,
1781 if (ftt
!= ftt_none
)
1783 if (little_endian
) {
1784 for (j
= 0, h
= 7; j
< 8; j
++, h
--)
1788 _fp_pack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
,
1793 for (i
= 0; i
< 8; i
++, nrd
+= 2) {
1794 _fp_unpack_extword(pfpsd
, &k
.f
.FPU_DREG_FIELD
,
1796 if (little_endian
) {
1797 for (j
= 0, h
= 7; j
< 8; j
++, h
--)
1801 ftt
= _fp_write_extword((uint64_t *)ea
, k
.ll
,
1803 if (ftt
!= ftt_none
)
1808 if ((asi
== ASI_BLK_COMMIT_P
) || (asi
== ASI_BLK_COMMIT_S
))
1809 sync_data_memory((caddr_t
)(ea
- 64), 64);
1812 /* addr of unimp inst */
1813 pfpsd
->fp_trapaddr
= (caddr_t
)pregs
->r_pc
;
1814 return (ftt_unimplemented
);
1817 pregs
->r_pc
= pregs
->r_npc
; /* Do not retry emulated instruction. */
1823 * Simulator for rd %gsr instruction.
1827 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1828 fp_inst_type pinst
, /* FPU instruction to simulate. */
1829 struct regs
*pregs
, /* Pointer to PCB image of registers. */
1830 void *prw
, /* Pointer to locals and ins. */
1831 kfpu_t
*fp
) /* Need to fp to access gsr reg */
1835 enum ftt_type ftt
= ftt_none
;
1839 r
= pfpsd
->fp_current_read_gsr(fp
);
1840 ftt
= write_iureg(pfpsd
, nrd
, pregs
, prw
, &r
);
1841 pregs
->r_pc
= pregs
->r_npc
; /* Do not retry emulated instruction. */
1847 * Simulator for wr %gsr instruction.
1851 fp_simd_type
*pfpsd
, /* FPU simulator data. */
1852 fp_inst_type pinst
, /* FPU instruction to simulate. */
1853 struct regs
*pregs
, /* Pointer to PCB image of registers. */
1854 void *prw
, /* Pointer to locals and ins. */
1855 kfpu_t
*fp
) /* Need to fp to access gsr reg */
1859 enum ftt_type ftt
= ftt_none
;
1862 ftt
= read_iureg(pfpsd
, nrs1
, pregs
, prw
, &r1
);
1863 if (ftt
!= ftt_none
)
1865 if (pinst
.ibit
== 0) { /* copy the value in r[rs2] */
1869 ftt
= read_iureg(pfpsd
, nrs2
, pregs
, prw
, &r2
);
1870 if (ftt
!= ftt_none
)
1872 } else { /* use sign_ext(simm13) */
1878 fp
.inst
= pinst
; /* Extract simm13 field */
1879 r2
= (fp
.i
<< 19) >> 19;
1882 pfpsd
->fp_current_write_gsr(r
, fp
);
1883 pregs
->r_pc
= pregs
->r_npc
; /* Do not retry emulated instruction. */
1889 * This is the loadable module wrapper.
1891 #include <sys/errno.h>
1892 #include <sys/modctl.h>
1895 * Module linkage information for the kernel.
1897 extern struct mod_ops mod_miscops
;
1899 static struct modlmisc modlmisc
= {
1901 "vis fp simulation",
1904 static struct modlinkage modlinkage
= {
1905 MODREV_1
, (void *)&modlmisc
, NULL
1911 return (mod_install(&modlinkage
));
1915 _info(struct modinfo
*modinfop
)
1917 return (mod_info(&modlinkage
, modinfop
));