]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vi/float.c
sshfs: usage
[plan9front.git] / sys / src / cmd / vi / float.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #define Extern extern
6 #include "mips.h"
7
8 void    unimp(ulong);
9 void    Ifcmp(ulong);
10 void    Ifdiv(ulong);
11 void    Ifmul(ulong);
12 void    Ifadd(ulong);
13 void    Ifsub(ulong);
14 void    Ifmov(ulong);
15 void    Icvtd(ulong);
16 void    Icvtw(ulong);
17 void    Icvts(ulong);
18 void    Ifabs(ulong);
19 void    Ifneg(ulong);
20
21 Inst cop1[] = {
22         { Ifadd,        "add.f", Ifloat },
23         { Ifsub,        "sub.f", Ifloat },
24         { Ifmul,        "mul.f", Ifloat },
25         { Ifdiv,        "div.f", Ifloat },
26         { unimp,        "", },
27         { Ifabs,        "abs.f", Ifloat },
28         { Ifmov,        "mov.f", Ifloat },
29         { Ifneg,        "neg.f", Ifloat },
30         { unimp,        "", },
31         { unimp,        "", },
32         { unimp,        "", },
33         { unimp,        "", },
34         { unimp,        "", },
35         { unimp,        "", },
36         { unimp,        "", },
37         { unimp,        "", },
38         { unimp,        "", },
39         { unimp,        "", },
40         { unimp,        "", },
41         { unimp,        "", },
42         { unimp,        "", },
43         { unimp,        "", },
44         { unimp,        "", },
45         { unimp,        "", },
46         { unimp,        "", },
47         { unimp,        "", },
48         { unimp,        "", },
49         { unimp,        "", },
50         { unimp,        "", },
51         { unimp,        "", },
52         { unimp,        "", },
53         { unimp,        "", },
54         { Icvts,        "cvt.s", Ifloat },
55         { Icvtd,        "cvt.d", Ifloat },
56         { unimp,        "", },
57         { unimp,        "", },
58         { Icvtw,        "cvt.w", Ifloat },
59         { unimp,        "", },
60         { unimp,        "", },
61         { unimp,        "", },
62         { unimp,        "", },
63         { unimp,        "", },
64         { unimp,        "", },
65         { unimp,        "", },
66         { unimp,        "", },
67         { unimp,        "", },
68         { unimp,        "", },
69         { unimp,        "", },
70         { Ifcmp,        "c.f",   Ifloat },
71         { Ifcmp,        "c.un",  Ifloat },
72         { Ifcmp,        "c.eq",  Ifloat },
73         { Ifcmp,        "c.ueq", Ifloat },
74         { Ifcmp,        "c.olt", Ifloat },
75         { Ifcmp,        "c.ult", Ifloat },
76         { Ifcmp,        "c.ole", Ifloat },
77         { Ifcmp,        "c.ule", Ifloat },
78         { Ifcmp,        "c,sf",  Ifloat },
79         { Ifcmp,        "c.ngle",Ifloat },
80         { Ifcmp,        "c.seq", Ifloat },
81         { Ifcmp,        "c.ngl", Ifloat },
82         { Ifcmp,        "c.lt",  Ifloat },
83         { Ifcmp,        "c.nge", Ifloat },
84         { Ifcmp,        "c.le",  Ifloat },
85         { Ifcmp,        "c.ngt", Ifloat },
86         { 0 }
87 };
88
89 void
90 unimp(ulong inst)
91 {
92         print("op %ld\n", inst&0x3f);
93         Bprint(bioout, "Unimplemented floating point Trap IR %.8lux\n", inst);
94         longjmp(errjmp, 0);
95 }
96
97 void
98 inval(ulong inst)
99 {
100         Bprint(bioout, "Invalid Operation Exception IR %.8lux\n", inst);
101         longjmp(errjmp, 0);
102 }
103
104 void
105 ifmt(int r)
106 {
107         Bprint(bioout, "Invalid Floating Data Format f%d pc 0x%lux\n", r, reg.pc);
108         longjmp(errjmp, 0);
109 }
110
111 void
112 floatop(int dst, int s1, int s2)
113 {
114         if(reg.ft[s1] == FPd && s1 != 24)
115                 ifmt(s1);
116         if(reg.ft[s2] == FPd && s2 != 24)
117                 ifmt(s2);
118         reg.ft[dst] = FPs;
119 }
120
121 void
122 doubop(int dst, int s1, int s2)
123 {
124         ulong l;
125
126         if(reg.ft[s1] != FPd) {
127                 if(reg.ft[s1] == FPs && s1 != 24)
128                         ifmt(s1);
129                 l = reg.di[s1];
130                 reg.di[s1] = reg.di[s1+1]; 
131                 reg.di[s1+1] = l; 
132                 reg.ft[s1] = FPd;
133         }
134         if(reg.ft[s2] != FPd) {
135                 if(reg.ft[s2] == FPs && s2 != 24)
136                         ifmt(s2);
137                 l = reg.di[s2];
138                 reg.di[s2] = reg.di[s2+1]; 
139                 reg.di[s2+1] = l; 
140                 reg.ft[s2] = FPd;
141         }
142         reg.ft[dst] = FPd;
143 }
144
145 void
146 Iswc1(ulong inst)
147 {
148         int off;
149         ulong l;
150         int rt, rb, ert;
151
152         Getrbrt(rb, rt, inst);
153         off = (short)(inst&0xffff);
154
155         if(trace)
156                 itrace("swc1\tf%d,0x%x(r%d) ea=%lux", rt, off, rb, reg.r[rb]+off);
157
158         ert = rt&~1;
159         if(reg.ft[ert] == FPd) {
160                 l = reg.di[ert];
161                 reg.di[ert] = reg.di[ert+1]; 
162                 reg.di[ert+1] = l; 
163                 reg.ft[ert] = FPmemory;
164         }
165         putmem_w(reg.r[rb]+off, reg.di[rt]);
166 }
167
168 void
169 Ifsub(ulong ir)
170 {
171         char fmt;
172         int fs, ft, fd;
173
174         Getf3(fs, ft, fd, ir);
175
176         switch((ir>>21)&0xf) {
177         default:
178                 unimp(ir);
179         case 0: /* single */
180                 fmt = 's';
181                 floatop(fd, fs, ft);
182                 reg.fl[fd] = reg.fl[fs] - reg.fl[ft];
183                 break;  
184         case 1: /* double */
185                 fmt = 'd';
186                 doubop(fd, fs, ft);
187                 reg.fd[fd>>1] = reg.fd[fs>>1] - reg.fd[ft>>1];
188                 break;  
189         case 4:
190                 fmt = 'w';
191                 reg.di[fd] = reg.di[fs] - reg.di[ft];
192                 break;
193         }
194         if(trace)
195                 itrace("sub.%c\tf%d,f%d,f%d", fmt, fd, fs, ft);
196 }
197
198 void
199 Ifmov(ulong ir)
200 {
201         char fmt;
202         int fs, fd;
203
204         Getf2(fs, fd, ir);
205
206         switch((ir>>21)&0xf) {
207         default:
208                 unimp(ir);
209         case 0: /* single */
210                 fmt = 's';
211                 reg.fl[fd] = reg.fl[fs];
212                 reg.ft[fd] = reg.ft[fs];
213                 break;  
214         case 1: /* double */
215                 fmt = 'd';
216                 reg.fd[fd>>1] = reg.fd[fs>>1];
217                 reg.ft[fd] = reg.ft[fs];
218                 break;  
219         case 4:
220                 fmt = 'w';
221                 reg.di[fd] = reg.di[fs];
222                 reg.ft[fd] = reg.ft[fs];
223                 break;
224         }
225         if(trace)
226                 itrace("mov.%c\tf%d,f%d", fmt, fd, fs);
227 }
228
229 void
230 Ifabs(ulong ir)
231 {
232         char fmt;
233         int fs, fd;
234
235         Getf2(fs, fd, ir);
236
237         switch((ir>>21)&0xf) {
238         default:
239                 unimp(ir);
240         case 0: /* single */
241                 fmt = 's';
242                 floatop(fd, fs, fs);
243                 if(reg.fl[fs] < 0.0)
244                         reg.fl[fd] = -reg.fl[fs];
245                 else
246                         reg.fl[fd] = reg.fl[fs];
247                 break;  
248         case 1: /* double */
249                 fmt = 'd';
250                 doubop(fd, fs, fs);
251                 if(reg.fd[fs>>1] < 0.0)
252                         reg.fd[fd>>1] = -reg.fd[fs>>1];
253                 else
254                         reg.fd[fd>>1] = reg.fd[fs>>1];
255                 break;  
256         case 4:
257                 fmt = 'w';
258                 if((long)reg.di[fs] < 0)
259                         reg.di[fd] = -reg.di[fs];
260                 else
261                         reg.di[fd] = reg.di[fs];
262                 break;
263         }
264         if(trace)
265                 itrace("abs.%c\tf%d,f%d", fmt, fd, fs);
266 }
267
268 void
269 Ifneg(ulong ir)
270 {
271         char fmt;
272         int fs, fd;
273
274         Getf2(fs, fd, ir);
275
276         switch((ir>>21)&0xf) {
277         default:
278                 unimp(ir);
279         case 0: /* single */
280                 fmt = 's';
281                 floatop(fd, fs, fs);
282                 reg.fl[fd] = -reg.fl[fs];
283                 break;  
284         case 1: /* double */
285                 fmt = 'd';
286                 doubop(fd, fs, fs);
287                 reg.fd[fd>>1] = -reg.fd[fs>>1];
288                 break;  
289         case 4:
290                 fmt = 'w';
291                 reg.di[fd] = -reg.di[fs];
292                 break;
293         }
294         if(trace)
295                 itrace("neg.%c\tf%d,f%d", fmt, fd, fs);
296 }
297
298 void
299 Icvtd(ulong ir)
300 {
301         char fmt;
302         int fs, fd;
303
304         Getf2(fs, fd, ir);
305
306         switch((ir>>21)&0xf) {
307         default:
308                 unimp(ir);
309         case 0: /* single */
310                 fmt = 's';
311                 floatop(fs, fs, fs);
312                 reg.fd[fd>>1] = reg.fl[fs];
313                 reg.ft[fd] = FPd;
314                 break;  
315         case 1: /* double */
316                 fmt = 'd';
317                 doubop(fd, fs, fs);
318                 reg.fd[fd>>1] = reg.fd[fs>>1];
319                 break;  
320         case 4:
321                 fmt = 'w';
322                 reg.fd[fd>>1] = (long)reg.di[fs];
323                 reg.ft[fd] = FPd;
324                 break;
325         }
326         if(trace)
327                 itrace("cvt.d.%c\tf%d,f%d", fmt, fd, fs);
328 }
329
330 void
331 Icvts(ulong ir)
332 {
333         char fmt;
334         int fs, fd;
335
336         Getf2(fs, fd, ir);
337
338         switch((ir>>21)&0xf) {
339         default:
340                 unimp(ir);
341         case 0: /* single */
342                 fmt = 's';
343                 floatop(fd, fs, fs);
344                 reg.fl[fd] = reg.fl[fs];
345                 break;  
346         case 1: /* double */
347                 fmt = 'd';
348                 doubop(fs, fs, fs);
349                 reg.fl[fd] = reg.fd[fs>>1];
350                 reg.ft[fd] = FPs;
351                 break;  
352         case 4:
353                 fmt = 'w';
354                 reg.fl[fd] = (long)reg.di[fs];
355                 reg.ft[fd] = FPs;
356                 break;
357         }
358         if(trace)
359                 itrace("cvt.s.%c\tf%d,f%d", fmt, fd, fs);
360 }
361
362 void
363 Icvtw(ulong ir)
364 {
365         long v;
366         char fmt;
367         int fs, fd;
368
369         Getf2(fs, fd, ir);
370
371         switch((ir>>21)&0xf) {
372         default:
373                 unimp(ir);
374         case 0: /* single */
375                 fmt = 's';
376                 floatop(fs, fs, fs);
377                 v = reg.fl[fs];
378                 break;  
379         case 1: /* double */
380                 fmt = 'd';
381                 doubop(fs, fs, fs);
382                 v = reg.fd[fs>>1];
383                 break;  
384         case 4:
385                 fmt = 'w';
386                 v = reg.di[fs];
387                 break;
388         }
389         reg.di[fd] = v;
390         reg.ft[fd] = FPmemory;
391         if(trace)
392                 itrace("cvt.w.%c\tf%d,f%d", fmt, fd, fs);
393 }
394
395 void
396 Ifadd(ulong ir)
397 {
398         char fmt;
399         int fs, ft, fd;
400
401         Getf3(fs, ft, fd, ir);
402
403         switch((ir>>21)&0xf) {
404         default:
405                 unimp(ir);
406         case 0: /* single */
407                 fmt = 's';
408                 floatop(fd, fs, ft);
409                 reg.fl[fd] = reg.fl[fs] + reg.fl[ft];
410                 break;  
411         case 1: /* double */
412                 fmt = 'd';
413                 doubop(fd, fs, ft);
414                 reg.fd[fd>>1] = reg.fd[fs>>1] + reg.fd[ft>>1];
415                 break;  
416         case 4:
417                 fmt = 'w';
418                 reg.di[fd] = reg.di[fs] + reg.di[ft];
419                 break;
420         }
421         if(trace)
422                 itrace("add.%c\tf%d,f%d,f%d", fmt, fd, fs, ft);
423 }
424
425 void
426 Ifmul(ulong ir)
427 {
428         char fmt;
429         int fs, ft, fd;
430
431         Getf3(fs, ft, fd, ir);
432
433         switch((ir>>21)&0xf) {
434         default:
435                 unimp(ir);
436         case 0: /* single */
437                 fmt = 's';
438                 floatop(fd, fs, ft);
439                 reg.fl[fd] = reg.fl[fs] * reg.fl[ft];
440                 break;  
441         case 1: /* double */
442                 fmt = 'd';
443                 doubop(fd, fs, ft);
444                 reg.fd[fd>>1] = reg.fd[fs>>1] * reg.fd[ft>>1];
445                 break;  
446         case 4:
447                 fmt = 'w';
448                 reg.di[fd] = reg.di[fs] * reg.di[ft];
449                 break;
450         }
451         if(trace)
452                 itrace("mul.%c\tf%d,f%d,f%d", fmt, fd, fs, ft);
453 }
454
455 void
456 Ifdiv(ulong ir)
457 {
458         char fmt;
459         int fs, ft, fd;
460
461         Getf3(fs, ft, fd, ir);
462
463         switch((ir>>21)&0xf) {
464         default:
465                 unimp(ir);
466         case 0: /* single */
467                 fmt = 's';
468                 floatop(fd, fs, ft);
469                 reg.fl[fd] = reg.fl[fs] / reg.fl[ft];
470                 break;  
471         case 1: /* double */
472                 fmt = 'd';
473                 doubop(fd, fs, ft);
474                 reg.fd[fd>>1] = reg.fd[fs>>1] / reg.fd[ft>>1];
475                 break;  
476         case 4:
477                 fmt = 'w';
478                 reg.di[fd] = reg.di[fs] / reg.di[ft];
479                 break;
480         }
481         if(trace)
482                 itrace("div.%c\tf%d,f%d,f%d", fmt, fd, fs, ft);
483 }
484
485 void
486 Ilwc1(ulong inst)
487 {
488         int rt, rb;
489         int off;
490
491         Getrbrt(rb, rt, inst);
492         off = (short)(inst&0xffff);
493
494         if(trace)
495                 itrace("lwc1\tf%d,0x%x(r%d) ea=%lux", rt, off, rb, reg.r[rb]+off);
496
497         reg.di[rt] = getmem_w(reg.r[rb]+off);
498         reg.ft[rt] = FPmemory;
499 }
500
501 void
502 Ibcfbct(ulong inst)
503 {
504         int takeit;
505         int off;
506         ulong npc;
507
508         off = (short)(inst&0xffff);
509
510         takeit = 0;
511         npc = reg.pc + (off<<2) + 4;
512         if(inst&(1<<16)) {
513                 if(trace)
514                         itrace("bc1t\t0x%lux", npc);
515
516                 if(reg.fpsr&FP_CBIT)
517                         takeit = 1;
518         }
519         else {
520                 if(trace)
521                         itrace("bc1f\t0x%lux", npc);
522
523                 if((reg.fpsr&FP_CBIT) == 0)
524                         takeit = 1;
525         }
526
527         if(takeit) {
528                 /* Do the delay slot */
529                 reg.ir = ifetch(reg.pc+4);
530                 Statbra();
531                 Iexec(reg.ir);
532                 reg.pc = npc-4;
533         }
534 }
535
536 void
537 Imtct(ulong ir)
538 {
539         int rt, fs;
540
541         SpecialGetrtrd(rt, fs, ir);
542         if(ir&(1<<22)) {                        /* CT */
543                 if(trace)
544                         itrace("ctc1\tr%d,f%d", rt, fs);
545         }
546         else {                                  /* MT */
547                 if(trace)
548                         itrace("mtc1\tr%d,f%d", rt, fs);
549
550                 reg.di[fs] = reg.r[rt];
551                 reg.ft[fs] = FPmemory;
552         }
553 }
554
555 void
556 Imfcf(ulong ir)
557 {
558         int rt, fs;
559
560         SpecialGetrtrd(rt, fs, ir);
561         if(ir&(1<<22)) {        /* CF */
562                 if(trace)
563                         itrace("cfc1\tr%d,f%d", rt, fs);
564         }
565         else {                  /* MF */
566                 if(trace)
567                         itrace("mfc1\tr%d,f%d", rt, fs);
568
569                 reg.r[rt] = reg.di[fs];
570         }
571 }
572
573 void
574 Icop1(ulong ir)
575 {
576         Inst *i;
577
578         switch((ir>>23)&7) {
579         case 0:
580                 Imfcf(ir);
581                 break;
582         case 1:
583                 Imtct(ir);
584                 break;
585         case 2:
586         case 3:
587                 Ibcfbct(ir);
588                 break;
589         case 4:
590         case 5:
591         case 6:
592         case 7:
593                 i = &cop1[ir&0x3f];
594                 i->count++;
595                 (*i->func)(ir);
596         }
597 }
598
599 void
600 Ifcmp(ulong ir)
601 {
602         char fmt;
603         int fc;
604         int ft, fs;
605
606         SpecialGetrtrd(ft, fs, ir);
607
608         SET(fc);
609         switch((ir>>21)&0xf) {
610         default:
611                 unimp(ir);
612         case 0: /* single */
613                 fmt = 's';
614                 floatop(fs, fs, ft);
615                 if(isNaN(reg.fl[fs]) || isNaN(reg.fl[ft])) {
616                         fc = FP_U;
617                         break;
618                 }
619                 if(reg.fl[fs] == reg.fl[ft]) {
620                         fc = FP_E;
621                         break;
622                 }
623                 if(reg.fl[fs] < reg.fl[ft]) {
624                         fc = FP_L;
625                         break;
626                 }
627                 if(reg.fl[fs] > reg.fl[ft]) {
628                         fc = FP_G;
629                         break;
630                 }
631                 print("vi: bad in fcmp");
632                 break;  
633         case 1: /* double */
634                 fmt = 'd';
635                 doubop(fs, fs, ft);
636                 if(isNaN(reg.fd[fs>>1]) || isNaN(reg.fd[ft>>1])) {
637                         fc = FP_U;
638                         break;
639                 }
640                 if(reg.fd[fs>>1] == reg.fd[ft>>1]) {
641                         fc = FP_E;
642                         break;
643                 }
644                 if(reg.fd[fs>>1] < reg.fd[ft>>1]) {
645                         fc = FP_L;
646                         break;
647                 }
648                 if(reg.fd[fs>>1] > reg.fd[ft>>1]) {
649                         fc = FP_G;
650                         break;
651                 }
652                 print("vi: bad in fcmp");
653                 break;  
654         case 4:
655                 fmt = 'w';
656                 if(reg.di[fs] == reg.di[ft]) {
657                         fc = FP_E;
658                         break;
659                 }
660                 if(reg.di[fs] < reg.di[ft]) {
661                         fc = FP_L;
662                         break;
663                 }
664                 if(reg.di[fs] > reg.di[ft]) {
665                         fc = FP_G;
666                         break;
667                 }
668                 break;
669         }
670
671         reg.fpsr &= ~FP_CBIT;
672         switch(ir&0xf) {
673         case 0:
674                 if(trace)
675                         itrace("c.f.%c\tf%d,f%d", fmt, fs, ft);
676                 break;
677         case 1:
678                 if(trace)
679                         itrace("c.un.%c\tf%d,f%d", fmt, fs, ft);
680                 if(fc == FP_U)
681                         reg.fpsr |= FP_CBIT;    
682                 break;
683         case 2:
684                 if(trace)
685                         itrace("c.eq.%c\tf%d,f%d", fmt, fs, ft);
686                 if(fc == FP_E)
687                         reg.fpsr |= FP_CBIT;    
688                 break;
689         case 3:
690                 if(trace)
691                         itrace("c.ueq.%c\tf%d,f%d", fmt, fs, ft);
692                 if(fc == FP_E || fc == FP_U)
693                         reg.fpsr |= FP_CBIT;    
694                 break;
695         case 4:
696                 if(trace)
697                         itrace("c.lt.%c\tf%d,f%d", fmt, fs, ft);
698                 if(fc == FP_L)
699                         reg.fpsr |= FP_CBIT;    
700                 break;
701         case 5:
702                 if(trace)
703                         itrace("c.ult.%c\tf%d,f%d", fmt, fs, ft);
704                 if(fc == FP_L || fc == FP_U)
705                         reg.fpsr |= FP_CBIT;    
706                 break;
707         case 6:
708                 if(trace)
709                         itrace("c.le.%c\tf%d,f%d", fmt, fs, ft);
710                 if(fc == FP_E || fc == FP_L)
711                         reg.fpsr |= FP_CBIT;    
712                 break;
713         case 7:
714                 if(trace)
715                         itrace("c.ule.%c\tf%d,f%d", fmt, fs, ft);
716                 if(fc == FP_E || fc == FP_L || fc == FP_U)
717                         reg.fpsr |= FP_CBIT;    
718                 break;
719         case 8:
720                 if(trace)
721                         itrace("c.sf.%c\tf%d,f%d", fmt, fs, ft);
722                 if(fc == FP_U)
723                         inval(ir);
724                 break;
725         case 9:
726                 if(trace)
727                         itrace("c.ngle.%c\tf%d,f%d", fmt, fs, ft);
728                 if(fc == FP_U) {
729                         reg.fpsr |= FP_CBIT;
730                         inval(ir);
731                 }
732                 break;
733         case 10:
734                 if(trace)
735                         itrace("c.seq.%c\tf%d,f%d", fmt, fs, ft);
736                 if(fc == FP_E)
737                         reg.fpsr |= FP_CBIT;    
738                 if(fc == FP_U)
739                         inval(ir);
740                 break;
741         case 11:
742                 if(trace)
743                         itrace("c.ngl.%c\tf%d,f%d", fmt, fs, ft);
744                 if(fc == FP_E || fc == FP_U)
745                         reg.fpsr |= FP_CBIT;    
746                 if(fc == FP_U)
747                         inval(ir);
748                 break;
749         case 12:
750                 if(trace)
751                         itrace("c.lt.%c\tf%d,f%d", fmt, fs, ft);
752                 if(fc == FP_L)
753                         reg.fpsr |= FP_CBIT;    
754                 if(fc == FP_U)
755                         inval(ir);
756                 break;
757         case 13:
758                 if(trace)
759                         itrace("c.nge.%c\tf%d,f%d", fmt, fs, ft);
760                 if(fc == FP_L || fc == FP_U)
761                         reg.fpsr |= FP_CBIT;    
762                 if(fc == FP_U)
763                         inval(ir);
764                 break;
765         case 14:
766                 if(trace)
767                         itrace("c.le.%c\tf%d,f%d", fmt, fs, ft);
768                 if(fc == FP_E || fc == FP_L)
769                         reg.fpsr |= FP_CBIT;    
770                 if(fc == FP_U)
771                         inval(ir);
772                 break;
773         case 15:
774                 if(trace)
775                         itrace("c.ngt.%c\tf%d,f%d", fmt, fs, ft);
776                 if(fc == FP_E || fc == FP_L || fc == FP_U)
777                         reg.fpsr |= FP_CBIT;    
778                 if(fc == FP_U)
779                         inval(ir);
780                 break;
781         }
782         USED(fmt);
783 }