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