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 } 446