lol
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 15.09-beta 507 lines 14 kB view raw
1From bf55ef4e3c2f622ac013f196affbd11b67b59223 Mon Sep 17 00:00:00 2001 2From: Mark H Weaver <mhw@netris.org> 3Date: Fri, 28 Oct 2011 13:24:37 -0400 4Subject: [PATCH 2/4] Fix handling of prefx instruction in mips/math-emu 5 6* The instruction is named prefx, not pfetch, and its function 7 field is 0x17, not 0x07. 8 9* Recognize the prefx instruction regardless of what bits happen to be 10 in bits 21-25, which is the format field of the floating-point ops, 11 but holds the base register of the prefx instruction. 12--- 13 arch/mips/include/asm/inst.h | 4 ++-- 14 arch/mips/math-emu/cp1emu.c | 16 +++++++--------- 15 2 files changed, 9 insertions(+), 11 deletions(-) 16 17diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h 18index ab84064..3048edc 100644 19--- a/arch/mips/include/asm/inst.h 20+++ b/arch/mips/include/asm/inst.h 21@@ -161,8 +161,8 @@ enum cop1_sdw_func { 22 */ 23 enum cop1x_func { 24 lwxc1_op = 0x00, ldxc1_op = 0x01, 25- pfetch_op = 0x07, swxc1_op = 0x08, 26- sdxc1_op = 0x09, madd_s_op = 0x20, 27+ swxc1_op = 0x08, sdxc1_op = 0x09, 28+ prefx_op = 0x17, madd_s_op = 0x20, 29 madd_d_op = 0x21, madd_e_op = 0x22, 30 msub_s_op = 0x28, msub_d_op = 0x29, 31 msub_e_op = 0x2a, nmadd_s_op = 0x30, 32diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c 33index dbf2f93..87ddba1 100644 34--- a/arch/mips/math-emu/cp1emu.c 35+++ b/arch/mips/math-emu/cp1emu.c 36@@ -739,7 +739,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 37 break; 38 39 default: 40- return SIGILL; 41+ goto SIGILL_unless_prefx_op; 42 } 43 break; 44 } 45@@ -809,19 +809,17 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 46 goto copcsr; 47 48 default: 49- return SIGILL; 50+ goto SIGILL_unless_prefx_op; 51 } 52 break; 53 } 54 55- case 0x7: /* 7 */ 56- if (MIPSInst_FUNC(ir) != pfetch_op) { 57- return SIGILL; 58- } 59- /* ignore prefx operation */ 60- break; 61- 62 default: 63+ SIGILL_unless_prefx_op: 64+ if (MIPSInst_FUNC(ir) == prefx_op) { 65+ /* ignore prefx operation */ 66+ break; 67+ } 68 return SIGILL; 69 } 70 71-- 721.7.5.4 73 74From 97a564e3eddbfb84844b8eccb3bd751c71dfb3eb Mon Sep 17 00:00:00 2001 75From: Mark H Weaver <mhw@netris.org> 76Date: Fri, 28 Oct 2011 13:35:27 -0400 77Subject: [PATCH 3/4] Don't process empty cause flags after simple fp move on 78 mips 79 80--- 81 arch/mips/math-emu/cp1emu.c | 4 ++-- 82 1 files changed, 2 insertions(+), 2 deletions(-) 83 84diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c 85index 87ddba1..fefcba2 100644 86--- a/arch/mips/math-emu/cp1emu.c 87+++ b/arch/mips/math-emu/cp1emu.c 88@@ -912,7 +912,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 89 case fmov_op: 90 /* an easy one */ 91 SPFROMREG(rv.s, MIPSInst_FS(ir)); 92- goto copcsr; 93+ break; 94 95 /* binary op on handler */ 96 scopbop: 97@@ -1099,7 +1099,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 98 case fmov_op: 99 /* an easy one */ 100 DPFROMREG(rv.d, MIPSInst_FS(ir)); 101- goto copcsr; 102+ break; 103 104 /* binary op on handler */ 105 dcopbop:{ 106-- 1071.7.5.4 108 109From 4051727b3007ef3675e7258ed86fa8517f86d929 Mon Sep 17 00:00:00 2001 110From: Mark H Weaver <mhw@netris.org> 111Date: Fri, 28 Oct 2011 13:39:10 -0400 112Subject: [PATCH 4/4] Support Loongson2f floating-point instructions in 113 mips/math-emu 114 115* (arch/mips/include/asm/inst.h): Add Loongson2f function field values 116 for madd/msub/nmadd/nmsub that use the spec2 opcode, and the 117 Loongson2f/MIPS-5 format field value for paired-single 118 floating-point operations. 119 120* (arch/mips/math-emu/cp1emu.c): Add support for the Loongson2f 121 instructions for madd/msub/nmadd/nmsub, which use the spec2 opcode. 122 Also add support for the Loongson2f instructions that use the 123 paired-single floating-point format. 124--- 125 arch/mips/include/asm/inst.h | 4 +- 126 arch/mips/math-emu/cp1emu.c | 287 +++++++++++++++++++++++++++++++++++++++++- 127 2 files changed, 289 insertions(+), 2 deletions(-) 128 129diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h 130index 3048edc..0e8ba7c 100644 131--- a/arch/mips/include/asm/inst.h 132+++ b/arch/mips/include/asm/inst.h 133@@ -61,6 +61,8 @@ enum spec_op { 134 enum spec2_op { 135 madd_op, maddu_op, mul_op, spec2_3_unused_op, 136 msub_op, msubu_op, /* more unused ops */ 137+ loongson_madd_op = 0x18, loongson_msub_op, 138+ loongson_nmadd_op, loongson_nmsub_op, 139 clz_op = 0x20, clo_op, 140 dclz_op = 0x24, dclo_op, 141 sdbpp_op = 0x3f 142@@ -133,7 +135,7 @@ enum cop0_com_func { 143 */ 144 enum cop1_fmt { 145 s_fmt, d_fmt, e_fmt, q_fmt, 146- w_fmt, l_fmt 147+ w_fmt, l_fmt, ps_fmt 148 }; 149 150 /* 151diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c 152index fefcba2..166b2a4 100644 153--- a/arch/mips/math-emu/cp1emu.c 154+++ b/arch/mips/math-emu/cp1emu.c 155@@ -7,6 +7,9 @@ 156 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com 157 * Copyright (C) 2000 MIPS Technologies, Inc. 158 * 159+ * Loongson instruction support 160+ * Copyright (C) 2011 Mark H Weaver <mhw@netris.org> 161+ * 162 * This program is free software; you can distribute it and/or modify it 163 * under the terms of the GNU General Public License (Version 2) as 164 * published by the Free Software Foundation. 165@@ -57,6 +60,14 @@ 166 #endif 167 #define __mips 4 168 169+#ifdef __loongson_fp 170+#undef __loongson_fp 171+#endif 172+#if __mips >= 4 && __mips != 32 173+/* Include support for Loongson floating point instructions */ 174+#define __loongson_fp 1 175+#endif 176+ 177 /* Function which emulates a floating point instruction. */ 178 179 static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, 180@@ -66,6 +77,10 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, 181 static int fpux_emu(struct pt_regs *, 182 struct mips_fpu_struct *, mips_instruction, void *__user *); 183 #endif 184+#ifdef __loongson_fp 185+static int loongson_spec2_emu(struct pt_regs *, 186+ struct mips_fpu_struct *, mips_instruction, void *__user *); 187+#endif 188 189 /* Further private data for which no space exists in mips_fpu_struct */ 190 191@@ -203,6 +218,14 @@ static inline int cop1_64bit(struct pt_regs *xcp) 192 #define DPFROMREG(dp, x) DIFROMREG((dp).bits, x) 193 #define DPTOREG(dp, x) DITOREG((dp).bits, x) 194 195+/* Support for Loongson paired single floating-point format */ 196+#define PSIFROMREG(si1, si2, x) ({ u64 di; DIFROMREG(di, x); \ 197+ (si1) = (u32)di; (si2) = (u32)(di >> 32); }) 198+#define PSITOREG(si1, si2, x) DITOREG((si1) | ((u64)(si2) << 32), x) 199+ 200+#define PSPFROMREG(sp1, sp2, x) PSIFROMREG((sp1).bits, (sp2).bits, x) 201+#define PSPTOREG(sp1, sp2, x) PSITOREG((sp1).bits, (sp2).bits, x) 202+ 203 /* 204 * Emulate the single floating point instruction pointed at by EPC. 205 * Two instructions if the instruction is in a branch delay slot. 206@@ -568,6 +591,15 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 207 break; 208 #endif 209 210+#ifdef __loongson_fp 211+ case spec2_op:{ 212+ int sig = loongson_spec2_emu(xcp, ctx, ir, fault_addr); 213+ if (sig) 214+ return sig; 215+ break; 216+ } 217+#endif 218+ 219 default: 220 return SIGILL; 221 } 222@@ -646,6 +678,172 @@ DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub, ); 223 DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); 224 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); 225 226+#ifdef __loongson_fp 227+static int loongson_spec2_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 228+ mips_instruction ir, void *__user *fault_addr) 229+{ 230+ int rfmt; /* resulting format */ 231+ unsigned rcsr = 0; /* resulting csr */ 232+ union { 233+ ieee754dp d; 234+ struct { 235+ ieee754sp s; 236+ ieee754sp s2; 237+ }; 238+ } rv; /* resulting value */ 239+ 240+ /* XXX maybe add a counter for loongson spec2 fp instructions? */ 241+ /* MIPS_FPU_EMU_INC_STATS(cp1xops); */ 242+ 243+ switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { 244+ case s_fmt:{ 245+ ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); 246+ ieee754sp fd, fs, ft; 247+ 248+ switch (MIPSInst_FUNC(ir)) { 249+ case loongson_madd_op: 250+ handler = fpemu_sp_madd; 251+ goto scoptop; 252+ case loongson_msub_op: 253+ handler = fpemu_sp_msub; 254+ goto scoptop; 255+ case loongson_nmadd_op: 256+ handler = fpemu_sp_nmadd; 257+ goto scoptop; 258+ case loongson_nmsub_op: 259+ handler = fpemu_sp_nmsub; 260+ goto scoptop; 261+ 262+ scoptop: 263+ SPFROMREG(fd, MIPSInst_FD(ir)); 264+ SPFROMREG(fs, MIPSInst_FS(ir)); 265+ SPFROMREG(ft, MIPSInst_FT(ir)); 266+ rv.s = (*handler) (fd, fs, ft); 267+ 268+ copcsr: 269+ if (ieee754_cxtest(IEEE754_INEXACT)) 270+ rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; 271+ if (ieee754_cxtest(IEEE754_UNDERFLOW)) 272+ rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; 273+ if (ieee754_cxtest(IEEE754_OVERFLOW)) 274+ rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; 275+ if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) 276+ rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; 277+ 278+ break; 279+ 280+ default: 281+ return SIGILL; 282+ } 283+ break; 284+ } 285+ 286+ case d_fmt:{ 287+ ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); 288+ ieee754dp fd, fs, ft; 289+ 290+ switch (MIPSInst_FUNC(ir)) { 291+ case loongson_madd_op: 292+ handler = fpemu_dp_madd; 293+ goto dcoptop; 294+ case loongson_msub_op: 295+ handler = fpemu_dp_msub; 296+ goto dcoptop; 297+ case loongson_nmadd_op: 298+ handler = fpemu_dp_nmadd; 299+ goto dcoptop; 300+ case loongson_nmsub_op: 301+ handler = fpemu_dp_nmsub; 302+ goto dcoptop; 303+ 304+ dcoptop: 305+ DPFROMREG(fd, MIPSInst_FD(ir)); 306+ DPFROMREG(fs, MIPSInst_FS(ir)); 307+ DPFROMREG(ft, MIPSInst_FT(ir)); 308+ rv.d = (*handler) (fd, fs, ft); 309+ goto copcsr; 310+ 311+ default: 312+ return SIGILL; 313+ } 314+ break; 315+ } 316+ 317+ case ps_fmt:{ 318+ ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); 319+ struct _ieee754_csr ieee754_csr_save; 320+ ieee754sp fd1, fs1, ft1; 321+ ieee754sp fd2, fs2, ft2; 322+ 323+ switch (MIPSInst_FUNC(ir)) { 324+ case loongson_madd_op: 325+ handler = fpemu_sp_madd; 326+ goto pscoptop; 327+ case loongson_msub_op: 328+ handler = fpemu_sp_msub; 329+ goto pscoptop; 330+ case loongson_nmadd_op: 331+ handler = fpemu_sp_nmadd; 332+ goto pscoptop; 333+ case loongson_nmsub_op: 334+ handler = fpemu_sp_nmsub; 335+ goto pscoptop; 336+ 337+ pscoptop: 338+ PSPFROMREG(fd1, fd2, MIPSInst_FD(ir)); 339+ PSPFROMREG(fs1, fs2, MIPSInst_FS(ir)); 340+ PSPFROMREG(ft1, ft2, MIPSInst_FT(ir)); 341+ rv.s = (*handler) (fd1, fs1, ft1); 342+ ieee754_csr_save = ieee754_csr; 343+ rv.s2 = (*handler) (fd2, fs2, ft2); 344+ ieee754_csr.cx |= ieee754_csr_save.cx; 345+ ieee754_csr.sx |= ieee754_csr_save.sx; 346+ goto copcsr; 347+ 348+ default: 349+ return SIGILL; 350+ } 351+ break; 352+ } 353+ 354+ default: 355+ return SIGILL; 356+ } 357+ 358+ /* 359+ * Update the fpu CSR register for this operation. 360+ * If an exception is required, generate a tidy SIGFPE exception, 361+ * without updating the result register. 362+ * Note: cause exception bits do not accumulate, they are rewritten 363+ * for each op; only the flag/sticky bits accumulate. 364+ */ 365+ ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; 366+ if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { 367+ /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */ 368+ return SIGFPE; 369+ } 370+ 371+ /* 372+ * Now we can safely write the result back to the register file. 373+ */ 374+ switch (rfmt) { 375+ case d_fmt: 376+ DPTOREG(rv.d, MIPSInst_FD(ir)); 377+ break; 378+ case s_fmt: 379+ SPTOREG(rv.s, MIPSInst_FD(ir)); 380+ break; 381+ case ps_fmt: 382+ PSPTOREG(rv.s, rv.s2, MIPSInst_FD(ir)); 383+ break; 384+ default: 385+ return SIGILL; 386+ } 387+ 388+ return 0; 389+} 390+#endif 391+ 392 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 393 mips_instruction ir, void *__user *fault_addr) 394 { 395@@ -840,7 +1038,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 396 unsigned cond; 397 union { 398 ieee754dp d; 399- ieee754sp s; 400+ struct { 401+ ieee754sp s; 402+#ifdef __loongson_fp 403+ ieee754sp s2; /* for Loongson paired singles */ 404+#endif 405+ }; 406 int w; 407 #ifdef __mips64 408 s64 l; 409@@ -1210,6 +1413,83 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 410 break; 411 } 412 413+#ifdef __loongson_fp 414+ case ps_fmt:{ /* 6 */ 415+ /* Support for Loongson paired single fp instructions */ 416+ union { 417+ ieee754sp(*b) (ieee754sp, ieee754sp); 418+ ieee754sp(*u) (ieee754sp); 419+ } handler; 420+ 421+ switch (MIPSInst_FUNC(ir)) { 422+ /* binary ops */ 423+ case fadd_op: 424+ handler.b = ieee754sp_add; 425+ goto pscopbop; 426+ case fsub_op: 427+ handler.b = ieee754sp_sub; 428+ goto pscopbop; 429+ case fmul_op: 430+ handler.b = ieee754sp_mul; 431+ goto pscopbop; 432+ 433+ /* unary ops */ 434+ case fabs_op: 435+ handler.u = ieee754sp_abs; 436+ goto pscopuop; 437+ case fneg_op: 438+ handler.u = ieee754sp_neg; 439+ goto pscopuop; 440+ case fmov_op: 441+ /* an easy one */ 442+ PSPFROMREG(rv.s, rv.s2, MIPSInst_FS(ir)); 443+ break; 444+ 445+ pscopbop: /* paired binary op handler */ 446+ { 447+ struct _ieee754_csr ieee754_csr_save; 448+ ieee754sp fs1, ft1; 449+ ieee754sp fs2, ft2; 450+ 451+ PSPFROMREG(fs1, fs2, MIPSInst_FS(ir)); 452+ PSPFROMREG(ft1, ft2, MIPSInst_FT(ir)); 453+ rv.s = (*handler.b) (fs1, ft1); 454+ ieee754_csr_save = ieee754_csr; 455+ rv.s2 = (*handler.b) (fs2, ft2); 456+ ieee754_csr.cx |= ieee754_csr_save.cx; 457+ ieee754_csr.sx |= ieee754_csr_save.sx; 458+ goto copcsr; 459+ } 460+ pscopuop: /* paired unary op handler */ 461+ { 462+ struct _ieee754_csr ieee754_csr_save; 463+ ieee754sp fs1; 464+ ieee754sp fs2; 465+ 466+ PSPFROMREG(fs1, fs2, MIPSInst_FS(ir)); 467+ rv.s = (*handler.u) (fs1); 468+ ieee754_csr_save = ieee754_csr; 469+ rv.s2 = (*handler.u) (fs2); 470+ ieee754_csr.cx |= ieee754_csr_save.cx; 471+ ieee754_csr.sx |= ieee754_csr_save.sx; 472+ goto copcsr; 473+ } 474+ break; 475+ 476+ default: 477+ if (MIPSInst_FUNC(ir) >= fcmp_op) { 478+ /* Loongson fp hardware handles all 479+ cases of fp compare insns, so we 480+ shouldn't have to */ 481+ printk ("Loongson paired-single fp compare" 482+ " unimplemented in cp1emu.c\n"); 483+ } 484+ return SIGILL; 485+ } 486+ break; 487+ } 488+#endif 489+ 490 case w_fmt:{ 491 ieee754sp fs; 492 493@@ -1299,6 +1579,11 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 494 DITOREG(rv.l, MIPSInst_FD(ir)); 495 break; 496 #endif 497+#ifdef __loongson_fp 498+ case ps_fmt: 499+ PSPTOREG(rv.s, rv.s2, MIPSInst_FD(ir)); 500+ break; 501+#endif 502 default: 503 return SIGILL; 504 } 505-- 5061.7.5.4 507