Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sparc/fpu/fpu_simulator.c
+++ new/usr/src/uts/sparc/fpu/fpu_simulator.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /* Main procedures for sparc FPU simulator. */
27 27
28 28 #include <sys/fpu/fpu_simulator.h>
29 29 #include <sys/fpu/globals.h>
30 30 #include <sys/fpu/fpusystm.h>
31 31 #include <sys/proc.h>
32 32 #include <sys/signal.h>
33 33 #include <sys/siginfo.h>
34 34 #include <sys/thread.h>
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
35 35 #include <sys/cpuvar.h>
36 36 #include <sys/cmn_err.h>
37 37 #include <sys/atomic.h>
38 38 #include <sys/privregs.h>
39 39 #include <sys/vis_simulator.h>
40 40
41 41 #define FPUINFO_KSTAT(opcode) { \
42 42 extern void __dtrace_probe___fpuinfo_##opcode(uint64_t *); \
43 43 uint64_t *stataddr = &fpuinfo.opcode.value.ui64; \
44 44 __dtrace_probe___fpuinfo_##opcode(stataddr); \
45 - atomic_add_64(&fpuinfo.opcode.value.ui64, 1); \
45 + atomic_inc_64(&fpuinfo.opcode.value.ui64); \
46 46 }
47 47
48 48 #define FPUINFO_KSTAT_PREC(prec, kstat_s, kstat_d, kstat_q) \
49 49 if (prec < 2) { \
50 50 FPUINFO_KSTAT(kstat_s); \
51 51 } else if (prec == 2) { \
52 52 FPUINFO_KSTAT(kstat_d); \
53 53 } else { \
54 54 FPUINFO_KSTAT(kstat_q); \
55 55 }
56 56
57 57 /*
58 58 * FPU simulator global kstat data
59 59 */
60 60 struct fpuinfo_kstat fpuinfo = {
61 61 { "fpu_sim_fmovs", KSTAT_DATA_UINT64},
62 62 { "fpu_sim_fmovd", KSTAT_DATA_UINT64},
63 63 { "fpu_sim_fmovq", KSTAT_DATA_UINT64},
64 64 { "fpu_sim_fnegs", KSTAT_DATA_UINT64},
65 65 { "fpu_sim_fnegd", KSTAT_DATA_UINT64},
66 66 { "fpu_sim_fnegq", KSTAT_DATA_UINT64},
67 67 { "fpu_sim_fabss", KSTAT_DATA_UINT64},
68 68 { "fpu_sim_fabsd", KSTAT_DATA_UINT64},
69 69 { "fpu_sim_fabsq", KSTAT_DATA_UINT64},
70 70 { "fpu_sim_fsqrts", KSTAT_DATA_UINT64},
71 71 { "fpu_sim_fsqrtd", KSTAT_DATA_UINT64},
72 72 { "fpu_sim_fsqrtq", KSTAT_DATA_UINT64},
73 73 { "fpu_sim_fadds", KSTAT_DATA_UINT64},
74 74 { "fpu_sim_faddd", KSTAT_DATA_UINT64},
75 75 { "fpu_sim_faddq", KSTAT_DATA_UINT64},
76 76 { "fpu_sim_fsubs", KSTAT_DATA_UINT64},
77 77 { "fpu_sim_fsubd", KSTAT_DATA_UINT64},
78 78 { "fpu_sim_fsubq", KSTAT_DATA_UINT64},
79 79 { "fpu_sim_fmuls", KSTAT_DATA_UINT64},
80 80 { "fpu_sim_fmuld", KSTAT_DATA_UINT64},
81 81 { "fpu_sim_fmulq", KSTAT_DATA_UINT64},
82 82 { "fpu_sim_fdivs", KSTAT_DATA_UINT64},
83 83 { "fpu_sim_fdivd", KSTAT_DATA_UINT64},
84 84 { "fpu_sim_fdivq", KSTAT_DATA_UINT64},
85 85 { "fpu_sim_fcmps", KSTAT_DATA_UINT64},
86 86 { "fpu_sim_fcmpd", KSTAT_DATA_UINT64},
87 87 { "fpu_sim_fcmpq", KSTAT_DATA_UINT64},
88 88 { "fpu_sim_fcmpes", KSTAT_DATA_UINT64},
89 89 { "fpu_sim_fcmped", KSTAT_DATA_UINT64},
90 90 { "fpu_sim_fcmpeq", KSTAT_DATA_UINT64},
91 91 { "fpu_sim_fsmuld", KSTAT_DATA_UINT64},
92 92 { "fpu_sim_fdmulx", KSTAT_DATA_UINT64},
93 93 { "fpu_sim_fstox", KSTAT_DATA_UINT64},
94 94 { "fpu_sim_fdtox", KSTAT_DATA_UINT64},
95 95 { "fpu_sim_fqtox", KSTAT_DATA_UINT64},
96 96 { "fpu_sim_fxtos", KSTAT_DATA_UINT64},
97 97 { "fpu_sim_fxtod", KSTAT_DATA_UINT64},
98 98 { "fpu_sim_fxtoq", KSTAT_DATA_UINT64},
99 99 { "fpu_sim_fitos", KSTAT_DATA_UINT64},
100 100 { "fpu_sim_fitod", KSTAT_DATA_UINT64},
101 101 { "fpu_sim_fitoq", KSTAT_DATA_UINT64},
102 102 { "fpu_sim_fstoi", KSTAT_DATA_UINT64},
103 103 { "fpu_sim_fdtoi", KSTAT_DATA_UINT64},
104 104 { "fpu_sim_fqtoi", KSTAT_DATA_UINT64},
105 105 { "fpu_sim_fmovcc", KSTAT_DATA_UINT64},
106 106 { "fpu_sim_fmovr", KSTAT_DATA_UINT64},
107 107 { "fpu_sim_fmadds", KSTAT_DATA_UINT64},
108 108 { "fpu_sim_fmaddd", KSTAT_DATA_UINT64},
109 109 { "fpu_sim_fmsubs", KSTAT_DATA_UINT64},
110 110 { "fpu_sim_fmsubd", KSTAT_DATA_UINT64},
111 111 { "fpu_sim_fnmadds", KSTAT_DATA_UINT64},
112 112 { "fpu_sim_fnmaddd", KSTAT_DATA_UINT64},
113 113 { "fpu_sim_fnmsubs", KSTAT_DATA_UINT64},
114 114 { "fpu_sim_fnmsubd", KSTAT_DATA_UINT64},
115 115 { "fpu_sim_invalid", KSTAT_DATA_UINT64},
116 116 };
117 117
118 118 struct visinfo_kstat visinfo = {
119 119 { "vis_edge8", KSTAT_DATA_UINT64},
120 120 { "vis_edge8n", KSTAT_DATA_UINT64},
121 121 { "vis_edge8l", KSTAT_DATA_UINT64},
122 122 { "vis_edge8ln", KSTAT_DATA_UINT64},
123 123 { "vis_edge16", KSTAT_DATA_UINT64},
124 124 { "vis_edge16n", KSTAT_DATA_UINT64},
125 125 { "vis_edge16l", KSTAT_DATA_UINT64},
126 126 { "vis_edge16ln", KSTAT_DATA_UINT64},
127 127 { "vis_edge32", KSTAT_DATA_UINT64},
128 128 { "vis_edge32n", KSTAT_DATA_UINT64},
129 129 { "vis_edge32l", KSTAT_DATA_UINT64},
130 130 { "vis_edge32ln", KSTAT_DATA_UINT64},
131 131 { "vis_array8", KSTAT_DATA_UINT64},
132 132 { "vis_array16", KSTAT_DATA_UINT64},
133 133 { "vis_array32", KSTAT_DATA_UINT64},
134 134 { "vis_bmask", KSTAT_DATA_UINT64},
135 135 { "vis_fcmple16", KSTAT_DATA_UINT64},
136 136 { "vis_fcmpne16", KSTAT_DATA_UINT64},
137 137 { "vis_fcmpgt16", KSTAT_DATA_UINT64},
138 138 { "vis_fcmpeq16", KSTAT_DATA_UINT64},
139 139 { "vis_fcmple32", KSTAT_DATA_UINT64},
140 140 { "vis_fcmpne32", KSTAT_DATA_UINT64},
141 141 { "vis_fcmpgt32", KSTAT_DATA_UINT64},
142 142 { "vis_fcmpeq32", KSTAT_DATA_UINT64},
143 143 { "vis_fmul8x16", KSTAT_DATA_UINT64},
144 144 { "vis_fmul8x16au", KSTAT_DATA_UINT64},
145 145 { "vis_fmul8x16al", KSTAT_DATA_UINT64},
146 146 { "vis_fmul8sux16", KSTAT_DATA_UINT64},
147 147 { "vis_fmul8ulx16", KSTAT_DATA_UINT64},
148 148 { "vis_fmuld8sux16", KSTAT_DATA_UINT64},
149 149 { "vis_fmuld8ulx16", KSTAT_DATA_UINT64},
150 150 { "vis_fpack16", KSTAT_DATA_UINT64},
151 151 { "vis_fpack32", KSTAT_DATA_UINT64},
152 152 { "vis_fpackfix", KSTAT_DATA_UINT64},
153 153 { "vis_fexpand", KSTAT_DATA_UINT64},
154 154 { "vis_fpmerge", KSTAT_DATA_UINT64},
155 155 { "vis_pdist", KSTAT_DATA_UINT64},
156 156 { "vis_pdistn", KSTAT_DATA_UINT64},
157 157 { "vis_bshuffle", KSTAT_DATA_UINT64},
158 158
159 159 };
160 160
161 161 /* PUBLIC FUNCTIONS */
162 162
163 163 int fp_notp = 1; /* fp checking not a problem */
164 164
165 165 /* ARGSUSED */
166 166 static enum ftt_type
167 167 _fp_fpu_simulator(
168 168 fp_simd_type *pfpsd, /* Pointer to fpu simulator data */
169 169 fp_inst_type inst, /* FPU instruction to simulate. */
170 170 fsr_type *pfsr, /* Pointer to image of FSR to read and write. */
171 171 uint64_t gsr) /* Image of GSR to read */
172 172 {
173 173 unpacked us1, us2, ud; /* Unpacked operands and result. */
174 174 uint32_t nrs1, nrs2, nrd; /* Register number fields. */
175 175 uint32_t usr, andexcep;
176 176 fsr_type fsr;
177 177 enum fcc_type cc;
178 178 uint32_t nfcc; /* fcc number field. */
179 179 uint64_t lusr;
180 180
181 181 nrs1 = inst.rs1;
182 182 nrs2 = inst.rs2;
183 183 nrd = inst.rd;
184 184 fsr = *pfsr;
185 185 pfpsd->fp_current_exceptions = 0; /* Init current exceptions. */
186 186 pfpsd->fp_fsrtem = fsr.tem; /* Obtain fsr's tem */
187 187 /*
188 188 * Obtain rounding direction and precision
189 189 */
190 190 pfpsd->fp_direction = GSR_IM(gsr) ? GSR_IRND(gsr) : fsr.rnd;
191 191 pfpsd->fp_precision = fsr.rnp;
192 192
193 193 if (inst.op3 == 0x37) { /* IMPDEP2B FMA-fused opcode */
194 194 fp_fma_inst_type *fma_inst;
195 195 uint32_t nrs3;
196 196 unpacked us3;
197 197 unpacked ust;
198 198 fma_inst = (fp_fma_inst_type *) &inst;
199 199 nrs2 = fma_inst->rs2;
200 200 nrs3 = fma_inst->rs3;
201 201 switch (fma_inst->var) {
202 202 case fmadd:
203 203 _fp_unpack(pfpsd, &us1, nrs1, fma_inst->sz);
204 204 _fp_unpack(pfpsd, &us2, nrs2, fma_inst->sz);
205 205 _fp_mul(pfpsd, &us1, &us2, &ust);
206 206 if ((pfpsd->fp_current_exceptions & fsr.tem) == 0) {
207 207 _fp_unpack(pfpsd, &us3, nrs3, fma_inst->sz);
208 208 _fp_add(pfpsd, &ust, &us3, &ud);
209 209 _fp_pack(pfpsd, &ud, nrd, fma_inst->sz);
210 210 }
211 211 FPUINFO_KSTAT_PREC(fma_inst->sz, fpu_sim_fmadds,
212 212 fpu_sim_fmaddd, fpu_sim_invalid);
213 213 break;
214 214 case fmsub:
215 215 _fp_unpack(pfpsd, &us1, nrs1, fma_inst->sz);
216 216 _fp_unpack(pfpsd, &us2, nrs2, fma_inst->sz);
217 217 _fp_mul(pfpsd, &us1, &us2, &ust);
218 218 if ((pfpsd->fp_current_exceptions & fsr.tem) == 0) {
219 219 _fp_unpack(pfpsd, &us3, nrs3, fma_inst->sz);
220 220 _fp_sub(pfpsd, &ust, &us3, &ud);
221 221 _fp_pack(pfpsd, &ud, nrd, fma_inst->sz);
222 222 }
223 223 FPUINFO_KSTAT_PREC(fma_inst->sz, fpu_sim_fmsubs,
224 224 fpu_sim_fmsubd, fpu_sim_invalid);
225 225 break;
226 226 case fnmadd:
227 227 _fp_unpack(pfpsd, &us1, nrs1, fma_inst->sz);
228 228 _fp_unpack(pfpsd, &us2, nrs2, fma_inst->sz);
229 229 _fp_mul(pfpsd, &us1, &us2, &ust);
230 230 if ((pfpsd->fp_current_exceptions & fsr.tem) == 0) {
231 231 _fp_unpack(pfpsd, &us3, nrs3, fma_inst->sz);
232 232 if (ust.fpclass != fp_quiet &&
233 233 ust.fpclass != fp_signaling)
234 234 ust.sign ^= 1;
235 235 _fp_sub(pfpsd, &ust, &us3, &ud);
236 236 _fp_pack(pfpsd, &ud, nrd, fma_inst->sz);
237 237 }
238 238 FPUINFO_KSTAT_PREC(fma_inst->sz, fpu_sim_fnmadds,
239 239 fpu_sim_fnmaddd, fpu_sim_invalid);
240 240 break;
241 241 case fnmsub:
242 242 _fp_unpack(pfpsd, &us1, nrs1, fma_inst->sz);
243 243 _fp_unpack(pfpsd, &us2, nrs2, fma_inst->sz);
244 244 _fp_mul(pfpsd, &us1, &us2, &ust);
245 245 if ((pfpsd->fp_current_exceptions & fsr.tem) == 0) {
246 246 _fp_unpack(pfpsd, &us3, nrs3, fma_inst->sz);
247 247 if (ust.fpclass != fp_quiet &&
248 248 ust.fpclass != fp_signaling)
249 249 ust.sign ^= 1;
250 250 _fp_add(pfpsd, &ust, &us3, &ud);
251 251 _fp_pack(pfpsd, &ud, nrd, fma_inst->sz);
252 252 }
253 253 FPUINFO_KSTAT_PREC(fma_inst->sz, fpu_sim_fnmsubs,
254 254 fpu_sim_fnmsubd, fpu_sim_invalid);
255 255 }
256 256 } else {
257 257 nfcc = nrd & 0x3;
258 258 if (inst.op3 == 0x35) { /* fpop2 */
259 259 fsr.cexc = 0;
260 260 *pfsr = fsr;
261 261 if ((inst.opcode & 0xf) == 0) {
262 262 if ((fp_notp) && (inst.prec == 0))
263 263 return (ftt_unimplemented);
264 264 FPUINFO_KSTAT(fpu_sim_fmovcc);
265 265 return (fmovcc(pfpsd, inst, pfsr)); /* fmovcc */
266 266 } else if ((inst.opcode & 0x7) == 1) {
267 267 if ((fp_notp) && (inst.prec == 0))
268 268 return (ftt_unimplemented);
269 269 FPUINFO_KSTAT(fpu_sim_fmovr);
270 270 return (fmovr(pfpsd, inst)); /* fmovr */
271 271 }
272 272 }
273 273 /* ibit not valid for fpop1 instructions */
274 274 if ((fp_notp) && (inst.ibit != 0))
275 275 return (ftt_unimplemented);
276 276 if ((fp_notp) && (inst.prec == 0)) { /* fxto[sdq], fito[sdq] */
277 277 if ((inst.opcode != flltos) &&
278 278 (inst.opcode != flltod) &&
279 279 (inst.opcode != flltox) &&
280 280 (inst.opcode != fitos) &&
281 281 (inst.opcode != fitod) &&
282 282 (inst.opcode != fitox)) {
283 283 return (ftt_unimplemented);
284 284 }
285 285 }
286 286 switch (inst.opcode) {
287 287 case fmovs: /* also covers fmovd, fmovq */
288 288 if (inst.prec < 2) { /* fmovs */
289 289 _fp_unpack_word(pfpsd, &usr, nrs2);
290 290 _fp_pack_word(pfpsd, &usr, nrd);
291 291 FPUINFO_KSTAT(fpu_sim_fmovs);
292 292 } else { /* fmovd */
293 293 _fp_unpack_extword(pfpsd, &lusr, nrs2);
294 294 _fp_pack_extword(pfpsd, &lusr, nrd);
295 295 if (inst.prec > 2) { /* fmovq */
296 296 _fp_unpack_extword(pfpsd, &lusr,
297 297 nrs2+2);
298 298 _fp_pack_extword(pfpsd, &lusr, nrd+2);
299 299 FPUINFO_KSTAT(fpu_sim_fmovq);
300 300 } else {
301 301 FPUINFO_KSTAT(fpu_sim_fmovd);
302 302 }
303 303 }
304 304 break;
305 305 case fabss: /* also covers fabsd, fabsq */
306 306 if (inst.prec < 2) { /* fabss */
307 307 _fp_unpack_word(pfpsd, &usr, nrs2);
308 308 usr &= 0x7fffffff;
309 309 _fp_pack_word(pfpsd, &usr, nrd);
310 310 FPUINFO_KSTAT(fpu_sim_fabss);
311 311 } else { /* fabsd */
312 312 _fp_unpack_extword(pfpsd, &lusr, nrs2);
313 313 lusr &= 0x7fffffffffffffff;
314 314 _fp_pack_extword(pfpsd, &lusr, nrd);
315 315 if (inst.prec > 2) { /* fabsq */
316 316 _fp_unpack_extword(pfpsd, &lusr,
317 317 nrs2+2);
318 318 _fp_pack_extword(pfpsd, &lusr, nrd+2);
319 319 FPUINFO_KSTAT(fpu_sim_fabsq);
320 320 } else {
321 321 FPUINFO_KSTAT(fpu_sim_fabsd);
322 322 }
323 323 }
324 324 break;
325 325 case fnegs: /* also covers fnegd, fnegq */
326 326 if (inst.prec < 2) { /* fnegs */
327 327 _fp_unpack_word(pfpsd, &usr, nrs2);
328 328 usr ^= 0x80000000;
329 329 _fp_pack_word(pfpsd, &usr, nrd);
330 330 FPUINFO_KSTAT(fpu_sim_fnegs);
331 331 } else { /* fnegd */
332 332 _fp_unpack_extword(pfpsd, &lusr, nrs2);
333 333 lusr ^= 0x8000000000000000;
334 334 _fp_pack_extword(pfpsd, &lusr, nrd);
335 335 if (inst.prec > 2) { /* fnegq */
336 336 _fp_unpack_extword(pfpsd, &lusr,
337 337 nrs2+2);
338 338 lusr ^= 0x0000000000000000;
339 339 _fp_pack_extword(pfpsd, &lusr, nrd+2);
340 340 FPUINFO_KSTAT(fpu_sim_fnegq);
341 341 } else {
342 342 FPUINFO_KSTAT(fpu_sim_fnegd);
343 343 }
344 344 }
345 345 break;
346 346 case fadd:
347 347 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
348 348 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
349 349 _fp_add(pfpsd, &us1, &us2, &ud);
350 350 _fp_pack(pfpsd, &ud, nrd, inst.prec);
351 351 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fadds,
352 352 fpu_sim_faddd, fpu_sim_faddq);
353 353 break;
354 354 case fsub:
355 355 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
356 356 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
357 357 _fp_sub(pfpsd, &us1, &us2, &ud);
358 358 _fp_pack(pfpsd, &ud, nrd, inst.prec);
359 359 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fsubs,
360 360 fpu_sim_fsubd, fpu_sim_fsubq);
361 361 break;
362 362 case fmul:
363 363 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
364 364 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
365 365 _fp_mul(pfpsd, &us1, &us2, &ud);
366 366 _fp_pack(pfpsd, &ud, nrd, inst.prec);
367 367 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fmuls,
368 368 fpu_sim_fmuld, fpu_sim_fmulq);
369 369 break;
370 370 case fsmuld:
371 371 if ((fp_notp) && (inst.prec != 1))
372 372 return (ftt_unimplemented);
373 373 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
374 374 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
375 375 _fp_mul(pfpsd, &us1, &us2, &ud);
376 376 _fp_pack(pfpsd, &ud, nrd,
377 377 (enum fp_op_type) ((int)inst.prec+1));
378 378 FPUINFO_KSTAT(fpu_sim_fsmuld);
379 379 break;
380 380 case fdmulx:
381 381 if ((fp_notp) && (inst.prec != 2))
382 382 return (ftt_unimplemented);
383 383 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
384 384 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
385 385 _fp_mul(pfpsd, &us1, &us2, &ud);
386 386 _fp_pack(pfpsd, &ud, nrd,
387 387 (enum fp_op_type) ((int)inst.prec+1));
388 388 FPUINFO_KSTAT(fpu_sim_fdmulx);
389 389 break;
390 390 case fdiv:
391 391 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
392 392 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
393 393 _fp_div(pfpsd, &us1, &us2, &ud);
394 394 _fp_pack(pfpsd, &ud, nrd, inst.prec);
395 395 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fdivs,
396 396 fpu_sim_fdivd, fpu_sim_fdivq);
397 397 break;
398 398 case fcmp:
399 399 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
400 400 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
401 401 cc = _fp_compare(pfpsd, &us1, &us2, 0);
402 402 if (!(pfpsd->fp_current_exceptions & pfpsd->fp_fsrtem))
403 403 switch (nfcc) {
404 404 case fcc_0:
405 405 fsr.fcc0 = cc;
406 406 break;
407 407 case fcc_1:
408 408 fsr.fcc1 = cc;
409 409 break;
410 410 case fcc_2:
411 411 fsr.fcc2 = cc;
412 412 break;
413 413 case fcc_3:
414 414 fsr.fcc3 = cc;
415 415 break;
416 416 }
417 417 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fcmps,
418 418 fpu_sim_fcmpd, fpu_sim_fcmpq);
419 419 break;
420 420 case fcmpe:
421 421 _fp_unpack(pfpsd, &us1, nrs1, inst.prec);
422 422 _fp_unpack(pfpsd, &us2, nrs2, inst.prec);
423 423 cc = _fp_compare(pfpsd, &us1, &us2, 1);
424 424 if (!(pfpsd->fp_current_exceptions & pfpsd->fp_fsrtem))
425 425 switch (nfcc) {
426 426 case fcc_0:
427 427 fsr.fcc0 = cc;
428 428 break;
429 429 case fcc_1:
430 430 fsr.fcc1 = cc;
431 431 break;
432 432 case fcc_2:
433 433 fsr.fcc2 = cc;
434 434 break;
435 435 case fcc_3:
436 436 fsr.fcc3 = cc;
437 437 break;
438 438 }
439 439 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fcmpes,
440 440 fpu_sim_fcmped, fpu_sim_fcmpeq);
441 441 break;
442 442 case fsqrt:
443 443 _fp_unpack(pfpsd, &us1, nrs2, inst.prec);
444 444 _fp_sqrt(pfpsd, &us1, &ud);
445 445 _fp_pack(pfpsd, &ud, nrd, inst.prec);
446 446 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fsqrts,
447 447 fpu_sim_fsqrtd, fpu_sim_fsqrtq);
448 448 break;
449 449 case ftoi:
450 450 _fp_unpack(pfpsd, &us1, nrs2, inst.prec);
451 451 pfpsd->fp_direction = fp_tozero;
452 452 /* Force rounding toward zero. */
453 453 _fp_pack(pfpsd, &us1, nrd, fp_op_int32);
454 454 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fstoi,
455 455 fpu_sim_fdtoi, fpu_sim_fqtoi);
456 456 break;
457 457 case ftoll:
458 458 _fp_unpack(pfpsd, &us1, nrs2, inst.prec);
459 459 pfpsd->fp_direction = fp_tozero;
460 460 /* Force rounding toward zero. */
461 461 _fp_pack(pfpsd, &us1, nrd, fp_op_int64);
462 462 FPUINFO_KSTAT_PREC(inst.prec, fpu_sim_fstox,
463 463 fpu_sim_fdtox, fpu_sim_fqtox);
464 464 break;
465 465 case flltos:
466 466 _fp_unpack(pfpsd, &us1, nrs2, fp_op_int64);
467 467 _fp_pack(pfpsd, &us1, nrd, fp_op_single);
468 468 FPUINFO_KSTAT(fpu_sim_fxtos);
469 469 break;
470 470 case flltod:
471 471 _fp_unpack(pfpsd, &us1, nrs2, fp_op_int64);
472 472 _fp_pack(pfpsd, &us1, nrd, fp_op_double);
473 473 FPUINFO_KSTAT(fpu_sim_fxtod);
474 474 break;
475 475 case flltox:
476 476 _fp_unpack(pfpsd, &us1, nrs2, fp_op_int64);
477 477 _fp_pack(pfpsd, &us1, nrd, fp_op_extended);
478 478 FPUINFO_KSTAT(fpu_sim_fxtoq);
479 479 break;
480 480 case fitos:
481 481 _fp_unpack(pfpsd, &us1, nrs2, inst.prec);
482 482 _fp_pack(pfpsd, &us1, nrd, fp_op_single);
483 483 FPUINFO_KSTAT(fpu_sim_fitos);
484 484 break;
485 485 case fitod:
486 486 _fp_unpack(pfpsd, &us1, nrs2, inst.prec);
487 487 _fp_pack(pfpsd, &us1, nrd, fp_op_double);
488 488 FPUINFO_KSTAT(fpu_sim_fitod);
489 489 break;
490 490 case fitox:
491 491 _fp_unpack(pfpsd, &us1, nrs2, inst.prec);
492 492 _fp_pack(pfpsd, &us1, nrd, fp_op_extended);
493 493 FPUINFO_KSTAT(fpu_sim_fitoq);
494 494 break;
495 495 default:
496 496 return (ftt_unimplemented);
497 497 }
498 498 }
499 499 fsr.cexc = pfpsd->fp_current_exceptions;
500 500 andexcep = pfpsd->fp_current_exceptions & fsr.tem;
501 501 if (andexcep != 0) { /* Signal an IEEE SIGFPE here. */
502 502 if (andexcep & (1 << fp_invalid)) {
503 503 pfpsd->fp_trapcode = FPE_FLTINV;
504 504 fsr.cexc = FSR_CEXC_NV;
505 505 } else if (andexcep & (1 << fp_overflow)) {
506 506 pfpsd->fp_trapcode = FPE_FLTOVF;
507 507 fsr.cexc = FSR_CEXC_OF;
508 508 } else if (andexcep & (1 << fp_underflow)) {
509 509 pfpsd->fp_trapcode = FPE_FLTUND;
510 510 fsr.cexc = FSR_CEXC_UF;
511 511 } else if (andexcep & (1 << fp_division)) {
512 512 pfpsd->fp_trapcode = FPE_FLTDIV;
513 513 fsr.cexc = FSR_CEXC_DZ;
514 514 } else if (andexcep & (1 << fp_inexact)) {
515 515 pfpsd->fp_trapcode = FPE_FLTRES;
516 516 fsr.cexc = FSR_CEXC_NX;
517 517 } else {
518 518 pfpsd->fp_trapcode = 0;
519 519 }
520 520 *pfsr = fsr;
521 521 return (ftt_ieee);
522 522 } else { /* Just set accrued exception field. */
523 523 fsr.aexc |= pfpsd->fp_current_exceptions;
524 524 }
525 525 *pfsr = fsr;
526 526 return (ftt_none);
527 527 }
528 528
529 529 /*
530 530 * fpu_vis_sim simulates fpu and vis instructions;
531 531 * It can work with both real and pcb image registers.
532 532 */
533 533 enum ftt_type
534 534 fpu_vis_sim(
535 535 fp_simd_type *pfpsd, /* Pointer to simulator data */
536 536 fp_inst_type *pinst, /* Address of FPU instruction to simulate */
537 537 struct regs *pregs, /* Pointer to PCB image of registers. */
538 538 fsr_type *pfsr, /* Pointer to image of FSR to read and write */
539 539 uint64_t gsr, /* Image of GSR to read */
540 540 uint32_t inst) /* The FPU instruction to simulate */
541 541 {
542 542 klwp_id_t lwp = ttolwp(curthread);
543 543 union {
544 544 uint32_t i;
545 545 fp_inst_type inst;
546 546 } fp;
547 547 kfpu_t *pfp = lwptofpu(lwp);
548 548 enum ftt_type ftt;
549 549
550 550 fp.i = inst;
551 551 pfpsd->fp_trapaddr = (caddr_t)pinst;
552 552 if (fpu_exists) {
553 553 pfpsd->fp_current_read_freg = _fp_read_pfreg;
554 554 pfpsd->fp_current_write_freg = _fp_write_pfreg;
555 555 pfpsd->fp_current_read_dreg = _fp_read_pdreg;
556 556 pfpsd->fp_current_write_dreg = _fp_write_pdreg;
557 557 pfpsd->fp_current_read_gsr = _fp_read_pgsr;
558 558 pfpsd->fp_current_write_gsr = _fp_write_pgsr;
559 559 } else {
560 560 pfpsd->fp_current_pfregs = pfp;
561 561 pfpsd->fp_current_read_freg = _fp_read_vfreg;
562 562 pfpsd->fp_current_write_freg = _fp_write_vfreg;
563 563 pfpsd->fp_current_read_dreg = _fp_read_vdreg;
564 564 pfpsd->fp_current_write_dreg = _fp_write_vdreg;
565 565 pfpsd->fp_current_read_gsr = get_gsr;
566 566 pfpsd->fp_current_write_gsr = set_gsr;
567 567 }
568 568
569 569 if ((fp.inst.hibits == 2) && (fp.inst.op3 == 0x36)) {
570 570 ftt = vis_fpu_simulator(pfpsd, fp.inst,
571 571 pregs, (ulong_t *)pregs->r_sp, pfp);
572 572 return (ftt);
573 573 } else if ((fp.inst.hibits == 2) &&
574 574 ((fp.inst.op3 == 0x34) || (fp.inst.op3 == 0x35) ||
575 575 (fp.inst.op3 == 0x37))) {
576 576 ftt = _fp_fpu_simulator(pfpsd, fp.inst, pfsr, gsr);
577 577 if (ftt == ftt_none || ftt == ftt_ieee) {
578 578 pregs->r_pc = pregs->r_npc;
579 579 pregs->r_npc += 4;
580 580 }
581 581 return (ftt);
582 582 } else {
583 583 ftt = _fp_iu_simulator(pfpsd, fp.inst, pregs,
584 584 (ulong_t *)pregs->r_sp, pfp);
585 585 return (ftt);
586 586 }
587 587 }
588 588
589 589 /*
590 590 * fpu_simulator simulates FPU instructions only;
591 591 * reads and writes FPU data registers directly.
592 592 */
593 593 enum ftt_type
594 594 fpu_simulator(
595 595 fp_simd_type *pfpsd, /* Pointer to simulator data */
596 596 fp_inst_type *pinst, /* Address of FPU instruction to simulate */
597 597 fsr_type *pfsr, /* Pointer to image of FSR to read and write */
598 598 uint64_t gsr, /* Image of GSR to read */
599 599 uint32_t inst) /* The FPU instruction to simulate */
600 600 {
601 601 union {
602 602 uint32_t i;
603 603 fp_inst_type inst;
604 604 } fp;
605 605
606 606 fp.i = inst;
607 607 pfpsd->fp_trapaddr = (caddr_t)pinst;
608 608 pfpsd->fp_current_read_freg = _fp_read_pfreg;
609 609 pfpsd->fp_current_write_freg = _fp_write_pfreg;
610 610 pfpsd->fp_current_read_dreg = _fp_read_pdreg;
611 611 pfpsd->fp_current_write_dreg = _fp_write_pdreg;
612 612 pfpsd->fp_current_read_gsr = _fp_read_pgsr;
613 613 pfpsd->fp_current_write_gsr = _fp_write_pgsr;
614 614 return (_fp_fpu_simulator(pfpsd, fp.inst, pfsr, gsr));
615 615 }
616 616
617 617 /*
618 618 * fp_emulator simulates FPU and CPU-FPU instructions; reads and writes FPU
619 619 * data registers from image in pfpu.
620 620 */
621 621 enum ftt_type
622 622 fp_emulator(
623 623 fp_simd_type *pfpsd, /* Pointer to simulator data */
624 624 fp_inst_type *pinst, /* Pointer to FPU instruction to simulate. */
625 625 struct regs *pregs, /* Pointer to PCB image of registers. */
626 626 void *prw, /* Pointer to locals and ins. */
627 627 kfpu_t *pfpu) /* Pointer to FPU register block. */
628 628 {
629 629 klwp_id_t lwp = ttolwp(curthread);
630 630 union {
631 631 uint32_t i;
632 632 fp_inst_type inst;
633 633 } fp;
634 634 enum ftt_type ftt;
635 635 uint64_t gsr = get_gsr(pfpu);
636 636 kfpu_t *pfp = lwptofpu(lwp);
637 637 uint64_t tfsr;
638 638
639 639 tfsr = pfpu->fpu_fsr;
640 640 pfpsd->fp_current_pfregs = pfpu;
641 641 pfpsd->fp_current_read_freg = _fp_read_vfreg;
642 642 pfpsd->fp_current_write_freg = _fp_write_vfreg;
643 643 pfpsd->fp_current_read_dreg = _fp_read_vdreg;
644 644 pfpsd->fp_current_write_dreg = _fp_write_vdreg;
645 645 pfpsd->fp_current_read_gsr = get_gsr;
646 646 pfpsd->fp_current_write_gsr = set_gsr;
647 647 pfpsd->fp_trapaddr = (caddr_t)pinst; /* bad inst addr in case we trap */
648 648 ftt = _fp_read_inst((uint32_t *)pinst, &(fp.i), pfpsd);
649 649 if (ftt != ftt_none)
650 650 return (ftt);
651 651
652 652 if ((fp.inst.hibits == 2) &&
653 653 ((fp.inst.op3 == 0x34) || (fp.inst.op3 == 0x35) ||
654 654 (fp.inst.op3 == 0x37))) {
655 655 ftt = _fp_fpu_simulator(pfpsd, fp.inst, (fsr_type *)&tfsr, gsr);
656 656 /* Do not retry emulated instruction. */
657 657 pregs->r_pc = pregs->r_npc;
658 658 pregs->r_npc += 4;
659 659 pfpu->fpu_fsr = tfsr;
660 660 if (ftt != ftt_none) {
661 661 /*
662 662 * Simulation generated an exception of some kind,
663 663 * simulate the fp queue for a signal.
664 664 */
665 665 pfpu->fpu_q->FQu.fpq.fpq_addr = (uint32_t *)pinst;
666 666 pfpu->fpu_q->FQu.fpq.fpq_instr = fp.i;
667 667 pfpu->fpu_qcnt = 1;
668 668 }
669 669 } else if ((fp.inst.hibits == 2) && (fp.inst.op3 == 0x36)) {
670 670 ftt = vis_fpu_simulator(pfpsd, fp.inst,
671 671 pregs, prw, pfp);
672 672 } else
673 673 ftt = _fp_iu_simulator(pfpsd, fp.inst, pregs, prw, pfpu);
674 674
675 675 if (ftt != ftt_none)
676 676 return (ftt);
677 677
678 678 /*
679 679 * If we are single-stepping, don't emulate any more instructions.
680 680 */
681 681 if (lwp->lwp_pcb.pcb_step != STEP_NONE)
682 682 return (ftt);
683 683 again:
684 684 /*
685 685 * now read next instruction and see if it can be emulated
686 686 */
687 687 pinst = (fp_inst_type *)pregs->r_pc;
688 688 pfpsd->fp_trapaddr = (caddr_t)pinst; /* bad inst addr in case we trap */
689 689 ftt = _fp_read_inst((uint32_t *)pinst, &(fp.i), pfpsd);
690 690 if (ftt != ftt_none)
691 691 return (ftt);
692 692 if ((fp.inst.hibits == 2) && /* fpops */
693 693 ((fp.inst.op3 == 0x34) || (fp.inst.op3 == 0x35) ||
694 694 (fp.inst.op3 == 0x37))) {
695 695 ftt = _fp_fpu_simulator(pfpsd, fp.inst, (fsr_type *)&tfsr, gsr);
696 696 /* Do not retry emulated instruction. */
697 697 pfpu->fpu_fsr = tfsr;
698 698 pregs->r_pc = pregs->r_npc;
699 699 pregs->r_npc += 4;
700 700 if (ftt != ftt_none) {
701 701 /*
702 702 * Simulation generated an exception of some kind,
703 703 * simulate the fp queue for a signal.
704 704 */
705 705 pfpu->fpu_q->FQu.fpq.fpq_addr = (uint32_t *)pinst;
706 706 pfpu->fpu_q->FQu.fpq.fpq_instr = fp.i;
707 707 pfpu->fpu_qcnt = 1;
708 708 }
709 709 } else if ((fp.inst.hibits == 2) && (fp.inst.op3 == 0x36)) {
710 710 ftt = vis_fpu_simulator(pfpsd, fp.inst,
711 711 pregs, prw, pfp);
712 712 } else if (
713 713 /* rd %gsr */
714 714 ((fp.inst.hibits == 2) && ((fp.inst.op3 & 0x3f) == 0x28) &&
715 715 (fp.inst.rs1 == 0x13)) ||
716 716 /* wr %gsr */
717 717 ((fp.inst.hibits == 2) && ((fp.inst.op3 & 0x3f) == 0x30) &&
718 718 (fp.inst.rd == 0x13)) ||
719 719 /* movcc */
720 720 ((fp.inst.hibits == 2) && ((fp.inst.op3 & 0x3f) == 0x2c) &&
721 721 (((fp.i>>18) & 0x1) == 0)) ||
722 722 /* fbpcc */
723 723 ((fp.inst.hibits == 0) && (((fp.i>>22) & 0x7) == 5)) ||
724 724 /* fldst */
725 725 ((fp.inst.hibits == 3) && ((fp.inst.op3 & 0x38) == 0x20)) ||
726 726 /* fbcc */
727 727 ((fp.inst.hibits == 0) && (((fp.i>>22) & 0x7) == 6))) {
728 728 ftt = _fp_iu_simulator(pfpsd, fp.inst, pregs, prw, pfpu);
729 729 } else
730 730 return (ftt);
731 731
732 732 if (ftt != ftt_none)
733 733 return (ftt);
734 734 else
735 735 goto again;
736 736 }
737 737
738 738 /*
739 739 * FPU simulator global kstat data
740 740 */
741 741 struct fpustat_kstat fpustat = {
742 742 { "fpu_ieee_traps", KSTAT_DATA_UINT64 },
743 743 { "fpu_unfinished_traps", KSTAT_DATA_UINT64 },
744 744 { "fpu_unimplemented", KSTAT_DATA_UINT64 },
745 745 };
746 746
747 747 kstat_t *fpu_kstat = NULL;
748 748 kstat_t *fpuinfo_kstat = NULL;
749 749 kstat_t *visinfo_kstat = NULL;
750 750
751 751 void
752 752 fp_kstat_init(void)
753 753 {
754 754 const uint_t fpustat_ndata = sizeof (fpustat) / sizeof (kstat_named_t);
755 755 const uint_t fpuinfo_ndata = sizeof (fpuinfo) / sizeof (kstat_named_t);
756 756 const uint_t visinfo_ndata = sizeof (visinfo) /sizeof (kstat_named_t);
757 757
758 758 ASSERT(fpu_kstat == NULL);
759 759 if ((fpu_kstat = kstat_create("unix", 0, "fpu_traps", "misc",
760 760 KSTAT_TYPE_NAMED, fpustat_ndata, KSTAT_FLAG_VIRTUAL)) == NULL) {
761 761 cmn_err(CE_WARN, "CPU%d: kstat_create for fpu_traps failed",
762 762 CPU->cpu_id);
763 763 } else {
764 764 fpu_kstat->ks_data = (void *)&fpustat;
765 765 kstat_install(fpu_kstat);
766 766 }
767 767
768 768 ASSERT(fpuinfo_kstat == NULL);
769 769 if ((fpuinfo_kstat = kstat_create("unix", 0, "fpu_info", "misc",
770 770 KSTAT_TYPE_NAMED, fpuinfo_ndata, KSTAT_FLAG_VIRTUAL)) == NULL) {
771 771 cmn_err(CE_WARN, "CPU%d: kstat_create for fpu_info failed",
772 772 CPU->cpu_id);
773 773 } else {
774 774 fpuinfo_kstat->ks_data = (void *)&fpuinfo;
775 775 kstat_install(fpuinfo_kstat);
776 776 }
777 777 ASSERT(visinfo_kstat == NULL);
778 778 if ((visinfo_kstat = kstat_create("unix", 0, "vis_info", "misc",
779 779 KSTAT_TYPE_NAMED, visinfo_ndata, KSTAT_FLAG_VIRTUAL)) == NULL) {
780 780 cmn_err(CE_WARN, "CPU%d: kstat_create for vis_info failed",
781 781 CPU->cpu_id);
782 782 } else {
783 783 visinfo_kstat->ks_data = (void *)&visinfo;
↓ open down ↓ |
728 lines elided |
↑ open up ↑ |
784 784 kstat_install(visinfo_kstat);
785 785 }
786 786 }
787 787
788 788 void
789 789 fp_kstat_update(enum ftt_type ftt)
790 790 {
791 791 ASSERT((ftt == ftt_ieee) || (ftt == ftt_unfinished) ||
792 792 (ftt == ftt_unimplemented));
793 793 if (ftt == ftt_ieee)
794 - atomic_add_64(&fpustat.fpu_ieee_traps.value.ui64, 1);
794 + atomic_inc_64(&fpustat.fpu_ieee_traps.value.ui64);
795 795 else if (ftt == ftt_unfinished)
796 - atomic_add_64(&fpustat.fpu_unfinished_traps.value.ui64, 1);
796 + atomic_inc_64(&fpustat.fpu_unfinished_traps.value.ui64);
797 797 else if (ftt == ftt_unimplemented)
798 - atomic_add_64(&fpustat.fpu_unimplemented_traps.value.ui64, 1);
798 + atomic_inc_64(&fpustat.fpu_unimplemented_traps.value.ui64);
799 799 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX