Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.21 2255 lines 74 kB view raw
1/* 2 * arch/s390/math-emu/math.c 3 * 4 * S390 version 5 * Copyright (C) 1999-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 7 * 8 * 'math.c' emulates IEEE instructions on a S390 processor 9 * that does not have the IEEE fpu (all processors before G5). 10 */ 11 12#include <linux/types.h> 13#include <linux/sched.h> 14#include <linux/mm.h> 15#include <asm/uaccess.h> 16#include <asm/lowcore.h> 17 18#include <asm/sfp-util.h> 19#include <math-emu/soft-fp.h> 20#include <math-emu/single.h> 21#include <math-emu/double.h> 22#include <math-emu/quad.h> 23 24/* 25 * I miss a macro to round a floating point number to the 26 * nearest integer in the same floating point format. 27 */ 28#define _FP_TO_FPINT_ROUND(fs, wc, X) \ 29 do { \ 30 switch (X##_c) \ 31 { \ 32 case FP_CLS_NORMAL: \ 33 if (X##_e > _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs) \ 34 { /* floating point number has no bits after the dot. */ \ 35 } \ 36 else if (X##_e <= _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs && \ 37 X##_e > _FP_EXPBIAS_##fs) \ 38 { /* some bits before the dot, some after it. */ \ 39 _FP_FRAC_SRS_##wc(X, _FP_WFRACBITS_##fs, \ 40 X##_e - _FP_EXPBIAS_##fs \ 41 + _FP_FRACBITS_##fs); \ 42 _FP_ROUND(wc, X); \ 43 _FP_FRAC_SLL_##wc(X, X##_e - _FP_EXPBIAS_##fs \ 44 + _FP_FRACBITS_##fs); \ 45 } \ 46 else \ 47 { /* all bits after the dot. */ \ 48 FP_SET_EXCEPTION(FP_EX_INEXACT); \ 49 X##_c = FP_CLS_ZERO; \ 50 } \ 51 break; \ 52 case FP_CLS_NAN: \ 53 case FP_CLS_INF: \ 54 case FP_CLS_ZERO: \ 55 break; \ 56 } \ 57 } while (0) 58 59#define FP_TO_FPINT_ROUND_S(X) _FP_TO_FPINT_ROUND(S,1,X) 60#define FP_TO_FPINT_ROUND_D(X) _FP_TO_FPINT_ROUND(D,2,X) 61#define FP_TO_FPINT_ROUND_Q(X) _FP_TO_FPINT_ROUND(Q,4,X) 62 63typedef union { 64 long double ld; 65 struct { 66 __u64 high; 67 __u64 low; 68 } w; 69} mathemu_ldcv; 70 71#ifdef CONFIG_SYSCTL 72int sysctl_ieee_emulation_warnings=1; 73#endif 74 75#define mathemu_put_user(x, p) \ 76 do { \ 77 if (put_user((x),(p))) \ 78 return SIGSEGV; \ 79 } while (0) 80 81#define mathemu_get_user(x, p) \ 82 do { \ 83 if (get_user((x),(p))) \ 84 return SIGSEGV; \ 85 } while (0) 86 87#define mathemu_copy_from_user(d, s, n)\ 88 do { \ 89 if (copy_from_user((d),(s),(n)) != 0) \ 90 return SIGSEGV; \ 91 } while (0) 92 93#define mathemu_copy_to_user(d, s, n) \ 94 do { \ 95 if (copy_to_user((d),(s),(n)) != 0) \ 96 return SIGSEGV; \ 97 } while (0) 98 99static void display_emulation_not_implemented(struct pt_regs *regs, char *instr) 100{ 101 __u16 *location; 102 103#ifdef CONFIG_SYSCTL 104 if(sysctl_ieee_emulation_warnings) 105#endif 106 { 107 location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc); 108 printk("%s ieee fpu instruction not emulated " 109 "process name: %s pid: %d \n", 110 instr, current->comm, current->pid); 111 printk("%s's PSW: %08lx %08lx\n", instr, 112 (unsigned long) regs->psw.mask, 113 (unsigned long) location); 114 } 115} 116 117static inline void emu_set_CC (struct pt_regs *regs, int cc) 118{ 119 regs->psw.mask = (regs->psw.mask & 0xFFFFCFFF) | ((cc&3) << 12); 120} 121 122/* 123 * Set the condition code in the user psw. 124 * 0 : Result is zero 125 * 1 : Result is less than zero 126 * 2 : Result is greater than zero 127 * 3 : Result is NaN or INF 128 */ 129static inline void emu_set_CC_cs(struct pt_regs *regs, int class, int sign) 130{ 131 switch (class) { 132 case FP_CLS_NORMAL: 133 case FP_CLS_INF: 134 emu_set_CC(regs, sign ? 1 : 2); 135 break; 136 case FP_CLS_ZERO: 137 emu_set_CC(regs, 0); 138 break; 139 case FP_CLS_NAN: 140 emu_set_CC(regs, 3); 141 break; 142 } 143} 144 145/* Add long double */ 146static int emu_axbr (struct pt_regs *regs, int rx, int ry) { 147 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR); 148 FP_DECL_EX; 149 mathemu_ldcv cvt; 150 int mode; 151 152 mode = current->thread.fp_regs.fpc & 3; 153 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 154 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 155 FP_UNPACK_QP(QA, &cvt.ld); 156 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 157 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 158 FP_UNPACK_QP(QB, &cvt.ld); 159 FP_ADD_Q(QR, QA, QB); 160 FP_PACK_QP(&cvt.ld, QR); 161 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 162 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 163 emu_set_CC_cs(regs, QR_c, QR_s); 164 return _fex; 165} 166 167/* Add double */ 168static int emu_adbr (struct pt_regs *regs, int rx, int ry) { 169 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 170 FP_DECL_EX; 171 int mode; 172 173 mode = current->thread.fp_regs.fpc & 3; 174 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 175 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d); 176 FP_ADD_D(DR, DA, DB); 177 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 178 emu_set_CC_cs(regs, DR_c, DR_s); 179 return _fex; 180} 181 182/* Add double */ 183static int emu_adb (struct pt_regs *regs, int rx, double *val) { 184 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 185 FP_DECL_EX; 186 int mode; 187 188 mode = current->thread.fp_regs.fpc & 3; 189 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 190 FP_UNPACK_DP(DB, val); 191 FP_ADD_D(DR, DA, DB); 192 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 193 emu_set_CC_cs(regs, DR_c, DR_s); 194 return _fex; 195} 196 197/* Add float */ 198static int emu_aebr (struct pt_regs *regs, int rx, int ry) { 199 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 200 FP_DECL_EX; 201 int mode; 202 203 mode = current->thread.fp_regs.fpc & 3; 204 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 205 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f); 206 FP_ADD_S(SR, SA, SB); 207 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 208 emu_set_CC_cs(regs, SR_c, SR_s); 209 return _fex; 210} 211 212/* Add float */ 213static int emu_aeb (struct pt_regs *regs, int rx, float *val) { 214 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 215 FP_DECL_EX; 216 int mode; 217 218 mode = current->thread.fp_regs.fpc & 3; 219 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 220 FP_UNPACK_SP(SB, val); 221 FP_ADD_S(SR, SA, SB); 222 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 223 emu_set_CC_cs(regs, SR_c, SR_s); 224 return _fex; 225} 226 227/* Compare long double */ 228static int emu_cxbr (struct pt_regs *regs, int rx, int ry) { 229 FP_DECL_Q(QA); FP_DECL_Q(QB); 230 mathemu_ldcv cvt; 231 int IR; 232 233 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 234 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 235 FP_UNPACK_RAW_QP(QA, &cvt.ld); 236 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 237 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 238 FP_UNPACK_RAW_QP(QB, &cvt.ld); 239 FP_CMP_Q(IR, QA, QB, 3); 240 /* 241 * IR == -1 if DA < DB, IR == 0 if DA == DB, 242 * IR == 1 if DA > DB and IR == 3 if unorderded 243 */ 244 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 245 return 0; 246} 247 248/* Compare double */ 249static int emu_cdbr (struct pt_regs *regs, int rx, int ry) { 250 FP_DECL_D(DA); FP_DECL_D(DB); 251 int IR; 252 253 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d); 254 FP_UNPACK_RAW_DP(DB, &current->thread.fp_regs.fprs[ry].d); 255 FP_CMP_D(IR, DA, DB, 3); 256 /* 257 * IR == -1 if DA < DB, IR == 0 if DA == DB, 258 * IR == 1 if DA > DB and IR == 3 if unorderded 259 */ 260 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 261 return 0; 262} 263 264/* Compare double */ 265static int emu_cdb (struct pt_regs *regs, int rx, double *val) { 266 FP_DECL_D(DA); FP_DECL_D(DB); 267 int IR; 268 269 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d); 270 FP_UNPACK_RAW_DP(DB, val); 271 FP_CMP_D(IR, DA, DB, 3); 272 /* 273 * IR == -1 if DA < DB, IR == 0 if DA == DB, 274 * IR == 1 if DA > DB and IR == 3 if unorderded 275 */ 276 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 277 return 0; 278} 279 280/* Compare float */ 281static int emu_cebr (struct pt_regs *regs, int rx, int ry) { 282 FP_DECL_S(SA); FP_DECL_S(SB); 283 int IR; 284 285 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f); 286 FP_UNPACK_RAW_SP(SB, &current->thread.fp_regs.fprs[ry].f); 287 FP_CMP_S(IR, SA, SB, 3); 288 /* 289 * IR == -1 if DA < DB, IR == 0 if DA == DB, 290 * IR == 1 if DA > DB and IR == 3 if unorderded 291 */ 292 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 293 return 0; 294} 295 296/* Compare float */ 297static int emu_ceb (struct pt_regs *regs, int rx, float *val) { 298 FP_DECL_S(SA); FP_DECL_S(SB); 299 int IR; 300 301 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f); 302 FP_UNPACK_RAW_SP(SB, val); 303 FP_CMP_S(IR, SA, SB, 3); 304 /* 305 * IR == -1 if DA < DB, IR == 0 if DA == DB, 306 * IR == 1 if DA > DB and IR == 3 if unorderded 307 */ 308 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 309 return 0; 310} 311 312/* Compare and signal long double */ 313static int emu_kxbr (struct pt_regs *regs, int rx, int ry) { 314 FP_DECL_Q(QA); FP_DECL_Q(QB); 315 FP_DECL_EX; 316 mathemu_ldcv cvt; 317 int IR; 318 319 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 320 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 321 FP_UNPACK_RAW_QP(QA, &cvt.ld); 322 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 323 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 324 FP_UNPACK_QP(QB, &cvt.ld); 325 FP_CMP_Q(IR, QA, QB, 3); 326 /* 327 * IR == -1 if DA < DB, IR == 0 if DA == DB, 328 * IR == 1 if DA > DB and IR == 3 if unorderded 329 */ 330 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 331 if (IR == 3) 332 FP_SET_EXCEPTION (FP_EX_INVALID); 333 return _fex; 334} 335 336/* Compare and signal double */ 337static int emu_kdbr (struct pt_regs *regs, int rx, int ry) { 338 FP_DECL_D(DA); FP_DECL_D(DB); 339 FP_DECL_EX; 340 int IR; 341 342 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d); 343 FP_UNPACK_RAW_DP(DB, &current->thread.fp_regs.fprs[ry].d); 344 FP_CMP_D(IR, DA, DB, 3); 345 /* 346 * IR == -1 if DA < DB, IR == 0 if DA == DB, 347 * IR == 1 if DA > DB and IR == 3 if unorderded 348 */ 349 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 350 if (IR == 3) 351 FP_SET_EXCEPTION (FP_EX_INVALID); 352 return _fex; 353} 354 355/* Compare and signal double */ 356static int emu_kdb (struct pt_regs *regs, int rx, double *val) { 357 FP_DECL_D(DA); FP_DECL_D(DB); 358 FP_DECL_EX; 359 int IR; 360 361 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d); 362 FP_UNPACK_RAW_DP(DB, val); 363 FP_CMP_D(IR, DA, DB, 3); 364 /* 365 * IR == -1 if DA < DB, IR == 0 if DA == DB, 366 * IR == 1 if DA > DB and IR == 3 if unorderded 367 */ 368 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 369 if (IR == 3) 370 FP_SET_EXCEPTION (FP_EX_INVALID); 371 return _fex; 372} 373 374/* Compare and signal float */ 375static int emu_kebr (struct pt_regs *regs, int rx, int ry) { 376 FP_DECL_S(SA); FP_DECL_S(SB); 377 FP_DECL_EX; 378 int IR; 379 380 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f); 381 FP_UNPACK_RAW_SP(SB, &current->thread.fp_regs.fprs[ry].f); 382 FP_CMP_S(IR, SA, SB, 3); 383 /* 384 * IR == -1 if DA < DB, IR == 0 if DA == DB, 385 * IR == 1 if DA > DB and IR == 3 if unorderded 386 */ 387 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 388 if (IR == 3) 389 FP_SET_EXCEPTION (FP_EX_INVALID); 390 return _fex; 391} 392 393/* Compare and signal float */ 394static int emu_keb (struct pt_regs *regs, int rx, float *val) { 395 FP_DECL_S(SA); FP_DECL_S(SB); 396 FP_DECL_EX; 397 int IR; 398 399 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f); 400 FP_UNPACK_RAW_SP(SB, val); 401 FP_CMP_S(IR, SA, SB, 3); 402 /* 403 * IR == -1 if DA < DB, IR == 0 if DA == DB, 404 * IR == 1 if DA > DB and IR == 3 if unorderded 405 */ 406 emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR); 407 if (IR == 3) 408 FP_SET_EXCEPTION (FP_EX_INVALID); 409 return _fex; 410} 411 412/* Convert from fixed long double */ 413static int emu_cxfbr (struct pt_regs *regs, int rx, int ry) { 414 FP_DECL_Q(QR); 415 FP_DECL_EX; 416 mathemu_ldcv cvt; 417 __s32 si; 418 int mode; 419 420 mode = current->thread.fp_regs.fpc & 3; 421 si = regs->gprs[ry]; 422 FP_FROM_INT_Q(QR, si, 32, int); 423 FP_PACK_QP(&cvt.ld, QR); 424 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 425 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 426 return _fex; 427} 428 429/* Convert from fixed double */ 430static int emu_cdfbr (struct pt_regs *regs, int rx, int ry) { 431 FP_DECL_D(DR); 432 FP_DECL_EX; 433 __s32 si; 434 int mode; 435 436 mode = current->thread.fp_regs.fpc & 3; 437 si = regs->gprs[ry]; 438 FP_FROM_INT_D(DR, si, 32, int); 439 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 440 return _fex; 441} 442 443/* Convert from fixed float */ 444static int emu_cefbr (struct pt_regs *regs, int rx, int ry) { 445 FP_DECL_S(SR); 446 FP_DECL_EX; 447 __s32 si; 448 int mode; 449 450 mode = current->thread.fp_regs.fpc & 3; 451 si = regs->gprs[ry]; 452 FP_FROM_INT_S(SR, si, 32, int); 453 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 454 return _fex; 455} 456 457/* Convert to fixed long double */ 458static int emu_cfxbr (struct pt_regs *regs, int rx, int ry, int mask) { 459 FP_DECL_Q(QA); 460 FP_DECL_EX; 461 mathemu_ldcv cvt; 462 __s32 si; 463 int mode; 464 465 if (mask == 0) 466 mode = current->thread.fp_regs.fpc & 3; 467 else if (mask == 1) 468 mode = FP_RND_NEAREST; 469 else 470 mode = mask - 4; 471 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 472 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 473 FP_UNPACK_QP(QA, &cvt.ld); 474 FP_TO_INT_ROUND_Q(si, QA, 32, 1); 475 regs->gprs[rx] = si; 476 emu_set_CC_cs(regs, QA_c, QA_s); 477 return _fex; 478} 479 480/* Convert to fixed double */ 481static int emu_cfdbr (struct pt_regs *regs, int rx, int ry, int mask) { 482 FP_DECL_D(DA); 483 FP_DECL_EX; 484 __s32 si; 485 int mode; 486 487 if (mask == 0) 488 mode = current->thread.fp_regs.fpc & 3; 489 else if (mask == 1) 490 mode = FP_RND_NEAREST; 491 else 492 mode = mask - 4; 493 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 494 FP_TO_INT_ROUND_D(si, DA, 32, 1); 495 regs->gprs[rx] = si; 496 emu_set_CC_cs(regs, DA_c, DA_s); 497 return _fex; 498} 499 500/* Convert to fixed float */ 501static int emu_cfebr (struct pt_regs *regs, int rx, int ry, int mask) { 502 FP_DECL_S(SA); 503 FP_DECL_EX; 504 __s32 si; 505 int mode; 506 507 if (mask == 0) 508 mode = current->thread.fp_regs.fpc & 3; 509 else if (mask == 1) 510 mode = FP_RND_NEAREST; 511 else 512 mode = mask - 4; 513 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 514 FP_TO_INT_ROUND_S(si, SA, 32, 1); 515 regs->gprs[rx] = si; 516 emu_set_CC_cs(regs, SA_c, SA_s); 517 return _fex; 518} 519 520/* Divide long double */ 521static int emu_dxbr (struct pt_regs *regs, int rx, int ry) { 522 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR); 523 FP_DECL_EX; 524 mathemu_ldcv cvt; 525 int mode; 526 527 mode = current->thread.fp_regs.fpc & 3; 528 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 529 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 530 FP_UNPACK_QP(QA, &cvt.ld); 531 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 532 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 533 FP_UNPACK_QP(QB, &cvt.ld); 534 FP_DIV_Q(QR, QA, QB); 535 FP_PACK_QP(&cvt.ld, QR); 536 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 537 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 538 return _fex; 539} 540 541/* Divide double */ 542static int emu_ddbr (struct pt_regs *regs, int rx, int ry) { 543 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 544 FP_DECL_EX; 545 int mode; 546 547 mode = current->thread.fp_regs.fpc & 3; 548 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 549 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d); 550 FP_DIV_D(DR, DA, DB); 551 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 552 return _fex; 553} 554 555/* Divide double */ 556static int emu_ddb (struct pt_regs *regs, int rx, double *val) { 557 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 558 FP_DECL_EX; 559 int mode; 560 561 mode = current->thread.fp_regs.fpc & 3; 562 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 563 FP_UNPACK_DP(DB, val); 564 FP_DIV_D(DR, DA, DB); 565 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 566 return _fex; 567} 568 569/* Divide float */ 570static int emu_debr (struct pt_regs *regs, int rx, int ry) { 571 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 572 FP_DECL_EX; 573 int mode; 574 575 mode = current->thread.fp_regs.fpc & 3; 576 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 577 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f); 578 FP_DIV_S(SR, SA, SB); 579 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 580 return _fex; 581} 582 583/* Divide float */ 584static int emu_deb (struct pt_regs *regs, int rx, float *val) { 585 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 586 FP_DECL_EX; 587 int mode; 588 589 mode = current->thread.fp_regs.fpc & 3; 590 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 591 FP_UNPACK_SP(SB, val); 592 FP_DIV_S(SR, SA, SB); 593 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 594 return _fex; 595} 596 597/* Divide to integer double */ 598static int emu_didbr (struct pt_regs *regs, int rx, int ry, int mask) { 599 display_emulation_not_implemented(regs, "didbr"); 600 return 0; 601} 602 603/* Divide to integer float */ 604static int emu_diebr (struct pt_regs *regs, int rx, int ry, int mask) { 605 display_emulation_not_implemented(regs, "diebr"); 606 return 0; 607} 608 609/* Extract fpc */ 610static int emu_efpc (struct pt_regs *regs, int rx, int ry) { 611 regs->gprs[rx] = current->thread.fp_regs.fpc; 612 return 0; 613} 614 615/* Load and test long double */ 616static int emu_ltxbr (struct pt_regs *regs, int rx, int ry) { 617 s390_fp_regs *fp_regs = &current->thread.fp_regs; 618 mathemu_ldcv cvt; 619 FP_DECL_Q(QA); 620 FP_DECL_EX; 621 622 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 623 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 624 FP_UNPACK_QP(QA, &cvt.ld); 625 fp_regs->fprs[rx].ui = fp_regs->fprs[ry].ui; 626 fp_regs->fprs[rx+2].ui = fp_regs->fprs[ry+2].ui; 627 emu_set_CC_cs(regs, QA_c, QA_s); 628 return _fex; 629} 630 631/* Load and test double */ 632static int emu_ltdbr (struct pt_regs *regs, int rx, int ry) { 633 s390_fp_regs *fp_regs = &current->thread.fp_regs; 634 FP_DECL_D(DA); 635 FP_DECL_EX; 636 637 FP_UNPACK_DP(DA, &fp_regs->fprs[ry].d); 638 fp_regs->fprs[rx].ui = fp_regs->fprs[ry].ui; 639 emu_set_CC_cs(regs, DA_c, DA_s); 640 return _fex; 641} 642 643/* Load and test double */ 644static int emu_ltebr (struct pt_regs *regs, int rx, int ry) { 645 s390_fp_regs *fp_regs = &current->thread.fp_regs; 646 FP_DECL_S(SA); 647 FP_DECL_EX; 648 649 FP_UNPACK_SP(SA, &fp_regs->fprs[ry].f); 650 fp_regs->fprs[rx].ui = fp_regs->fprs[ry].ui; 651 emu_set_CC_cs(regs, SA_c, SA_s); 652 return _fex; 653} 654 655/* Load complement long double */ 656static int emu_lcxbr (struct pt_regs *regs, int rx, int ry) { 657 FP_DECL_Q(QA); FP_DECL_Q(QR); 658 FP_DECL_EX; 659 mathemu_ldcv cvt; 660 int mode; 661 662 mode = current->thread.fp_regs.fpc & 3; 663 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 664 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 665 FP_UNPACK_QP(QA, &cvt.ld); 666 FP_NEG_Q(QR, QA); 667 FP_PACK_QP(&cvt.ld, QR); 668 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 669 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 670 emu_set_CC_cs(regs, QR_c, QR_s); 671 return _fex; 672} 673 674/* Load complement double */ 675static int emu_lcdbr (struct pt_regs *regs, int rx, int ry) { 676 FP_DECL_D(DA); FP_DECL_D(DR); 677 FP_DECL_EX; 678 int mode; 679 680 mode = current->thread.fp_regs.fpc & 3; 681 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 682 FP_NEG_D(DR, DA); 683 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 684 emu_set_CC_cs(regs, DR_c, DR_s); 685 return _fex; 686} 687 688/* Load complement float */ 689static int emu_lcebr (struct pt_regs *regs, int rx, int ry) { 690 FP_DECL_S(SA); FP_DECL_S(SR); 691 FP_DECL_EX; 692 int mode; 693 694 mode = current->thread.fp_regs.fpc & 3; 695 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 696 FP_NEG_S(SR, SA); 697 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 698 emu_set_CC_cs(regs, SR_c, SR_s); 699 return _fex; 700} 701 702/* Load floating point integer long double */ 703static int emu_fixbr (struct pt_regs *regs, int rx, int ry, int mask) { 704 s390_fp_regs *fp_regs = &current->thread.fp_regs; 705 FP_DECL_Q(QA); 706 FP_DECL_EX; 707 mathemu_ldcv cvt; 708 __s32 si; 709 int mode; 710 711 if (mask == 0) 712 mode = fp_regs->fpc & 3; 713 else if (mask == 1) 714 mode = FP_RND_NEAREST; 715 else 716 mode = mask - 4; 717 cvt.w.high = fp_regs->fprs[ry].ui; 718 cvt.w.low = fp_regs->fprs[ry+2].ui; 719 FP_UNPACK_QP(QA, &cvt.ld); 720 FP_TO_FPINT_ROUND_Q(QA); 721 FP_PACK_QP(&cvt.ld, QA); 722 fp_regs->fprs[rx].ui = cvt.w.high; 723 fp_regs->fprs[rx+2].ui = cvt.w.low; 724 return _fex; 725} 726 727/* Load floating point integer double */ 728static int emu_fidbr (struct pt_regs *regs, int rx, int ry, int mask) { 729 /* FIXME: rounding mode !! */ 730 s390_fp_regs *fp_regs = &current->thread.fp_regs; 731 FP_DECL_D(DA); 732 FP_DECL_EX; 733 __s32 si; 734 int mode; 735 736 if (mask == 0) 737 mode = fp_regs->fpc & 3; 738 else if (mask == 1) 739 mode = FP_RND_NEAREST; 740 else 741 mode = mask - 4; 742 FP_UNPACK_DP(DA, &fp_regs->fprs[ry].d); 743 FP_TO_FPINT_ROUND_D(DA); 744 FP_PACK_DP(&fp_regs->fprs[rx].d, DA); 745 return _fex; 746} 747 748/* Load floating point integer float */ 749static int emu_fiebr (struct pt_regs *regs, int rx, int ry, int mask) { 750 s390_fp_regs *fp_regs = &current->thread.fp_regs; 751 FP_DECL_S(SA); 752 FP_DECL_EX; 753 __s32 si; 754 int mode; 755 756 if (mask == 0) 757 mode = fp_regs->fpc & 3; 758 else if (mask == 1) 759 mode = FP_RND_NEAREST; 760 else 761 mode = mask - 4; 762 FP_UNPACK_SP(SA, &fp_regs->fprs[ry].f); 763 FP_TO_FPINT_ROUND_S(SA); 764 FP_PACK_SP(&fp_regs->fprs[rx].f, SA); 765 return _fex; 766} 767 768/* Load lengthened double to long double */ 769static int emu_lxdbr (struct pt_regs *regs, int rx, int ry) { 770 FP_DECL_D(DA); FP_DECL_Q(QR); 771 FP_DECL_EX; 772 mathemu_ldcv cvt; 773 int mode; 774 775 mode = current->thread.fp_regs.fpc & 3; 776 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 777 FP_CONV (Q, D, 4, 2, QR, DA); 778 FP_PACK_QP(&cvt.ld, QR); 779 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 780 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 781 return _fex; 782} 783 784/* Load lengthened double to long double */ 785static int emu_lxdb (struct pt_regs *regs, int rx, double *val) { 786 FP_DECL_D(DA); FP_DECL_Q(QR); 787 FP_DECL_EX; 788 mathemu_ldcv cvt; 789 int mode; 790 791 mode = current->thread.fp_regs.fpc & 3; 792 FP_UNPACK_DP(DA, val); 793 FP_CONV (Q, D, 4, 2, QR, DA); 794 FP_PACK_QP(&cvt.ld, QR); 795 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 796 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 797 return _fex; 798} 799 800/* Load lengthened float to long double */ 801static int emu_lxebr (struct pt_regs *regs, int rx, int ry) { 802 FP_DECL_S(SA); FP_DECL_Q(QR); 803 FP_DECL_EX; 804 mathemu_ldcv cvt; 805 int mode; 806 807 mode = current->thread.fp_regs.fpc & 3; 808 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 809 FP_CONV (Q, S, 4, 1, QR, SA); 810 FP_PACK_QP(&cvt.ld, QR); 811 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 812 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 813 return _fex; 814} 815 816/* Load lengthened float to long double */ 817static int emu_lxeb (struct pt_regs *regs, int rx, float *val) { 818 FP_DECL_S(SA); FP_DECL_Q(QR); 819 FP_DECL_EX; 820 mathemu_ldcv cvt; 821 int mode; 822 823 mode = current->thread.fp_regs.fpc & 3; 824 FP_UNPACK_SP(SA, val); 825 FP_CONV (Q, S, 4, 1, QR, SA); 826 FP_PACK_QP(&cvt.ld, QR); 827 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 828 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 829 return _fex; 830} 831 832/* Load lengthened float to double */ 833static int emu_ldebr (struct pt_regs *regs, int rx, int ry) { 834 FP_DECL_S(SA); FP_DECL_D(DR); 835 FP_DECL_EX; 836 int mode; 837 838 mode = current->thread.fp_regs.fpc & 3; 839 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 840 FP_CONV (D, S, 2, 1, DR, SA); 841 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 842 return _fex; 843} 844 845/* Load lengthened float to double */ 846static int emu_ldeb (struct pt_regs *regs, int rx, float *val) { 847 FP_DECL_S(SA); FP_DECL_D(DR); 848 FP_DECL_EX; 849 int mode; 850 851 mode = current->thread.fp_regs.fpc & 3; 852 FP_UNPACK_SP(SA, val); 853 FP_CONV (D, S, 2, 1, DR, SA); 854 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 855 return _fex; 856} 857 858/* Load negative long double */ 859static int emu_lnxbr (struct pt_regs *regs, int rx, int ry) { 860 FP_DECL_Q(QA); FP_DECL_Q(QR); 861 FP_DECL_EX; 862 mathemu_ldcv cvt; 863 int mode; 864 865 mode = current->thread.fp_regs.fpc & 3; 866 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 867 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 868 FP_UNPACK_QP(QA, &cvt.ld); 869 if (QA_s == 0) { 870 FP_NEG_Q(QR, QA); 871 FP_PACK_QP(&cvt.ld, QR); 872 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 873 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 874 } else { 875 current->thread.fp_regs.fprs[rx].ui = 876 current->thread.fp_regs.fprs[ry].ui; 877 current->thread.fp_regs.fprs[rx+2].ui = 878 current->thread.fp_regs.fprs[ry+2].ui; 879 } 880 emu_set_CC_cs(regs, QR_c, QR_s); 881 return _fex; 882} 883 884/* Load negative double */ 885static int emu_lndbr (struct pt_regs *regs, int rx, int ry) { 886 FP_DECL_D(DA); FP_DECL_D(DR); 887 FP_DECL_EX; 888 int mode; 889 890 mode = current->thread.fp_regs.fpc & 3; 891 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 892 if (DA_s == 0) { 893 FP_NEG_D(DR, DA); 894 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 895 } else 896 current->thread.fp_regs.fprs[rx].ui = 897 current->thread.fp_regs.fprs[ry].ui; 898 emu_set_CC_cs(regs, DR_c, DR_s); 899 return _fex; 900} 901 902/* Load negative float */ 903static int emu_lnebr (struct pt_regs *regs, int rx, int ry) { 904 FP_DECL_S(SA); FP_DECL_S(SR); 905 FP_DECL_EX; 906 int mode; 907 908 mode = current->thread.fp_regs.fpc & 3; 909 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 910 if (SA_s == 0) { 911 FP_NEG_S(SR, SA); 912 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 913 } else 914 current->thread.fp_regs.fprs[rx].ui = 915 current->thread.fp_regs.fprs[ry].ui; 916 emu_set_CC_cs(regs, SR_c, SR_s); 917 return _fex; 918} 919 920/* Load positive long double */ 921static int emu_lpxbr (struct pt_regs *regs, int rx, int ry) { 922 FP_DECL_Q(QA); FP_DECL_Q(QR); 923 FP_DECL_EX; 924 mathemu_ldcv cvt; 925 int mode; 926 927 mode = current->thread.fp_regs.fpc & 3; 928 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 929 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 930 FP_UNPACK_QP(QA, &cvt.ld); 931 if (QA_s != 0) { 932 FP_NEG_Q(QR, QA); 933 FP_PACK_QP(&cvt.ld, QR); 934 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 935 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 936 } else{ 937 current->thread.fp_regs.fprs[rx].ui = 938 current->thread.fp_regs.fprs[ry].ui; 939 current->thread.fp_regs.fprs[rx+2].ui = 940 current->thread.fp_regs.fprs[ry+2].ui; 941 } 942 emu_set_CC_cs(regs, QR_c, QR_s); 943 return _fex; 944} 945 946/* Load positive double */ 947static int emu_lpdbr (struct pt_regs *regs, int rx, int ry) { 948 FP_DECL_D(DA); FP_DECL_D(DR); 949 FP_DECL_EX; 950 int mode; 951 952 mode = current->thread.fp_regs.fpc & 3; 953 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 954 if (DA_s != 0) { 955 FP_NEG_D(DR, DA); 956 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 957 } else 958 current->thread.fp_regs.fprs[rx].ui = 959 current->thread.fp_regs.fprs[ry].ui; 960 emu_set_CC_cs(regs, DR_c, DR_s); 961 return _fex; 962} 963 964/* Load positive float */ 965static int emu_lpebr (struct pt_regs *regs, int rx, int ry) { 966 FP_DECL_S(SA); FP_DECL_S(SR); 967 FP_DECL_EX; 968 int mode; 969 970 mode = current->thread.fp_regs.fpc & 3; 971 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 972 if (SA_s != 0) { 973 FP_NEG_S(SR, SA); 974 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 975 } else 976 current->thread.fp_regs.fprs[rx].ui = 977 current->thread.fp_regs.fprs[ry].ui; 978 emu_set_CC_cs(regs, SR_c, SR_s); 979 return _fex; 980} 981 982/* Load rounded long double to double */ 983static int emu_ldxbr (struct pt_regs *regs, int rx, int ry) { 984 FP_DECL_Q(QA); FP_DECL_D(DR); 985 FP_DECL_EX; 986 mathemu_ldcv cvt; 987 int mode; 988 989 mode = current->thread.fp_regs.fpc & 3; 990 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 991 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 992 FP_UNPACK_QP(QA, &cvt.ld); 993 FP_CONV (D, Q, 2, 4, DR, QA); 994 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].f, DR); 995 return _fex; 996} 997 998/* Load rounded long double to float */ 999static int emu_lexbr (struct pt_regs *regs, int rx, int ry) { 1000 FP_DECL_Q(QA); FP_DECL_S(SR); 1001 FP_DECL_EX; 1002 mathemu_ldcv cvt; 1003 int mode; 1004 1005 mode = current->thread.fp_regs.fpc & 3; 1006 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 1007 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 1008 FP_UNPACK_QP(QA, &cvt.ld); 1009 FP_CONV (S, Q, 1, 4, SR, QA); 1010 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1011 return _fex; 1012} 1013 1014/* Load rounded double to float */ 1015static int emu_ledbr (struct pt_regs *regs, int rx, int ry) { 1016 FP_DECL_D(DA); FP_DECL_S(SR); 1017 FP_DECL_EX; 1018 int mode; 1019 1020 mode = current->thread.fp_regs.fpc & 3; 1021 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 1022 FP_CONV (S, D, 1, 2, SR, DA); 1023 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1024 return _fex; 1025} 1026 1027/* Multiply long double */ 1028static int emu_mxbr (struct pt_regs *regs, int rx, int ry) { 1029 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR); 1030 FP_DECL_EX; 1031 mathemu_ldcv cvt; 1032 int mode; 1033 1034 mode = current->thread.fp_regs.fpc & 3; 1035 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 1036 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 1037 FP_UNPACK_QP(QA, &cvt.ld); 1038 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 1039 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 1040 FP_UNPACK_QP(QB, &cvt.ld); 1041 FP_MUL_Q(QR, QA, QB); 1042 FP_PACK_QP(&cvt.ld, QR); 1043 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 1044 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 1045 return _fex; 1046} 1047 1048/* Multiply double */ 1049static int emu_mdbr (struct pt_regs *regs, int rx, int ry) { 1050 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 1051 FP_DECL_EX; 1052 int mode; 1053 1054 mode = current->thread.fp_regs.fpc & 3; 1055 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1056 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d); 1057 FP_MUL_D(DR, DA, DB); 1058 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1059 return _fex; 1060} 1061 1062/* Multiply double */ 1063static int emu_mdb (struct pt_regs *regs, int rx, double *val) { 1064 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 1065 FP_DECL_EX; 1066 int mode; 1067 1068 mode = current->thread.fp_regs.fpc & 3; 1069 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1070 FP_UNPACK_DP(DB, val); 1071 FP_MUL_D(DR, DA, DB); 1072 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1073 return _fex; 1074} 1075 1076/* Multiply double to long double */ 1077static int emu_mxdbr (struct pt_regs *regs, int rx, int ry) { 1078 FP_DECL_D(DA); FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR); 1079 FP_DECL_EX; 1080 mathemu_ldcv cvt; 1081 int mode; 1082 1083 mode = current->thread.fp_regs.fpc & 3; 1084 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1085 FP_CONV (Q, D, 4, 2, QA, DA); 1086 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 1087 FP_CONV (Q, D, 4, 2, QB, DA); 1088 FP_MUL_Q(QR, QA, QB); 1089 FP_PACK_QP(&cvt.ld, QR); 1090 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 1091 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 1092 return _fex; 1093} 1094 1095/* Multiply double to long double */ 1096static int emu_mxdb (struct pt_regs *regs, int rx, long double *val) { 1097 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR); 1098 FP_DECL_EX; 1099 mathemu_ldcv cvt; 1100 int mode; 1101 1102 mode = current->thread.fp_regs.fpc & 3; 1103 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 1104 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 1105 FP_UNPACK_QP(QA, &cvt.ld); 1106 FP_UNPACK_QP(QB, val); 1107 FP_MUL_Q(QR, QA, QB); 1108 FP_PACK_QP(&cvt.ld, QR); 1109 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 1110 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 1111 return _fex; 1112} 1113 1114/* Multiply float */ 1115static int emu_meebr (struct pt_regs *regs, int rx, int ry) { 1116 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 1117 FP_DECL_EX; 1118 int mode; 1119 1120 mode = current->thread.fp_regs.fpc & 3; 1121 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1122 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f); 1123 FP_MUL_S(SR, SA, SB); 1124 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1125 return _fex; 1126} 1127 1128/* Multiply float */ 1129static int emu_meeb (struct pt_regs *regs, int rx, float *val) { 1130 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 1131 FP_DECL_EX; 1132 int mode; 1133 1134 mode = current->thread.fp_regs.fpc & 3; 1135 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1136 FP_UNPACK_SP(SB, val); 1137 FP_MUL_S(SR, SA, SB); 1138 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1139 return _fex; 1140} 1141 1142/* Multiply float to double */ 1143static int emu_mdebr (struct pt_regs *regs, int rx, int ry) { 1144 FP_DECL_S(SA); FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 1145 FP_DECL_EX; 1146 int mode; 1147 1148 mode = current->thread.fp_regs.fpc & 3; 1149 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1150 FP_CONV (D, S, 2, 1, DA, SA); 1151 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 1152 FP_CONV (D, S, 2, 1, DB, SA); 1153 FP_MUL_D(DR, DA, DB); 1154 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1155 return _fex; 1156} 1157 1158/* Multiply float to double */ 1159static int emu_mdeb (struct pt_regs *regs, int rx, float *val) { 1160 FP_DECL_S(SA); FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 1161 FP_DECL_EX; 1162 int mode; 1163 1164 mode = current->thread.fp_regs.fpc & 3; 1165 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1166 FP_CONV (D, S, 2, 1, DA, SA); 1167 FP_UNPACK_SP(SA, val); 1168 FP_CONV (D, S, 2, 1, DB, SA); 1169 FP_MUL_D(DR, DA, DB); 1170 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1171 return _fex; 1172} 1173 1174/* Multiply and add double */ 1175static int emu_madbr (struct pt_regs *regs, int rx, int ry, int rz) { 1176 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR); 1177 FP_DECL_EX; 1178 int mode; 1179 1180 mode = current->thread.fp_regs.fpc & 3; 1181 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1182 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d); 1183 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d); 1184 FP_MUL_D(DR, DA, DB); 1185 FP_ADD_D(DR, DR, DC); 1186 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR); 1187 return _fex; 1188} 1189 1190/* Multiply and add double */ 1191static int emu_madb (struct pt_regs *regs, int rx, double *val, int rz) { 1192 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR); 1193 FP_DECL_EX; 1194 int mode; 1195 1196 mode = current->thread.fp_regs.fpc & 3; 1197 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1198 FP_UNPACK_DP(DB, val); 1199 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d); 1200 FP_MUL_D(DR, DA, DB); 1201 FP_ADD_D(DR, DR, DC); 1202 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR); 1203 return _fex; 1204} 1205 1206/* Multiply and add float */ 1207static int emu_maebr (struct pt_regs *regs, int rx, int ry, int rz) { 1208 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR); 1209 FP_DECL_EX; 1210 int mode; 1211 1212 mode = current->thread.fp_regs.fpc & 3; 1213 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1214 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f); 1215 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f); 1216 FP_MUL_S(SR, SA, SB); 1217 FP_ADD_S(SR, SR, SC); 1218 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR); 1219 return _fex; 1220} 1221 1222/* Multiply and add float */ 1223static int emu_maeb (struct pt_regs *regs, int rx, float *val, int rz) { 1224 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR); 1225 FP_DECL_EX; 1226 int mode; 1227 1228 mode = current->thread.fp_regs.fpc & 3; 1229 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1230 FP_UNPACK_SP(SB, val); 1231 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f); 1232 FP_MUL_S(SR, SA, SB); 1233 FP_ADD_S(SR, SR, SC); 1234 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR); 1235 return _fex; 1236} 1237 1238/* Multiply and subtract double */ 1239static int emu_msdbr (struct pt_regs *regs, int rx, int ry, int rz) { 1240 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR); 1241 FP_DECL_EX; 1242 int mode; 1243 1244 mode = current->thread.fp_regs.fpc & 3; 1245 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1246 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d); 1247 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d); 1248 FP_MUL_D(DR, DA, DB); 1249 FP_SUB_D(DR, DR, DC); 1250 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR); 1251 return _fex; 1252} 1253 1254/* Multiply and subtract double */ 1255static int emu_msdb (struct pt_regs *regs, int rx, double *val, int rz) { 1256 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DC); FP_DECL_D(DR); 1257 FP_DECL_EX; 1258 int mode; 1259 1260 mode = current->thread.fp_regs.fpc & 3; 1261 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1262 FP_UNPACK_DP(DB, val); 1263 FP_UNPACK_DP(DC, &current->thread.fp_regs.fprs[rz].d); 1264 FP_MUL_D(DR, DA, DB); 1265 FP_SUB_D(DR, DR, DC); 1266 FP_PACK_DP(&current->thread.fp_regs.fprs[rz].d, DR); 1267 return _fex; 1268} 1269 1270/* Multiply and subtract float */ 1271static int emu_msebr (struct pt_regs *regs, int rx, int ry, int rz) { 1272 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR); 1273 FP_DECL_EX; 1274 int mode; 1275 1276 mode = current->thread.fp_regs.fpc & 3; 1277 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1278 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f); 1279 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f); 1280 FP_MUL_S(SR, SA, SB); 1281 FP_SUB_S(SR, SR, SC); 1282 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR); 1283 return _fex; 1284} 1285 1286/* Multiply and subtract float */ 1287static int emu_mseb (struct pt_regs *regs, int rx, float *val, int rz) { 1288 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SC); FP_DECL_S(SR); 1289 FP_DECL_EX; 1290 int mode; 1291 1292 mode = current->thread.fp_regs.fpc & 3; 1293 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1294 FP_UNPACK_SP(SB, val); 1295 FP_UNPACK_SP(SC, &current->thread.fp_regs.fprs[rz].f); 1296 FP_MUL_S(SR, SA, SB); 1297 FP_SUB_S(SR, SR, SC); 1298 FP_PACK_SP(&current->thread.fp_regs.fprs[rz].f, SR); 1299 return _fex; 1300} 1301 1302/* Set floating point control word */ 1303static int emu_sfpc (struct pt_regs *regs, int rx, int ry) { 1304 __u32 temp; 1305 1306 temp = regs->gprs[rx]; 1307 if ((temp & ~FPC_VALID_MASK) != 0) 1308 return SIGILL; 1309 current->thread.fp_regs.fpc = temp; 1310 return 0; 1311} 1312 1313/* Square root long double */ 1314static int emu_sqxbr (struct pt_regs *regs, int rx, int ry) { 1315 FP_DECL_Q(QA); FP_DECL_Q(QR); 1316 FP_DECL_EX; 1317 mathemu_ldcv cvt; 1318 int mode; 1319 1320 mode = current->thread.fp_regs.fpc & 3; 1321 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 1322 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 1323 FP_UNPACK_QP(QA, &cvt.ld); 1324 FP_SQRT_Q(QR, QA); 1325 FP_PACK_QP(&cvt.ld, QR); 1326 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 1327 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 1328 emu_set_CC_cs(regs, QR_c, QR_s); 1329 return _fex; 1330} 1331 1332/* Square root double */ 1333static int emu_sqdbr (struct pt_regs *regs, int rx, int ry) { 1334 FP_DECL_D(DA); FP_DECL_D(DR); 1335 FP_DECL_EX; 1336 int mode; 1337 1338 mode = current->thread.fp_regs.fpc & 3; 1339 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[ry].d); 1340 FP_SQRT_D(DR, DA); 1341 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1342 emu_set_CC_cs(regs, DR_c, DR_s); 1343 return _fex; 1344} 1345 1346/* Square root double */ 1347static int emu_sqdb (struct pt_regs *regs, int rx, double *val) { 1348 FP_DECL_D(DA); FP_DECL_D(DR); 1349 FP_DECL_EX; 1350 int mode; 1351 1352 mode = current->thread.fp_regs.fpc & 3; 1353 FP_UNPACK_DP(DA, val); 1354 FP_SQRT_D(DR, DA); 1355 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1356 emu_set_CC_cs(regs, DR_c, DR_s); 1357 return _fex; 1358} 1359 1360/* Square root float */ 1361static int emu_sqebr (struct pt_regs *regs, int rx, int ry) { 1362 FP_DECL_S(SA); FP_DECL_S(SR); 1363 FP_DECL_EX; 1364 int mode; 1365 1366 mode = current->thread.fp_regs.fpc & 3; 1367 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[ry].f); 1368 FP_SQRT_S(SR, SA); 1369 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1370 emu_set_CC_cs(regs, SR_c, SR_s); 1371 return _fex; 1372} 1373 1374/* Square root float */ 1375static int emu_sqeb (struct pt_regs *regs, int rx, float *val) { 1376 FP_DECL_S(SA); FP_DECL_S(SR); 1377 FP_DECL_EX; 1378 int mode; 1379 1380 mode = current->thread.fp_regs.fpc & 3; 1381 FP_UNPACK_SP(SA, val); 1382 FP_SQRT_S(SR, SA); 1383 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1384 emu_set_CC_cs(regs, SR_c, SR_s); 1385 return _fex; 1386} 1387 1388/* Subtract long double */ 1389static int emu_sxbr (struct pt_regs *regs, int rx, int ry) { 1390 FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR); 1391 FP_DECL_EX; 1392 mathemu_ldcv cvt; 1393 int mode; 1394 1395 mode = current->thread.fp_regs.fpc & 3; 1396 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 1397 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 1398 FP_UNPACK_QP(QA, &cvt.ld); 1399 cvt.w.high = current->thread.fp_regs.fprs[ry].ui; 1400 cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui; 1401 FP_UNPACK_QP(QB, &cvt.ld); 1402 FP_SUB_Q(QR, QA, QB); 1403 FP_PACK_QP(&cvt.ld, QR); 1404 current->thread.fp_regs.fprs[rx].ui = cvt.w.high; 1405 current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low; 1406 emu_set_CC_cs(regs, QR_c, QR_s); 1407 return _fex; 1408} 1409 1410/* Subtract double */ 1411static int emu_sdbr (struct pt_regs *regs, int rx, int ry) { 1412 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 1413 FP_DECL_EX; 1414 int mode; 1415 1416 mode = current->thread.fp_regs.fpc & 3; 1417 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1418 FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d); 1419 FP_SUB_D(DR, DA, DB); 1420 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1421 emu_set_CC_cs(regs, DR_c, DR_s); 1422 return _fex; 1423} 1424 1425/* Subtract double */ 1426static int emu_sdb (struct pt_regs *regs, int rx, double *val) { 1427 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR); 1428 FP_DECL_EX; 1429 int mode; 1430 1431 mode = current->thread.fp_regs.fpc & 3; 1432 FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1433 FP_UNPACK_DP(DB, val); 1434 FP_SUB_D(DR, DA, DB); 1435 FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR); 1436 emu_set_CC_cs(regs, DR_c, DR_s); 1437 return _fex; 1438} 1439 1440/* Subtract float */ 1441static int emu_sebr (struct pt_regs *regs, int rx, int ry) { 1442 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 1443 FP_DECL_EX; 1444 int mode; 1445 1446 mode = current->thread.fp_regs.fpc & 3; 1447 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1448 FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f); 1449 FP_SUB_S(SR, SA, SB); 1450 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1451 emu_set_CC_cs(regs, SR_c, SR_s); 1452 return _fex; 1453} 1454 1455/* Subtract float */ 1456static int emu_seb (struct pt_regs *regs, int rx, float *val) { 1457 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 1458 FP_DECL_EX; 1459 int mode; 1460 1461 mode = current->thread.fp_regs.fpc & 3; 1462 FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1463 FP_UNPACK_SP(SB, val); 1464 FP_SUB_S(SR, SA, SB); 1465 FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR); 1466 emu_set_CC_cs(regs, SR_c, SR_s); 1467 return _fex; 1468} 1469 1470/* Test data class long double */ 1471static int emu_tcxb (struct pt_regs *regs, int rx, long val) { 1472 FP_DECL_Q(QA); 1473 mathemu_ldcv cvt; 1474 int bit; 1475 1476 cvt.w.high = current->thread.fp_regs.fprs[rx].ui; 1477 cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui; 1478 FP_UNPACK_RAW_QP(QA, &cvt.ld); 1479 switch (QA_e) { 1480 default: 1481 bit = 8; /* normalized number */ 1482 break; 1483 case 0: 1484 if (_FP_FRAC_ZEROP_4(QA)) 1485 bit = 10; /* zero */ 1486 else 1487 bit = 6; /* denormalized number */ 1488 break; 1489 case _FP_EXPMAX_Q: 1490 if (_FP_FRAC_ZEROP_4(QA)) 1491 bit = 4; /* infinity */ 1492 else if (_FP_FRAC_HIGH_RAW_Q(QA) & _FP_QNANBIT_Q) 1493 bit = 2; /* quiet NAN */ 1494 else 1495 bit = 0; /* signaling NAN */ 1496 break; 1497 } 1498 if (!QA_s) 1499 bit++; 1500 emu_set_CC(regs, ((__u32) val >> bit) & 1); 1501 return 0; 1502} 1503 1504/* Test data class double */ 1505static int emu_tcdb (struct pt_regs *regs, int rx, long val) { 1506 FP_DECL_D(DA); 1507 int bit; 1508 1509 FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d); 1510 switch (DA_e) { 1511 default: 1512 bit = 8; /* normalized number */ 1513 break; 1514 case 0: 1515 if (_FP_FRAC_ZEROP_2(DA)) 1516 bit = 10; /* zero */ 1517 else 1518 bit = 6; /* denormalized number */ 1519 break; 1520 case _FP_EXPMAX_D: 1521 if (_FP_FRAC_ZEROP_2(DA)) 1522 bit = 4; /* infinity */ 1523 else if (_FP_FRAC_HIGH_RAW_D(DA) & _FP_QNANBIT_D) 1524 bit = 2; /* quiet NAN */ 1525 else 1526 bit = 0; /* signaling NAN */ 1527 break; 1528 } 1529 if (!DA_s) 1530 bit++; 1531 emu_set_CC(regs, ((__u32) val >> bit) & 1); 1532 return 0; 1533} 1534 1535/* Test data class float */ 1536static int emu_tceb (struct pt_regs *regs, int rx, long val) { 1537 FP_DECL_S(SA); 1538 int bit; 1539 1540 FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f); 1541 switch (SA_e) { 1542 default: 1543 bit = 8; /* normalized number */ 1544 break; 1545 case 0: 1546 if (_FP_FRAC_ZEROP_1(SA)) 1547 bit = 10; /* zero */ 1548 else 1549 bit = 6; /* denormalized number */ 1550 break; 1551 case _FP_EXPMAX_S: 1552 if (_FP_FRAC_ZEROP_1(SA)) 1553 bit = 4; /* infinity */ 1554 else if (_FP_FRAC_HIGH_RAW_S(SA) & _FP_QNANBIT_S) 1555 bit = 2; /* quiet NAN */ 1556 else 1557 bit = 0; /* signaling NAN */ 1558 break; 1559 } 1560 if (!SA_s) 1561 bit++; 1562 emu_set_CC(regs, ((__u32) val >> bit) & 1); 1563 return 0; 1564} 1565 1566static inline void emu_load_regd(int reg) { 1567 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */ 1568 return; 1569 asm volatile( /* load reg from fp_regs.fprs[reg] */ 1570 " bras 1,0f\n" 1571 " ld 0,0(%1)\n" 1572 "0: ex %0,0(1)" 1573 : /* no output */ 1574 : "a" (reg<<4),"a" (&current->thread.fp_regs.fprs[reg].d) 1575 : "1"); 1576} 1577 1578static inline void emu_load_rege(int reg) { 1579 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */ 1580 return; 1581 asm volatile( /* load reg from fp_regs.fprs[reg] */ 1582 " bras 1,0f\n" 1583 " le 0,0(%1)\n" 1584 "0: ex %0,0(1)" 1585 : /* no output */ 1586 : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f) 1587 : "1"); 1588} 1589 1590static inline void emu_store_regd(int reg) { 1591 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */ 1592 return; 1593 asm volatile( /* store reg to fp_regs.fprs[reg] */ 1594 " bras 1,0f\n" 1595 " std 0,0(%1)\n" 1596 "0: ex %0,0(1)" 1597 : /* no output */ 1598 : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d) 1599 : "1"); 1600} 1601 1602 1603static inline void emu_store_rege(int reg) { 1604 if ((reg&9) != 0) /* test if reg in {0,2,4,6} */ 1605 return; 1606 asm volatile( /* store reg to fp_regs.fprs[reg] */ 1607 " bras 1,0f\n" 1608 " ste 0,0(%1)\n" 1609 "0: ex %0,0(1)" 1610 : /* no output */ 1611 : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f) 1612 : "1"); 1613} 1614 1615int math_emu_b3(__u8 *opcode, struct pt_regs * regs) { 1616 int _fex = 0; 1617 static const __u8 format_table[256] = { 1618 [0x00] = 0x03,[0x01] = 0x03,[0x02] = 0x03,[0x03] = 0x03, 1619 [0x04] = 0x0f,[0x05] = 0x0d,[0x06] = 0x0e,[0x07] = 0x0d, 1620 [0x08] = 0x03,[0x09] = 0x03,[0x0a] = 0x03,[0x0b] = 0x03, 1621 [0x0c] = 0x0f,[0x0d] = 0x03,[0x0e] = 0x06,[0x0f] = 0x06, 1622 [0x10] = 0x02,[0x11] = 0x02,[0x12] = 0x02,[0x13] = 0x02, 1623 [0x14] = 0x03,[0x15] = 0x02,[0x16] = 0x01,[0x17] = 0x03, 1624 [0x18] = 0x02,[0x19] = 0x02,[0x1a] = 0x02,[0x1b] = 0x02, 1625 [0x1c] = 0x02,[0x1d] = 0x02,[0x1e] = 0x05,[0x1f] = 0x05, 1626 [0x40] = 0x01,[0x41] = 0x01,[0x42] = 0x01,[0x43] = 0x01, 1627 [0x44] = 0x12,[0x45] = 0x0d,[0x46] = 0x11,[0x47] = 0x04, 1628 [0x48] = 0x01,[0x49] = 0x01,[0x4a] = 0x01,[0x4b] = 0x01, 1629 [0x4c] = 0x01,[0x4d] = 0x01,[0x53] = 0x06,[0x57] = 0x06, 1630 [0x5b] = 0x05,[0x5f] = 0x05,[0x84] = 0x13,[0x8c] = 0x13, 1631 [0x94] = 0x09,[0x95] = 0x08,[0x96] = 0x07,[0x98] = 0x0c, 1632 [0x99] = 0x0b,[0x9a] = 0x0a 1633 }; 1634 static const void *jump_table[256]= { 1635 [0x00] = emu_lpebr,[0x01] = emu_lnebr,[0x02] = emu_ltebr, 1636 [0x03] = emu_lcebr,[0x04] = emu_ldebr,[0x05] = emu_lxdbr, 1637 [0x06] = emu_lxebr,[0x07] = emu_mxdbr,[0x08] = emu_kebr, 1638 [0x09] = emu_cebr, [0x0a] = emu_aebr, [0x0b] = emu_sebr, 1639 [0x0c] = emu_mdebr,[0x0d] = emu_debr, [0x0e] = emu_maebr, 1640 [0x0f] = emu_msebr,[0x10] = emu_lpdbr,[0x11] = emu_lndbr, 1641 [0x12] = emu_ltdbr,[0x13] = emu_lcdbr,[0x14] = emu_sqebr, 1642 [0x15] = emu_sqdbr,[0x16] = emu_sqxbr,[0x17] = emu_meebr, 1643 [0x18] = emu_kdbr, [0x19] = emu_cdbr, [0x1a] = emu_adbr, 1644 [0x1b] = emu_sdbr, [0x1c] = emu_mdbr, [0x1d] = emu_ddbr, 1645 [0x1e] = emu_madbr,[0x1f] = emu_msdbr,[0x40] = emu_lpxbr, 1646 [0x41] = emu_lnxbr,[0x42] = emu_ltxbr,[0x43] = emu_lcxbr, 1647 [0x44] = emu_ledbr,[0x45] = emu_ldxbr,[0x46] = emu_lexbr, 1648 [0x47] = emu_fixbr,[0x48] = emu_kxbr, [0x49] = emu_cxbr, 1649 [0x4a] = emu_axbr, [0x4b] = emu_sxbr, [0x4c] = emu_mxbr, 1650 [0x4d] = emu_dxbr, [0x53] = emu_diebr,[0x57] = emu_fiebr, 1651 [0x5b] = emu_didbr,[0x5f] = emu_fidbr,[0x84] = emu_sfpc, 1652 [0x8c] = emu_efpc, [0x94] = emu_cefbr,[0x95] = emu_cdfbr, 1653 [0x96] = emu_cxfbr,[0x98] = emu_cfebr,[0x99] = emu_cfdbr, 1654 [0x9a] = emu_cfxbr 1655 }; 1656 1657 switch (format_table[opcode[1]]) { 1658 case 1: /* RRE format, long double operation */ 1659 if (opcode[3] & 0x22) 1660 return SIGILL; 1661 emu_store_regd((opcode[3] >> 4) & 15); 1662 emu_store_regd(((opcode[3] >> 4) & 15) + 2); 1663 emu_store_regd(opcode[3] & 15); 1664 emu_store_regd((opcode[3] & 15) + 2); 1665 /* call the emulation function */ 1666 _fex = ((int (*)(struct pt_regs *,int, int)) 1667 jump_table[opcode[1]]) 1668 (regs, opcode[3] >> 4, opcode[3] & 15); 1669 emu_load_regd((opcode[3] >> 4) & 15); 1670 emu_load_regd(((opcode[3] >> 4) & 15) + 2); 1671 emu_load_regd(opcode[3] & 15); 1672 emu_load_regd((opcode[3] & 15) + 2); 1673 break; 1674 case 2: /* RRE format, double operation */ 1675 emu_store_regd((opcode[3] >> 4) & 15); 1676 emu_store_regd(opcode[3] & 15); 1677 /* call the emulation function */ 1678 _fex = ((int (*)(struct pt_regs *, int, int)) 1679 jump_table[opcode[1]]) 1680 (regs, opcode[3] >> 4, opcode[3] & 15); 1681 emu_load_regd((opcode[3] >> 4) & 15); 1682 emu_load_regd(opcode[3] & 15); 1683 break; 1684 case 3: /* RRE format, float operation */ 1685 emu_store_rege((opcode[3] >> 4) & 15); 1686 emu_store_rege(opcode[3] & 15); 1687 /* call the emulation function */ 1688 _fex = ((int (*)(struct pt_regs *, int, int)) 1689 jump_table[opcode[1]]) 1690 (regs, opcode[3] >> 4, opcode[3] & 15); 1691 emu_load_rege((opcode[3] >> 4) & 15); 1692 emu_load_rege(opcode[3] & 15); 1693 break; 1694 case 4: /* RRF format, long double operation */ 1695 if (opcode[3] & 0x22) 1696 return SIGILL; 1697 emu_store_regd((opcode[3] >> 4) & 15); 1698 emu_store_regd(((opcode[3] >> 4) & 15) + 2); 1699 emu_store_regd(opcode[3] & 15); 1700 emu_store_regd((opcode[3] & 15) + 2); 1701 /* call the emulation function */ 1702 _fex = ((int (*)(struct pt_regs *, int, int, int)) 1703 jump_table[opcode[1]]) 1704 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4); 1705 emu_load_regd((opcode[3] >> 4) & 15); 1706 emu_load_regd(((opcode[3] >> 4) & 15) + 2); 1707 emu_load_regd(opcode[3] & 15); 1708 emu_load_regd((opcode[3] & 15) + 2); 1709 break; 1710 case 5: /* RRF format, double operation */ 1711 emu_store_regd((opcode[2] >> 4) & 15); 1712 emu_store_regd((opcode[3] >> 4) & 15); 1713 emu_store_regd(opcode[3] & 15); 1714 /* call the emulation function */ 1715 _fex = ((int (*)(struct pt_regs *, int, int, int)) 1716 jump_table[opcode[1]]) 1717 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4); 1718 emu_load_regd((opcode[2] >> 4) & 15); 1719 emu_load_regd((opcode[3] >> 4) & 15); 1720 emu_load_regd(opcode[3] & 15); 1721 break; 1722 case 6: /* RRF format, float operation */ 1723 emu_store_rege((opcode[2] >> 4) & 15); 1724 emu_store_rege((opcode[3] >> 4) & 15); 1725 emu_store_rege(opcode[3] & 15); 1726 /* call the emulation function */ 1727 _fex = ((int (*)(struct pt_regs *, int, int, int)) 1728 jump_table[opcode[1]]) 1729 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4); 1730 emu_load_rege((opcode[2] >> 4) & 15); 1731 emu_load_rege((opcode[3] >> 4) & 15); 1732 emu_load_rege(opcode[3] & 15); 1733 break; 1734 case 7: /* RRE format, cxfbr instruction */ 1735 /* call the emulation function */ 1736 if (opcode[3] & 0x20) 1737 return SIGILL; 1738 _fex = ((int (*)(struct pt_regs *, int, int)) 1739 jump_table[opcode[1]]) 1740 (regs, opcode[3] >> 4, opcode[3] & 15); 1741 emu_load_regd((opcode[3] >> 4) & 15); 1742 emu_load_regd(((opcode[3] >> 4) & 15) + 2); 1743 break; 1744 case 8: /* RRE format, cdfbr instruction */ 1745 /* call the emulation function */ 1746 _fex = ((int (*)(struct pt_regs *, int, int)) 1747 jump_table[opcode[1]]) 1748 (regs, opcode[3] >> 4, opcode[3] & 15); 1749 emu_load_regd((opcode[3] >> 4) & 15); 1750 break; 1751 case 9: /* RRE format, cefbr instruction */ 1752 /* call the emulation function */ 1753 _fex = ((int (*)(struct pt_regs *, int, int)) 1754 jump_table[opcode[1]]) 1755 (regs, opcode[3] >> 4, opcode[3] & 15); 1756 emu_load_rege((opcode[3] >> 4) & 15); 1757 break; 1758 case 10: /* RRF format, cfxbr instruction */ 1759 if ((opcode[2] & 128) == 128 || (opcode[2] & 96) == 32) 1760 /* mask of { 2,3,8-15 } is invalid */ 1761 return SIGILL; 1762 if (opcode[3] & 2) 1763 return SIGILL; 1764 emu_store_regd(opcode[3] & 15); 1765 emu_store_regd((opcode[3] & 15) + 2); 1766 /* call the emulation function */ 1767 _fex = ((int (*)(struct pt_regs *, int, int, int)) 1768 jump_table[opcode[1]]) 1769 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4); 1770 break; 1771 case 11: /* RRF format, cfdbr instruction */ 1772 if ((opcode[2] & 128) == 128 || (opcode[2] & 96) == 32) 1773 /* mask of { 2,3,8-15 } is invalid */ 1774 return SIGILL; 1775 emu_store_regd(opcode[3] & 15); 1776 /* call the emulation function */ 1777 _fex = ((int (*)(struct pt_regs *, int, int, int)) 1778 jump_table[opcode[1]]) 1779 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4); 1780 break; 1781 case 12: /* RRF format, cfebr instruction */ 1782 if ((opcode[2] & 128) == 128 || (opcode[2] & 96) == 32) 1783 /* mask of { 2,3,8-15 } is invalid */ 1784 return SIGILL; 1785 emu_store_rege(opcode[3] & 15); 1786 /* call the emulation function */ 1787 _fex = ((int (*)(struct pt_regs *, int, int, int)) 1788 jump_table[opcode[1]]) 1789 (regs, opcode[3] >> 4, opcode[3] & 15, opcode[2] >> 4); 1790 break; 1791 case 13: /* RRE format, ldxbr & mdxbr instruction */ 1792 /* double store but long double load */ 1793 if (opcode[3] & 0x20) 1794 return SIGILL; 1795 emu_store_regd((opcode[3] >> 4) & 15); 1796 emu_store_regd(opcode[3] & 15); 1797 /* call the emulation function */ 1798 _fex = ((int (*)(struct pt_regs *, int, int)) 1799 jump_table[opcode[1]]) 1800 (regs, opcode[3] >> 4, opcode[3] & 15); 1801 emu_load_regd((opcode[3] >> 4) & 15); 1802 emu_load_regd(((opcode[3] >> 4) & 15) + 2); 1803 break; 1804 case 14: /* RRE format, ldxbr & mdxbr instruction */ 1805 /* float store but long double load */ 1806 if (opcode[3] & 0x20) 1807 return SIGILL; 1808 emu_store_rege((opcode[3] >> 4) & 15); 1809 emu_store_rege(opcode[3] & 15); 1810 /* call the emulation function */ 1811 _fex = ((int (*)(struct pt_regs *, int, int)) 1812 jump_table[opcode[1]]) 1813 (regs, opcode[3] >> 4, opcode[3] & 15); 1814 emu_load_regd((opcode[3] >> 4) & 15); 1815 emu_load_regd(((opcode[3] >> 4) & 15) + 2); 1816 break; 1817 case 15: /* RRE format, ldebr & mdebr instruction */ 1818 /* float store but double load */ 1819 emu_store_rege((opcode[3] >> 4) & 15); 1820 emu_store_rege(opcode[3] & 15); 1821 /* call the emulation function */ 1822 _fex = ((int (*)(struct pt_regs *, int, int)) 1823 jump_table[opcode[1]]) 1824 (regs, opcode[3] >> 4, opcode[3] & 15); 1825 emu_load_regd((opcode[3] >> 4) & 15); 1826 break; 1827 case 16: /* RRE format, ldxbr instruction */ 1828 /* long double store but double load */ 1829 if (opcode[3] & 2) 1830 return SIGILL; 1831 emu_store_regd(opcode[3] & 15); 1832 emu_store_regd((opcode[3] & 15) + 2); 1833 /* call the emulation function */ 1834 _fex = ((int (*)(struct pt_regs *, int, int)) 1835 jump_table[opcode[1]]) 1836 (regs, opcode[3] >> 4, opcode[3] & 15); 1837 emu_load_regd((opcode[3] >> 4) & 15); 1838 break; 1839 case 17: /* RRE format, ldxbr instruction */ 1840 /* long double store but float load */ 1841 if (opcode[3] & 2) 1842 return SIGILL; 1843 emu_store_regd(opcode[3] & 15); 1844 emu_store_regd((opcode[3] & 15) + 2); 1845 /* call the emulation function */ 1846 _fex = ((int (*)(struct pt_regs *, int, int)) 1847 jump_table[opcode[1]]) 1848 (regs, opcode[3] >> 4, opcode[3] & 15); 1849 emu_load_rege((opcode[3] >> 4) & 15); 1850 break; 1851 case 18: /* RRE format, ledbr instruction */ 1852 /* double store but float load */ 1853 emu_store_regd(opcode[3] & 15); 1854 /* call the emulation function */ 1855 _fex = ((int (*)(struct pt_regs *, int, int)) 1856 jump_table[opcode[1]]) 1857 (regs, opcode[3] >> 4, opcode[3] & 15); 1858 emu_load_rege((opcode[3] >> 4) & 15); 1859 break; 1860 case 19: /* RRE format, efpc & sfpc instruction */ 1861 /* call the emulation function */ 1862 _fex = ((int (*)(struct pt_regs *, int, int)) 1863 jump_table[opcode[1]]) 1864 (regs, opcode[3] >> 4, opcode[3] & 15); 1865 break; 1866 default: /* invalid operation */ 1867 return SIGILL; 1868 } 1869 if (_fex != 0) { 1870 current->thread.fp_regs.fpc |= _fex; 1871 if (current->thread.fp_regs.fpc & (_fex << 8)) 1872 return SIGFPE; 1873 } 1874 return 0; 1875} 1876 1877static void* calc_addr(struct pt_regs *regs, int rx, int rb, int disp) 1878{ 1879 addr_t addr; 1880 1881 rx &= 15; 1882 rb &= 15; 1883 addr = disp & 0xfff; 1884 addr += (rx != 0) ? regs->gprs[rx] : 0; /* + index */ 1885 addr += (rb != 0) ? regs->gprs[rb] : 0; /* + base */ 1886 return (void*) addr; 1887} 1888 1889int math_emu_ed(__u8 *opcode, struct pt_regs * regs) { 1890 int _fex = 0; 1891 1892 static const __u8 format_table[256] = { 1893 [0x04] = 0x06,[0x05] = 0x05,[0x06] = 0x07,[0x07] = 0x05, 1894 [0x08] = 0x02,[0x09] = 0x02,[0x0a] = 0x02,[0x0b] = 0x02, 1895 [0x0c] = 0x06,[0x0d] = 0x02,[0x0e] = 0x04,[0x0f] = 0x04, 1896 [0x10] = 0x08,[0x11] = 0x09,[0x12] = 0x0a,[0x14] = 0x02, 1897 [0x15] = 0x01,[0x17] = 0x02,[0x18] = 0x01,[0x19] = 0x01, 1898 [0x1a] = 0x01,[0x1b] = 0x01,[0x1c] = 0x01,[0x1d] = 0x01, 1899 [0x1e] = 0x03,[0x1f] = 0x03, 1900 }; 1901 static const void *jump_table[]= { 1902 [0x04] = emu_ldeb,[0x05] = emu_lxdb,[0x06] = emu_lxeb, 1903 [0x07] = emu_mxdb,[0x08] = emu_keb, [0x09] = emu_ceb, 1904 [0x0a] = emu_aeb, [0x0b] = emu_seb, [0x0c] = emu_mdeb, 1905 [0x0d] = emu_deb, [0x0e] = emu_maeb,[0x0f] = emu_mseb, 1906 [0x10] = emu_tceb,[0x11] = emu_tcdb,[0x12] = emu_tcxb, 1907 [0x14] = emu_sqeb,[0x15] = emu_sqdb,[0x17] = emu_meeb, 1908 [0x18] = emu_kdb, [0x19] = emu_cdb, [0x1a] = emu_adb, 1909 [0x1b] = emu_sdb, [0x1c] = emu_mdb, [0x1d] = emu_ddb, 1910 [0x1e] = emu_madb,[0x1f] = emu_msdb 1911 }; 1912 1913 switch (format_table[opcode[5]]) { 1914 case 1: /* RXE format, double constant */ { 1915 __u64 *dxb, temp; 1916 __u32 opc; 1917 1918 emu_store_regd((opcode[1] >> 4) & 15); 1919 opc = *((__u32 *) opcode); 1920 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 1921 mathemu_copy_from_user(&temp, dxb, 8); 1922 /* call the emulation function */ 1923 _fex = ((int (*)(struct pt_regs *, int, double *)) 1924 jump_table[opcode[5]]) 1925 (regs, opcode[1] >> 4, (double *) &temp); 1926 emu_load_regd((opcode[1] >> 4) & 15); 1927 break; 1928 } 1929 case 2: /* RXE format, float constant */ { 1930 __u32 *dxb, temp; 1931 __u32 opc; 1932 1933 emu_store_rege((opcode[1] >> 4) & 15); 1934 opc = *((__u32 *) opcode); 1935 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 1936 mathemu_get_user(temp, dxb); 1937 /* call the emulation function */ 1938 _fex = ((int (*)(struct pt_regs *, int, float *)) 1939 jump_table[opcode[5]]) 1940 (regs, opcode[1] >> 4, (float *) &temp); 1941 emu_load_rege((opcode[1] >> 4) & 15); 1942 break; 1943 } 1944 case 3: /* RXF format, double constant */ { 1945 __u64 *dxb, temp; 1946 __u32 opc; 1947 1948 emu_store_regd((opcode[1] >> 4) & 15); 1949 emu_store_regd((opcode[4] >> 4) & 15); 1950 opc = *((__u32 *) opcode); 1951 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 1952 mathemu_copy_from_user(&temp, dxb, 8); 1953 /* call the emulation function */ 1954 _fex = ((int (*)(struct pt_regs *, int, double *, int)) 1955 jump_table[opcode[5]]) 1956 (regs, opcode[1] >> 4, (double *) &temp, opcode[4] >> 4); 1957 emu_load_regd((opcode[1] >> 4) & 15); 1958 break; 1959 } 1960 case 4: /* RXF format, float constant */ { 1961 __u32 *dxb, temp; 1962 __u32 opc; 1963 1964 emu_store_rege((opcode[1] >> 4) & 15); 1965 emu_store_rege((opcode[4] >> 4) & 15); 1966 opc = *((__u32 *) opcode); 1967 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 1968 mathemu_get_user(temp, dxb); 1969 /* call the emulation function */ 1970 _fex = ((int (*)(struct pt_regs *, int, float *, int)) 1971 jump_table[opcode[5]]) 1972 (regs, opcode[1] >> 4, (float *) &temp, opcode[4] >> 4); 1973 emu_load_rege((opcode[4] >> 4) & 15); 1974 break; 1975 } 1976 case 5: /* RXE format, double constant */ 1977 /* store double and load long double */ 1978 { 1979 __u64 *dxb, temp; 1980 __u32 opc; 1981 if ((opcode[1] >> 4) & 0x20) 1982 return SIGILL; 1983 emu_store_regd((opcode[1] >> 4) & 15); 1984 opc = *((__u32 *) opcode); 1985 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 1986 mathemu_copy_from_user(&temp, dxb, 8); 1987 /* call the emulation function */ 1988 _fex = ((int (*)(struct pt_regs *, int, double *)) 1989 jump_table[opcode[5]]) 1990 (regs, opcode[1] >> 4, (double *) &temp); 1991 emu_load_regd((opcode[1] >> 4) & 15); 1992 emu_load_regd(((opcode[1] >> 4) & 15) + 2); 1993 break; 1994 } 1995 case 6: /* RXE format, float constant */ 1996 /* store float and load double */ 1997 { 1998 __u32 *dxb, temp; 1999 __u32 opc; 2000 emu_store_rege((opcode[1] >> 4) & 15); 2001 opc = *((__u32 *) opcode); 2002 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 2003 mathemu_get_user(temp, dxb); 2004 /* call the emulation function */ 2005 _fex = ((int (*)(struct pt_regs *, int, float *)) 2006 jump_table[opcode[5]]) 2007 (regs, opcode[1] >> 4, (float *) &temp); 2008 emu_load_regd((opcode[1] >> 4) & 15); 2009 break; 2010 } 2011 case 7: /* RXE format, float constant */ 2012 /* store float and load long double */ 2013 { 2014 __u32 *dxb, temp; 2015 __u32 opc; 2016 if ((opcode[1] >> 4) & 0x20) 2017 return SIGILL; 2018 emu_store_rege((opcode[1] >> 4) & 15); 2019 opc = *((__u32 *) opcode); 2020 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 2021 mathemu_get_user(temp, dxb); 2022 /* call the emulation function */ 2023 _fex = ((int (*)(struct pt_regs *, int, float *)) 2024 jump_table[opcode[5]]) 2025 (regs, opcode[1] >> 4, (float *) &temp); 2026 emu_load_regd((opcode[1] >> 4) & 15); 2027 emu_load_regd(((opcode[1] >> 4) & 15) + 2); 2028 break; 2029 } 2030 case 8: /* RXE format, RX address used as int value */ { 2031 __u64 dxb; 2032 __u32 opc; 2033 2034 emu_store_rege((opcode[1] >> 4) & 15); 2035 opc = *((__u32 *) opcode); 2036 dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc); 2037 /* call the emulation function */ 2038 _fex = ((int (*)(struct pt_regs *, int, long)) 2039 jump_table[opcode[5]]) 2040 (regs, opcode[1] >> 4, dxb); 2041 break; 2042 } 2043 case 9: /* RXE format, RX address used as int value */ { 2044 __u64 dxb; 2045 __u32 opc; 2046 2047 emu_store_regd((opcode[1] >> 4) & 15); 2048 opc = *((__u32 *) opcode); 2049 dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc); 2050 /* call the emulation function */ 2051 _fex = ((int (*)(struct pt_regs *, int, long)) 2052 jump_table[opcode[5]]) 2053 (regs, opcode[1] >> 4, dxb); 2054 break; 2055 } 2056 case 10: /* RXE format, RX address used as int value */ { 2057 __u64 dxb; 2058 __u32 opc; 2059 2060 if ((opcode[1] >> 4) & 2) 2061 return SIGILL; 2062 emu_store_regd((opcode[1] >> 4) & 15); 2063 emu_store_regd(((opcode[1] >> 4) & 15) + 2); 2064 opc = *((__u32 *) opcode); 2065 dxb = (__u64) calc_addr(regs, opc >> 16, opc >> 12, opc); 2066 /* call the emulation function */ 2067 _fex = ((int (*)(struct pt_regs *, int, long)) 2068 jump_table[opcode[5]]) 2069 (regs, opcode[1] >> 4, dxb); 2070 break; 2071 } 2072 default: /* invalid operation */ 2073 return SIGILL; 2074 } 2075 if (_fex != 0) { 2076 current->thread.fp_regs.fpc |= _fex; 2077 if (current->thread.fp_regs.fpc & (_fex << 8)) 2078 return SIGFPE; 2079 } 2080 return 0; 2081} 2082 2083/* 2084 * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6} 2085 */ 2086int math_emu_ldr(__u8 *opcode) { 2087 s390_fp_regs *fp_regs = &current->thread.fp_regs; 2088 __u16 opc = *((__u16 *) opcode); 2089 2090 if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */ 2091 /* we got an exception therfore ry can't be in {0,2,4,6} */ 2092 asm volatile( /* load rx from fp_regs.fprs[ry] */ 2093 " bras 1,0f\n" 2094 " ld 0,0(%1)\n" 2095 "0: ex %0,0(1)" 2096 : /* no output */ 2097 : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].d) 2098 : "1"); 2099 } else if ((opc & 0x9) == 0) { /* test if ry in {0,2,4,6} */ 2100 asm volatile ( /* store ry to fp_regs.fprs[rx] */ 2101 " bras 1,0f\n" 2102 " std 0,0(%1)\n" 2103 "0: ex %0,0(1)" 2104 : /* no output */ 2105 : "a" ((opc & 0xf) << 4), 2106 "a" (&fp_regs->fprs[(opc & 0xf0)>>4].d) 2107 : "1"); 2108 } else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */ 2109 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf]; 2110 return 0; 2111} 2112 2113/* 2114 * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6} 2115 */ 2116int math_emu_ler(__u8 *opcode) { 2117 s390_fp_regs *fp_regs = &current->thread.fp_regs; 2118 __u16 opc = *((__u16 *) opcode); 2119 2120 if ((opc & 0x90) == 0) { /* test if rx in {0,2,4,6} */ 2121 /* we got an exception therfore ry can't be in {0,2,4,6} */ 2122 asm volatile( /* load rx from fp_regs.fprs[ry] */ 2123 " bras 1,0f\n" 2124 " le 0,0(%1)\n" 2125 "0: ex %0,0(1)" 2126 : /* no output */ 2127 : "a" (opc & 0xf0), "a" (&fp_regs->fprs[opc & 0xf].f) 2128 : "1"); 2129 } else if ((opc & 0x9) == 0) { /* test if ry in {0,2,4,6} */ 2130 asm volatile( /* store ry to fp_regs.fprs[rx] */ 2131 " bras 1,0f\n" 2132 " ste 0,0(%1)\n" 2133 "0: ex %0,0(1)" 2134 : /* no output */ 2135 : "a" ((opc & 0xf) << 4), 2136 "a" (&fp_regs->fprs[(opc & 0xf0) >> 4].f) 2137 : "1"); 2138 } else /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */ 2139 fp_regs->fprs[(opc & 0xf0) >> 4] = fp_regs->fprs[opc & 0xf]; 2140 return 0; 2141} 2142 2143/* 2144 * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6} 2145 */ 2146int math_emu_ld(__u8 *opcode, struct pt_regs * regs) { 2147 s390_fp_regs *fp_regs = &current->thread.fp_regs; 2148 __u32 opc = *((__u32 *) opcode); 2149 __u64 *dxb; 2150 2151 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 2152 mathemu_copy_from_user(&fp_regs->fprs[(opc >> 20) & 0xf].d, dxb, 8); 2153 return 0; 2154} 2155 2156/* 2157 * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6} 2158 */ 2159int math_emu_le(__u8 *opcode, struct pt_regs * regs) { 2160 s390_fp_regs *fp_regs = &current->thread.fp_regs; 2161 __u32 opc = *((__u32 *) opcode); 2162 __u32 *mem, *dxb; 2163 2164 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 2165 mem = (__u32 *) (&fp_regs->fprs[(opc >> 20) & 0xf].f); 2166 mathemu_get_user(mem[0], dxb); 2167 return 0; 2168} 2169 2170/* 2171 * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6} 2172 */ 2173int math_emu_std(__u8 *opcode, struct pt_regs * regs) { 2174 s390_fp_regs *fp_regs = &current->thread.fp_regs; 2175 __u32 opc = *((__u32 *) opcode); 2176 __u64 *dxb; 2177 2178 dxb = (__u64 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 2179 mathemu_copy_to_user(dxb, &fp_regs->fprs[(opc >> 20) & 0xf].d, 8); 2180 return 0; 2181} 2182 2183/* 2184 * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6} 2185 */ 2186int math_emu_ste(__u8 *opcode, struct pt_regs * regs) { 2187 s390_fp_regs *fp_regs = &current->thread.fp_regs; 2188 __u32 opc = *((__u32 *) opcode); 2189 __u32 *mem, *dxb; 2190 2191 dxb = (__u32 *) calc_addr(regs, opc >> 16, opc >> 12, opc); 2192 mem = (__u32 *) (&fp_regs->fprs[(opc >> 20) & 0xf].f); 2193 mathemu_put_user(mem[0], dxb); 2194 return 0; 2195} 2196 2197/* 2198 * Emulate LFPC D(B) 2199 */ 2200int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) { 2201 __u32 opc = *((__u32 *) opcode); 2202 __u32 *dxb, temp; 2203 2204 dxb= (__u32 *) calc_addr(regs, 0, opc>>12, opc); 2205 mathemu_get_user(temp, dxb); 2206 if ((temp & ~FPC_VALID_MASK) != 0) 2207 return SIGILL; 2208 current->thread.fp_regs.fpc = temp; 2209 return 0; 2210} 2211 2212/* 2213 * Emulate STFPC D(B) 2214 */ 2215int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) { 2216 __u32 opc = *((__u32 *) opcode); 2217 __u32 *dxb; 2218 2219 dxb= (__u32 *) calc_addr(regs, 0, opc>>12, opc); 2220 mathemu_put_user(current->thread.fp_regs.fpc, dxb); 2221 return 0; 2222} 2223 2224/* 2225 * Emulate SRNM D(B) 2226 */ 2227int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) { 2228 __u32 opc = *((__u32 *) opcode); 2229 __u32 temp; 2230 2231 temp = calc_addr(regs, 0, opc>>12, opc); 2232 current->thread.fp_regs.fpc &= ~3; 2233 current->thread.fp_regs.fpc |= (temp & 3); 2234 return 0; 2235} 2236 2237/* broken compiler ... */ 2238long long 2239__negdi2 (long long u) 2240{ 2241 2242 union lll { 2243 long long ll; 2244 long s[2]; 2245 }; 2246 2247 union lll w,uu; 2248 2249 uu.ll = u; 2250 2251 w.s[1] = -uu.s[1]; 2252 w.s[0] = -uu.s[0] - ((int) w.s[1] != 0); 2253 2254 return w.ll; 2255}