diff mbox

[RFC,11/15] memory: Allow unaligned address_space_rw

Message ID aefb8a5d6923a1ce1ade1c109a789edc4a6e0fea.1367849167.git.jan.kiszka@siemens.com
State New
Headers show

Commit Message

Jan Kiszka May 6, 2013, 2:26 p.m. UTC
This will be needed for some corner cases with para-virtual the I/O
ports.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 exec.c |   33 ++++++++++++++++++---------------
 1 files changed, 18 insertions(+), 15 deletions(-)
diff mbox

Patch

diff --git a/exec.c b/exec.c
index 3ee1f3f..9c582b1 100644
--- a/exec.c
+++ b/exec.c
@@ -1833,38 +1833,41 @@  void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
     uint8_t *ptr;
     uint32_t val;
     MemoryRegionSection *section;
+    MemoryRegion *mr;
 
     while (len > 0) {
         l = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr;
         if (l > len)
             l = len;
         section = address_space_lookup_region(as, addr);
+        mr = section->mr;
 
         if (is_write) {
-            if (!memory_region_is_ram(section->mr)) {
+            if (!memory_region_is_ram(mr)) {
                 hwaddr addr1;
                 addr1 = memory_region_section_addr(section, addr);
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
-                if (l >= 4 && ((addr1 & 3) == 0)) {
+                if (l >= 4 && ((addr1 & 3) == 0 || mr->ops->impl.unaligned)) {
                     /* 32 bit write access */
                     val = ldl_p(buf);
-                    io_mem_write(section->mr, addr1, val, 4);
+                    io_mem_write(mr, addr1, val, 4);
                     l = 4;
-                } else if (l >= 2 && ((addr1 & 1) == 0)) {
+                } else if (l >= 2 &&
+                           ((addr1 & 1) == 0 || mr->ops->impl.unaligned)) {
                     /* 16 bit write access */
                     val = lduw_p(buf);
-                    io_mem_write(section->mr, addr1, val, 2);
+                    io_mem_write(mr, addr1, val, 2);
                     l = 2;
                 } else {
                     /* 8 bit write access */
                     val = ldub_p(buf);
-                    io_mem_write(section->mr, addr1, val, 1);
+                    io_mem_write(mr, addr1, val, 1);
                     l = 1;
                 }
             } else if (!section->readonly) {
                 ram_addr_t addr1;
-                addr1 = memory_region_get_ram_addr(section->mr)
+                addr1 = memory_region_get_ram_addr(mr)
                     + memory_region_section_addr(section, addr);
                 /* RAM case */
                 ptr = qemu_get_ram_ptr(addr1);
@@ -1873,30 +1876,30 @@  void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                 qemu_put_ram_ptr(ptr);
             }
         } else {
-            if (!(memory_region_is_ram(section->mr) ||
-                  memory_region_is_romd(section->mr))) {
+            if (!(memory_region_is_ram(mr) || memory_region_is_romd(mr))) {
                 hwaddr addr1;
                 /* I/O case */
                 addr1 = memory_region_section_addr(section, addr);
-                if (l >= 4 && ((addr1 & 3) == 0)) {
+                if (l >= 4 && ((addr1 & 3) == 0 || mr->ops->impl.unaligned)) {
                     /* 32 bit read access */
-                    val = io_mem_read(section->mr, addr1, 4);
+                    val = io_mem_read(mr, addr1, 4);
                     stl_p(buf, val);
                     l = 4;
-                } else if (l >= 2 && ((addr1 & 1) == 0)) {
+                } else if (l >= 2 &&
+                           ((addr1 & 1) == 0 || mr->ops->impl.unaligned)) {
                     /* 16 bit read access */
-                    val = io_mem_read(section->mr, addr1, 2);
+                    val = io_mem_read(mr, addr1, 2);
                     stw_p(buf, val);
                     l = 2;
                 } else {
                     /* 8 bit read access */
-                    val = io_mem_read(section->mr, addr1, 1);
+                    val = io_mem_read(mr, addr1, 1);
                     stb_p(buf, val);
                     l = 1;
                 }
             } else {
                 /* RAM case */
-                ptr = qemu_get_ram_ptr(section->mr->ram_addr
+                ptr = qemu_get_ram_ptr(mr->ram_addr
                                        + memory_region_section_addr(section,
                                                                     addr));
                 memcpy(buf, ptr, l);