]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5e/vfp.c
merge
[plan9front.git] / sys / src / cmd / 5e / vfp.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <bio.h>
5 #include <mach.h>
6 #include "dat.h"
7 #include "fns.h"
8
9 void
10 resetvfp(void)
11 {
12         int i;
13
14         P->FPSR = 0x00000000;
15         for(i = 0; i < Nfpregs; i++)
16                 P->F[i] = 0;
17 }
18
19 void
20 vfpregtransfer(u32int instr)
21 {
22         u32int *Rt;
23         long double *Fn;
24         Rt = P->R + ((instr>>12)&0xF);
25         Fn = P->F + ((instr>>16)&0xF);
26
27         switch((instr>>20)&0xF){
28         case 0:
29                 *((int*)Fn) = *Rt; break;
30         case 1:
31                 *Rt = *((int*)Fn); break;
32         case 14:
33                 P->FPSR = *Rt; break;
34         case 15:
35                 if(Rt == (P->R + 15))
36                         P->CPSR = P->FPSR;
37                 else
38                         *Rt = P->FPSR;
39                 break;
40         default:
41                 sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
42         }
43 }
44
45 void
46 vfprmtransfer(u32int instr)
47 {
48         int n, d, off, sz;
49         void* ea;
50         Segment *seg;
51
52         n = (instr>>16) & 0xF;
53         d = (instr>>12) & 0xF;
54         off = (instr & 0xFF) << 2;
55         sz = instr & (1<<8);
56         if((instr & (1<<23)) == 0)
57                 off = -off;
58         ea = vaddr(P->R[n] + off, 8, &seg);
59
60         switch((instr>>20)&0x3){
61         case 0:
62                 if(sz)
63                         *(double*)ea = P->F[d];
64                 else
65                         *(float*)ea = P->F[d];
66                 break;
67         case 1:
68                 if(sz)
69                         P->F[d] = *(double*)ea;
70                 else
71                         P->F[d] = *(float*)ea;
72                 break;
73         default:
74                 sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
75         }
76         segunlock(seg);
77 }
78
79 void
80 vfparithop(int opc, u32int instr)
81 {
82         int o;
83         long double *Fd, *Fn, *Fm;
84         Fd = P->F + ((instr>>12)&0xF);
85         Fn = P->F + ((instr>>16)&0xF);
86         Fm = P->F + (instr&0xF);
87         o = ((opc&0x3)<<1) | (opc&0x8) | ((instr>>6)&0x1);
88
89         switch(o){
90         case 4:
91                 *Fd = *Fn * *Fm; break;
92         case 6:
93                 *Fd = *Fn + *Fm; break;
94         case 7:
95                 *Fd = *Fn - *Fm; break;
96         case 8:
97                 *Fd = *Fn / *Fm; break;
98         default:
99                 sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
100         }
101 }
102
103 void
104 vfpotherop(u32int instr)
105 {
106         int o2, o3;
107         long double *Fd, *Fm, F0;
108         Fd = P->F + ((instr>>12)&0xF);
109         Fm = P->F + (instr&0xF);
110         F0 = 0.0;
111         o2 = (instr>>16) & 0xF;
112         o3 = (instr>>6) & 0x3;
113
114         if((o3&1) == 0)
115                 sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
116         switch(o2){
117         case 0x5:
118                 Fm = &F0;
119         case 0x4:
120                 if(*Fd < *Fm)
121                         P->FPSR = (P->FPSR & ~FLAGS) | flN;
122                 else if(*Fd >= *Fm) {
123                         P->FPSR = (P->FPSR & ~FLAGS) | flC;
124                         if(*Fd == *Fm)
125                                 P->FPSR |= flZ;
126                 } else
127                         P->FPSR = (P->FPSR & ~FLAGS) | flV | flC;
128                 break;
129         case 0x8:
130                 *Fd = *((int*)Fm); break;
131         case 0xD:
132                 *((int*)Fd) = (int)*Fm; break;
133         default:
134                 switch((o2<<1)|(o3>>1)){
135                 case 0:
136                 case 15:
137                         *Fd = *Fm; break;
138                 case 1:
139                         *Fd = fabs(*Fm); break;
140                 case 2:
141                         *Fd = -*Fm; break;
142                 case 3:
143                         *Fd = sqrt(*Fm); break;
144                 default:
145                         sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
146                 }
147         }
148 }
149
150 void
151 vfpoperation(u32int instr)
152 {
153         int o1;
154         o1 = (instr>>20) & 0xF;
155         if(o1 == 0xB)
156                 vfpotherop(instr);
157         else
158                 vfparithop(o1, instr);
159 }
160