qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH][SPARC] Fix the shift instructions for theSPARC


From: Aurelien Jarno
Subject: Re: [Qemu-devel] [PATCH][SPARC] Fix the shift instructions for theSPARC target
Date: Sun, 1 Apr 2007 13:39:56 +0200
User-agent: Mutt/1.5.13 (2006-08-11)

On Sun, Apr 01, 2007 at 11:32:06AM +0200, Blue Swirl wrote:
> >The shift instructions on the SPARC target currently take into account
> >the whole register as the shift count. According to the SPARC v8 and v9
> >manuals, only the lower 5 bits should be taken into account for 32-bit
> >instructions (SLL, SRL, SRA), and only the lower 6 bits for 64-bit
> >instructions (SLLX, SRLX, SRAX).
> >
> >The patch below fixes that. Note that SLL and SLLX are now different, as
> >they don't take into account the same number of bits. Please apply.
> 
> Can you check what happens in real hardware, especially in the case when 
> the shift amount is in a register, not immediate, and the value is either 
> >32 or ==32?

I have just made the test on real hardware. Specifying a value of 32 leave
the register unchanged. Specifying a value > 32 only takes the lower 5
bits of the value. So exactly as specified in the manual.

> The 64-bit mask should be 0x3f, not 0x2f.

Oops you are right, please find an updated patch below.


Index: target-sparc/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-sparc/op.c,v
retrieving revision 1.26
diff -u -d -p -r1.26 op.c
--- target-sparc/op.c   23 Mar 2007 20:01:20 -0000      1.26
+++ target-sparc/op.c   25 Mar 2007 13:50:45 -0000
@@ -965,38 +965,43 @@ void OPPROTO op_logic_T0_cc(void)
 
 void OPPROTO op_sll(void)
 {
-    T0 <<= T1;
+    T0 <<= (T1 & 0x1f);
 }
 
 #ifdef TARGET_SPARC64
+void OPPROTO op_sllx(void)
+{
+    T0 <<= (T1 & 0x3f);
+}
+
 void OPPROTO op_srl(void)
 {
-    T0 = (T0 & 0xffffffff) >> T1;
+    T0 = (T0 & 0xffffffff) >> (T1 & 0x1f);
 }
 
 void OPPROTO op_srlx(void)
 {
-    T0 >>= T1;
+    T0 >>= (T1 & 0x3f);
 }
 
 void OPPROTO op_sra(void)
 {
-    T0 = ((int32_t) (T0 & 0xffffffff)) >> T1;
+    T0 = ((int32_t) (T0 & 0xffffffff)) >> (T1 & 0x1f);
 }
 
 void OPPROTO op_srax(void)
 {
-    T0 = ((int64_t) T0) >> T1;
+    T0 = ((int64_t) T0) >> (T1 & 0x3f);
 }
 #else
 void OPPROTO op_srl(void)
 {
-    T0 >>= T1;
+    T0 >>= (T1 & 0x1f);
 }
 
 void OPPROTO op_sra(void)
 {
-    T0 = ((int32_t) T0) >> T1;
+    T0 = ((int32_t) T0) >> (T1 & 0x1f);
 }
 #endif
 
Index: target-sparc/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-sparc/translate.c,v
retrieving revision 1.38
diff -u -d -p -r1.38 translate.c
--- target-sparc/translate.c    25 Mar 2007 07:55:52 -0000      1.38
+++ target-sparc/translate.c    25 Mar 2007 13:50:45 -0000
@@ -1693,7 +1693,7 @@ static void disas_sparc_insn(DisasContex
                }
 #endif
 #ifdef TARGET_SPARC64
-           } else if (xop == 0x25) { /* sll, V9 sllx ( == sll) */
+           } else if (xop == 0x25) { /* sll, V9 sllx */
                 rs1 = GET_FIELD(insn, 13, 17);
                gen_movl_reg_T0(rs1);
                if (IS_IMM) {   /* immediate */
@@ -1703,7 +1703,10 @@ static void disas_sparc_insn(DisasContex
                     rs2 = GET_FIELD(insn, 27, 31);
                     gen_movl_reg_T1(rs2);
                 }
-               gen_op_sll();
+               if (insn & (1 << 12))
+                   gen_op_sllx();
+               else
+                   gen_op_sll();
                gen_movl_T0_reg(rd);
            } else if (xop == 0x26) { /* srl, V9 srlx */
                 rs1 = GET_FIELD(insn, 13, 17);
 


-- 
  .''`.  Aurelien Jarno             | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   address@hidden         | address@hidden
   `-    people.debian.org/~aurel32 | www.aurel32.net




reply via email to

[Prev in Thread] Current Thread [Next in Thread]