|
@@ -826,3 +826,106 @@ do_entUnaUser(void __user * va, unsigned long opcode,
|
|
|
__asm__ __volatile__(
|
|
|
"1: ldq_u %1,0(%3)\n"
|
|
|
"2: ldq_u %2,1(%3)\n"
|
|
|
+ " extwl %1,%3,%1\n"
|
|
|
+ " extwh %2,%3,%2\n"
|
|
|
+ "3:\n"
|
|
|
+ ".section __ex_table,\"a\"\n"
|
|
|
+ " .long 1b - .\n"
|
|
|
+ " lda %1,3b-1b(%0)\n"
|
|
|
+ " .long 2b - .\n"
|
|
|
+ " lda %2,3b-2b(%0)\n"
|
|
|
+ ".previous"
|
|
|
+ : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
|
|
|
+ : "r"(va), "0"(0));
|
|
|
+ if (error)
|
|
|
+ goto give_sigsegv;
|
|
|
+ *reg_addr = tmp1|tmp2;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0x22: /* lds */
|
|
|
+ __asm__ __volatile__(
|
|
|
+ "1: ldq_u %1,0(%3)\n"
|
|
|
+ "2: ldq_u %2,3(%3)\n"
|
|
|
+ " extll %1,%3,%1\n"
|
|
|
+ " extlh %2,%3,%2\n"
|
|
|
+ "3:\n"
|
|
|
+ ".section __ex_table,\"a\"\n"
|
|
|
+ " .long 1b - .\n"
|
|
|
+ " lda %1,3b-1b(%0)\n"
|
|
|
+ " .long 2b - .\n"
|
|
|
+ " lda %2,3b-2b(%0)\n"
|
|
|
+ ".previous"
|
|
|
+ : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
|
|
|
+ : "r"(va), "0"(0));
|
|
|
+ if (error)
|
|
|
+ goto give_sigsegv;
|
|
|
+ alpha_write_fp_reg(reg, s_mem_to_reg((int)(tmp1|tmp2)));
|
|
|
+ return;
|
|
|
+
|
|
|
+ case 0x23: /* ldt */
|
|
|
+ __asm__ __volatile__(
|
|
|
+ "1: ldq_u %1,0(%3)\n"
|
|
|
+ "2: ldq_u %2,7(%3)\n"
|
|
|
+ " extql %1,%3,%1\n"
|
|
|
+ " extqh %2,%3,%2\n"
|
|
|
+ "3:\n"
|
|
|
+ ".section __ex_table,\"a\"\n"
|
|
|
+ " .long 1b - .\n"
|
|
|
+ " lda %1,3b-1b(%0)\n"
|
|
|
+ " .long 2b - .\n"
|
|
|
+ " lda %2,3b-2b(%0)\n"
|
|
|
+ ".previous"
|
|
|
+ : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
|
|
|
+ : "r"(va), "0"(0));
|
|
|
+ if (error)
|
|
|
+ goto give_sigsegv;
|
|
|
+ alpha_write_fp_reg(reg, tmp1|tmp2);
|
|
|
+ return;
|
|
|
+
|
|
|
+ case 0x28: /* ldl */
|
|
|
+ __asm__ __volatile__(
|
|
|
+ "1: ldq_u %1,0(%3)\n"
|
|
|
+ "2: ldq_u %2,3(%3)\n"
|
|
|
+ " extll %1,%3,%1\n"
|
|
|
+ " extlh %2,%3,%2\n"
|
|
|
+ "3:\n"
|
|
|
+ ".section __ex_table,\"a\"\n"
|
|
|
+ " .long 1b - .\n"
|
|
|
+ " lda %1,3b-1b(%0)\n"
|
|
|
+ " .long 2b - .\n"
|
|
|
+ " lda %2,3b-2b(%0)\n"
|
|
|
+ ".previous"
|
|
|
+ : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
|
|
|
+ : "r"(va), "0"(0));
|
|
|
+ if (error)
|
|
|
+ goto give_sigsegv;
|
|
|
+ *reg_addr = (int)(tmp1|tmp2);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 0x29: /* ldq */
|
|
|
+ __asm__ __volatile__(
|
|
|
+ "1: ldq_u %1,0(%3)\n"
|
|
|
+ "2: ldq_u %2,7(%3)\n"
|
|
|
+ " extql %1,%3,%1\n"
|
|
|
+ " extqh %2,%3,%2\n"
|
|
|
+ "3:\n"
|
|
|
+ ".section __ex_table,\"a\"\n"
|
|
|
+ " .long 1b - .\n"
|
|
|
+ " lda %1,3b-1b(%0)\n"
|
|
|
+ " .long 2b - .\n"
|
|
|
+ " lda %2,3b-2b(%0)\n"
|
|
|
+ ".previous"
|
|
|
+ : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
|
|
|
+ : "r"(va), "0"(0));
|
|
|
+ if (error)
|
|
|
+ goto give_sigsegv;
|
|
|
+ *reg_addr = tmp1|tmp2;
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* Note that the store sequences do not indicate that they change
|
|
|
+ memory because it _should_ be affecting nothing in this context.
|
|
|
+ (Otherwise we have other, much larger, problems.) */
|
|
|
+ case 0x0d: /* stw */
|
|
|
+ __asm__ __volatile__(
|
|
|
+ "1: ldq_u %2,1(%5)\n"
|
|
|
+ "2: ldq_u %1,0(%5)\n"
|