Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/parisc/math-emu/fpudispatch.c
10817 views
1
/*
2
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
3
*
4
* Floating-point emulation code
5
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2, or (at your option)
10
* any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
/*
22
* BEGIN_DESC
23
*
24
* File:
25
* @(#) pa/fp/fpudispatch.c $Revision: 1.1 $
26
*
27
* Purpose:
28
* <<please update with a synopsis of the functionality provided by this file>>
29
*
30
* External Interfaces:
31
* <<the following list was autogenerated, please review>>
32
* emfpudispatch(ir, dummy1, dummy2, fpregs)
33
* fpudispatch(ir, excp_code, holder, fpregs)
34
*
35
* Internal Interfaces:
36
* <<the following list was autogenerated, please review>>
37
* static u_int decode_06(u_int, u_int *)
38
* static u_int decode_0c(u_int, u_int, u_int, u_int *)
39
* static u_int decode_0e(u_int, u_int, u_int, u_int *)
40
* static u_int decode_26(u_int, u_int *)
41
* static u_int decode_2e(u_int, u_int *)
42
* static void update_status_cbit(u_int *, u_int, u_int, u_int)
43
*
44
* Theory:
45
* <<please update with a overview of the operation of this file>>
46
*
47
* END_DESC
48
*/
49
50
#define FPUDEBUG 0
51
52
#include "float.h"
53
#include <linux/kernel.h>
54
#include <asm/processor.h>
55
/* #include <sys/debug.h> */
56
/* #include <machine/sys/mdep_private.h> */
57
58
#define COPR_INST 0x30000000
59
60
/*
61
* definition of extru macro. If pos and len are constants, the compiler
62
* will generate an extru instruction when optimized
63
*/
64
#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
65
/* definitions of bit field locations in the instruction */
66
#define fpmajorpos 5
67
#define fpr1pos 10
68
#define fpr2pos 15
69
#define fptpos 31
70
#define fpsubpos 18
71
#define fpclass1subpos 16
72
#define fpclasspos 22
73
#define fpfmtpos 20
74
#define fpdfpos 18
75
#define fpnulpos 26
76
/*
77
* the following are the extra bits for the 0E major op
78
*/
79
#define fpxr1pos 24
80
#define fpxr2pos 19
81
#define fpxtpos 25
82
#define fpxpos 23
83
#define fp0efmtpos 20
84
/*
85
* the following are for the multi-ops
86
*/
87
#define fprm1pos 10
88
#define fprm2pos 15
89
#define fptmpos 31
90
#define fprapos 25
91
#define fptapos 20
92
#define fpmultifmt 26
93
/*
94
* the following are for the fused FP instructions
95
*/
96
/* fprm1pos 10 */
97
/* fprm2pos 15 */
98
#define fpraupos 18
99
#define fpxrm2pos 19
100
/* fpfmtpos 20 */
101
#define fpralpos 23
102
#define fpxrm1pos 24
103
/* fpxtpos 25 */
104
#define fpfusedsubop 26
105
/* fptpos 31 */
106
107
/*
108
* offset to constant zero in the FP emulation registers
109
*/
110
#define fpzeroreg (32*sizeof(double)/sizeof(u_int))
111
112
/*
113
* extract the major opcode from the instruction
114
*/
115
#define get_major(op) extru(op,fpmajorpos,6)
116
/*
117
* extract the two bit class field from the FP instruction. The class is at bit
118
* positions 21-22
119
*/
120
#define get_class(op) extru(op,fpclasspos,2)
121
/*
122
* extract the 3 bit subop field. For all but class 1 instructions, it is
123
* located at bit positions 16-18
124
*/
125
#define get_subop(op) extru(op,fpsubpos,3)
126
/*
127
* extract the 2 or 3 bit subop field from class 1 instructions. It is located
128
* at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
129
*/
130
#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */
131
#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */
132
133
/* definitions of unimplemented exceptions */
134
#define MAJOR_0C_EXCP 0x09
135
#define MAJOR_0E_EXCP 0x0b
136
#define MAJOR_06_EXCP 0x03
137
#define MAJOR_26_EXCP 0x23
138
#define MAJOR_2E_EXCP 0x2b
139
#define PA83_UNIMP_EXCP 0x01
140
141
/*
142
* Special Defines for TIMEX specific code
143
*/
144
145
#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
146
#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
147
148
/*
149
* Static function definitions
150
*/
151
#define _PROTOTYPES
152
#if defined(_PROTOTYPES) || defined(_lint)
153
static u_int decode_0c(u_int, u_int, u_int, u_int *);
154
static u_int decode_0e(u_int, u_int, u_int, u_int *);
155
static u_int decode_06(u_int, u_int *);
156
static u_int decode_26(u_int, u_int *);
157
static u_int decode_2e(u_int, u_int *);
158
static void update_status_cbit(u_int *, u_int, u_int, u_int);
159
#else /* !_PROTOTYPES&&!_lint */
160
static u_int decode_0c();
161
static u_int decode_0e();
162
static u_int decode_06();
163
static u_int decode_26();
164
static u_int decode_2e();
165
static void update_status_cbit();
166
#endif /* _PROTOTYPES&&!_lint */
167
168
#define VASSERT(x)
169
170
static void parisc_linux_get_fpu_type(u_int fpregs[])
171
{
172
/* on pa-linux the fpu type is not filled in by the
173
* caller; it is constructed here
174
*/
175
if (boot_cpu_data.cpu_type == pcxs)
176
fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
177
else if (boot_cpu_data.cpu_type == pcxt ||
178
boot_cpu_data.cpu_type == pcxt_)
179
fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
180
else if (boot_cpu_data.cpu_type >= pcxu)
181
fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
182
}
183
184
/*
185
* this routine will decode the excepting floating point instruction and
186
* call the approiate emulation routine.
187
* It is called by decode_fpu with the following parameters:
188
* fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
189
* where current_ir is the instruction to be emulated,
190
* unimplemented_code is the exception_code that the hardware generated
191
* and &Fpu_register is the address of emulated FP reg 0.
192
*/
193
u_int
194
fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
195
{
196
u_int class, subop;
197
u_int fpu_type_flags;
198
199
/* All FP emulation code assumes that ints are 4-bytes in length */
200
VASSERT(sizeof(int) == 4);
201
202
parisc_linux_get_fpu_type(fpregs);
203
204
fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
205
206
class = get_class(ir);
207
if (class == 1) {
208
if (fpu_type_flags & PA2_0_FPU_FLAG)
209
subop = get_subop1_PA2_0(ir);
210
else
211
subop = get_subop1_PA1_1(ir);
212
}
213
else
214
subop = get_subop(ir);
215
216
if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
217
218
switch (excp_code) {
219
case MAJOR_0C_EXCP:
220
case PA83_UNIMP_EXCP:
221
return(decode_0c(ir,class,subop,fpregs));
222
case MAJOR_0E_EXCP:
223
return(decode_0e(ir,class,subop,fpregs));
224
case MAJOR_06_EXCP:
225
return(decode_06(ir,fpregs));
226
case MAJOR_26_EXCP:
227
return(decode_26(ir,fpregs));
228
case MAJOR_2E_EXCP:
229
return(decode_2e(ir,fpregs));
230
default:
231
/* "crashme Night Gallery painting nr 2. (asm_crash.s).
232
* This was fixed for multi-user kernels, but
233
* workstation kernels had a panic here. This allowed
234
* any arbitrary user to panic the kernel by executing
235
* setting the FP exception registers to strange values
236
* and generating an emulation trap. The emulation and
237
* exception code must never be able to panic the
238
* kernel.
239
*/
240
return(UNIMPLEMENTEDEXCEPTION);
241
}
242
}
243
244
/*
245
* this routine is called by $emulation_trap to emulate a coprocessor
246
* instruction if one doesn't exist
247
*/
248
u_int
249
emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
250
{
251
u_int class, subop, major;
252
u_int fpu_type_flags;
253
254
/* All FP emulation code assumes that ints are 4-bytes in length */
255
VASSERT(sizeof(int) == 4);
256
257
fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
258
259
major = get_major(ir);
260
class = get_class(ir);
261
if (class == 1) {
262
if (fpu_type_flags & PA2_0_FPU_FLAG)
263
subop = get_subop1_PA2_0(ir);
264
else
265
subop = get_subop1_PA1_1(ir);
266
}
267
else
268
subop = get_subop(ir);
269
switch (major) {
270
case 0x0C:
271
return(decode_0c(ir,class,subop,fpregs));
272
case 0x0E:
273
return(decode_0e(ir,class,subop,fpregs));
274
case 0x06:
275
return(decode_06(ir,fpregs));
276
case 0x26:
277
return(decode_26(ir,fpregs));
278
case 0x2E:
279
return(decode_2e(ir,fpregs));
280
default:
281
return(PA83_UNIMP_EXCP);
282
}
283
}
284
285
286
static u_int
287
decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
288
{
289
u_int r1,r2,t; /* operand register offsets */
290
u_int fmt; /* also sf for class 1 conversions */
291
u_int df; /* for class 1 conversions */
292
u_int *status;
293
u_int retval, local_status;
294
u_int fpu_type_flags;
295
296
if (ir == COPR_INST) {
297
fpregs[0] = EMULATION_VERSION << 11;
298
return(NOEXCEPTION);
299
}
300
status = &fpregs[0]; /* fp status register */
301
local_status = fpregs[0]; /* and local copy */
302
r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
303
if (r1 == 0) /* map fr0 source to constant zero */
304
r1 = fpzeroreg;
305
t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
306
if (t == 0 && class != 2) /* don't allow fr0 as a dest */
307
return(MAJOR_0C_EXCP);
308
fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
309
310
switch (class) {
311
case 0:
312
switch (subop) {
313
case 0: /* COPR 0,0 emulated above*/
314
case 1:
315
return(MAJOR_0C_EXCP);
316
case 2: /* FCPY */
317
switch (fmt) {
318
case 2: /* illegal */
319
return(MAJOR_0C_EXCP);
320
case 3: /* quad */
321
t &= ~3; /* force to even reg #s */
322
r1 &= ~3;
323
fpregs[t+3] = fpregs[r1+3];
324
fpregs[t+2] = fpregs[r1+2];
325
case 1: /* double */
326
fpregs[t+1] = fpregs[r1+1];
327
case 0: /* single */
328
fpregs[t] = fpregs[r1];
329
return(NOEXCEPTION);
330
}
331
case 3: /* FABS */
332
switch (fmt) {
333
case 2: /* illegal */
334
return(MAJOR_0C_EXCP);
335
case 3: /* quad */
336
t &= ~3; /* force to even reg #s */
337
r1 &= ~3;
338
fpregs[t+3] = fpregs[r1+3];
339
fpregs[t+2] = fpregs[r1+2];
340
case 1: /* double */
341
fpregs[t+1] = fpregs[r1+1];
342
case 0: /* single */
343
/* copy and clear sign bit */
344
fpregs[t] = fpregs[r1] & 0x7fffffff;
345
return(NOEXCEPTION);
346
}
347
case 6: /* FNEG */
348
switch (fmt) {
349
case 2: /* illegal */
350
return(MAJOR_0C_EXCP);
351
case 3: /* quad */
352
t &= ~3; /* force to even reg #s */
353
r1 &= ~3;
354
fpregs[t+3] = fpregs[r1+3];
355
fpregs[t+2] = fpregs[r1+2];
356
case 1: /* double */
357
fpregs[t+1] = fpregs[r1+1];
358
case 0: /* single */
359
/* copy and invert sign bit */
360
fpregs[t] = fpregs[r1] ^ 0x80000000;
361
return(NOEXCEPTION);
362
}
363
case 7: /* FNEGABS */
364
switch (fmt) {
365
case 2: /* illegal */
366
return(MAJOR_0C_EXCP);
367
case 3: /* quad */
368
t &= ~3; /* force to even reg #s */
369
r1 &= ~3;
370
fpregs[t+3] = fpregs[r1+3];
371
fpregs[t+2] = fpregs[r1+2];
372
case 1: /* double */
373
fpregs[t+1] = fpregs[r1+1];
374
case 0: /* single */
375
/* copy and set sign bit */
376
fpregs[t] = fpregs[r1] | 0x80000000;
377
return(NOEXCEPTION);
378
}
379
case 4: /* FSQRT */
380
switch (fmt) {
381
case 0:
382
return(sgl_fsqrt(&fpregs[r1],0,
383
&fpregs[t],status));
384
case 1:
385
return(dbl_fsqrt(&fpregs[r1],0,
386
&fpregs[t],status));
387
case 2:
388
case 3: /* quad not implemented */
389
return(MAJOR_0C_EXCP);
390
}
391
case 5: /* FRND */
392
switch (fmt) {
393
case 0:
394
return(sgl_frnd(&fpregs[r1],0,
395
&fpregs[t],status));
396
case 1:
397
return(dbl_frnd(&fpregs[r1],0,
398
&fpregs[t],status));
399
case 2:
400
case 3: /* quad not implemented */
401
return(MAJOR_0C_EXCP);
402
}
403
} /* end of switch (subop) */
404
405
case 1: /* class 1 */
406
df = extru(ir,fpdfpos,2); /* get dest format */
407
if ((df & 2) || (fmt & 2)) {
408
/*
409
* fmt's 2 and 3 are illegal of not implemented
410
* quad conversions
411
*/
412
return(MAJOR_0C_EXCP);
413
}
414
/*
415
* encode source and dest formats into 2 bits.
416
* high bit is source, low bit is dest.
417
* bit = 1 --> double precision
418
*/
419
fmt = (fmt << 1) | df;
420
switch (subop) {
421
case 0: /* FCNVFF */
422
switch(fmt) {
423
case 0: /* sgl/sgl */
424
return(MAJOR_0C_EXCP);
425
case 1: /* sgl/dbl */
426
return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
427
&fpregs[t],status));
428
case 2: /* dbl/sgl */
429
return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
430
&fpregs[t],status));
431
case 3: /* dbl/dbl */
432
return(MAJOR_0C_EXCP);
433
}
434
case 1: /* FCNVXF */
435
switch(fmt) {
436
case 0: /* sgl/sgl */
437
return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
438
&fpregs[t],status));
439
case 1: /* sgl/dbl */
440
return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
441
&fpregs[t],status));
442
case 2: /* dbl/sgl */
443
return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
444
&fpregs[t],status));
445
case 3: /* dbl/dbl */
446
return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
447
&fpregs[t],status));
448
}
449
case 2: /* FCNVFX */
450
switch(fmt) {
451
case 0: /* sgl/sgl */
452
return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
453
&fpregs[t],status));
454
case 1: /* sgl/dbl */
455
return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
456
&fpregs[t],status));
457
case 2: /* dbl/sgl */
458
return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
459
&fpregs[t],status));
460
case 3: /* dbl/dbl */
461
return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
462
&fpregs[t],status));
463
}
464
case 3: /* FCNVFXT */
465
switch(fmt) {
466
case 0: /* sgl/sgl */
467
return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
468
&fpregs[t],status));
469
case 1: /* sgl/dbl */
470
return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
471
&fpregs[t],status));
472
case 2: /* dbl/sgl */
473
return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
474
&fpregs[t],status));
475
case 3: /* dbl/dbl */
476
return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
477
&fpregs[t],status));
478
}
479
case 5: /* FCNVUF (PA2.0 only) */
480
switch(fmt) {
481
case 0: /* sgl/sgl */
482
return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
483
&fpregs[t],status));
484
case 1: /* sgl/dbl */
485
return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
486
&fpregs[t],status));
487
case 2: /* dbl/sgl */
488
return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
489
&fpregs[t],status));
490
case 3: /* dbl/dbl */
491
return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
492
&fpregs[t],status));
493
}
494
case 6: /* FCNVFU (PA2.0 only) */
495
switch(fmt) {
496
case 0: /* sgl/sgl */
497
return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
498
&fpregs[t],status));
499
case 1: /* sgl/dbl */
500
return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
501
&fpregs[t],status));
502
case 2: /* dbl/sgl */
503
return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
504
&fpregs[t],status));
505
case 3: /* dbl/dbl */
506
return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
507
&fpregs[t],status));
508
}
509
case 7: /* FCNVFUT (PA2.0 only) */
510
switch(fmt) {
511
case 0: /* sgl/sgl */
512
return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
513
&fpregs[t],status));
514
case 1: /* sgl/dbl */
515
return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
516
&fpregs[t],status));
517
case 2: /* dbl/sgl */
518
return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
519
&fpregs[t],status));
520
case 3: /* dbl/dbl */
521
return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
522
&fpregs[t],status));
523
}
524
case 4: /* undefined */
525
return(MAJOR_0C_EXCP);
526
} /* end of switch subop */
527
528
case 2: /* class 2 */
529
fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
530
r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
531
if (r2 == 0)
532
r2 = fpzeroreg;
533
if (fpu_type_flags & PA2_0_FPU_FLAG) {
534
/* FTEST if nullify bit set, otherwise FCMP */
535
if (extru(ir, fpnulpos, 1)) { /* FTEST */
536
switch (fmt) {
537
case 0:
538
/*
539
* arg0 is not used
540
* second param is the t field used for
541
* ftest,acc and ftest,rej
542
* third param is the subop (y-field)
543
*/
544
BUG();
545
/* Unsupported
546
* return(ftest(0L,extru(ir,fptpos,5),
547
* &fpregs[0],subop));
548
*/
549
case 1:
550
case 2:
551
case 3:
552
return(MAJOR_0C_EXCP);
553
}
554
} else { /* FCMP */
555
switch (fmt) {
556
case 0:
557
retval = sgl_fcmp(&fpregs[r1],
558
&fpregs[r2],extru(ir,fptpos,5),
559
&local_status);
560
update_status_cbit(status,local_status,
561
fpu_type_flags, subop);
562
return(retval);
563
case 1:
564
retval = dbl_fcmp(&fpregs[r1],
565
&fpregs[r2],extru(ir,fptpos,5),
566
&local_status);
567
update_status_cbit(status,local_status,
568
fpu_type_flags, subop);
569
return(retval);
570
case 2: /* illegal */
571
case 3: /* quad not implemented */
572
return(MAJOR_0C_EXCP);
573
}
574
}
575
} /* end of if for PA2.0 */
576
else { /* PA1.0 & PA1.1 */
577
switch (subop) {
578
case 2:
579
case 3:
580
case 4:
581
case 5:
582
case 6:
583
case 7:
584
return(MAJOR_0C_EXCP);
585
case 0: /* FCMP */
586
switch (fmt) {
587
case 0:
588
retval = sgl_fcmp(&fpregs[r1],
589
&fpregs[r2],extru(ir,fptpos,5),
590
&local_status);
591
update_status_cbit(status,local_status,
592
fpu_type_flags, subop);
593
return(retval);
594
case 1:
595
retval = dbl_fcmp(&fpregs[r1],
596
&fpregs[r2],extru(ir,fptpos,5),
597
&local_status);
598
update_status_cbit(status,local_status,
599
fpu_type_flags, subop);
600
return(retval);
601
case 2: /* illegal */
602
case 3: /* quad not implemented */
603
return(MAJOR_0C_EXCP);
604
}
605
case 1: /* FTEST */
606
switch (fmt) {
607
case 0:
608
/*
609
* arg0 is not used
610
* second param is the t field used for
611
* ftest,acc and ftest,rej
612
* third param is the subop (y-field)
613
*/
614
BUG();
615
/* unsupported
616
* return(ftest(0L,extru(ir,fptpos,5),
617
* &fpregs[0],subop));
618
*/
619
case 1:
620
case 2:
621
case 3:
622
return(MAJOR_0C_EXCP);
623
}
624
} /* end of switch subop */
625
} /* end of else for PA1.0 & PA1.1 */
626
case 3: /* class 3 */
627
r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
628
if (r2 == 0)
629
r2 = fpzeroreg;
630
switch (subop) {
631
case 5:
632
case 6:
633
case 7:
634
return(MAJOR_0C_EXCP);
635
636
case 0: /* FADD */
637
switch (fmt) {
638
case 0:
639
return(sgl_fadd(&fpregs[r1],&fpregs[r2],
640
&fpregs[t],status));
641
case 1:
642
return(dbl_fadd(&fpregs[r1],&fpregs[r2],
643
&fpregs[t],status));
644
case 2: /* illegal */
645
case 3: /* quad not implemented */
646
return(MAJOR_0C_EXCP);
647
}
648
case 1: /* FSUB */
649
switch (fmt) {
650
case 0:
651
return(sgl_fsub(&fpregs[r1],&fpregs[r2],
652
&fpregs[t],status));
653
case 1:
654
return(dbl_fsub(&fpregs[r1],&fpregs[r2],
655
&fpregs[t],status));
656
case 2: /* illegal */
657
case 3: /* quad not implemented */
658
return(MAJOR_0C_EXCP);
659
}
660
case 2: /* FMPY */
661
switch (fmt) {
662
case 0:
663
return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
664
&fpregs[t],status));
665
case 1:
666
return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
667
&fpregs[t],status));
668
case 2: /* illegal */
669
case 3: /* quad not implemented */
670
return(MAJOR_0C_EXCP);
671
}
672
case 3: /* FDIV */
673
switch (fmt) {
674
case 0:
675
return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
676
&fpregs[t],status));
677
case 1:
678
return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
679
&fpregs[t],status));
680
case 2: /* illegal */
681
case 3: /* quad not implemented */
682
return(MAJOR_0C_EXCP);
683
}
684
case 4: /* FREM */
685
switch (fmt) {
686
case 0:
687
return(sgl_frem(&fpregs[r1],&fpregs[r2],
688
&fpregs[t],status));
689
case 1:
690
return(dbl_frem(&fpregs[r1],&fpregs[r2],
691
&fpregs[t],status));
692
case 2: /* illegal */
693
case 3: /* quad not implemented */
694
return(MAJOR_0C_EXCP);
695
}
696
} /* end of class 3 switch */
697
} /* end of switch(class) */
698
699
/* If we get here, something is really wrong! */
700
return(MAJOR_0C_EXCP);
701
}
702
703
static u_int
704
decode_0e(ir,class,subop,fpregs)
705
u_int ir,class,subop;
706
u_int fpregs[];
707
{
708
u_int r1,r2,t; /* operand register offsets */
709
u_int fmt; /* also sf for class 1 conversions */
710
u_int df; /* dest format for class 1 conversions */
711
u_int *status;
712
u_int retval, local_status;
713
u_int fpu_type_flags;
714
715
status = &fpregs[0];
716
local_status = fpregs[0];
717
r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
718
if (r1 == 0)
719
r1 = fpzeroreg;
720
t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
721
if (t == 0 && class != 2)
722
return(MAJOR_0E_EXCP);
723
if (class < 2) /* class 0 or 1 has 2 bit fmt */
724
fmt = extru(ir,fpfmtpos,2);
725
else /* class 2 and 3 have 1 bit fmt */
726
fmt = extru(ir,fp0efmtpos,1);
727
/*
728
* An undefined combination, double precision accessing the
729
* right half of a FPR, can get us into trouble.
730
* Let's just force proper alignment on it.
731
*/
732
if (fmt == DBL) {
733
r1 &= ~1;
734
if (class != 1)
735
t &= ~1;
736
}
737
738
switch (class) {
739
case 0:
740
switch (subop) {
741
case 0: /* unimplemented */
742
case 1:
743
return(MAJOR_0E_EXCP);
744
case 2: /* FCPY */
745
switch (fmt) {
746
case 2:
747
case 3:
748
return(MAJOR_0E_EXCP);
749
case 1: /* double */
750
fpregs[t+1] = fpregs[r1+1];
751
case 0: /* single */
752
fpregs[t] = fpregs[r1];
753
return(NOEXCEPTION);
754
}
755
case 3: /* FABS */
756
switch (fmt) {
757
case 2:
758
case 3:
759
return(MAJOR_0E_EXCP);
760
case 1: /* double */
761
fpregs[t+1] = fpregs[r1+1];
762
case 0: /* single */
763
fpregs[t] = fpregs[r1] & 0x7fffffff;
764
return(NOEXCEPTION);
765
}
766
case 6: /* FNEG */
767
switch (fmt) {
768
case 2:
769
case 3:
770
return(MAJOR_0E_EXCP);
771
case 1: /* double */
772
fpregs[t+1] = fpregs[r1+1];
773
case 0: /* single */
774
fpregs[t] = fpregs[r1] ^ 0x80000000;
775
return(NOEXCEPTION);
776
}
777
case 7: /* FNEGABS */
778
switch (fmt) {
779
case 2:
780
case 3:
781
return(MAJOR_0E_EXCP);
782
case 1: /* double */
783
fpregs[t+1] = fpregs[r1+1];
784
case 0: /* single */
785
fpregs[t] = fpregs[r1] | 0x80000000;
786
return(NOEXCEPTION);
787
}
788
case 4: /* FSQRT */
789
switch (fmt) {
790
case 0:
791
return(sgl_fsqrt(&fpregs[r1],0,
792
&fpregs[t], status));
793
case 1:
794
return(dbl_fsqrt(&fpregs[r1],0,
795
&fpregs[t], status));
796
case 2:
797
case 3:
798
return(MAJOR_0E_EXCP);
799
}
800
case 5: /* FRMD */
801
switch (fmt) {
802
case 0:
803
return(sgl_frnd(&fpregs[r1],0,
804
&fpregs[t], status));
805
case 1:
806
return(dbl_frnd(&fpregs[r1],0,
807
&fpregs[t], status));
808
case 2:
809
case 3:
810
return(MAJOR_0E_EXCP);
811
}
812
} /* end of switch (subop */
813
814
case 1: /* class 1 */
815
df = extru(ir,fpdfpos,2); /* get dest format */
816
/*
817
* Fix Crashme problem (writing to 31R in double precision)
818
* here too.
819
*/
820
if (df == DBL) {
821
t &= ~1;
822
}
823
if ((df & 2) || (fmt & 2))
824
return(MAJOR_0E_EXCP);
825
826
fmt = (fmt << 1) | df;
827
switch (subop) {
828
case 0: /* FCNVFF */
829
switch(fmt) {
830
case 0: /* sgl/sgl */
831
return(MAJOR_0E_EXCP);
832
case 1: /* sgl/dbl */
833
return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
834
&fpregs[t],status));
835
case 2: /* dbl/sgl */
836
return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
837
&fpregs[t],status));
838
case 3: /* dbl/dbl */
839
return(MAJOR_0E_EXCP);
840
}
841
case 1: /* FCNVXF */
842
switch(fmt) {
843
case 0: /* sgl/sgl */
844
return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
845
&fpregs[t],status));
846
case 1: /* sgl/dbl */
847
return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
848
&fpregs[t],status));
849
case 2: /* dbl/sgl */
850
return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
851
&fpregs[t],status));
852
case 3: /* dbl/dbl */
853
return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
854
&fpregs[t],status));
855
}
856
case 2: /* FCNVFX */
857
switch(fmt) {
858
case 0: /* sgl/sgl */
859
return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
860
&fpregs[t],status));
861
case 1: /* sgl/dbl */
862
return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
863
&fpregs[t],status));
864
case 2: /* dbl/sgl */
865
return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
866
&fpregs[t],status));
867
case 3: /* dbl/dbl */
868
return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
869
&fpregs[t],status));
870
}
871
case 3: /* FCNVFXT */
872
switch(fmt) {
873
case 0: /* sgl/sgl */
874
return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
875
&fpregs[t],status));
876
case 1: /* sgl/dbl */
877
return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
878
&fpregs[t],status));
879
case 2: /* dbl/sgl */
880
return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
881
&fpregs[t],status));
882
case 3: /* dbl/dbl */
883
return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
884
&fpregs[t],status));
885
}
886
case 5: /* FCNVUF (PA2.0 only) */
887
switch(fmt) {
888
case 0: /* sgl/sgl */
889
return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
890
&fpregs[t],status));
891
case 1: /* sgl/dbl */
892
return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
893
&fpregs[t],status));
894
case 2: /* dbl/sgl */
895
return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
896
&fpregs[t],status));
897
case 3: /* dbl/dbl */
898
return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
899
&fpregs[t],status));
900
}
901
case 6: /* FCNVFU (PA2.0 only) */
902
switch(fmt) {
903
case 0: /* sgl/sgl */
904
return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
905
&fpregs[t],status));
906
case 1: /* sgl/dbl */
907
return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
908
&fpregs[t],status));
909
case 2: /* dbl/sgl */
910
return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
911
&fpregs[t],status));
912
case 3: /* dbl/dbl */
913
return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
914
&fpregs[t],status));
915
}
916
case 7: /* FCNVFUT (PA2.0 only) */
917
switch(fmt) {
918
case 0: /* sgl/sgl */
919
return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
920
&fpregs[t],status));
921
case 1: /* sgl/dbl */
922
return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
923
&fpregs[t],status));
924
case 2: /* dbl/sgl */
925
return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
926
&fpregs[t],status));
927
case 3: /* dbl/dbl */
928
return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
929
&fpregs[t],status));
930
}
931
case 4: /* undefined */
932
return(MAJOR_0C_EXCP);
933
} /* end of switch subop */
934
case 2: /* class 2 */
935
/*
936
* Be careful out there.
937
* Crashme can generate cases where FR31R is specified
938
* as the source or target of a double precision operation.
939
* Since we just pass the address of the floating-point
940
* register to the emulation routines, this can cause
941
* corruption of fpzeroreg.
942
*/
943
if (fmt == DBL)
944
r2 = (extru(ir,fpr2pos,5)<<1);
945
else
946
r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
947
fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
948
if (r2 == 0)
949
r2 = fpzeroreg;
950
if (fpu_type_flags & PA2_0_FPU_FLAG) {
951
/* FTEST if nullify bit set, otherwise FCMP */
952
if (extru(ir, fpnulpos, 1)) { /* FTEST */
953
/* not legal */
954
return(MAJOR_0E_EXCP);
955
} else { /* FCMP */
956
switch (fmt) {
957
/*
958
* fmt is only 1 bit long
959
*/
960
case 0:
961
retval = sgl_fcmp(&fpregs[r1],
962
&fpregs[r2],extru(ir,fptpos,5),
963
&local_status);
964
update_status_cbit(status,local_status,
965
fpu_type_flags, subop);
966
return(retval);
967
case 1:
968
retval = dbl_fcmp(&fpregs[r1],
969
&fpregs[r2],extru(ir,fptpos,5),
970
&local_status);
971
update_status_cbit(status,local_status,
972
fpu_type_flags, subop);
973
return(retval);
974
}
975
}
976
} /* end of if for PA2.0 */
977
else { /* PA1.0 & PA1.1 */
978
switch (subop) {
979
case 1:
980
case 2:
981
case 3:
982
case 4:
983
case 5:
984
case 6:
985
case 7:
986
return(MAJOR_0E_EXCP);
987
case 0: /* FCMP */
988
switch (fmt) {
989
/*
990
* fmt is only 1 bit long
991
*/
992
case 0:
993
retval = sgl_fcmp(&fpregs[r1],
994
&fpregs[r2],extru(ir,fptpos,5),
995
&local_status);
996
update_status_cbit(status,local_status,
997
fpu_type_flags, subop);
998
return(retval);
999
case 1:
1000
retval = dbl_fcmp(&fpregs[r1],
1001
&fpregs[r2],extru(ir,fptpos,5),
1002
&local_status);
1003
update_status_cbit(status,local_status,
1004
fpu_type_flags, subop);
1005
return(retval);
1006
}
1007
} /* end of switch subop */
1008
} /* end of else for PA1.0 & PA1.1 */
1009
case 3: /* class 3 */
1010
/*
1011
* Be careful out there.
1012
* Crashme can generate cases where FR31R is specified
1013
* as the source or target of a double precision operation.
1014
* Since we just pass the address of the floating-point
1015
* register to the emulation routines, this can cause
1016
* corruption of fpzeroreg.
1017
*/
1018
if (fmt == DBL)
1019
r2 = (extru(ir,fpr2pos,5)<<1);
1020
else
1021
r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
1022
if (r2 == 0)
1023
r2 = fpzeroreg;
1024
switch (subop) {
1025
case 5:
1026
case 6:
1027
case 7:
1028
return(MAJOR_0E_EXCP);
1029
1030
/*
1031
* Note that fmt is only 1 bit for class 3 */
1032
case 0: /* FADD */
1033
switch (fmt) {
1034
case 0:
1035
return(sgl_fadd(&fpregs[r1],&fpregs[r2],
1036
&fpregs[t],status));
1037
case 1:
1038
return(dbl_fadd(&fpregs[r1],&fpregs[r2],
1039
&fpregs[t],status));
1040
}
1041
case 1: /* FSUB */
1042
switch (fmt) {
1043
case 0:
1044
return(sgl_fsub(&fpregs[r1],&fpregs[r2],
1045
&fpregs[t],status));
1046
case 1:
1047
return(dbl_fsub(&fpregs[r1],&fpregs[r2],
1048
&fpregs[t],status));
1049
}
1050
case 2: /* FMPY or XMPYU */
1051
/*
1052
* check for integer multiply (x bit set)
1053
*/
1054
if (extru(ir,fpxpos,1)) {
1055
/*
1056
* emulate XMPYU
1057
*/
1058
switch (fmt) {
1059
case 0:
1060
/*
1061
* bad instruction if t specifies
1062
* the right half of a register
1063
*/
1064
if (t & 1)
1065
return(MAJOR_0E_EXCP);
1066
BUG();
1067
/* unsupported
1068
* impyu(&fpregs[r1],&fpregs[r2],
1069
* &fpregs[t]);
1070
*/
1071
return(NOEXCEPTION);
1072
case 1:
1073
return(MAJOR_0E_EXCP);
1074
}
1075
}
1076
else { /* FMPY */
1077
switch (fmt) {
1078
case 0:
1079
return(sgl_fmpy(&fpregs[r1],
1080
&fpregs[r2],&fpregs[t],status));
1081
case 1:
1082
return(dbl_fmpy(&fpregs[r1],
1083
&fpregs[r2],&fpregs[t],status));
1084
}
1085
}
1086
case 3: /* FDIV */
1087
switch (fmt) {
1088
case 0:
1089
return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
1090
&fpregs[t],status));
1091
case 1:
1092
return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
1093
&fpregs[t],status));
1094
}
1095
case 4: /* FREM */
1096
switch (fmt) {
1097
case 0:
1098
return(sgl_frem(&fpregs[r1],&fpregs[r2],
1099
&fpregs[t],status));
1100
case 1:
1101
return(dbl_frem(&fpregs[r1],&fpregs[r2],
1102
&fpregs[t],status));
1103
}
1104
} /* end of class 3 switch */
1105
} /* end of switch(class) */
1106
1107
/* If we get here, something is really wrong! */
1108
return(MAJOR_0E_EXCP);
1109
}
1110
1111
1112
/*
1113
* routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
1114
*/
1115
static u_int
1116
decode_06(ir,fpregs)
1117
u_int ir;
1118
u_int fpregs[];
1119
{
1120
u_int rm1, rm2, tm, ra, ta; /* operands */
1121
u_int fmt;
1122
u_int error = 0;
1123
u_int status;
1124
u_int fpu_type_flags;
1125
union {
1126
double dbl;
1127
float flt;
1128
struct { u_int i1; u_int i2; } ints;
1129
} mtmp, atmp;
1130
1131
1132
status = fpregs[0]; /* use a local copy of status reg */
1133
fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */
1134
fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
1135
if (fmt == 0) { /* DBL */
1136
rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
1137
if (rm1 == 0)
1138
rm1 = fpzeroreg;
1139
rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
1140
if (rm2 == 0)
1141
rm2 = fpzeroreg;
1142
tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
1143
if (tm == 0)
1144
return(MAJOR_06_EXCP);
1145
ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
1146
ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
1147
if (ta == 0)
1148
return(MAJOR_06_EXCP);
1149
1150
if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) {
1151
1152
if (ra == 0) {
1153
/* special case FMPYCFXT, see sgl case below */
1154
if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
1155
&mtmp.ints.i1,&status))
1156
error = 1;
1157
if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
1158
&atmp.ints.i1,&atmp.ints.i1,&status))
1159
error = 1;
1160
}
1161
else {
1162
1163
if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1164
&status))
1165
error = 1;
1166
if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1167
&status))
1168
error = 1;
1169
}
1170
}
1171
1172
else
1173
1174
{
1175
if (ra == 0)
1176
ra = fpzeroreg;
1177
1178
if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1179
&status))
1180
error = 1;
1181
if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1182
&status))
1183
error = 1;
1184
1185
}
1186
1187
if (error)
1188
return(MAJOR_06_EXCP);
1189
else {
1190
/* copy results */
1191
fpregs[tm] = mtmp.ints.i1;
1192
fpregs[tm+1] = mtmp.ints.i2;
1193
fpregs[ta] = atmp.ints.i1;
1194
fpregs[ta+1] = atmp.ints.i2;
1195
fpregs[0] = status;
1196
return(NOEXCEPTION);
1197
}
1198
}
1199
else { /* SGL */
1200
/*
1201
* calculate offsets for single precision numbers
1202
* See table 6-14 in PA-89 architecture for mapping
1203
*/
1204
rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
1205
rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
1206
1207
rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
1208
rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
1209
1210
tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
1211
tm |= extru(ir,fptmpos-4,1); /* add right word offset */
1212
1213
ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
1214
ra |= extru(ir,fprapos-4,1); /* add right word offset */
1215
1216
ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
1217
ta |= extru(ir,fptapos-4,1); /* add right word offset */
1218
1219
if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
1220
/* special case FMPYCFXT (really 0)
1221
* This instruction is only present on the Timex and
1222
* Rolex fpu's in so if it is the special case and
1223
* one of these fpu's we run the FMPYCFXT instruction
1224
*/
1225
if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1226
&status))
1227
error = 1;
1228
if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
1229
&atmp.ints.i1,&status))
1230
error = 1;
1231
}
1232
else {
1233
if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
1234
&status))
1235
error = 1;
1236
if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
1237
&status))
1238
error = 1;
1239
}
1240
if (error)
1241
return(MAJOR_06_EXCP);
1242
else {
1243
/* copy results */
1244
fpregs[tm] = mtmp.ints.i1;
1245
fpregs[ta] = atmp.ints.i1;
1246
fpregs[0] = status;
1247
return(NOEXCEPTION);
1248
}
1249
}
1250
}
1251
1252
/*
1253
* routine to decode the 26 (FMPYSUB) instruction
1254
*/
1255
static u_int
1256
decode_26(ir,fpregs)
1257
u_int ir;
1258
u_int fpregs[];
1259
{
1260
u_int rm1, rm2, tm, ra, ta; /* operands */
1261
u_int fmt;
1262
u_int error = 0;
1263
u_int status;
1264
union {
1265
double dbl;
1266
float flt;
1267
struct { u_int i1; u_int i2; } ints;
1268
} mtmp, atmp;
1269
1270
1271
status = fpregs[0];
1272
fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
1273
if (fmt == 0) { /* DBL */
1274
rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
1275
if (rm1 == 0)
1276
rm1 = fpzeroreg;
1277
rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
1278
if (rm2 == 0)
1279
rm2 = fpzeroreg;
1280
tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
1281
if (tm == 0)
1282
return(MAJOR_26_EXCP);
1283
ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
1284
if (ra == 0)
1285
return(MAJOR_26_EXCP);
1286
ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
1287
if (ta == 0)
1288
return(MAJOR_26_EXCP);
1289
1290
if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
1291
error = 1;
1292
if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
1293
error = 1;
1294
if (error)
1295
return(MAJOR_26_EXCP);
1296
else {
1297
/* copy results */
1298
fpregs[tm] = mtmp.ints.i1;
1299
fpregs[tm+1] = mtmp.ints.i2;
1300
fpregs[ta] = atmp.ints.i1;
1301
fpregs[ta+1] = atmp.ints.i2;
1302
fpregs[0] = status;
1303
return(NOEXCEPTION);
1304
}
1305
}
1306
else { /* SGL */
1307
/*
1308
* calculate offsets for single precision numbers
1309
* See table 6-14 in PA-89 architecture for mapping
1310
*/
1311
rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
1312
rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
1313
1314
rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
1315
rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
1316
1317
tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
1318
tm |= extru(ir,fptmpos-4,1); /* add right word offset */
1319
1320
ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
1321
ra |= extru(ir,fprapos-4,1); /* add right word offset */
1322
1323
ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
1324
ta |= extru(ir,fptapos-4,1); /* add right word offset */
1325
1326
if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
1327
error = 1;
1328
if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
1329
error = 1;
1330
if (error)
1331
return(MAJOR_26_EXCP);
1332
else {
1333
/* copy results */
1334
fpregs[tm] = mtmp.ints.i1;
1335
fpregs[ta] = atmp.ints.i1;
1336
fpregs[0] = status;
1337
return(NOEXCEPTION);
1338
}
1339
}
1340
1341
}
1342
1343
/*
1344
* routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
1345
*/
1346
static u_int
1347
decode_2e(ir,fpregs)
1348
u_int ir;
1349
u_int fpregs[];
1350
{
1351
u_int rm1, rm2, ra, t; /* operands */
1352
u_int fmt;
1353
1354
fmt = extru(ir,fpfmtpos,1); /* get fmt completer */
1355
if (fmt == DBL) { /* DBL */
1356
rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
1357
if (rm1 == 0)
1358
rm1 = fpzeroreg;
1359
rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
1360
if (rm2 == 0)
1361
rm2 = fpzeroreg;
1362
ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
1363
sizeof(double)/sizeof(u_int);
1364
if (ra == 0)
1365
ra = fpzeroreg;
1366
t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
1367
if (t == 0)
1368
return(MAJOR_2E_EXCP);
1369
1370
if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
1371
return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
1372
&fpregs[ra], &fpregs[0], &fpregs[t]));
1373
} else {
1374
return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
1375
&fpregs[ra], &fpregs[0], &fpregs[t]));
1376
}
1377
} /* end DBL */
1378
else { /* SGL */
1379
rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
1380
if (rm1 == 0)
1381
rm1 = fpzeroreg;
1382
rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
1383
if (rm2 == 0)
1384
rm2 = fpzeroreg;
1385
ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
1386
if (ra == 0)
1387
ra = fpzeroreg;
1388
t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
1389
if (t == 0)
1390
return(MAJOR_2E_EXCP);
1391
1392
if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
1393
return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
1394
&fpregs[ra], &fpregs[0], &fpregs[t]));
1395
} else {
1396
return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
1397
&fpregs[ra], &fpregs[0], &fpregs[t]));
1398
}
1399
} /* end SGL */
1400
}
1401
1402
/*
1403
* update_status_cbit
1404
*
1405
* This routine returns the correct FP status register value in
1406
* *status, based on the C-bit & V-bit returned by the FCMP
1407
* emulation routine in new_status. The architecture type
1408
* (PA83, PA89 or PA2.0) is available in fpu_type. The y_field
1409
* and the architecture type are used to determine what flavor
1410
* of FCMP is being emulated.
1411
*/
1412
static void
1413
update_status_cbit(status, new_status, fpu_type, y_field)
1414
u_int *status, new_status;
1415
u_int fpu_type;
1416
u_int y_field;
1417
{
1418
/*
1419
* For PA89 FPU's which implement the Compare Queue and
1420
* for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
1421
* otherwise update the specified bit in the Compare Array.
1422
* Note that the y-field will always be 0 for non-PA2.0 FPU's.
1423
*/
1424
if ((fpu_type & TIMEX_EXTEN_FLAG) ||
1425
(fpu_type & ROLEX_EXTEN_FLAG) ||
1426
(fpu_type & PA2_0_FPU_FLAG)) {
1427
if (y_field == 0) {
1428
*status = ((*status & 0x04000000) >> 5) | /* old Cbit */
1429
((*status & 0x003ff000) >> 1) | /* old CQ */
1430
(new_status & 0xffc007ff); /* all other bits*/
1431
} else {
1432
*status = (*status & 0x04000000) | /* old Cbit */
1433
((new_status & 0x04000000) >> (y_field+4)) |
1434
(new_status & ~0x04000000 & /* other bits */
1435
~(0x04000000 >> (y_field+4)));
1436
}
1437
}
1438
/* if PA83, just update the C-bit */
1439
else {
1440
*status = new_status;
1441
}
1442
}
1443
1444