X86: Make 64 bit unaligned accesses work as well as the other sizes.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 5 Aug 2007 03:22:20 +0000 (20:22 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 5 Aug 2007 03:22:20 +0000 (20:22 -0700)
There is a fundemental flaw in how unaligned accesses are supported, but this
is still an improvement.

--HG--
extra : convert_revision : 1c20b524ac24cd4a812c876b067495ee6a7ae29f

src/arch/x86/insts/microldstop.hh
src/arch/x86/isa/microops/ldstop.isa

index 8fef141214bf71501ca901e6230a367eab29c72e..fac1fa3aaef0a83aa16123c5b25d14a9d4814104 100644 (file)
@@ -113,19 +113,22 @@ namespace X86ISA
             switch(size)
             {
               case 1:
-                fault = xc->read(alignedEA, (uint8_t&)Mem, flags);
+                fault = xc->read(alignedEA, (uint8_t&)(Mem.a), flags);
                 break;
               case 2:
-                fault = xc->read(alignedEA, (uint16_t&)Mem, flags);
+                fault = xc->read(alignedEA, (uint16_t&)(Mem.a), flags);
                 break;
               case 4:
-                fault = xc->read(alignedEA, (uint32_t&)Mem, flags);
+                fault = xc->read(alignedEA, (uint32_t&)(Mem.a), flags);
                 break;
               case 8:
-                fault = xc->read(alignedEA, (uint64_t&)Mem, flags);
+                fault = xc->read(alignedEA, (uint64_t&)(Mem.a), flags);
+                break;
+              case 16:
+                fault = xc->read(alignedEA, Mem, flags);
                 break;
               default:
-                panic("Bad operand size %d!\n", size);
+                panic("Bad operand size %d for read at %#x.\n", size, EA);
             }
             return fault;
         }
@@ -141,19 +144,22 @@ namespace X86ISA
             switch(size)
             {
               case 1:
-                fault = xc->write((uint8_t&)Mem, alignedEA, flags, 0);
+                fault = xc->write((uint8_t&)(Mem.a), alignedEA, flags, 0);
                 break;
               case 2:
-                fault = xc->write((uint16_t&)Mem, alignedEA, flags, 0);
+                fault = xc->write((uint16_t&)(Mem.a), alignedEA, flags, 0);
                 break;
               case 4:
-                fault = xc->write((uint32_t&)Mem, alignedEA, flags, 0);
+                fault = xc->write((uint32_t&)(Mem.a), alignedEA, flags, 0);
                 break;
               case 8:
-                fault = xc->write((uint64_t&)Mem, alignedEA, flags, 0);
+                fault = xc->write((uint64_t&)(Mem.a), alignedEA, flags, 0);
+                break;
+              case 16:
+                fault = xc->write(Mem, alignedEA, flags, 0);
                 break;
               default:
-                panic("Bad operand size %d!\n", size);
+                panic("Bad operand size %d for write at %#x.\n", size, EA);
             }
             return fault;
         }
index 8dbd4d5cce481fdcf4040a8f164432b3dbdf560b..403a1aacfffe4e333283da8c76627c0759b02b2a 100644 (file)
@@ -123,9 +123,19 @@ def template MicroLoadExecute {{
         %(ea_code)s;
         DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
 
-        fault = read(xc, EA, Mem, 0);
+        Twin64_t alignedMem;
+        fault = read(xc, EA, alignedMem, 0);
         int offset = EA & (dataSize - 1);
-        Mem = bits(Mem, (offset + dataSize) * 8 - 1,  offset * 8);
+        if(dataSize != 8 || !offset)
+        {
+            Mem = bits(alignedMem.a,
+                    (offset + dataSize) * 8 - 1,  offset * 8);
+        }
+        else
+        {
+            Mem = alignedMem.b << (dataSize - offset) * 8;
+            Mem |= bits(alignedMem.a, dataSize * 8 - 1, offset * 8);
+        }
 
         if(fault == NoFault)
         {
@@ -153,7 +163,8 @@ def template MicroLoadInitiateAcc {{
         DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
 
         int offset = EA & (dataSize - 1);
-        fault = read(xc, EA, Mem, offset);
+        Twin64_t alignedMem;
+        fault = read(xc, EA, alignedMem, offset);
 
         return fault;
     }
@@ -169,9 +180,18 @@ def template MicroLoadCompleteAcc {{
         %(op_decl)s;
         %(op_rd)s;
 
-        Mem = pkt->get<typeof(Mem)>();
+        Twin64_t alignedMem = pkt->get<Twin64_t>();
         int offset = pkt->req->getFlags();
-        Mem = bits(Mem, (offset + dataSize) * 8 - 1,  offset * 8);
+        if(dataSize != 8 || !offset)
+        {
+            Mem = bits(alignedMem.a,
+                    (offset + dataSize) * 8 - 1,  offset * 8);
+        }
+        else
+        {
+            Mem = alignedMem.b << (dataSize - offset) * 8;
+            Mem |= bits(alignedMem.a, dataSize * 8 - 1, offset * 8);
+        }
         %(code)s;
 
         if(fault == NoFault)
@@ -201,8 +221,14 @@ def template MicroStoreExecute {{
 
         if(fault == NoFault)
         {
-            Mem = Mem << ((EA & (dataSize - 1)) * 8);
-            fault = write(xc, Mem, EA, 0);
+            int offset = EA & (dataSize - 1);
+
+            Twin64_t alignedMem;
+            alignedMem.a = Mem << (offset * 8);
+            alignedMem.b =
+                bits(Mem, dataSize * 8 - 1, (dataSize - offset) * 8);
+
+            fault = write(xc, alignedMem, EA, 0);
             if(fault == NoFault)
             {
                 %(op_wb)s;
@@ -229,8 +255,14 @@ def template MicroStoreInitiateAcc {{
 
         if(fault == NoFault)
         {
-            Mem = Mem << ((EA & (dataSize - 1)) * 8);
-            fault = write(xc, Mem, EA, 0);
+            int offset = EA & (dataSize - 1);
+
+            Twin64_t alignedMem;
+            alignedMem.a = Mem << (offset * 8);
+            alignedMem.b =
+                bits(Mem, dataSize * 8 - 1, (dataSize - offset) * 8);
+
+            fault = write(xc, alignedMem, EA, 0);
             if(fault == NoFault)
             {
                 %(op_wb)s;