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