xref: /plan9/sys/src/cmd/vi/float.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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
unimp(ulong inst)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
inval(ulong inst)98 inval(ulong inst)
99 {
100 	Bprint(bioout, "Invalid Operation Exception IR %.8lux\n", inst);
101 	longjmp(errjmp, 0);
102 }
103 
104 void
ifmt(int r)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
floatop(int dst,int s1,int s2)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
doubop(int dst,int s1,int s2)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
Iswc1(ulong inst)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
Ifsub(ulong ir)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
Ifmov(ulong ir)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
Ifabs(ulong ir)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
Ifneg(ulong ir)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
Icvtd(ulong ir)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
Icvts(ulong ir)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
Icvtw(ulong ir)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
Ifadd(ulong ir)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
Ifmul(ulong ir)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
Ifdiv(ulong ir)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
Ilwc1(ulong inst)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
Ibcfbct(ulong inst)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
Imtct(ulong ir)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
Imfcf(ulong ir)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
Icop1(ulong ir)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
Ifcmp(ulong ir)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 }
784