xref: /plan9/sys/src/cmd/ki/float.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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
ldf(ulong ir)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
lddf(ulong ir)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
stf(ulong ir)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
stdf(ulong ir)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
fcmp(ulong ir)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
fbcc(ulong ir)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
farith(ulong ir)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 }
446