]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ki/float.c
libtags, zuke: add *.mod support (thanks kemal)
[plan9front.git] / sys / src / cmd / ki / float.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #define Extern extern
6 #include "sparc.h"
7
8 void
9 ldf(ulong ir)
10 {
11         ulong ea;
12         int rd, rs1, rs2;
13
14         getrop23(ir);
15         if(ir&IMMBIT) {
16                 ximm(ea, ir);
17                 if(trace)
18                         itrace("ldf\tf%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]);
19                 ea += reg.r[rs1];
20         }
21         else {
22                 ea = reg.r[rs1] + reg.r[rs2];
23                 if(trace)
24                         itrace("ldf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
25         }
26
27         reg.di[rd] = getmem_w(ea);
28 }
29
30 void
31 lddf(ulong ir)
32 {
33         ulong ea;
34         int rd, rs1, rs2;
35
36         getrop23(ir);
37         if(ir&IMMBIT) {
38                 ximm(ea, ir);
39                 if(trace)
40                         itrace("lddf\tf%d,0x%lux(r%d) ea=%lux",
41                                                         rd, ea, rs1, ea+reg.r[rs1]);
42                 ea += reg.r[rs1];
43         }
44         else {
45                 ea = reg.r[rs1] + reg.r[rs2];
46                 if(trace)
47                         itrace("lddf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
48         }
49
50         if(ea&7) {
51                 Bprint(bioout, "mem_address_not_aligned [load addr %.8lux]\n", ea);
52                 longjmp(errjmp, 0);
53         }
54         if(rd&1)
55                 undef(ir);
56
57         reg.di[rd] = getmem_w(ea);
58         reg.di[rd+1] = getmem_w(ea+4);
59 }
60
61 void
62 stf(ulong ir)
63 {
64         ulong ea;
65         int rd, rs1, rs2;
66
67         getrop23(ir);
68         if(ir&IMMBIT) {
69                 ximm(ea, ir);
70                 if(trace)
71                         itrace("stf\tf%d,0x%lux(r%d) %lux=%g",
72                                         rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]);
73                 ea += reg.r[rs1];
74         }
75         else {
76                 ea = reg.r[rs1] + reg.r[rs2];
77                 if(trace)
78                         itrace("stf\tf%d,[r%d+r%d] %lux=%lux",
79                                         rd, rs1, rs2, ea, reg.r[rd]);
80         }
81
82         putmem_w(ea, reg.di[rd]);
83 }
84
85 void
86 stdf(ulong ir)
87 {
88         ulong ea;
89         int rd, rs1, rs2;
90
91         getrop23(ir);
92         if(ir&IMMBIT) {
93                 ximm(ea, ir);
94                 if(trace)
95                         itrace("stdf\tf%d,0x%lux(r%d) %lux=%g",
96                                         rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]);
97                 ea += reg.r[rs1];
98         }
99         else {
100                 ea = reg.r[rs1] + reg.r[rs2];
101                 if(trace)
102                         itrace("stdf\tf%d,[r%d+r%d] %lux=%lux",
103                                         rd, rs1, rs2, ea, reg.r[rd]);
104         }
105
106         if(ea&7) {
107                 Bprint(bioout, "mem_address_not_aligned [store addr %.8lux]\n", ea);
108                 longjmp(errjmp, 0);
109         }
110         if(rd&1)
111                 undef(ir);
112
113         putmem_w(ea, reg.di[rd]);
114         putmem_w(ea+4, reg.di[rd+1]);
115 }
116
117 void
118 fcmp(ulong ir)
119 {
120         int fc, rd, rs1, rs2;
121
122         getrop23(ir);
123         USED(rd);
124         SET(fc);
125         switch((ir>>5)&0x1FF) {
126         default:
127                 undef(ir);
128         case 0x51:              /* fcmps */
129                 if(trace)
130                         itrace("fcmps\tf%d,f%d", rs1, rs2);
131                 if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) {
132                         fc = 3;
133                         break;
134                 }
135                 if(reg.fl[rs1] == reg.fl[rs2]) {
136                         fc = 0;
137                         break;
138                 }
139                 if(reg.fl[rs1] < reg.fl[rs2]) {
140                         fc = 1;
141                         break;
142                 }
143                 if(reg.fl[rs1] > reg.fl[rs2]) {
144                         fc = 2;
145                         break;
146                 }
147                 print("ki: fcmp error\n");
148                 break;
149         case 0x52:
150                 if(trace)
151                         itrace("fcmpd\tf%d,f%d", rs1, rs2);
152                 rs1 >>= 1;
153                 rs2 >>= 1;
154                 if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) {
155                         fc = 3;
156                         break;
157                 }
158                 if(reg.fd[rs1] == reg.fd[rs2]) {
159                         fc = 0;
160                         break;
161                 }
162                 if(reg.fd[rs1] < reg.fd[rs2]) {
163                         fc = 1;
164                         break;
165                 }
166                 if(reg.fd[rs1] > reg.fd[rs2]) {
167                         fc = 2;
168                         break;
169                 }
170                 print("ki: fcmp error\n");
171                 break;
172         case 0x55:              /* fcmpes */
173                 if(trace)
174                         itrace("fcmpes\tf%d,f%d", rs1, rs2);
175                 rs1 >>= 1;
176                 rs2 >>= 2;
177                 if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) {
178                         Bprint(bioout, "invalid_fp_register\n");
179                         longjmp(errjmp, 0);
180                 }
181                 if(reg.fl[rs1] == reg.fl[rs2]) {
182                         fc = 0;
183                         break;
184                 }
185                 if(reg.fl[rs1] < reg.fl[rs2]) {
186                         fc = 1;
187                         break;
188                 }
189                 if(reg.fl[rs1] > reg.fl[rs2]) {
190                         fc = 2;
191                         break;
192                 }
193                 print("ki: fcmp error\n");
194                 break;
195         case 0x56:
196                 if(trace)
197                         itrace("fcmped\tf%d,f%d", rs1, rs2);
198                 if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) {
199                         Bprint(bioout, "invalid_fp_register\n");
200                         longjmp(errjmp, 0);
201                 }
202                 if(reg.fd[rs1] == reg.fd[rs2]) {
203                         fc = 0;
204                         break;
205                 }
206                 if(reg.fd[rs1] < reg.fd[rs2]) {
207                         fc = 1;
208                         break;
209                 }
210                 if(reg.fd[rs1] > reg.fd[rs2]) {
211                         fc = 2;
212                         break;
213                 }
214                 print("ki: fcmp error\n");
215                 break;
216
217         }
218         reg.fpsr = (reg.fpsr&~(0x3<<10)) | (fc<<10);
219 }
220
221 void
222 fbcc(ulong ir)
223 {
224         char *op;
225         ulong npc;
226         int takeit, fc, ba, anul;
227
228         fc = (reg.fpsr>>10)&3;
229         ba = 0;
230         SET(op, takeit);
231         switch((ir>>25)&0x0F) {
232         case 0:
233                 op = "fbn";
234                 takeit = 0;
235                 break;
236         case 1:
237                 op = "fbne";
238                 takeit = fc == FP_L || fc == FP_G || fc == FP_U;
239                 break;
240         case 2:
241                 op = "fblg";
242                 takeit = fc == FP_L || fc == FP_G;
243                 break;
244         case 3:
245                 op = "fbul";
246                 takeit = fc == FP_L || fc == FP_U;
247                 break;
248         case 4:
249                 op = "fbl";
250                 takeit = fc == FP_L;
251                 break;
252         case 5:
253                 op = "fbug";
254                 takeit = fc == FP_U || fc == FP_G;
255                 break;
256         case 6:
257                 op = "fbg";
258                 takeit = fc == FP_G;
259                 break;
260         case 7:
261                 op = "fbu";
262                 takeit = fc == FP_U;
263                 break;
264         case 8:
265                 op = "fba";
266                 ba = 1;
267                 takeit = 1;
268                 break;
269         case 9:
270                 op = "fbe";
271                 takeit = fc == FP_E;
272                 break;
273         case 10:
274                 op = "fbue";
275                 takeit = fc == FP_E || fc == FP_U;
276                 break;
277         case 11:
278                 op = "fbge";
279                 takeit = fc == FP_E || fc == FP_G;
280                 break;
281         case 12:
282                 op = "fbuge";
283                 takeit = fc == FP_E || fc == FP_G || fc == FP_U;
284                 break;
285         case 13:
286                 op = "fble";
287                 takeit = fc == FP_E || fc == FP_L;
288                 break;
289         case 14:
290                 op = "fbule";
291                 takeit = fc == FP_E || fc == FP_L || fc == FP_U;
292                 break;
293         case 15:
294                 op = "fbo";
295                 takeit = fc == FP_E || fc == FP_L || fc == FP_G;
296                 break;
297         }
298
299         npc = ir & 0x3FFFFF;
300         if(npc & (1<<21))
301                 npc |= ~((1<<22)-1);
302         npc = (npc<<2) + reg.pc;
303
304         anul = ir&ANUL;
305         if(trace) {
306                 if(anul)
307                         itrace("%s,a\t%lux", op, npc);
308                 else
309                         itrace("%s\t%lux", op, npc);
310         }
311
312         if(takeit == 0) {
313                 reg.pc += 4;
314                 if(anul == 0) {
315                         reg.ir = ifetch(reg.pc);
316                         delay(reg.pc+4);
317                 }
318                 else
319                         anulled++;
320                 return;
321         }
322
323         ci->taken++;
324         if(ba && anul) {
325                 reg.pc = npc-4;
326                 anulled++;
327                 return; 
328         }
329         reg.ir = ifetch(reg.pc+4);
330         delay(npc);
331         reg.pc = npc-4;
332 }
333
334 void
335 farith(ulong ir)
336 {
337         char *op;
338         long v;
339         int rd, rs1, rs2, fmt;
340
341         fmt = 0;
342         getrop23(ir);
343         switch((ir>>5)&0x1FF) {
344         default:
345                 undef(ir);
346         case 0x41:
347                 reg.fl[rd] = reg.fl[rs1] + reg.fl[rs2];
348                 op = "fadds";
349                 break;
350         case 0x42:
351                 reg.fd[rd>>1] = reg.fd[rs1>>1] + reg.fd[rs2>>1];
352                 op = "faddd";
353                 break;
354         case 0x45:
355                 reg.fl[rd] = reg.fl[rs1] - reg.fl[rs2];
356                 op = "fsubs";
357                 break;
358         case 0x46:
359                 reg.fd[rd>>1] = reg.fd[rs1>>1] - reg.fd[rs2>>1];
360                 op = "fsubd";
361                 break;
362         case 0x4d:
363                 if(reg.fl[rs2] == 0.0) {
364                         Bprint(bioout, "fp_exception DZ\n");
365                         longjmp(errjmp, 0);
366                 }
367                 reg.fl[rd] = reg.fl[rs1] / reg.fl[rs2];
368                 op = "fdivs";
369                 break;
370         case 0x4e:
371                 if(reg.fd[rs2>>1] == 0.0) {
372                         Bprint(bioout, "fp_exception DZ\n");
373                         longjmp(errjmp, 0);
374                 }
375                 reg.fd[rd>>1] = reg.fd[rs1>>1] / reg.fd[rs2>>1];
376                 op = "fdivd";
377                 break;
378         case 0x49:
379                 reg.fl[rd] = reg.fl[rs1] * reg.fl[rs2];
380                 op = "fmuls";
381                 break;
382         case 0x4a:
383                 reg.fd[rd>>1] = reg.fd[rs1>>1] * reg.fd[rs2>>1];
384                 op = "fmuld";
385                 break;
386         case 0xc4:
387                 reg.fl[rd] = (long)reg.di[rs2];
388                 fmt = 1;
389                 op = "fitos";
390                 break;
391         case 0xc8:
392                 reg.fd[rd>>1] = (long)reg.di[rs2];
393                 fmt = 1;
394                 op = "fitod";
395                 break;
396         case 0xd1:
397                 v = reg.fl[rs2];
398                 reg.di[rd] = v;
399                 fmt = 1;
400                 op = "fstoi";
401                 break;
402         case 0xd2:
403                 v = reg.fd[rs2>>1];
404                 reg.di[rd] = v;
405                 fmt = 1;
406                 op = "fdtoi";
407                 break;
408         case 0x01:
409                 reg.di[rd] = reg.di[rs2];
410                 fmt = 1;
411                 op = "fmovs";
412                 break;
413         case 0x05:
414                 reg.fl[rd] = -reg.fl[rs2];
415                 fmt = 1;
416                 op = "fnegs";
417                 break;
418         case 0x09:
419                 reg.fl[rd] = fabs(reg.fl[rs2]);
420                 fmt = 1;
421                 op = "fabss";
422                 break;
423         case 0xc9:
424                 reg.fd[rd>>1] = reg.fl[rs2];
425                 fmt = 1;
426                 op = "fstod";
427                 break;
428         case 0xc6:
429                 reg.fl[rd] = reg.fd[rs2>>1];
430                 fmt = 1;
431                 op = "fdtos";
432                 break;
433         }
434
435         if(trace) {
436                 switch(fmt) {
437                 case 0:
438                         itrace("%s\tf%d,f%d,f%d", op, rs1, rs2, rd);
439                         break;
440                 case 1:
441                         itrace("%s\tf%d,f%d", op, rs2, rd);
442                         break;
443                 }
444         }
445 }